数据结构 课程设计 迷宫程序Word格式.docx
- 文档编号:18422265
- 上传时间:2022-12-16
- 格式:DOCX
- 页数:28
- 大小:120.09KB
数据结构 课程设计 迷宫程序Word格式.docx
《数据结构 课程设计 迷宫程序Word格式.docx》由会员分享,可在线阅读,更多相关《数据结构 课程设计 迷宫程序Word格式.docx(28页珍藏版)》请在冰豆网上搜索。
程序启动时,执行main()函数输出菜单。
用户根据菜单的提示输入要执行的功能,程序会根据用户的选择执行不同的功能。
程序详细功能如下:
1.自动演示:
命令1,由程序自动生成一个迷宫,并进行路径求解的演示。
2.手动迷宫:
命令2,由用户自行创建一个迷宫,定义迷宫的大小、形状等,程序将对用户指定的迷宫进行求解。
3.程序帮助:
命令3,显示程序帮助和必要信息。
4.退出:
命令4,退出程序。
执行流程如下图:
图2主函数main()执行流程图
3.1.2.创建模块
本模块将进行待解迷宫的创建。
1.在<
自动演示>
中,机器会调用autocreat()函数自动创建一个10*10的迷宫。
2.在<
手动迷宫>
中,程序会使用creat()函数,用户可以通过指定迷宫大小m*n,输入迷宫每一行的数据来自行创建迷宫。
3.1.3.路径查找模块
1.路径查找。
本模块实现了路径的查找和脚步的移动。
思路是依次判断上右下左四个方向,若可以通过则前进,不可通过则转向下一个方向,四个方向都不可通过则后退。
<
1>
可通性检查。
可通性检查用来判断指定的方向是否可以通过。
需要判断两方面内容,即下一点是否有障碍(通过chk()函数完成)和下一点是否已包含在了已有路径之中。
若同时满足无障碍和无包含条件,则可以通过。
否则不能通过。
2>
脚步前进。
下一点若经过检查可以通过,则通过move()函数完成前进。
“前进”的实现有两方面,第一方面,将新脚步纳入双向链表中,另一方面,在迷宫数组中将本步坐标所指标记为“已走”。
3>
脚步后退。
若本步四个方向都不能行走,则通过back()函数退后。
退后包括两方面,一方面把链表中最后一个节点抛弃,当前脚步指向倒数第二个节点。
另一方面,将迷宫数组中已抛弃节点指向的元素重新标记为“未走”,以便进行其他路径的寻路操作时可以顺利通过。
2.更优解替换。
本模块完成了更优解的替换。
当程序查找到比已存解更短的解时,将会销毁已存解,并将新解作为优解。
直到最后所有的路径都搜索完毕,优解所存的路径即为最短路径。
3.1.3.输出模块
输出模块调用outlin()函数,根据不同的参数值,输出不同的内容。
主要功能是输出迷宫的图形化路径,并输出此路径的坐标顺序表示。
3.1.4.其他模块
1.格式化模块。
调用formatmaze()函数,初始化存储迷宫的二维数组、各变量值,销毁上次求解时产生的双向链表,释放内存空间。
2.迷宫数组改写模块,调用revise()函数,按照最终生成的最短双向链表记录的结果改写迷宫二维数组,以满足最终输出需要。
存储脚步的双向链表定义如下:
typedefstructlnode{
structlnode*next;
structlnode*pre;
intx;
inty;
intstepsum;
//表示当前脚步为第几步。
intdi;
//用di代表已尝试的脚步方向。
}node,*linklist;
1.autocreat()
autocreat()用以自动生成一个10*10的迷宫。
2.creat()
通过用户输入的数据,创建一个指定大小为m*n,具有特定形状的迷宫。
3.seek()
seek()程序为迷宫查找的核心函数,通过调用chk()、move()、back()以及自身的优解替换功能,最终求解出一个迷宫的最短路径,存储在双向链表之中。
此外,seek()函数还具有判断处理特殊迷宫的功能。
seek()函数不同返回值的含义,返回-1无解,1正常解出,2入口和出口重合。
4.chk(intdirection)
chk()函数用来判断指定方向的可通性,并返回。
返回1表示可通,返回0表示不可通。
5.move(intdirection)
move()函数可以实现脚步向指定方向移动。
即把新的脚步纳入脚步双向链表中,并将maze数组中相应的元素记录为-1表示已走。
6.back()
当脚步的四个方向均已不能通过时,调用back()函数删除双向链表的最后一个脚步,并将maze数组中相应元素标记为1,实现脚步的回退。
7.revise()
使用指针p,根据已求的的脚步,改写maze数组,使之满足输出需要。
设有指针p,则根据p->
pre,p,p->
next三点所记录的坐标,可以求出p的脚步形状,并标记在maze[p->
x][p->
y]中。
8.outlin()
输出迷宫求解的结果。
9.help()
help()函数用以输出程序必要的帮助信息。
10.formatmaze()
初始化存储迷宫的二维数组、各变量值,销毁上次求解时产生的双向链表,释放内存空间。
四.程序实现
4.1.源码分析
#include<
stdio.h>
stdlib.h>
math.h>
#definemaxsize36
#definestatusint
01234分别代表未尝试、↑、→、↓、←。
//全局变量开始
linklistL,L2,p,q,g;
//三个指针pqg满足不同函数临时指针需要
node*nowstep,*laststep;
intmaze[maxsize+2][maxsize+2];
//存储迷宫的数组,+2是为了加围墙。
intm,n;
//迷宫行、列数变量
intexitx,exity,entrancex,entrancey;
//出入口。
。
xy分别代表行列.
intfinish=0;
//走迷宫的最终全局结果。
1有路,-1无路,2出入口重合。
intexistL=0;
//手动创建迷宫,选择r重新创建迷宫,formatmaze()将格式化各变量。
检测L链表是否存在防止程序崩溃。
intmindistance=0;
//存放求出的最短路径的步数。
//创建迷宫
statuscreat()
{
inti,j;
charcord='
a'
;
system("
cls"
);
do
{
if(cord=='
r'
)
formatmaze();
printf("
\n请输入迷宫行、列数(最大%d*%d)。
\n行:
"
maxsize,maxsize);
scanf("
%d"
&
m);
列:
n);
while(m>
maxsize||n>
maxsize||m<
1||n<
1)
{
printf("
输入有误。
只支持%d*%d以内的迷宫,请重新输入行列数。
scanf("
}
\n输入迷宫数据,0为砖头,1为通路,数字间用空格间隔。
系统将自动添加围墙。
\n"
for(i=1;
i<
=m;
i++)
第%d行的%d个数据(共%d行):
i,n,m);
for(j=1;
j<
=n;
j++)
scanf("
maze[i][j]);
\n已成功建立迷宫,图形如下:
outlin();
\n\n设定出入口数学坐标(x,y)。
\n已建立%d行%d列的迷宫,坐标应在(1,1)至(%d,%d)之间。
m,n,n,m);
设定入口坐标,格式示例1,1:
"
%d,%d"
entrancey,&
entrancex);
while(entrancex>
m||entrancey>
n||maze[entrancex][entrancey]==0)
输入有误,请检查。
坐标应在(1,1)至(%d,%d)之间。
\n请重新输入入口坐标,格式示例1,1:
n,m);
输入出口坐标,格式示例%d,%d:
exity,&
exitx);
while(exitx>
m||exity>
n||maze[exitx][exity]==0)
\n请重新输入出口坐标,格式示例%d,%d:
system("
\n你设定的迷宫如下:
maze[entrancex][entrancey]=-1;
maze[exitx][exity]=-2;
maze[entrancex][entrancey]=1;
maze[exitx][exity]=1;
入口和出口分别为(%d,%d)(%d,%d)。
\n键入y将开始求解,键入r重新设定:
entrancey,entrancex,exity,exitx);
%c%c"
cord,&
cord);
while(cord!
='
y'
&
cord!
输入有误,请重新输入:
}while(cord!
}
//格式化迷宫。
再创建新迷宫时用。
formatmaze()
for(i=0;
m+2;
for(j=0;
n+2;
maze[i][j]=0;
finish=0;
//以下语句把上次求解迷宫时建立的链表空间释放。
if(existL!
=0)
while(L->
next)
L=L->
next;
free(L->
pre);
free(L);
if(existL==2)
while(L2->
{
L2=L2->
free(L2->
}
free(L2);
}
existL=0;
mindistance=0;
//迷宫求解。
statusseek()
intallfinished=0;
if(entrancex==exitx&
entrancey==exity)//入口和出口重合的特殊情况。
return2;
L=(linklist)malloc(sizeof(node));
//建立存储脚步的链表.
L->
next=NULL;
pre=NULL;
stepsum=0;
existL=1;
//初始化nowstep,令其在入口处。
nowstep=(node*)malloc(sizeof(node));
nowstep->
x=entrancex;
y=entrancey;
pre=L;
di=0;
stepsum=1;
next=nowstep;
//开始查找第一条可通路径。
while(nowstep->
x!
=exitx||nowstep->
y!
=exity)//用1234代表↑→↓←四个方向。
if(nowstep->
di==0&
chk
(1)==1)//可通必须满足两个条件,下一个点无障碍、下一个点未出现在已构建的路径中。
move
(1);
elseif(nowstep->
di==1&
chk
(2)==1)
move
(2);
di==2&
chk(3)==1)
move(3);
di==3&
chk(4)==1)
move(4);
x==entrancex&
nowstep->
y==entrancey)//如果脚步停留在了入口,说明迷宫无解,不再查找。
return-1;
else
back();
//本步无路了,回退。
mindistance=laststep->
stepsum;
//OK,查找出了第一条路径L,说明迷宫有解。
建立L2比较路径,尝试寻找比L更短的路径。
if(laststep->
stepsum==abs(entrancex-exitx)+abs(entrancey-exity))//若第一条路径与理论最小路径相等,则不需要再次比较,直接返回。
L2=L;
revise();
return1;
existL=2;
while(allfinished==0)
{
L2=(linklist)malloc(sizeof(node));
L2->
//将最后一个最小路径备份到L2,继续求解。
p=L2;
g=L->
while(g)
q=(node*)malloc(sizeof(node));
q->
di=g->
di;
stepsum=g->
x=g->
x;
y=g->
y;
pre=p;
p->
next=q;
g=g->
p=q;
q->
//开始查找第二条可通路径。
back();
while(nowstep->
=exity)
if(nowstep->
chk
(1)==1)
move
(1);
elseif(nowstep->
move
(2);
move(3);
move(4);
else
if(nowstep->
stepsum==1&
di==4)//第一步的四个方向也都尝试过了,说明迷宫所有可能路径都已尝试完毕。
{
allfinished=1;
break;
}
back();
}
if(nowstep->
stepsum>
=mindistance)//新路径大于旧路径,就不要再往下尝试浪费时间了。
换其他路径。
}
if(allfinished==0)//每次找到更短路径,都要存入L2,并销毁原L2释放空间。
mindistance=laststep->
};
revise();
//改写maze数组里存储的内容,把每一步的方向信息写进去,以便输出图形路径。
return1;
statuschk(intdirection)//判断下一个方向是否有障碍的函数。
di++;
if(direction==1)
if(maze[(nowstep->
x)-1][nowstep->
y]==1)
return1;
else
return0;
elseif(direction==2)
if(maze[nowstep->
x][(nowstep->
y)+1]==1)
elseif(direction==3)
x)+1][nowstep->
elseif(direction==4)
y)-1]==1)
statusmove(intdirection)//如果chk函数判断下一点可通,则使用此函数实现走动。
laststep=nowstep;
//将laststep指向nowstep,再建立新的nowstep,实现nowstep的前进。
pre=laststep;
stepsum=laststep->
stepsum+1;
x=laststep->
y=laststep->
laststep->
maze[laststep->
x][laststep->
y]=-1;
//用-1将maze数组中的值标记,表示已经走过
switch(direction)
case1:
x--;
break;
case2:
y++;
case3:
x++;
case4:
y--;
statusback()
nowstep=laststep;
free(nowstep->
next);
maze[nowstep->
x][nowstep->
y]=1;
//将maze数组中标记的-1改为1,以便其他路径尝试时可以通过。
laststep=laststep->
pre;
revise()//│─┌┐└┘六个符号在maze数组里分别由234567表示.
{intdx,dy;
p=L2->
next->
while(p->
next&
p->
pre)
dx=(p->
x)-(p->
pre->
x);
dy=(p->
y)-(p->
y);
if(dy==0)
maze[p->
y]=2;
elseif(dx==0)
y]=3;
elseif(dx==1&
dy==1)
if(p->
x==p->
x)
maze[p->
y]=5;
y]=6;
elseif(dx==-1&
y]=7;
y]=4;
dy==-1)
x][
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计 迷宫程序 迷宫 程序