c语言实现迷宫问题#仅供借鉴_第1页
c语言实现迷宫问题#仅供借鉴_第2页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、数据结构试验迷宫问题(一)基本问题1.问题描述这是心理学中的一个经典问题。心理学家把一只老鼠从一个无顶盖的大盒子的入口处放入,让老鼠自行找到出口出来。迷宫中设置很多障碍阻止老鼠前行,迷宫唯一的出口处放有一块奶酪,吸引老鼠找到出口。简而言之,迷宫问题是解决从布置了许多障碍的通道中寻找出路的问题。本题设置的迷宫如图1所示。图1 迷宫示意图迷宫四周设为墙;无填充处,为可通处。设每个点有四个可通方向,分别为东、南、西、北(为了清晰,以下称“上下左右”)。左上角为入口。右下角为出口。迷宫有一个入口,一个出口。设计程序求解迷宫的一条通路。2.数据结构设计以一个mn的数组mg表示迷宫,每个元素表示一个方块状

2、态,数组元素0和1分别表示迷宫中的通路和障碍。迷宫四周为墙,对应的迷宫数组的边界元素均为1。根据题目中的数据,设置一个数组mg如下int mgM+2N+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 int i; /当前方块的行号 int j; /当前方块的列号 int di; /di是下一个相邻的可走的方位号stMaxSize;/ 定义栈int top=-1 /初始化栈3设计运算算法要寻找

3、一条通过迷宫的路径,就必须进行试探性搜索,只要有路可走就前进一步,无路可进,换一个方向进行尝试;当所有方向均不可走时,则沿原路退回一步(称为回溯),重新选择未走过可走的路,如此继续,直至到达出口或返回入口(没有通路)。在探索前进路径时,需要将搜索的踪迹记录下来,以便走不通时,可沿原路返回到前一个点换一个方向再进行新的探索。后退的尝试路径与前进路径正好相反,因此可以借用一个栈来记录前进路径。方向:每一个可通点有4个可尝试的方向,向不同的方向前进时,目的地的坐标不同。预先把4个方向上的位移存在一个数组中。如把上、右、下、左(即顺时针方向)依次编号为0、1、2、3.其增量数组move4如图3所示。m

4、ove4xy0-1010121030-1图2数组move4方位示意图如下: 通路:通路上的每一个点有3个属性:一个横坐标属性i、一个列坐标属性j和一个方向属性di,表示其下一点的位置。如果约定尝试的顺序为上、右、下、左(即顺时针方向),则每尝试一个方向不通时,di值增1,当d增至4时,表示此位置一定不是通路上的点,从栈中去除。在找到出口时,栈中保存的就是一条迷宫通路。(1)下面介绍求解迷宫(xi,yj)到终点(xe,ye)的路径的函数:先将入口进栈(其初始位置设置为1),在栈不空时循环取栈顶方块(不退栈)若该方块为出口,输出所有的方块即为路径,其代码和相应解释如下:int mgpath(int

5、 xi,int yi,int xe,int ye)/求解路径为:(xi,yi)-(xe,ye)struct int i;/当前方块的行号int j;/当前方块的列号int di;/di是下一可走方位的方位号 stMaxSize;/定义栈int top=-1;/初始化栈指针int i,j,k,di,find;top+; /初始方块进栈sttop.i=xi;sttop.j=yi;sttop.di=-1;mg11=-1; while (top-1)/栈不空时循环i=sttop.i;j=sttop.j;di=sttop.di; /取栈顶方块if (i=xe & j=ye)/找到了出口,输出路径 pri

6、ntf(迷宫路径如下:n);for (k=0;k=top;k+)printf(t(%d,%d),stk.i,stk.j);if (k+1)%5=0)/每输出每5个方块后换一行printf(n); printf(n);return(1);/找到一条路径后返回1否则,找下一个可走的相邻方块若不存在这样的路径,说明当前的路径不可能走通,也就是恢复当前方块为0后退栈。若存在这样的方块,则其方位保存在栈顶元素中,并将这个可走的相邻方块进栈(其初始位置设置为-1) 求迷宫回溯过程如图4所示从前一个方块找到相邻可走方块之后,再从当前方块找在、相邻可走方块,若没有这样的方快,说明当前方块不可能是从入口路径到出

