c语言实现迷宫问题.docx
- 文档编号:25868925
- 上传时间:2023-06-16
- 格式:DOCX
- 页数:13
- 大小:69.61KB
c语言实现迷宫问题.docx
《c语言实现迷宫问题.docx》由会员分享,可在线阅读,更多相关《c语言实现迷宫问题.docx(13页珍藏版)》请在冰豆网上搜索。
c语言实现迷宫问题
数据结构试验——迷宫问题
(一)基本问题
1.问题描述
这是心理学中的一个经典问题。
心理学家把一只老鼠从一个无顶盖的大盒子的入口处放入,让老鼠自行找到出口出来。
迷宫中设置很多障碍阻止老鼠前行,迷宫唯一的出口处放有一块奶酪,吸引老鼠找到出口。
简而言之,迷宫问题是解决从布置了许多障碍的通道中寻找出路的问题。
本题设置的迷宫如图1所示。
图1迷宫示意图
迷宫四周设为墙;无填充处,为可通处。
设每个点有四个可通方向,分别为东、南、西、北(为了清晰,以下称“上下左右”)。
左上角为入口。
右下角为出口。
迷宫有一个入口,一个出口。
设计程序求解迷宫的一条通路。
2.数据结构设计
以一个m×n的数组mg表示迷宫,每个元素表示一个方块状态,数组元素0和1分别表示迷宫中的通路和障碍。
迷宫四周为墙,对应的迷宫数组的边界元素均为1。
根据题目中的数据,设置一个数组mg如下
intmg[M+2][N+2]=
{
{1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1},
{1,1,0,0,0,1,1,1},
{1,0,0,1,0,0,0,1},
{1,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1}
};在算法中用到的栈采用顺序存储结构,将栈定义为
Struct
{inti;增量数组move[4]如图3所示。
move[4]
x
y
0
-1
0
1
0
1
2
1
0
3
0
-1
图2数组move[4]
方位示意图如下:
通路:
通路上的每一个点有3个属性:
一个横坐标属性i、一个列坐标属性j和一个方向属性di,表示其下一点的位置。
如果约定尝试的顺序为上、右、下、左(即顺时针方向),则每尝试一个方向不通时,di值增1,当d增至4时,表示此位置一定不是通路上的点,从栈中去除。
在找到出口时,栈中保存的就是一条迷宫通路。
(1)下面介绍求解迷宫(xi,yj)到终点(xe,ye)的路径的函数:
先将入口进栈(其初始位置设置为—1),在栈不空时循环——取栈顶方块(不退栈)①若该方块为出口,输出所有的方块即为路径,其代码和相应解释如下:
intmgpath(intxi,intyi,intxe,intye)=xi;st[top].j=yi;
st[top].di=-1;mg[1][1]=-1;
while(top>-1);j=st[top].j;di=st[top].di;,st[k].j);
if((k+1)%5==0)-1;j=st[top].j;break;
case1:
i=st[top].i;j=st[top].j+1;break;
case2:
i=st[top].i+1;j=st[top].j;break;
case3:
i=st[top].i,j=st[top].j-1;break;
}
if(mg[i][j]==0)find=1;i=di;=i;st[top].j=j;st[top].di=-1;
mg[i][j]=-1;][st[top].j]=0;计思想
(1)设置一个迷宫节点的数据结构。
(2)建立迷宫图形。
(3)对迷宫进行处理找出一条从入口点到出口点的路径。
(4)输出该路径。
(5)打印通路迷宫图。
当迷宫采用二维数组表示时,老鼠在迷宫任一时刻的位置可由数组的行列序号i,j来表示。
而从[i],[j]位置出发可能进行的方向见下图7.如果[i],[j]周围的位置均为0值,则老鼠可以选择这8个位置中的任一个作为它的下一位置。
将这8个方向分别记作:
E(东)、SE(东南)、S(南)SW(西南)W(西)、NW(西北)、N(北)和NE(东北)。
但是并非每一个位置都有8个相邻位置。
如果[i],[j]位于边界上,即i=1,或i=m,或j=1,或j=n,则相邻位置可能是3个或5个为了避免检查边界条件,将数组四周围用值为1的边框包围起来,这样二维数组maze应该声明为maze[m+2],[n+2]在迷宫行进时,可能有多个行进方向可选,我们可以规定方向搜索的次序是从东(E)沿顺时针方向进行。
为了简化问题,规定[i],[j]的下一步位置的坐标是[x],[y],并将这8个方位伤的x和y坐标的增量预先放在一个结构数组move[8]中(见图8)。
该数组的每个分量有两个域dx和dy。
例如要向东走,只要在j值上加上dy,就可以得到下一步位置的[x],[y]值为[i],[j+dy]。
于是搜索方向的变化只要令方向值dir从0增至7,便可以从move数组中得到从[i],[j]点出发搜索到的每一个相邻点[x],[y]。
x=i+move[dir].dx
y=j+move[dir].dy
dxdy
图7方向位移图图8向量差图
为了防止重走原路,我们规定对已经走过的位置,将原值为0改为-1,这既可以区别该位置是否已经走到过,又可以与边界值1相区别。
当整个搜索过程结束后可以将所有的-1改回到0,从而恢复迷宫原样。
这样计算机走迷宫的方法是:
采取一步一步试探的方法。
每一步都从(E)开始,按顺时针对8个方向进行探测,若某个方位上的maze[x],[y]=0,表示可以通行,则走一步;若maze[x],[y]=1,表示此方向不可通行须换方向再试。
直至8个方向都试过,maze[x],[y]均为1,说明此步已无路可走,需退回一步,在上一步的下一个方向重新开始探测。
为此需要设置一个栈,用来记录所走过的位置和方向(i,j,dir)。
当退回一步时,就从栈中退出一个元素,以便在上一个位置的下一个方向上探测,如又找到一个行进方向,则把当前位置和新的方向重新进栈,并走到新的位置。
如果探测到x=m,y=n,则已经到达迷宫的出口,可以停止检测,输出存在栈中的路径;若在某一位置的8个方向上都堵塞,则退回一步,继续探测,如果已经退到迷宫的入口(栈中无元素),则表示此迷宫无路径可通行。
2系统算法(伪代码描述):
(1)建立迷宫节点的结构类型stack[]。
(2)入迷宫图形0表示可以通1表示不可以通。
用二维数组maze[m+2][n+2]进行存储。
数组四周用1表示墙壁,其中入口点(1,1)与出口点(m,n)固定。
(3)函数path()对迷宫进行处理,从入口开始:
While(!
((s->top==-1)&&(dir>=7)||(x==M)&&(y==N)&&(maze[x][y]==-1)))
{
For(扫描八个可以走的方向)
{
If(找到一个可以走的方向)
{
进入栈
标志在当前点可以找到一个可以走的方向
避免重复选择maze[x][y]=-1
不再对当前节点扫描
}
If(八个方向已经被全部扫描过,无可以通的路)
{
标志当前节点没有往前的路
后退一个节点搜索
}
}
If(找到了目的地)
{
输出路径退出循环
}
}
未找到路径
(4)输出从入口点到出口点的一条路径。
(5)输出标有通路的迷宫图。
3.算法流程图:
4.程序代码:
#defineM212/*M2*N2为实际使用迷宫数组的大小*/
#defineN211
#definemaxlenM2x=0;move[0].dy=1;
move[1].dx=1;move[1].dy=1;
move[2].dx=1;move[2].dy=0;
move[3].dx=1;move[3].dy=-1;
move[4].dx=0;move[4].dy=-1;
move[5].dx=-1;move[5].dy-=1;
move[6].dx=-1;move[6].dy=0;
move[7].dx=-1;move[7].dy=1;
}x;y;
if(maze[x][y]==0)
{
=i;=j;=dir;
f=push(s,elem);<<","<
(三)求所有通路和最短路径的算法
1.源代码(用原题的数据)
#include<>
#defineM5/*行数*/
#defineN7/*列数*/
#defineMaxSize100/*栈最多元素个数*/
intmg[M+1][N+1]={/*一个迷宫,其四周要加上均为1的外框*/
{1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1},
{1,1,0,0,0,1,1,1},
{1,0,0,1,0,0,0,1},
{1,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1}
};
struct
{
inti;intj;intdi;
}Stack[MaxSize],Path[MaxSize];/*定义栈和存放最短路径的数组*/
inttop=-1;/*栈指针*/
intcount=1;/*路径数计数*/
intminlen=MaxSize;/*最短路径长度*/
voidmgpath()/*路径为:
(1,1)->(M-2,N-2)*/
{
inti,j,di,find,k;
top++;/*进栈*/
Stack[top].i=1;
Stack[top].j=1;
Stack[top].di=-1;mg[1][1]=-1;/*初始结点进栈*/
while(top>-1)/*栈不空时循环*/
{
i=Stack[top].i;j=Stack[top].j;di=Stack[top].di;
if(i==M-2&&j==N-2)/*找到了出口,输出路径*/
{
printf("%4d:
",count++);
for(k=0;k<=top;k++)
{
printf("(%d,%d)",Stack[k].i,Stack[k].j);
if((k+1)%5==0)printf("\n\t");/*输出时每5个结点换一行*/
}
printf("\n");
if(top+1 { for(k=0;k<=top;k++) Path[k]=Stack[k]; minlen=top+1; } mg[Stack[top].i][Stack[top].j]=0;/*让该位置变为其他路径可走结点*/ top--; i=Stack[top].i;j=Stack[top].j;di=Stack[top].di; } find=0; while(di<4&&find==0)/*找下一个可走结点*/ {di++; switch(di) { case0: i=Stack[top].i-1;j=Stack[top].j;break; case1: i=Stack[top].i;j=Stack[top].j+1;break; case2: i=Stack[top].i+1;j=Stack[top].j;break; case3: i=Stack[top].i,j=Stack[top].j-1;break; } if(mg[i][j]==0)find=1; } if(find==1)/*找到了下一个可走结点*/ {Stack[top].di=di;/*修改原栈顶元素的di值*/ top++;Stack[top].i=i;Stack[top].j=j;Stack[top].di=-1;/*下一个可走结点进栈*/ mg[i][j]=-1;/*避免重复走到该结点*/ } else/*没有路径可走,则退栈*/ { mg[Stack[top].i][Stack[top].j]=0;/*让该位置变为其他路径可走结点*/ top--; } } printf("最短路径如下: \n"); printf("长度: %d\n",minlen); printf("路径: "); for(k=0;k { printf("(%d,%d)",Path[k].i,Path[k].j); if((k+1)%5==0)printf("\n\t");/*输出时每5个结点换一行*/ } printf("\n"); } voidmain() { printf("迷宫所有路径如下: \n"); mgpath(); } 2求解结果 6.实验收获及思考 这次试验总体来说还是比较简单的,因为几个思考问题都是在基本问题的源代码上进行改进和补充。 有了第一次数据结构编程和测试的经验,这次试验减少了很多困难,相对来说容易多了。 附录 基本问题换代码(思考问题源代码在上文中已经全部给出) #defineM4 #defineN6 #defineMaxSize100 #include<> intmg[M+2][N+2]= { {1,1,1,1,1,1,1,1}, {1,0,0,1,0,0,0,1}, {1,1,0,0,0,1,1,1}, {1,0,0,1,0,0,0,1}, {1,0,0,0,0,0,0,1}, {1,1,1,1,1,1,1,1} }; intmgpath(intxi,intyi,intxe,intye)=xi;st[top].j=yi; st[top].di=-1;mg[1][1]=-1; while(top>-1);j=st[top].j;di=st[top].di;,st[k].j); if((k+1)%5==0)-1;j=st[top].j;break; case1: i=st[top].i;j=st[top].j+1;break; case2: i=st[top].i+1;j=st[top].j;break; case3: i=st[top].i,j=st[top].j-1;break; } if(mg[i][j]==0)find=1;i=di;=i;st[top].j=j;st[top].di=-1; mg[i][j]=-1;][st[top].j]=0;//让该位置变为其他路径可走方块 top--;//将该方块退栈 } } return(0);//表示没有可走路径,返回0 } voidmain() { mgpath(1,1,M,N); }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- c语言实现 迷宫问题 语言 实现 迷宫 问题