迷宫.docx
《迷宫.docx》由会员分享,可在线阅读,更多相关《迷宫.docx(9页珍藏版)》请在冰豆网上搜索。
迷宫
一:
程序要求:
设计一个算法实现迷宫求解
二:
具体程序
#include
#include
#include
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXLEN 20//迷宫最大行列数目
typedef int Status;
#define INIT_SIZE 100 //存储空间初始分配量
#define INCREMENT 10 //存储空间分配增量
typedef struct{
int r;
int c;
}PostType;//r行c列的位置
typedef struct{
PostType seat;//当前坐标
int di; //往下一坐标的方向
}SElemType; //栈元素类型
typedef struct{
SElemType* base; //栈初始地址
SElemType* top; //栈顶
int stackSize; //栈容量
}Stack; //栈类型
Status InitStack(Stack &S){
S.base=(SElemType*)malloc(INIT_SIZE *sizeof(SElemType));
if(!
S.base)
exit(OVERFLOW);//存储分配失败
S.top=S.base;//栈顶指针和栈底指针指向同一元素
S.stackSize=INIT_SIZE;
return OK;
}//构造空栈
Status StackEmpty(Stack S){
if(S.top==S.base)
return TRUE;
return FALSE;
}//判栈空的程序
Status Push(Stack &S,SElemType e){
if(S.top-S.base >=S.stackSize){//栈满,加空间
S.base=(SElemType *)realloc(S.base,(S.stackSize+INCREMENT)*sizeof(SElemType));
if(!
S.base)
exit(OVERFLOW); //存储分配失败
S.top=S.base+S.stackSize;
S.stackSize+=INCREMENT;
}
*S.top++=e;
return OK;
}//入栈
Status Pop(Stack &S,SElemType &e){
if(S.top==S.base)//判空
return ERROR;
e=*--S.top;
return OK;
}//出栈
Status DestroyStack(Stack &S){//销毁栈S,
free(S.base);
S.top=S.base;
return OK;
}
typedef struct{
int r;
int c;
char adr[MAXLEN][MAXLEN];
}MazeType; //迷宫类型
Status InitMaze(MazeType &maze){
int m,n,i,j;
printf("请分别输入迷宫的行数和列数:
");
scanf("%d%d",&maze.r,&maze.c); //迷宫行和列数
for(i=0;i for(j=0;j maze.adr[i][j]='0';//初始化迷宫
printf("输入障碍的坐标((-1,-1) 结束):
");
scanf("%d%d",&m,&n);//接收障碍的坐标
while(m!
=-1){
if(m>maze.r || n>maze.c)//越界
exit(ERROR);
maze.adr[m][n]='1';//迷宫障碍用1标记
printf("输入障碍的坐标((-1,-1) 结束):
");
scanf("%d%d",&m,&n);
}//while
return OK;
}//设置迷宫,从屏幕接收障碍的横纵坐标
Status Pass(MazeType maze,PostType curpos){
if(maze.adr[curpos.r][curpos.c]=='0')//可通
return TRUE;
else
return FALSE;
}//判断当前位置是否可通
Status FootPrint(MazeType &maze,PostType curpos){
maze.adr[curpos.r][curpos.c]='*';//"*"表示可通
return OK;
}//在可以走通的地方用”*”标记
PostType NextPos(PostType &curpos,int i){
PostType cpos;
cpos=curpos;
switch(i){ //1.2.3.4分别表示东,南,西,北方向
case 1 :
cpos.c+=1; break;
case 2 :
cpos.r+=1; break;
case 3 :
cpos.c-=1; break;
case 4 :
cpos.r-=1; break;
default:
exit(ERROR);
}
return cpos;
}//指示并返回下一位置的坐标
Status MarkPrint(MazeType &maze,PostType curpos){
maze.adr[curpos.r][curpos.c]='@';//"@"表示曾走过但不通
return OK;
}//曾走过但不通返回OK
Status MazePath(MazeType &maze,PostType start,PostType end){
Stack S;
PostType curpos;
SElemType e;
InitStack(S);
curpos=start; //设置"当前位置"为"入口位置"
do{
if(Pass(maze,curpos)){//当前位置可以通过,
FootPrint(maze,curpos);//留下足迹
e.seat=curpos;
e.di=1;
Push(S,e); //加入路径
if(curpos.r==end.r&& curpos.c==end.c)
if(!
DestroyStack(S))//销毁失败
exit(OVERFLOW);
else
return TRUE; //到达出口
else{
curpos=NextPos(curpos,1); //下一位置是当前位置的东邻
}
}
else{ //当前位置不通
if(!
StackEmpty(S)){
Pop(S,e);
while(e.di==4&& !
StackEmpty(S)){
MarkPrint(maze,e.seat);
Pop(S,e); //留下不能通过的标记,并退一步
}//while
if(e.di < 4){
e.di++;//换下一个方向探索
Push(S,e);
curpos=NextPos(e.seat,e.di);//设定当前位置是该新方向上的相邻
}
}
}
}while(!
StackEmpty(S));
if(!
DestroyStack(S))//销毁失败
exit(OVERFLOW);
else
return FALSE;
}//寻找一条可通路径放于栈中
void PrintMaze(MazeType &maze){
int i,j;
printf("\n输出正确路径,用*表示:
\n\n");
for(i=0;i for(j=0;j printf("%4c",maze.adr[i][j]);//输出迷宫
printf("\n\n");
}
}//输出路径
void main(){
MazeType maze;
PostType start,end;
char cmd;
do{
if(!
InitMaze(maze)){ //初始化并创建迷宫
printf("\n初始化失败!
!
!
\n");
exit(OVERFLOW); //初始化错误
}
do{ //输入迷宫入口坐标
printf("\n请输入迷宫入口坐标:
");
scanf("%d%d",&start.r,&start.c);
if(start.r>maze.r || start.c>maze.c){
printf("\n超过迷宫最大边界!
!
!
\n");
continue;
}
}while(start.r>maze.r || start.c>maze.c);
do{ //输入迷宫出口坐标
printf("\n请输入迷宫出口坐标:
");
scanf("%d%d",&end.r,&end.c);
if(end.r>maze.r || end.c>maze.c){
printf("\n超过迷宫最大边界!
!
!
\n");
continue;
}
}while(end.r>maze.r || end.c>maze.c);
if(!
MazePath(maze,start,end))//迷宫求解
printf("\n该迷宫没有出口!
\n\n");
else
PrintMaze(maze);//打印路径
printf(" 继续探索迷宫?
?
?
(y/n):
");
scanf("%s",&cmd);
}while(cmd=='y' || cmd=='Y');
}
三:
程序思路
首先,定义三个结构体分别用来存放迷宫中某点位置和栈元素类型以及栈类型。
然后,定义了与栈有关的初始化,入栈,出栈,判空,销毁等函数,用于对栈实施一系列操作并返回状态,在MazePath调用。
其次,定义了初始化迷宫的函数,用屏幕接收障碍的坐标。
定义Pass,FootPrint和NextPos分别用来判断当前位置是否可通,做标记和指示下一位置坐标。
MazePath用于寻找迷宫中的可通路径并存放在栈中,PrintMaze用于输出可通迷宫路径。
最后,在主函数中调用MazePath和FootPrint,完成对迷宫问题的探索。
四:
运行结果
五:
心得体会
在编写MazePath的过程中遇到较大困难,不知道该怎样把对迷宫的操作和对栈的操作结合起来,后来查阅相关方面的资料得以解决。
因为大一时指针学得不是很好,这个学期学数据结构的同时也学了C++,在需要用指针的地方用了引用,引用更易掌握也更方便一些。
程序还存在不足,定义了迷宫最大是20,不知道怎样由用户来确定迷宫的大小。