7、口路径的一个方块,则从当前方块回溯到前一个方块,继续从前一个方块找可走的方块。 为了保证试探的可走的相邻方块不是已走路径上的方块,如(i,j)已经进栈,在试探(i+1,j)的下一方块时,又试探道(i,j),这样会很悲剧的引起死循环,为此,在一个方块进栈后,将对应的mg数组元素的值改为-1(变为不可走的相邻方块),当退栈时(表示该方块没有相邻的可走方块),将其值恢复0,其算法代码和相应的解释如下:find=0;while (ditop=-1)&(dir=7)|(x=M)&(y=N)&(mazexy=-1) For(扫描八个可以走的方向) If(找到一个可以走的方向)进入栈标志在当前点可以找到一个

8、可以走的方向避免重复选择mazexy=-1不再对当前节点扫描 If(八个方向已经被全部扫描过,无可以通的路) 标志当前节点没有往前的路 后退一个节点搜索If(找到了目的地) 输出路径退出循环 未找到路径 (4)输出从入口点到出口点的一条路径。 (5)输出标有通路的迷宫图。3.算法流程图:开始初始化迷宫,显示迷宫初始化方向位移数组寻找迷宫中的一条出路If mazexy=0设1,1为出口该点数据入栈TFWhile 栈不空且dir7doelseIf dir=7 或栈空显示通路结束图9 算法流程图4.程序代码:#define M2 12 /*M2*N2为实际使用迷宫数组的大小*/#define N2

9、11#define maxlen M2 / 栈长度#include #include#include int M=M2-2,N=N2-2;/M*N迷宫的大小typedef struct /定义栈元素的类型int x,y,dir;elemtype;typedef struct / 定义顺序栈elemtype stack maxlen;int top;sqstktp; struct moved /定义方向位移数组的元素类型对于存储坐标增量的方向位移数组move int dx,dy;/ void inimaze(int mazeN2)/初始化迷宫 int i,j,num; for(i=0,j=0;i

10、=M+1;i+)/设置迷宫边界mazeij=1; for(i=0,j=0;j=N+1;j+) mazeij=1; for(i=M+1,j=0;j=N+1;j+) mazeij=1; cout原始迷宫为:endl; for(i=1;i=M;i+) for (j=1;j=N;j+) num=(800*(i+j)+1500) % 327;/根据MN的值产生迷宫 if (num150)&(i!=M|j!=N) mazeij=1; else mazeij=0; coutmazeij ;/显示迷宫 coutendl; couttop=-1; /*inistack*/int push(sqstktp*s,e

11、lemtype x)if(s-top=maxlen-1)return(false);elses-stack+s-top=x;/*栈不满,执行入栈操作*/return(true);/*push*/elemtype pop(sqstktp *s)/*栈顶元素出栈*/elemtype elem;if(s-toptop-;return(s-stacks-top+1); /栈不空,返回栈顶元素 /pop/void path(int mazeN2,struct moved move,sqstktp *s) /寻找迷宫中的一条通路int i,j,dir,x,y,f;elemtype elem;i=1;j=1

12、;dir=0;maze11=-1; /设11为入口处do x=i+movedir.dx;/球下一步可行的到达点的坐标y=j+movedir.dy;if(mazexy=0)elem.x=i;elem.y=j;elem.dir=dir;f=push(s,elem);/如果可行将数据入栈if(f=false)/如果返回假,说明栈容量不足cout栈长不足;i=x;j=y;dir=0;mazexy=-1;elseif (dir top=-1)&(dir=7)|(x=M)&(y=N)&(mazexy=-1); /循环if(s-top=-1)/若是入口,则无通路cout此迷宫不通;elseelem.x=x;

13、 elem.y=y; elem.dir=dir;/将出口坐标入栈f=push(s,elem);cout迷宫通路是:endl;i=0;while (i top)cout(stacki.x,stacki.ytop)cout;if(i+1)%4=0)coutendl;i+; /void draw(int mazeN2,sqstktp *s) /在迷宫中绘制出通路 cout逃逸路线为:endl;int i,j;elemtype elem;for(i=1;i=M;i+) /将迷宫中全部的-1值回复为0值for(j=1;jtop-1) /根据栈中元素的坐标,将通路的各个点的值改为8elem=pop(s);

