数据结构课程设计大作业.docx
《数据结构课程设计大作业.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计大作业.docx(25页珍藏版)》请在冰豆网上搜索。
![数据结构课程设计大作业.docx](https://file1.bdocx.com/fileroot1/2022-12/14/8a172609-c6bd-445b-a249-a753efdac74c/8a172609-c6bd-445b-a249-a753efdac74c1.gif)
数据结构课程设计大作业
数据结构课程设计大作业
100821班
题目迷宫问题
专业计算机科学与技术
学生姓名陈瑜
学号10082102
指导教师唐国民樊艳芬
完成日期2011.12.26
湖州师院信息与工程学院
目录
目录2
迷宫3
【内容摘要】3
【关键字】3
【Abstract】3
【Keywords】3
一、实验内容概述1
二、实验目的概述1
三、解题思路的描述2
四、源程序清单7
五、程序调试及测试结果19
六、实验小结20
七、参考文献20
迷宫
【内容摘要】
根据任务要求,需要在已知起点和终点的迷宫中找到一条简单通路或者得到没有通路的结论。
可以采用逐步分析的方法,考虑每一坐标的可行性和方向性,向各个方向模拟移动,从而标记当前位置的属性,以便再次搜索时提高效率。
其实本质上依然是采用递归的思想,只是利用链式栈来存储实际走过的步数,若存在通路,则依次压出栈元素得到通路路线,否则,结论为找不到通路。
【关键字】迷宫,递归,栈,搜索
【Abstract】
Accordingtotherequirementsoftask,Ineedtofindasimplepathwayorgettotheconclusionthatthereisnoaccessinthemazewithastartandanend.Icouldusethemethodofconsideringthefeasibilityanddirectionalityofeachcoordinatestepbystep,thenmovevirtuallyinalldirectionstomarkthepropertyofthecurrentlocationinordertoimprovetheefficiencyofthefollowingsearch.InfactIamstillusingtherecursivethinkingnaturallybutusingachainstacktostoretherealstepsIhavewalked.Ifthepathwayexists,pressthestackelementstoprinttheaccessroute,otherwise,theconclusionisnottofindthepathway.
【Keywords】maze,recursion,stack,search
一、实验内容概述
[迷宫问题]在迷宫中求从入口到出口的一条简单路径。
迷宫可用下图中所示的方块来表示,每个方块或者是通道(用空白方块表示)或者是墻(用带阴影的方块表示)。
图1-1题目要求示意图
二、实验目的概述
在迷宫设计中,可以输入迷宫的行列数,然后让电脑任意生成迷宫。
同时在根据输入的入口来寻找迷宫的出口,并把路径输出来。
在这个编程中由于不知道所走路步数,所以采用了链式栈实现每一步的移动,若找到出路则前进否则返回下一步改变方向来实现相关的移动,所以栈在其间起到了工具作用。
在设计迷宫大小和出入口时,采用的是根据操作者实现的,但迷宫的具体路障和通道是随机实现的。
求迷宫的一条通路的伪码如下:
设当前初始位置为出口:
do{
若当前位置可通,则
{
将该位置插入到栈顶;//纳入路径
若该位置为出口位置,则结束当前程序;//求得的路径放在栈中
否则切换当前位置的东临位置(即向右)为新的当前的位置;
};
否则
{
若栈不为空且栈顶元素尚有其他位置未被探索,则设定新的当前位置为沿着顺时针旋转得到的栈顶位置的下一个临快;
若栈不为空且栈顶位置的四周均不通
{
则删去栈顶元素;//后退一步,从路径中删去该通块
若栈不空,则重新测试新的栈顶位置,直到找到一个可通的相邻块或出栈至栈空;
}
}
}while(栈不为空)
三、解题思路的描述
1.坐标类型:
typedefstruct
{
intr;
intc;
}PosType;
2.栈类型:
typedefstruct
{
NodeLinktop;
intsize;
}Stack;
3.迷宫类型定义:
typedefstruct
{
intCol,Row;
intarr[Rangle][Rangle];//0表示障碍,1表示是可走的通道,-1表示外界的围墙,2表示已经走过,3表示已经知道不能通过
}MazeType;
4.建立迷宫:
voidInitMaze(MazeType&M,intcol,introw)
{
inti,j;
M.Col=col;
M.Row=row;
for(i=1;ifor(j=1;j{
intn=rand()%101+100;
M.arr[i][j]=n%2;//得到的值是1或者0,即恰好是路或是障碍
}//设置迷宫的初始值,加上边缘的一圈的值
for(i=0;i{
M.arr[0][i]=-1;
M.arr[M.Row+1][i]=-1;
}
for(i=0;i{
M.arr[i][0]=-1;
M.arr[i][M.Col+1]=-1;
}
}
5.输出迷宫:
voidPrintMaze(MazeTypeM)
{
//根据已经进行二维数组的标记值来输出迷宫(或者其通路)
inti,j;
for(i=0;i{
for(j=0;jif(M.arr[i][j]==0)
{
cout<<"█";//障碍
}
elseif(M.arr[i][j]==-1)
{
if(i==0||i==M.Row+1)
{
printf("%2d",j);//列边界
}
elseif(j==0||j==M.Col+1)
{
printf("%2d",i);//行边界
}
}
elseif(M.arr[i][j]==2)
{
cout<<"◇";//通路路线标记
}
else
{
cout<<"";//路
}
cout<<"\n";
}
}
6.判断能否通过:
boolPass(MazeTypeM,PosTypepos)
{
if(M.arr[pos.r][pos.c]!
=0&&M.arr[pos.r][pos.c]!
=-1&&M.arr[pos.r][pos.c]!
=2&&M.arr[pos.r][pos.c]!
=2&&M.arr[pos.r][pos.c]!
=3)
{
returntrue;
}//若在迷宫M中,当前位置pos不是障碍物0,不是围墙-1,以前没有经过2且不是不可通过3则可以通过,并返回true
else
{
returnfalse;
}
}
7.在迷宫中的pos的位置留下足迹,证明已经经过这个位置:
voidFootPrint(MazeType&M,PosTypepos)
{
M.arr[pos.r][pos.c]=2;
}
8.在迷宫的pos位置留下标记,证明不能通过这个位置:
voidMarkPrint(MazeType&M,PosTypepos)
{
M.arr[pos.r][pos.c]=3;
}
9.根据不同的方向来进行移动:
PosTypeNextPos(PosTypeCurPos,intDir)
{
PosTypeReturnPos;
switch(Dir)
{
case1:
//向右
ReturnPos.r=CurPos.r;
ReturnPos.c=CurPos.c+1;
break;
case2:
//向下
ReturnPos.r=CurPos.r+1;
ReturnPos.c=CurPos.c;
break;
case3:
//向左
ReturnPos.r=CurPos.r;
ReturnPos.c=CurPos.c-1;
break;
case4:
//向上
ReturnPos.r=CurPos.r-1;
ReturnPos.c=CurPos.c;
break;
}//通路路线由此优先级决定唯一
returnReturnPos;
}
10.求解迷宫M中,从Start到end的一条路径,若存在则返回true,否则返回false:
boolMazePath(MazeType&M,PosTypestart,PosTypeend)
{
StackS;
InitStack(S);//建栈
PosTypecurpos=start;//设置当前坐标为入口位置;
intcurstep=1;//当前的步数
boolFind=false;//标记是否找到出口
ElemTypee;
do
{
if(Pass(M,curpos))//如果当前位置可以通过(不是障碍物且未曾留下足迹)
{
FootPrint(M,curpos);//在当前位置标记为2
e.step=1;
e.seat=curpos;
e.di=1;//初始化为向右移动
Push(S,e);//将已经走过的放入栈中
if(curpos.c==end.c&&curpos.r==end.r)//如果找到了出口则终止,并返回true
{
Find=true;
returnFind;
}
else//向右移动,当前步数加一
{
curpos=NextPos(curpos,1);
curstep++;
}
}
else//当前位置不能通过
{
if(!
StackEmpty(S))
{
Pop(S,e);//将已经走过的最近位置弹出,数据保存在e中
while(e.di==4&&!
(StackEmpty(S)))//当方向改变一周后仍不能找到可通过的路径
{
MarkPrint(M,e.seat);//留下不能通过的标记
Pop(S,e);//删除栈顶元素
curstep--;
}
if(e.di<4)//不能通过则改变方向
{
e.di++;//方向顺时针改变
Push(S,e);
curpos=NextPos(e.seat,e.di);//求下一个结点
}
}
}
}while(!
StackEmpty(S)&&!
Find);//当栈不为空且没有找到出口
returnfalse;//没有找到出口则返回false
}
图3-1迷宫求出口流程图
四、源程序清单
#include
#include
#include
#include
#include
#include
#include
//坐标类型
typedefstruct
{
intr;
intc;
}PosType;
//位置类型
typedefstruct
{
intstep;//当前位置在路径上的序号
PosTypeseat;//当前位置的坐标
intdi;//往下一坐标的方向
}ElemType;
//栈元素类型
typedefstructNodeType
{
ElemTypedata;
NodeType*next;
}*NodeLink;
//栈类型
typedefstruct
{
NodeLinktop;
intsize;
}Stack;
//栈操作
//建栈
voidInitStack(Stack&S)
{
S.size=0;
S.top=NULL;
}
//求栈长
intLengthStack(StackS)
{
returnS.size;
}
//判断栈是否为空
boolStackEmpty(StackS)
{
if(S.size==0)
{
returntrue;
}
else
{
returnfalse;
}
}
//入栈
boolPush(Stack&S,ElemTypee)
{
NodeType*p;
if((p=(NodeType*)malloc(sizeof(NodeType)))==NULL)
{
returnfalse;
}
p->data=e;
p->next=S.top;
S.top=p;
S.size++;
returntrue;
}
//出栈
boolPop(Stack&S,ElemType&e)
{
NodeType*p=S.top;
if(p==NULL)
{
cout<<"栈为kong,无法删除栈顶元素……\n";
returnfalse;
}
e=p->data;
S.size--;
S.top=p->next;
free(p);
returntrue;
}
//遍历并输出栈
boolStackTraveser(StackS)
{
NodeType*p;
p=S.top;
if(p==NULL)
{
returnfalse;
}
while(!
p)
{
cout<data.di<p=p->next;
}
returntrue;
}
#defineRangle100//规定迷宫范围最大为100*100
//迷宫类型定义
typedefstruct
{
intCol,Row;
intarr[Rangle][Rangle];//0表示障碍,1表示是可走的通道,-1表示外界的围墙,2表示已经走过,3表示已经知道不能通过
}MazeType;
//建立迷宫
voidInitMaze(MazeType&M,intcol,introw)
{
inti,j;
M.Col=col;
M.Row=row;
for(i=1;ifor(j=1;j{
intn=rand()%101+100;
M.arr[i][j]=n%2;//得到的值是1或者0,即恰好是路或是障碍
}//设置迷宫的初始值,加上边缘的一圈的值
for(i=0;i{
M.arr[0][i]=-1;
M.arr[M.Row+1][i]=-1;
}
for(i=0;i{
M.arr[i][0]=-1;
M.arr[i][M.Col+1]=-1;
}
}
//输出迷宫
voidPrintMaze(MazeTypeM)
{
//根据已经进行二维数组的标记值来输出迷宫(或者其通路)
inti,j;
for(i=0;i{
for(j=0;jif(M.arr[i][j]==0)
{
cout<<"█";//障碍
}
elseif(M.arr[i][j]==-1)
{
if(i==0||i==M.Row+1)
{
printf("%2d",j);//列边界
}
elseif(j==0||j==M.Col+1)
{
printf("%2d",i);//行边界
}
}
elseif(M.arr[i][j]==2)
{
cout<<"◇";//通路路线标记
}
else
{
cout<<"";//路
}
cout<<"\n";
}
}
//判断能否通过
boolPass(MazeTypeM,PosTypepos)
{
if(M.arr[pos.r][pos.c]!
=0&&M.arr[pos.r][pos.c]!
=-1&&M.arr[pos.r][pos.c]!
=2&&M.arr[pos.r][pos.c]!
=2&&M.arr[pos.r][pos.c]!
=3)
{
returntrue;
}//若在迷宫M中,当前位置pos不是障碍物0,不是围墙-1,以前没有经过2且不是不可通过3则可以通过,并返回true
else
{
returnfalse;
}
}
//在迷宫中的pos的位置留下足迹,证明已经经过这个位置
voidFootPrint(MazeType&M,PosTypepos)
{
M.arr[pos.r][pos.c]=2;
}
//在迷宫的pos位置留下标记,证明不能通过这个位置
voidMarkPrint(MazeType&M,PosTypepos)
{
M.arr[pos.r][pos.c]=3;
}
//根据不同的方向来进行移动
PosTypeNextPos(PosTypeCurPos,intDir)
{
PosTypeReturnPos;
switch(Dir)
{
case1:
//向右
ReturnPos.r=CurPos.r;
ReturnPos.c=CurPos.c+1;
break;
case2:
//向下
ReturnPos.r=CurPos.r+1;
ReturnPos.c=CurPos.c;
break;
case3:
//向左
ReturnPos.r=CurPos.r;
ReturnPos.c=CurPos.c-1;
break;
case4:
//向上
ReturnPos.r=CurPos.r-1;
ReturnPos.c=CurPos.c;
break;
}//通路路线由此优先级决定唯一
returnReturnPos;
}
//求解迷宫M中,从Start到end的一条路径,若存在则返回true,否则返回false
boolMazePath(MazeType&M,PosTypestart,PosTypeend)
{
StackS;
InitStack(S);//建栈
PosTypecurpos=start;//设置当前坐标为入口位置;
intcurstep=1;//当前的步数
boolFind=false;//标记是否找到出口
ElemTypee;
do
{
if(Pass(M,curpos))//如果当前位置可以通过(不是障碍物且未曾留下足迹)
{
FootPrint(M,curpos);//在当前位置标记为2
e.step=1;
e.seat=curpos;
e.di=1;//初始化为向右移动
Push(S,e);//将已经走过的放入栈中
if(curpos.c==end.c&&curpos.r==end.r)//如果找到了出口则终止,并返回true
{
Find=true;
returnFind;
}
else//向右移动,当前步数加一
{
curpos=NextPos(curpos,1);
curstep++;
}
}
else//当前位置不能通过
{
if(!
StackEmpty(S))
{
Pop(S,e);//将已经走过的最近位置弹出,数据保存在e中
while(e.di==4&&!
(StackEmpty(S)))//当方向改变一周后仍不能找到可通过的路径
{
MarkPrint(M,e.seat);//留下不能通过的标记
Pop(S,e);//删除栈顶元素
curstep--;
}
if(e.di<4)//不能通过则改变方向
{
e.di++;//方向顺时针改变
Push(S,e);
curpos=NextPos(e.seat,e.di);//求下一个结点
}
}
}
}while(!
StackEmpty(S)&&!
Find);//当栈不为空且没有找到出口
returnfalse;//没有找到出口则返回false
}
//总菜单,构建操作模型
intmain()
{
MazeTypeM;//定义迷宫
introw,col;//定义行和列
intcommand;
charch;
intop=1;
PosTypestart,end;//定义入口和出口
do//进入菜单
{
printf("\n\n\n\n");
printf("==========欢迎来到迷宫世界=========\n");
printf("**\n");
printf("*1.开始游戏*\n");
printf("**\n");
printf("*0.退出*\n");
printf("**\n");
printf("===========================================\n\n");
printf("请选择!
!
!
\n");