迷宫问题课程设计报告.docx
- 文档编号:5630739
- 上传时间:2022-12-29
- 格式:DOCX
- 页数:20
- 大小:113.98KB
迷宫问题课程设计报告.docx
《迷宫问题课程设计报告.docx》由会员分享,可在线阅读,更多相关《迷宫问题课程设计报告.docx(20页珍藏版)》请在冰豆网上搜索。
迷宫问题课程设计报告
合肥学院
计算机科学与技术系
一、课程设计名称及内容
名称:
迷宫问题
内容:
生成一个N×M(N行M列)的迷宫,完成迷宫的组织和存储,并实现迷宫路由算法。
基本要求1、N和M是用户可配置的,缺省值为50和50。
2、迷宫的入口和出口分别在左上角和右下角。
提示:
(1)可以使用二维数组maze[M+2][N+2]表示迷宫,其中M,N为迷宫的行、列数,当元素值为0时表示该点是通路,当元素值为1时表示该点是墙。
老鼠在每一点都有4种方向可以走,可以用数组move[4]来表示每一个方向上的横纵坐标的偏移量,可用另一个二维数组mark[M+2][N+2]记录节点的访问情况。
(2)可以选用深度优先算法或广度优先算法实行,迷宫可由自动或手动生成。
测试用例应该包含有解迷宫和无解迷宫。
二、问题分析
本程序要求实现迷宫问题的相关操作,包括迷宫的组织和存储,并实现迷宫路由算法(即查找迷宫路径)。
程序所能达到的:
具体包括迷宫的建立,迷宫的存储(迷宫由自动生成或手动生成),迷宫中路径的查找(以广度优先算法实现迷宫中最短路径的查找)。
迷宫是一个矩形区域,迷宫存在一个入口和一个出口,其内部包含了不能穿越的墙或者障碍。
迷宫的建立即是建立这样一个迷宫矩阵,用于存储迷宫信息,包括可穿越的路和不可穿越的墙或者障碍,分别用0表示通路,1表示障碍。
对于迷宫矩阵,用m×n的矩阵来描述,m和n分别代表迷宫的行数和列数。
这样,则迷宫中的每个位置都可以用其行号和列号来指定。
(0,0)表述入口位置,(m-1,n-1)表示出口位置;从入口到出口的路径是由一组位置构成的。
每个位置上都没有障碍,且每个位置(第一个除外)都是前一个位置的上、下、左、右的邻居。
为了描述迷宫中位置(i,j)处有无障碍,规定,当位置(i,j)处有一个障碍时,其值为1,否则为0.这样迷宫就可以用0、1矩阵来描述。
对于查找迷宫路由问题
首先,考察,迷宫的入口位置,如果该位置就是迷宫出口,则已经找到了一条路径,搜索工作,结束。
否则,考察其上、下、左、右位置上的邻居是否是障碍,若不是就移动到这个相邻位置上,然后对于这个位置开始搜索通往出口的路径。
如果不成功,就选择另一个相邻的位置,并从它开始搜索路径。
为防止搜索出现重复,则将已搜索过的位置标记为2。
同时为保留过搜索的痕迹,在考察相邻位置之前,将当前位置保存在一个队列中,如果所有相邻的非障碍位置均被搜索过,且未能找到通往出口的路径,则表明不存在从入口到出口的路径。
且对于此,实现的是广度遍历优先算法,如果查找到路径,则为从入口到出口的最短路径,而使用深度优先遍历则可以查找到路径,但未必是最短路径。
下面实现如何利用队列实行广度优先遍历算法进行迷宫最短路径的查找。
以矩阵00101
10010
10001
00100
首先,将位置(0,0)(序列号0)放入队列中,其前节点为空,从它开始搜索,标记。
由于其只有一个非障碍位置,所以接下来移动到(0,1)(序列号1),其前节点序列号为0,防止稍后的搜索再经过这个位置。
从(0,1)移动到(1,1)(序列号2),放入队列中,其前节点序列号为1,(1,1)存在(1,2)(序列号3)、(2,1)(序列号4)两个可移动位置,其前序列号均为2。
标记已被搜索过,对于每一个非障碍位置,它的相邻非障碍节点均入队列,实现了广度优先遍历算法,且它们的前序列号均为该位置的序列号。
所以如果存在路径,则从出口处节点的位置,逆序则可以找到其从出口到入口的通路。
实现了查找最短路径。
(如表格1所示为所建队列)
将(0,0)入队列
判断首节点是否为通路
路
判断队列否为空
左边
是否存在通路
下边是否存在通路
右边是否存在通路
上边是否存在通路
是否到达迷宫出口处
将队头出队
存储节点,将节点入队列
迷宫路由算法流程图:
N循环结束
无解迷宫
Y
N
N
Y
有解迷宫
循环结束
图1迷宫路由算法流程图
表1图示队列表
012345678910
(0,0)
(0,1)
(1,1)
(1,2)
(2,1)
(2,2)
(1,3)
(2,3)
(0,3)
(3,3)
(3,4)
-1
0
1
2
2
3
4
5
6
7
9
由此可看出,从(3,4)->(3,3)->(2,3)->(2,2)->(1,2)->(1,1)->(0,1)->(0,0)得到最短路径。
1、数据输入形式和输入值的范围:
生成迷宫时须输入迷宫的行数和列数,其最大值均不应超过50;手动输入迷宫矩阵时以0表示无障碍为通路,1表示该点有障碍为墙。
所有输入中,元素的值均为整数。
2、结果的输出形式:
所有进入界面中,只有当输入正确(如密码正确或输入值在可操作范围内)时才可进入下一界面,否则均不可进入下一届面操作,当完成迷宫生成后,进入迷宫路由查找算法,输出查找的每次循环过程,及最终查找结果:
如找到,则显示路径(表述);否则显示为查找到。
显示迷宫生成图形(如有路径则同样显示路径结果)。
3、测试数据:
a、在输入密码中输入13,输入1234
b、在输入行、列数中:
输入5、56,输入5、5
c、在输入选择自动生成或手动生成中,选择相应操作,查看结果
d、选择输入3,重新输入矩阵的行列数。
e、选择是否循环执行此程序。
(-1表示输入结束)
三、概要设计
1、为了实现上述功能,需要:
①构造一个二维数组maze[M+2][N+2]用于存储迷宫矩阵;②自动或手动生成迷宫,即为二维数组maze[M+2][N+2]赋值;③将构造一个队列用于存储迷宫路由;④建立迷宫节点structpoint,用于存储迷宫中每个节点的访问情况。
⑤实现迷宫路由算法,用广度优先遍历实现查找迷宫最短路径。
如找到路径则显示路径,否则显示为查找到。
同时显示生成迷宫。
⑥在屏幕上显示操作菜单。
2、本程序包含12个函数:
(1)主函数main()
(2)手动生成迷宫函数shoudong_maze()
(3)自动生成迷宫函数zidong_maze()
(4)打印每次显示结果print_maze()
(5)显示生成迷宫bulid_maze()
(6)显示迷宫生成图形(如有路径生成,则显示路径)result_maze()
(7)入队操作enqueue()
(8)出队操作dequeue()
(9)判断队列是否为空is_empty()
(10)访问节点visit()
(11)寻找迷宫路由(求解迷宫中最短路径)mgpath()
(12)菜单操作menu()
各函数之间的关系如下图(图1)所示:
函数关系图:
shoudong_maze
idong_maze
build_maze
mainmenuenqueue
dequeue
mgpathis_empty
visit
print_maze
result_maze
图2各函数间关系图
四、详细设计
实现概要设计中定义的所有数据类型,对各个操作给出伪代码算法。
对于主程序和各个模块也给出相应的伪代码算法。
1、节点类型和指针类型
迷宫矩阵类型:
intmaze[M+2][N+2];为方便操作使得其为全局变量
迷宫中节点类型及队列类型:
structpoint{introw,col;intpredecessor;}queue[512];
2、迷宫的操作
(1)手动生成迷宫
voidshoudong_maze(intm,intn)
{定义变量i,j;
m为迷宫中行数,n为迷宫中列数
利用for循环控制循环
以i,j控制迷宫中行列数的循环输入
以0表示通路,以1表示障碍,给maze[i][j]赋值。
循环结束,完成迷宫生成}
(2)自动生成迷宫
voidzidong_maze(intm,intn)
{定义变量i,j;
m为迷宫中行数,n为迷宫中列数
以i,j控制迷宫中行列数的循环赋值操作
以0表示通路,以1表示障碍
用0+(int)(2*rand()/(RAND_MAX+1.0))随机获得0、1,给maze[i][j]赋值,循环结束,完成迷宫生成}
(3)生成迷宫打印
voidprint_maze(intm,intn)
{此函数主要用于将迷宫路由算法中每次操作结果显示出来
定义变量,用for控制循环
以i,j控制迷宫中行列数的循环操作,将maze[i][j]显示出来}
(4)出示时显示迷宫生成结果
voidbuild_maze(intm,intn)
{首先进行清屏,打出屏幕提示信息,显示迷宫入口和出口,调用函数print_maze()}
(5)迷宫生成图形的显示操作
voidresult_maze(intm,intn)
{定义整型变量i,j;用i,j控制迷宫行列数的循环操作,显示迷宫图形。
在循环中,如果迷宫中为通路,(即maze[i][j]=0或2)则显示“”;如果迷宫中为障碍(maze[i][j]=1),则显示“■”,如果有最短路径(maze[i][j]=3)则显示“□”。
}
(6)迷宫求解路由求解操作
①迷宫中队列入队操作
voidenqueue(structpointp)
{将p放入队尾tail,将tail加1}
②迷宫中队列出队操作
structpointdequeue()
{head加1;返回queue的队头[head-1]}
③判断队列是否为空
intis_empty()
{返回head==tail值,即当队列为空时,返回0值;}
④访问矩阵中某一个节点
voidvisit(introw,intcol,intmaze[52][52])
{建立新的队列节点visit_point,将其中的值分别赋为row,col,head-1;head-1表示前一个可以走的通路的位置。
将maze[row][col]=2,表示该节点已被访问过;调用enqueue(visit_point);将该节点入队列;}
⑤迷宫求解路径算法实现函数
intmgpath(intmaze[52][52],intm,intn)
{首先定义迷宫入口处节点structpointp={0,0,-1},入口为最左上角,从maze[0][0]开始访问。
如果入口处即为障碍,则此迷宫无解,返回0值;程序结束。
否则访问入口处节点,将入口处节点标记为访问过maze[p.row][p.col]=2,调用函数enqueue(p)将该节点入队列。
判断队列是否为空,如果不为空,则运行底下的操作:
{调用dequeue()函数,将队头元素返回给p,
如果p.row=m-1同时p.col=n-1即访问到迷宫出口处,即所有通路处全部被访问过,且找到了路径,则程序结束。
如果p.col+1 如果p.col+1 如果p.col-1>0同时maze[p.row][p.col-1]=0即访问未超过迷宫范围p的左边存在节点,同时该节点为通路,则调用visit(p.row,p.col-1,maze);访问该位置,新建节点存储该位置(其p.predecessor所存储的为前一个可以被访问的可通过的通路节点的位置)并将该节点入队列,标志该节点已被访问过。 如果p.row-1>0同时maze[p.row][p.col-1]=0即访问未超过迷宫范围p的上边存在节点,同时该节点为通路,则调用visit(p.row-1,p.col,maze);访问该位置,新建节点存储该位置(其p.predecessor所存储的为前一个可以被访问的可通过的通路节点的位置)并将该节点入队列,标志该节点已被访问过。 调用函数print_maze,打印出关于p节点周围的横纵坐标的访问情况。 } 在未访问到无通路,或者未访问到出口处时,循环执行以上程序。 如果最后p.row=m-1同时p.col=n-1,访问到出口处,即找到从迷宫入口处到出口处的路径时,将迷宫路径打印出来: {首先打印出出口节点,标记其为最短路径的通路标志,maze[p.row][p.col]=3如果p.predecessor不等于-1,则继续打印,p=queue[p.predecessor]打印该节点,标记节点为最短路径通路} 否则显示此迷宫无解。 返回0。 } 3、菜单操作 voidmenu() {定义整型变量m,n,用于控制管理迷宫的行数和列数 定义整型变量cycle,用于控制循环,是否重复运行此程序。 定义整型变量secret_code,进入本操作界面的密码。 定义整型变量choice,用于控制选择菜单。 显示欢迎界面,输入用户密码,如果密码不正确,则显示“密码错误,请重新输入”,重新输入,只有当输入密码正确时,才进入操作界面。 清屏处理,进入操作界面。 输入迷宫的行数、列数,迷宫的行列数均不得超过50,否则显示“行列数超出预设范围,请重新输入”重新输入行、列数。 当输入行列数符合要求时,进入操作菜单栏 1------------------------------手动生成迷宫 2------------------------------自动生成迷宫 3------------------------------迷宫行列数输入有误,选择重新输入 输入选择(choice) 使用switch语句根据choice选择,以下操作 case1(如果选择的是1): 执行手动生成迷宫函数shoudong_maze(m,n);调用build_maze(m,n)显示出生成的迷宫,及其入口和出口,break。 case2(如果选择的是2): 执行自动生成迷宫函数zidong_maze(m,n);调用build_maze(m,n)显示出生成的迷宫,及其入口和出口,break。 case3(如果选择的是3): 首先进行清屏,重新输入迷宫的行列数且同样必须在可操作范围内。 否则循环此操作,重新输入行列数。 } 调用 mgpath(maze,m,n),寻找迷宫路由(即迷宫路径) 调用result_maze(m,n),显示出迷宫图形及路径 选择是否重新输入迷宫,如果不继续,-1退出。 } 4、主函数 voidmain() {system(“colorf0”);//设置屏幕及字体颜色 调用菜单函数menu();} 五、调试分析 在调试过程中,首先使用的是栈进行存储,但是由此产生了,寻找到路径,但是此路径并不一定就是最短路径,所以通过比较算法,改使用广度优先遍历可以查找到最短路径。 由此可以得出使用栈不利于实现这一算法,因此改使用队列存储,查找最短路径。 在实现这一算法过程,注意将访问过的节点进行标记,且注意障碍的不同设置方式对此操作的不同影响。 同时注意队列中存储的是非障碍节点,但是由于广度遍历的算法,使得从出口到入口处所有节点彼此相关。 则在调用时注意区别。 六、使用说明 程序名为maze.exe,运行环境为DOS,程序执行后显示: ——————欢迎进入用户界面———————— 请输入用户密码 (注: 密码为1234,方可进入用户界面,否则不可进入。 ) 输入1234,显示密码正确。 请输入行数: 请输入列数: 进入选择界面: 1------------------------------手动生成迷宫 2------------------------------自动生成迷宫 3------------------------------迷宫行列数输入有误,选择重新输入 请输入选择: 在输入选择后输入数字选择执行不同的功能。 要求输入在可操作范围内的行、列数,可执行1、2操作。 执行显示迷宫每次的遍历过程。 显示生成的迷宫及路径。 七、测试结果 1、输入密码13,输入错误,重新输入1234 图3登陆界面图 2、输入迷宫行、列数5、56,超过预设范围,重新输入5、5 图4输入行列数图 3、进入选择界面: 1进入手动输入,输入迷宫 图5初始化迷宫图 4、显示输出结果 图6建立迷宫图图7结果运行图1 图8结果运行图2图9结果运行图3 图10路径查找结果图 选择2进入自动生成迷宫。 图11选择图 自动生成迷宫 图12生成过程图 显示输出结果 图13迷宫求解过程图1图14迷宫求解过程图2 图15迷宫求解过程图3图16迷宫求解过程图4 图17路径查找结果图 八、参考文献 [1]王昆仑,李红.《数据结构与算法.》北京: 中国铁道出版社,2006年5月。 [2]李春葆《数据结构教程》北京: 清华大学出版社2005年1月。 源代码: #include"iostream" #include"stdlib.h" usingnamespacestd; #defineN50 #defineM50 intmaze[N+2][M+2]; structpoint{introw,col,predecessor;}queue[512];// inthead=0,tail=0; voidshoudong_maze(intm,intn){//手动生成迷宫函数 system("cls"); inti,j;//控制循环变量 printf("选择手动生成迷宫\n"); printf("0表示通路,1表示障碍\n"); printf("请按行、列数,对应输入0、1\n"); for(i=0;i for(j=0;j scanf("%d",&maze[i][j]);} voidzidong_maze(intm,intn){//自动生成迷宫函数 system("cls"); inti,j; printf("自动生成迷宫\n"); printf("生成中……\n"); system("pause");//暂停 for(i=0;i for(j=0;j maze[i][j]=0+(int)(2*rand()/(RAND_MAX+1.0));//0、1随机数产生,生成迷宫} voidprint_maze(intm,intn)//生成迷宫打印 {inti,j; for(i=0;i printf("\n"); for(j=0;j printf("%d",maze[i][j]);} } voidbuild_maze(intm,intn) {system("cls"); printf("生成结果\n"); printf("迷宫入口\n"); printf("↓"); print_maze(m,n); printf("→迷宫出口\n"); } voidresult_maze(intm,intn)//迷宫生成图形 {inti,j; printf("迷宫生成图形如下所示: \n"); for(i=0;i printf("\n"); for(j=0;j {if(maze[i][j]==0||maze[i][j]==2)printf(""); if(maze[i][j]==1)printf("■"); if(maze[i][j]==3)printf("□");}} } voidenqueue(structpointp) {queue[tail]=p; tail++; } structpointdequeue(void) {head++; returnqueue[head-1];} intis_empty(void) {returnhead==tail;} voidvisit(introw,intcol,intmaze[52][52])//访问节点 {structpointvisit_point={row,col,head-1}; maze[row][col]=2; enqueue(visit_point);} intmgpath(intmaze[52][52],intm,intn) {structpointp={0,0,-1}; if(maze[p.row][p.col]==1){ printf("此迷宫无解\n\n"); return0;} maze[p.row][p.col]=2; enqueue(p); while(! is_empty()){ p=dequeue(); if(p.row==m-1/*goal*/ &&p.col==n-1) break; if(p.col+1 &&maze[p.row][p.col+1]==0) visit(p.row,p.col+1,maze); if(p.row+1 &&maze[p.row+1][p.col]==0) visit(p.row+1,p.col,maze); if(p.col-1>=0/*left*/ &&maze[p.row][p.col-1]==0) visit(p.row,p.col-1,maze); if(p.row-1>=0/*up*/ &&maze[p.row-1][p.col]==0) visit(p.row-1,p.col,maze); print_maze(m,n); printf("\n--
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 迷宫 问题 课程设计 报告