14、i=elem.x;j=elem.y;mazeij=8;for(i=1;i=M;i+)for(j=1;j=N;j+)printf(%3d,mazeij); /显示已标记通路的迷宫coutendl;void main() /寻找迷宫通路程序sqstktp *s;int mazeM2N2;struct moved move8;inimaze(maze); /初始化迷宫数组s=(sqstktp *)malloc(sizeof(sqstktp);inistack(s); /初始化栈inimove(move); /初始化方向位移数组path(maze,move,s); /寻找迷宫通路coutendl;dr

15、aw(maze,s); /绘制作出通路标记的迷宫5.运行结果(三)求所有通路和最短路径的算法1.源代码(用原题的数据)#include #define M 5/*行数*/#define N 7/*列数*/#define MaxSize 100/*栈最多元素个数*/int mgM+1N+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 int i;int j;int di; StackMaxSiz

16、e,PathMaxSize;/*定义栈和存放最短路径的数组*/int top=-1;/*栈指针*/int count=1;/*路径数计数*/int minlen=MaxSize;/*最短路径长度*/void mgpath()/*路径为:(1,1)-(M-2,N-2)*/int i,j,di,find,k;top+;/*进栈*/Stacktop.i=1;Stacktop.j=1;Stacktop.di=-1;mg11=-1; /*初始结点进栈*/while (top-1)/*栈不空时循环*/i=Stacktop.i;j=Stacktop.j;di=Stacktop.di;if (i=M-2 &

17、j=N-2)/*找到了出口,输出路径*/ printf(%4d: ,count+);for (k=0;k=top;k+)printf(%d,%d) ,Stackk.i,Stackk.j);if (k+1)%5=0) printf(nt); /*输出时每5个结点换一行*/printf(n);if (top+1minlen)/*比较找最短路径*/for (k=0;k=top;k+)Pathk=Stackk;minlen=top+1;mgStacktop.iStacktop.j=0; /*让该位置变为其他路径可走结点*/top-; i=Stacktop.i;j=Stacktop.j;di=Stack

18、top.di;find=0;while (di4 & find=0) /*找下一个可走结点*/di+;switch(di)case 0:i=Stacktop.i-1;j=Stacktop.j;break;case 1:i=Stacktop.i;j=Stacktop.j+1;break;case 2:i=Stacktop.i+1;j=Stacktop.j;break;case 3:i=Stacktop.i,j=Stacktop.j-1;break;if (mgij=0) find=1;if (find=1)/*找到了下一个可走结点*/Stacktop.di=di;/*修改原栈顶元素的di值*/t

19、op+;Stacktop.i=i;Stacktop.j=j;Stacktop.di=-1;/*下一个可走结点进栈*/mgij=-1;/*避免重复走到该结点*/else/*没有路径可走,则退栈*/mgStacktop.iStacktop.j=0; /*让该位置变为其他路径可走结点*/top-;printf(最短路径如下:n);printf(长度: %dn,minlen);printf(路径: );for (k=0;kminlen;k+)printf(%d,%d) ,Pathk.i,Pathk.j);if (k+1)%5=0) printf(nt); /*输出时每5个结点换一行*/printf(n

20、);void main()printf(迷宫所有路径如下:n);mgpath();2求解结果6.实验收获及思考 这次试验总体来说还是比较简单的,因为几个思考问题都是在基本问题的源代码上进行改进和补充。有了第一次数据结构编程和测试的经验,这次试验减少了很多困难,相对来说容易多了。附录基本问题换代码(思考问题源代码在上文中已经全部给出)#define M 4#define N 6#define MaxSize 100#include int mgM+2N+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;int mgpath(int xi,int yi,int xe,int ye)/求解路径为:(xi,yi)-(xe,ye)struct int i;/当前方块的行号int j;/当前方块的列号int di;/di是下一可走方位的方位号 stMaxSize;/定义栈int top=-1;/初始化栈指针int i,j,k,di,find;top+; /初始方块进栈sttop.i=xi;sttop.j=yi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论