《数据结构课程设计报告迷宫求解(13页).doc》由会员分享,可在线阅读,更多相关《数据结构课程设计报告迷宫求解(13页).doc(13页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、-数据结构课程设计报告迷宫求解-第 10 页数据结构课程设计报告 题 目 迷 宫 求 解 学生姓名 刘 照 学 号 201517030216 专业班级 网络工程15102班 指导老师 方霞 设计日期 2016年12.26-12.30 指导老师评阅意见:评阅成绩: 签名:目 录一、问题定义1二、可行性分析(含流程图)21.迷宫的建立:22.迷宫的存储:23.迷宫路径的搜索:21、概要设计:42.本程序包含10个函数:53、实现概要设计中定义的所有数据类型及操作的伪代码算法51、节点类型和指针类型52、迷宫的操作53.菜单选择74、程序源码8四、 调试过程及其解决方法13五、 运行验证结果(含实验
2、数据以及分析过程)131、手动输入132、自动输入14六、附录或参考资料14七、课程设计总结(心得)14一、问题定义目的:仅仅认识到队列是一种特殊的线性表是远远不够的,本次实习的目的在于使学生深入了解队列的特征,以便在实际问题背景下灵活运用它,同时还将巩固这种数据结构的构造方法。 功能:输入一个任意大小的迷宫数据,用非递归的方法求出一条走出迷宫的路径,并将路径输出;分步实施:1) 初步完成总体设计,搭好框架,确定人机对话的界面,确定函数个数;2) 完成最低要求:完成基本功能,实现一条路径的求解。3) 进一步要求:求出一条最短路径。二、可行性分析(含流程图)1.迷宫的建立: 迷宫中存在通路和障碍
3、,为了方便迷宫的创建,可用0表示通路,用1表示障碍,这样迷宫就可以用0、1矩阵来描述,2.迷宫的存储: 迷宫是一个矩形区域,可以使用二维数组表示迷宫,这样迷宫的每一个位置都可以用其行列号来唯一指定,但是二维数组不能动态定义其大小,我们可以考虑先定义一个较大的二维数组mazeM+2N+2,然后用它的前m行n列来存放元素,即可得到一个mn的二维数组,这样(0,0)表示迷宫入口位置,(m-1,n-1)表示迷宫出口位置。注:其中M,N分别表示迷宫最大行、列数,本程序M、N的缺省值为39、39,当然,用户也可根据需要,调整其大小。3.迷宫路径的搜索: 首先从迷宫的入口开始,如果该位置就是迷宫出口,则已经
4、找到了一条路径,搜索工作结束。否则搜索其上、下、左、右位置是否是障碍,若不是障碍,就移动到该位置,然后再从该位置开始搜索通往出口的路径;若是障碍就选择另一个相邻的位置,并从它开始搜索路径。为防止搜索重复出现,则将已搜索过的位置标记为2,同时保留搜索痕迹,在考虑进入下一个位置搜索之前,将当前位置保存在一个队列中,如果所有相邻的非障碍位置均被搜索过,且未找到通往出口的路径,则表明不存在从入口到出口的路径。这实现的是广度优先遍历的算法,如果找到路径,则为最短路径。 以矩阵 0 0 1 0 1 为例,来示范一下 0 0 1 0 1 1 0 0 1 01 0 0 0 10 0 1 0 0首先,将位置(0
5、,0)(序号0)放入队列中,其前节点为空,从它开始搜索,其标记变为2,由于其只有一个非障碍位置,所以接下来移动到(0,1)(序号1),其前节点序号为0,标记变为2,然后从(0,1)移动到(1,1)(序号2),放入队列中,其前节点序号为1,(1,1)存在(1,2)(序号3)、(2,1)(序号4)两个可移动位置,其前节点序号均为2.对于每一个非障碍位置,它的相邻非障碍节点均入队列,且它们的前节点序号均为该位置的序号,所以如果存在路径,则从出口处节点的位置,逆序就可以找到其从出口到入口的通路。如下表所示: 0 1 2 3 4 5 6 7 8 9 10(0,0)(0,1)(1,1)(1,2)(2,1)
6、(2,2)(1,3)(2,3)(0,3)(3,3)(3,4)-10122345679由此可以看出,得到最短路径:(3,4)(3,3)(2,3)(2,2)(1,2)(1,1)(0,1)(0,0) 搜索算法流程图如下所示:三、程序设计(含变量、类型说明、程序源码等)1、概要设计:构建一个二维数组mazeM+2N+2用于存储迷宫矩阵自动或手动生成迷宫,即为二维数组mazeM+2N+2赋值构建一个队列用于存储迷宫路径建立迷宫节点struct point,用于存储迷宫中每个节点的访问情况实现搜索算法屏幕上显示操作菜单2.本程序包含10个函数:(1)主函数 main()(2)手动生成迷宫函数 shoudo
7、ng_maze()(3)自动生成迷宫函数 zidong_maze()(4)将迷宫打印成图形 print_maze()(5)打印迷宫路径 (若存在路径) result_maze()(6)入队 enqueue()(7)出队 dequeue()(8)判断队列是否为空 is_empty()(9)访问节点 visit()(10)搜索迷宫路径 mgpath()3、实现概要设计中定义的所有数据类型及操作的伪代码算法1、节点类型和指针类型迷宫矩阵类型:int mazeM+2N+2;为方便操作使其为全局变量迷宫中节点类型及队列类型:struct pointint row,col,predecessor que5
8、122、迷宫的操作(1)手动生成迷宫void shoudong_maze(int m,int n)定义i,j为循环变量for(i=m)for(j=n)输入mazeij的值(2)自动生成迷宫void zidong_maze(int m,int n)定义i,j为循环变量for(i=m)for(j=n)mazeij=rand()%2 /由于rand()产生的随机数是从0到RAND_MAX,RAND_MAX是定义在stdlib.h中的,其值至少为32767),要产生从X到Y的数,只需要这样写:k=rand()%(Y-X+1)+X;(3)打印迷宫图形void print_maze(int m,int n
9、)用i,j循环变量,将mazeij输出 、(4)打印迷宫路径void result_maze(int m,int n)用i,j循环变量,将mazeij输出 、(5)搜索迷宫路径迷宫中队列入队操作void enqueue(struct point p)将p放入队尾,tail+迷宫中队列出队操作struct point dequeue(struct point p)head+,返回quehead-1判断队列是否为空int is_empty()返回head=tail的值,当队列为空时,返回0访问迷宫矩阵中节点void visit(int row,int col,int maze4141)建立新的队列
10、节点visit_point,将其值分别赋为row,col,head-1,mazerowcol=2,表示该节点以被访问过;调用enqueue(visit_point),将该节点入队路径求解void mgpath(int maze4141,int m,int n)先定义入口节点为struct point p=0,0,-1,从maze00开始访问。如果入口处即为障碍,则此迷宫无解,返回0 ,程序结束。否则访问入口节点,将入口节点标记为访问过mazep.rowp.col=2,调用函数enqueue(p)将该节点入队。判断队列是否为空,当队列不为空时,则运行以下操作: 调用dequeue()函数,将队头
11、元素返回给p,如果p.row=m-1且p.col=n-1,即到达出口节点,即找到了路径,结束。如果p.col+1n且mazep.rowp.col+1=0,说明未到迷宫右边界,且其右方有通路,则visit(p.row,p.col+1,maze),将右边节点入队标记已访问如果p.row+10且mazep.rowp.col-1=0,说明未到迷宫左边界,且其左方有通路,则visit(p.row,p.col-1,maze),将左方节点入队标记已访问如果p.row-10且mazep.row-1p.col=0,说明未到迷宫上边界,且其上方有通路,则visit(p.row,p.col+1,maze),将上方节
12、点入队标记已访问访问到出口(找到路径)即p.row=m-1且p.col=n-1,则逆序将路径标记为3即:mazep.rowp.col=3;while(p.predecessor!=-1)p=queuep.predecessor; mazep.rowp.col=3; 最后将路径图形打印出来。3.菜单选择 while(cycle!=(-1) 手动生成迷宫 请按:1 自动生成迷宫 请按:2 退出 请按:3 scanf(%d,&i); switch(i) case 1:请输入行列数(如果超出预设范围则提示重新输入) shoudong_maze(m,n); print_maze(m,n); mgpath
13、(maze,m,n); if(X!=0) result_maze(m,n);case 2 :请输入行列数(如果超出预设范围则提示重新输入) zidong_maze(m,n); print_maze(m,n); mgpath(maze,m,n); if(X!=0) result_maze(m,n);case 3:cycle=(-1); break;4、程序源码#includestdlib.h#includestdio.h#include time.h#define N 39#define M 39int X;int mazeN+2M+2;struct pointint row,col,prede
14、cessor;/先驱queue512;int head=0,tail=0;void shoudong_maze(int m,int n)int i,j;printf(nn);printf(请按行输入迷宫,0表示通路,1表示障碍:nn);for(i=0;im;i+)for(j=0;jn;j+) scanf(%d,&mazeij);int random (int i)int r=rand()%i;return r;void zidong_maze(int m,int n)srand(time(NULL);int i,j;printf(n迷宫生成中nn);system(pause);for(i=0;
15、im;i+)for(j=0;jn;j+)mazeij=random(2);/由于rand()产生的随机数是从0到RAND_MAX/RAND_MAX是定义在stdlib.h中的,其值至少为32767)/要产生从X到Y的数,只需要这样写:k=rand()%(Y-X+1)+X; void print_maze(int m,int n)int i,j;printf(n迷宫生成结果如下:nn);printf(迷宫入口n);printf();for(i=0;im;i+)printf(n);for(j=0;jn;j+) if(mazeij=0) printf();if(mazeij=1) printf();
16、printf(迷宫出口n);void result_maze(int m,int n)int i,j;printf(迷宫通路(用表示)如下所示:nt);for(i=0;im;i+)printf(n);for(j=0;jn;j+) if(mazeij=0|mazeij=2) printf(); if(mazeij=1) printf(); if(mazeij=3) printf();void enqueue(struct point p)queuetail=p;tail+;struct point dequeue()head+;return queuehead-1;int is_empty()r
17、eturn head=tail;void visit(int row,int col,int maze4141)struct point visit_point=row,col,head-1;mazerowcol=2;enqueue(visit_point);int mgpath(int maze4141,int m,int n)X=1;struct point p=0,0,-1;if(mazep.rowp.col=1)printf(n=n);printf(此迷宫无解nn);X=0;return 0;mazep.rowp.col=2;/做标记enqueue(p);while(!is_empty
18、()p=dequeue();if(p.row=m-1)&(p.col=n-1) break;/判断是否为出口if(p.col+1n)&(mazep.rowp.col+1=0) visit(p.row,p.col+1,maze);/向右访问if(p.row+1=0)&(mazep.rowp.col-1=0) visit(p.row,p.col-1,maze);/向左访问if(p.row-1=0)&(mazep.row-1p.col=0) visit(p.row-1,p.col,maze);/向上访问if(p.row=m-1&p.col=n-1)printf(n=n);printf(迷宫路径为:n
19、);printf(%d,%d)n,p.row,p.col);mazep.rowp.col=3;while(p.predecessor!=-1)p=queuep.predecessor;printf(%d,%d)n,p.row,p.col);mazep.rowp.col=3;else printf(n=n); printf(此迷宫无解!nn);X=0;return 0;void menu()printf(*n); printf( 欢迎进入迷宫求解系统n); printf( 设计者:罗平,刘照 n); printf(*n); printf( 手动生成迷宫 请按:1n); printf( 自动生成迷
20、宫 请按:2n); printf( 退出 请按:3nn); printf(*n); printf(n);void main()int i,m,n,cycle=0;while(cycle!=(-1) menu(); printf(请选择你的操作:n); scanf(%d,&i); switch(i)case 1:printf(n请输入行数:);scanf(%d,&m); printf(n); printf(请输入列数:);scanf(%d,&n); while(m39)|(n39)printf(n抱歉,你输入的行列数超出预设范围(0-39,0-39),请重新输入:nn); printf(请输入行
21、数:);scanf(%d,&m); printf(n); printf(请输入列数:);scanf(%d,&n); shoudong_maze(m,n); print_maze(m,n); mgpath(maze,m,n); if(X!=0) result_maze(m,n); printf(nnPress Enter Contiue!n);getchar();while(getchar()!=n);break; case 2:printf(n请输入行数:);scanf(%d,&m); printf(n); printf(请输入列数:);scanf(%d,&n); while(m39)|(n3
22、9) printf(n抱歉,你输入的行列数超出预设范围(0-39,0-39),请重新输入:nn);printf(请输入行数:);scanf(%d,&m); printf(n); printf(请输入列数:);scanf(%d,&n); zidong_maze(m,n); print_maze(m,n); mgpath(maze,m,n); if(X!=0) result_maze(m,n); printf(nnPress Enter Contiue!n);getchar();while(getchar()!=n);break;case 3:cycle=(-1);break;default:pr
23、intf(n);printf(你的输入有误!n);printf(nPress Enter Contiue!n);getchar();while(getchar()!=n);break;四、 调试过程及其解决方法在调试过程中,首先使用的是栈进行存储,但是产生的路径是多条或不是最短路径,所以通过算法比较,改用此算法。五、 运行验证结果(含实验数据以及分析过程)1、手动输入实验数据见上图。实验分析:实验结果达到预期效果。此程序手动输入时用户自己输入迷宫行数和列数不超过预先设置二维数组,然后将输入的数据送给预先准备的的一个二维数组(通过已输入的行数和列数控制)。最后通过搜索算法找出一条路径。并显示出来
24、。显示的路径按反序输出。2、自动输入自动生成迷宫是利用系统随机函数随机生成迷宫。其余部分和手动原理一样。六、附录或参考资料【1】 严蔚敏 吴伟民 数据结构(C语言版) 清华大学出版社, 2009年9月【2】 谭浩强 C程序设计(第三版) 清华大学出版社 2009年1月七、课程设计总结(心得)通过为期一周的课程设计,我对数据结构的作用以及c语言中在原来的基础上有了更进一步的认识。说实话,开始觉得自己很倒霉,没有抢到好的题目,抢到了这个迷宫。一头雾水,甚至不知道从哪里下手。还好同组的小伙伴罗平是一位学习基础很好的人,带着我分析问题,解决问题。从开始的不懂到后来的清楚。原来这里使用广度优先搜索。让我
25、深刻的感受到任何所学的知识都需要实践,没有实践就无法真正理解这些知识以及掌握它们,让其成为自己的。上机实践中,通过小伙伴的带领,我收获了不少。当然也遇到不少的问题,比如说我不知道这一块是干嘛的,这个结构体是怎么弄的。老师提出的关键性问题让自己更能考虑我们的程序的漏洞还有知识上的不过关,比如说我们进行的广度优先搜索怎么回溯,怎么实现让我们有了更深更多的思考。我们往往只是学习理论的知识没有实现,不知道怎么才能实现,现在的上机操作刚好给我们机会熟悉操作,熟悉怎么做。在实际的上机操作过程中,不仅是让我们了解数据结构的理论知识,更重要的是培养解决实际问题的能力,所以我相信我通过此次实习可以提高我们分析设计能力和编程能力,为后续课程的学习及实践打下良好的基础。、实验过程中,也对我和小伙伴合作精神的进行了考察,让我们在实验起来更加默契,在成功后一起体会喜悦的心情。果然是团结就是力量,只有互相之间默契融洽的配合才能换来最终完美的结果。我和小伙伴的契合也是我们实验成功的因素。没有彼此也许我们不会这样。最后感谢老师的教导,倾听我们的想法,给我们支持和鼓励。