数据结构课程设计迷宫求解.docx
《数据结构课程设计迷宫求解.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计迷宫求解.docx(17页珍藏版)》请在冰豆网上搜索。
数据结构课程设计迷宫求解
指导教师对课程设计的评语
指导教师签字:
年月日
设计2迷宫问题
一、需求分析
1、问题描述
迷宫是一些互相连通的交叉路口的集合,给定一个迷宫入口,一个迷宫出口,当从入口到出口存在通路时输出其中的一条通路,当从入口到出口不存在通路时输出无通路存在。
要求:
随机产生一个mXn的迷宫,0和1分别表示迷宫中的通路和障碍。
存在回路时能记住已经走过的路口,不重复已经走过的路口。
2、需要用户自己设置入口和出口。
3、本程序只求出一条成功的通路。
二、概要设计
1、计算机解迷宫通常用的是“穷举求解”方法,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前进;否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。
假如所有可能的通路都探索到则未能到达出口,则所设定的迷宫没有通解。
可以二维数组存储迷宫数据,通常设定入口点的下标为(1,1),出口点的下标为(n,n)。
为处理方便起见,可以迷宫的四周加一圈障碍。
对于迷宫任一位置,均可约定有东、南、西、北四个方向可通。
1.设定栈的抽象数据类型定义:
ADTStack{
数据对象:
D={ai|ai∈CharSet,i=1,2,3.....,n,n>=0}
数据关系:
R1={|ai-1,ai∈D,i=2,.....,n}
基本操作:
StackSize(&S)操作结果:
构造一个空栈S。
DestoryStack(&S)
Push(&S,e)初始条件:
栈S已存在。
操作结果:
在栈S的栈顶插入新的栈顶元素e。
Pop(&S,&e)初始条件:
栈S已存在。
操作结果:
删除S的栈顶元素,并以e返回其值。
StackEmpty(&S)初始条件:
栈S已存在。
操作结果:
若栈S为空栈,则返回TRUE,否则返回FALSE。
}ADTStack
2.设定迷宫的抽象数据类型为:
ADTmaze{
数据对象:
D={ai,j∈{‘’,‘#’、’@’、’*’},0<=i<=m+1,0<=j<=n+1,m,n<=10}
数据关系:
R={ROW,COL}
ROW={|ai-1,j,ai,j∈D,i=1,……,m+1,j=0,……n+1}
COL={|ai,j-1,ai,j∈D,i=1,……,m+1,j=0,……n+1}
基本操作:
InitMaze(&maze,a,row,col)
初始条件:
二维数组a[row+2][col+2]已存在,其中自第1行至第row+1行、每行中自第1
列至第col+1列的元素已有值,并且以值0表示通路,以值1表示障碍。
操作结果:
构造迷宫的字符数组,以空白字符表示通路,以字符‘#‘表示障碍,并在迷宫四周加上一圈障碍。
MazePath(&maze,start,end)
初始条件:
迷宫maze已被赋值。
操作结果:
若迷宫maze中存在一条通路,则按照如下规定改变迷宫maze的状态;以字符“*”表示路径上的位置,字符“@”表示”死胡同”;否则迷宫的状态不变。
PrintMaze(maze)
初始条件:
迷宫maze已存在。
操作结果:
以字符形式输出迷宫。
}ADTmaze
3、为了实现上述操作,以栈为存储结构。
1)主程序模块:
Voidmain()
{初始化;
do{接受命令;处理命令;
}while(命令!
=“退出”);}
2)栈模块——实现栈抽象数据类型
3)迷宫模块——实习迷宫抽象数据类型
4.求解迷宫中一条通路的伪代码:
do{
若当前位置可通,
则{
将当前位置插入栈顶;
若该位置是出口位置,则结束;
否则切换当前位置的东临方块为新的当前位置;
}否则{
若栈不空且栈顶位置尚有其他方向未被探索,
则设定新的的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻块
若栈不空但栈顶位置的四周均不可通,
则{
删去栈顶位置;
若栈不空,则重新测试新的栈顶位置,直至找到一个可通的相邻块或出栈至栈空。
}}}while(栈不空)
三、详细设计
1,位置设置
typedefstruct{
intr,c;
}PosType;//位置类型
2)栈类型:
typedefstruct{
intstep;//当前位置在路径上的序号
PosTypeseat;//当前的坐标位置
intdi;//往下一坐标位置的方向
}ElemType;//栈的元素类型
typedefstructNodeType{
ElemTypedata;
NodeType*next;
}NodeType,*LinkType;//结点类型,指针类型
typedefstruct{
LinkTypetop;
intsize;
}Stack;//栈类型
3)迷宫类型:
typedefstruct{
intm,n;
chararr[15][15];
}MazeType;
voidInitMaze(MazeType&maze,inta[100][100],introw,intcol)
{//按照用户输入的row行和col列的二维数组(元素为0或1)
intm,n;
printf("请输入迷宫的行数和列数:
\n");
scanf("%d%d",&row,&col);
printf("请输入迷宫数据,1为障碍,0为通路\n");
for(m=1;m<=row;m++)
for(n=1;n<=col;n++{
scanf("%d",&a[m][n]);
}printf("数据输入结束.\n");
for(inti=0;i<=col+1;i++)
{
a[0][i]=1;
a[row+1][i]=1;
}
for(intj=0;j<=row+1;j++)
{
a[j][0]=1;
a[j][col+1]=1;
}
for(m=0;m<=row+1;m++)
for(n=0;n<=col+1;n++)
{
maze.arr[m][n]=a[m][n];}
maze.m=row;maze.n=col;
for(m=0;m<=row+1;m++){
for(n=0;n<=col+1;n++)
{printf("%d",maze.arr[m][n]);
}printf("\n");
}
for(i=0;i{for(j=0;j
if(maze.arr[i][j]==1)
maze.arr[i][j]='#';
else
maze.arr[i][j]='';}
}
for(i=0;i{for(j=0;j
printf("%c",maze.arr[i][j]);}
printf("\n");
}}
boolPass(MazeType&maze,PosType&curpos)//判断是否可达
{
if(maze.arr[curpos.r][curpos.c]=='')
returntrue;
else
returnfalse;
}
voidFootPrint(MazeType&maze,PosType&curpos)
{
maze.arr[curpos.r][curpos.c]='*';//可达路径标识
}
voidMarkPrint(MazeType&maze,PosType&curpos)
{
maze.arr[curpos.r][curpos.c]='@';//死胡同
}
PosTypeNextPos(PosType&curpos,inta)
{
switch(a){
case1:
{curpos.c=curpos.c+1;curpos.r=curpos.r;returncurpos;}
case2:
{
curpos.r=curpos.r+1;curpos.c=curpos.c;returncurpos;}
case3:
{
curpos.c=curpos.c-1;curpos.r=curpos.r;returncurpos;}
case4:
{
curpos.r=curpos.r-1;curpos.c=curpos.c;returncurpos;}
default:
returncurpos;//方向错误返回原位置
}
}
boolMazePath(MazeType&maze,PosTypestart,PosTypeend)
{//求解迷宫maze中,从入口start到出口end的一条路径,
//若存在则返回TRUE,否则返回FALSE
PosTypecurpos;
intcurstep;
StackS;
ElemTypee;
InitStack(S);
curpos=start;//设定入口位置
curstep=1;
boolfound=false;
do{
if(Pass(maze,curpos))
{//当前位置可以通过,即是未曾走到过的通道块留下足迹
FootPrint(maze,curpos);//做可以通过的标识
e.step=curstep;
e.seat=curpos;
e.di=1;//为栈顶元素赋值
if(Push(S,e)!
=OK)returnERROR;
if(curpos.r==end.r&&curpos.c==end.c)found=true;//如果到达终点返回true
else{
curpos=NextPos(curpos,1);//下一位置是当前位置的东邻
curstep++;//探索下一步
}//else
}//if
else
if(StackEmpty(S)!
=true)
{Pop(S,e);
while(e.di==4&&!
StackEmpty(S))
{
MarkPrint(maze,e.seat);
Pop(S,e);curstep--;
}//while
if(e.di<4){{
e.di++;Push(S,e);//换下个方向探索
curpos=NextPos(e.seat,e.di);
}//if
}//if
}while(!
StackEmpty(S)&&!
found);
DestoryStack(S);
if(found)returntrue;
elsereturnfalse;}//没有找到路径
voidPrintMaze(MazeTypemaze)
{//将迷宫以字符型方阵形式输出到标准输出文件上
for(inti=0;i<=maze.m+1;i++){
{
for(intj=0;j<=maze.n+1;j++)
printf("%c",maze.arr[i][j]);
}
printf("\n");
}
}
4)主函数:
intmain()
{charcmd;
Init();
do{
ReadCommand(cmd);//读入一个操作命令符
Interpret(cmd);
}while(cmd!
='q');
}
四、运行结果及分析
测试结果如下
五、总结
通过这次试验,我学到了很多东西,比如说,开始根本不懂文件如何打开和如何传递,通过查资料才明白,头文件的编译,引用都是一个难题。
还有运用.H是要注意顺序。
这是一个很大型的设计题目,要充分搞懂各个部分之间的关系。
需要各个部分的完整结合,而且各个部分的基本知识应该很扎实。
通过这个实验,进一步提高了我的C语言水平。
附:
主要源代码
public.h:
enumStatus{
ERROR,
OK,
};//状态类型
typedefstruct{
intr,c;
}PosType;//位置类型
stack.h:
typedefstruct{
intstep;//当前位置在路径上的序号
PosTypeseat;//当前的坐标位置
intdi;//往下一坐标位置的方向
}ElemType;//栈的元素类型
typedefstructNodeType{
ElemTypedata;
NodeType*next;
}NodeType,*LinkType;//结点类型,指针类型
typedefstruct{
LinkTypetop;
intsize;
}Stack;//栈类型
intStackSize(Stack&S)
{returnS.size;}
voidInitStack(Stack&S)
{
S.top=(LinkType)malloc(sizeof(NodeType));
S.top->next=NULL;S.size=0;}
boolStackEmpty(Stack&S)
{if(S.top->next==NULL)returntrue;
elsereturnfalse;
}
voidDestoryStack(Stack&S)
{LinkTypep;
while(S.top!
=NULL)
{
p=S.top;S.top=S.top->next;free(p);
}
}
StatusPush(Stack&S,ElemTypee)
{//若分配空间失败,就返回,否则成功则在S的栈顶插入新元素e
LinkTypeL;
L=(LinkType)malloc(sizeof(NodeType));
if(L==NULL)
returnERROR;
else
L->next=S.top;S.top=L;S.top->data=e;S.size++;returnOK;
}
StatusPop(Stack&S,ElemType&e)
{//若栈不空则删除S的栈顶元素并以e带回其值
//否则返回错误
LinkTypep;
if(StackEmpty(S))returnERROR;
else{
p=S.top;S.top=S.top->next;e=p->data;S.size--;returnOK;
}}
maze.h
typedefstruct{
intm,n;
chararr[15][15];
}MazeType;
voidInitMaze(MazeType&maze,inta[100][100],introw,intcol)
{//按照用户输入的row行和col列的二维数组(元素为0或1)
//设置迷宫maze的值,包括加上边缘一圈的值
intm,n;
printf("请输入迷宫的行数和列数:
\n");
scanf("%d%d",&row,&col);
printf("请输入迷宫数据,1为障碍,0为通路\n");
for(m=1;m<=row;m++)
for(n=1;n<=col;n++)
{scanf("%d",&a[m][n]);}、printf("数据输入结束.\n");
for(inti=0;i<=col+1;i++)
{a[0][i]=1;a[row+1][i]=1;
}
for(intj=0;j<=row+1;j++)
{a[j][0]=1;a[j][col+1]=1;
}
for(m=0;m<=row+1;m++)
for(n=0;n<=col+1;n++)
{maze.arr[m][n]=a[m][n];
}
maze.m=row;maze.n=col;
for(m=0;m<=row+1;m++){
for(n=0;n<=col+1;n++)
{printf("%d",maze.arr[m][n]);
}printf("\n");
}
for(i=0;i{for(j=0;j
{if(maze.arr[i][j]==1)maze.arr[i][j]='#';
elsemaze.arr[i][j]='';
}}
for(i=0;i{for(j=0;j
printf("%c",maze.arr[i][j]);}
printf("\n");
}}
boolPass(MazeType&maze,PosType&curpos)//判断是否可达
{if(maze.arr[curpos.r][curpos.c]=='')returntrue;
elsereturnfalse;}
voidFootPrint(MazeType&maze,PosType&curpos){
maze.arr[curpos.r][curpos.c]='*';//可达路径标识
}
voidMarkPrint(MazeType&maze,PosType&curpos){
maze.arr[curpos.r][curpos.c]='@';}//死胡同
PosTypeNextPos(PosType&curpos,inta){
switch(a){
case1:
{
curpos.c=curpos.c+1;curpos.r=curpos.r;returncurpos;}
case2:
{
curpos.r=curpos.r+1;curpos.c=curpos.c;returncurpos;}
case3:
{
curpos.c=curpos.c-1;curpos.r=curpos.r;returncurpos;}
case4:
{
curpos.r=curpos.r-1;curpos.c=curpos.c;returncurpos;}
default:
returncurpos;//方向错误返回原位置
}}
boolMazePath(MazeType&maze,PosTypestart,PosTypeend)
{//求解迷宫maze中,从入口start到出口end的一条路径,
//若存在则返回TRUE,否则返回FALSE
PosTypecurpos;
intcurstep;
StackS;
ElemTypee;
InitStack(S);
curpos=start;//设定入口位置
curstep=1;
boolfound=false;
do{
if(Pass(maze,curpos))
{//当前位置可以通过,即是未曾走到过的通道块留下足迹
FootPrint(maze,curpos);//做可以通过的标识
e.step=curstep;e.seat=curpos;e.di=1;//为栈顶元素赋值
if(Push(S,e)!
=OK)returnERROR;
if(curpos.r==end.r&&curpos.c==end.c)found=true;//如果到达终点返回true
else{curpos=NextPos(curpos,1);//下一位置是当前位置的东邻
curstep++;//探索下一步
}//else
}//if
else
if(StackEmpty(S)!
=true)
{Pop(S,e);
while(e.di==4&&!
StackEmpty(S))
{MarkPrint(maze,e.seat);
Pop(S,e);curstep--;}//while
if(e.di<4)
{e.di++;Push(S,e);//换下个方向探索
curpos=NextPos(e.seat,e.di);
}//if
}//if
}while(!
StackEmpty(S)&&!
found);
DestoryStack(S);
if(found)returntrue;
elsereturnfalse;//没有找到路径
}
voidPrintMaze(MazeTypemaze)
{//将迷宫以字符型方阵形式输出到标准输出文件上
for(inti=0;i<=maze.m+1;i++){
{for(intj=0;j<=maze.n+1;j++)printf("%c",maze.arr[i][j]);
}printf("\n");}
}
testmaze.cpp
#include"public.h"
#include"malloc.h"
#include
#include
#include"stack.h"
#include"maze.h"
inta[100][100];
introw,col;
MazeTypemaze;
PosTypestart,end;
voidInit()
{system("cls");//清屏
printf("\n\t************************************\n");
printf("\tc:
CreatMaze\n");
printf("\tm:
MazePath\n");
printf("\tp:
PrintMaze\n");
printf("\tq:
Quit\n");
printf("\t***************THEMAZE***************\n");
printf("\tChoosefromctoq:
\n\t");
}
voidReadCommand(char&cmd)
{//读入操作命令符
do{
cmd=getchar();
}while(cmd!
='c'&&cmd!
='m'&&cmd!
='p'&&cmd!
='q');
}
voidInterpret(charcmd){
switch(cmd){
case'c':
{
InitMaze(maze,a,row,col);break;
}
case'm':
{
printf("请输入迷宫的入口位置\n");
|
|
|
|