首页 > 代码库 > 栈的运用---迷宫
栈的运用---迷宫
实验2-1 栈与迷宫求解【实验目的】1.熟悉C语言的上机环境VC6,掌握C语言程序设计方法与特点。2.掌握栈的顺序存储结构的定义及C语言实现。3.掌握栈的顺序存储结构上的各种基本操作。4.应用栈实现迷宫通路算法。5.迷宫求解的关键结构定义及C语言实现。【问题说明】一个迷宫可用n阶方阵表示,1表示能通过,0 表示不能通过。现假设老鼠从左上角[1,1]进入迷宫,编写算法,寻求一条从右下角[n,n] 出去的路径。下图是一个迷宫的示意图: 迷宫示意图【算法基本思想】迷宫求解是栈的一个典型应用。基本算法思想是:(1)若当前位置“可通”,则纳入“当前路径”,并继续朝着“下一位置”探索,即切换“下一位置”为“当前位置”,如此重复直至到达出口;(2)若当前位置“不可通过”,则应顺着“来向”退回到“前一通道块”,然后朝着除“来向”之外的其他方向继续探索;(3)若该通道块的四周4个方块均“不可通过”,则应从“当前路径”上删除该通道块。注:(1)下一位置:“当前位置”四周4个方向(东南西北)上相邻的方块。(2)假设用栈记录当前路径,则栈顶存放的是“当前路径上最后一个通道块”。(3)纳入路径:当前位置入栈。(4)从当前路径上删除前一通道块:出栈。 求迷宫中一条从入口到出口的路径的算法,具体请参见p51。【实验内容】1. 顺序栈的初始化、元素的入栈、出栈、以及栈的判空。2. 迷宫关键操作:a) 迷宫的初始化b) 判断当前位置可否通过c) 为能通过的地方留下足迹,为当前走过的有效的步骤数d) 探索下一位置并返回下一位置的坐标e) 曾走过但不通的地方也留下足迹,为-1f) 关键算法:迷宫存在从入口到出口的通道,则求得一条存放在栈中,并返回tureg) 输出迷宫3. 测试:不同入口和出口的迷宫问题求解路径。【实验重点】1、 C语言定义顺序栈2、 会多文件组织方式编写程序3、 顺序栈的初始化、元素的入栈、出栈、以及栈的判空操作4、 迷宫的关键算法。【实验步骤与代码指导】1. 定义相关结构:(1)定义位置类型typedef struct{ int r; //迷宫矩阵的行 int c; //迷宫矩阵的列}PosType;(2)定义栈的元素类型typedef struct{ int ord; //通道块在路径上的“序号” PosType seat; //通道块在迷宫中的“坐标位置” int di; //从此通道块走向下一通道块的“方向”,1-4表示东南西北 }SElemType; (3)定义顺序/栈类型typedef struct{ SElemType *base; //栈底指针,栈构造前和销毁后,base为NULL SElemType *top; //栈顶指针 int stacksize; //当前已分配的存储空间,以元素为单位}SqStack; (4)定义迷宫类型typedef int MazeType[MAXLEN][MAXLEN]; //MAXLEN*MAXLEN二维数组 2.建立头文件maze.h如下:#ifndef _MAZE_H#define _MAZE_H#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include "common.h"#define STACK_INIT_SIZE 100 //存储空间初始化分配量#define STACK_INCREMENT 10 //存储空间分配增量#define MAXLEN 10typedef struct{ int r; //迷宫矩阵的行 int c; //迷宫矩阵的列}PosType;typedef struct{ int ord; //通道块在路径上的“序号” PosType seat; //通道块在迷宫中的“坐标位置” int di; //从此通道块走向下一通道块的“方向”,1-4表示东南西北 }SElemType; //栈的元素类型typedef struct{ SElemType *base; //栈底指针,栈构造前和销毁后,base为NULL SElemType *top; //栈顶指针 int stacksize; //当前已分配的存储空间,以元素为单位}SqStack; //栈类型-顺序存储typedef int MazeType[MAXLEN][MAXLEN]; //MAXLEN*MAXLEN二维数组 //迷宫类型Status InitStack(SqStack &S); //初始化栈Status DestroyStack(SqStack &S); //销毁栈Status Push(SqStack &S,SElemType e); //向栈顶插入元素Status Pop(SqStack &S,SElemType &e); //出栈Status StackEmpty(SqStack S); //栈是否为空Status InitMaze(MazeType &maze); //初始化迷宫Status Pass(MazeType &maze,PosType curpos); //判断当前位置可否通过Status FootPrint(MazeType &maze,PosType curpos,int curstep); //留下足迹,足迹为步骤数PosType NextPos(PosType curpos,int i); //探索下一位置并返回下一位置的坐标Status MarkPrint(MazeType &maze,PosType curpos); //曾走过但不通留下标记-1//迷宫maze存在从入口start到end的通道则求得一条存放在栈中Status MazePath(MazeType &maze,PosType start,PosType end); void PrintMaze(MazeType &maze); //输出迷宫#endif3. 再建立一个头文件common.h如下:#ifndef _COMMON_H#define _COMMON_H#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2typedef int Status;#endif4. 将实现放在Maze.cpp里,文件内容如下:#include <time.h>#include "maze.h"Status InitStack(SqStack &S){ S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType)); if(!S.base) exit(OVERFLOW); S.top=S.base; S.stacksize=STACK_INIT_SIZE; return OK;}Status DestroyStack(SqStack &S){ if (S.base!=NULL){ free(S.base); S.stacksize=0; printf("顺序栈已经销毁\n"); return OK; } else return FALSE;}Status Push(SqStack &S,SElemType e){ if (S.top-S.base>=S.stacksize ){ S.base=(SElemType *) realloc(S.base,(S.stacksize+STACK_INCREMENT)*sizeof(SElemType)); if(!S.base) exit(OVERFLOW); S.top=S.base+S.stacksize; S.stacksize+=STACK_INCREMENT; } *S.top++=e; return OK;}Status Pop(SqStack &S,SElemType &e){ if(S.top==S.base) return ERROR; e=*--S.top; return OK; }Status StackEmpty(SqStack S){ if (S.base==S.top) return TRUE; else return FALSE;}//定义墙值为0,可通过路径为1,不可通过路径为-1Status InitMaze(MazeType &maze){ int i,j; for(i=0;i<MAXLEN;i++){ //迷宫行外墙 maze[0][i]=0; maze[MAXLEN-1][i]=0; } for(i=0;i<MAXLEN;i++){ //迷宫列外墙 maze[i][0]=0; maze[i][MAXLEN-1]=0; } srand((unsigned)time(NULL)); //随机种子 for(i=1;i<MAXLEN-1;i++) for(j=1;j<MAXLEN-1;j++) maze[i][j]=1; //初始化迷宫 for(i=1;i<MAXLEN-1;i++){ for(j=1;j<MAXLEN-1;j++){ int n=rand()%29; //利用随机函数随机生成n值 if(n<MAXLEN-1) maze[i][j]=0; //随机设置通道块上的不通的路块 } } maze[1][1]=1; maze[MAXLEN-2][MAXLEN-2]=1; return OK; }void PrintMaze(MazeType &maze){ int i,j; printf("用递增的数字代表迷宫的从入口到出口的一条路径\n"); printf("用0代表墙和不通的地方用\n用-1代表曾走过的通道块但不通\n"); printf("用1代表可以通过的通道块\n"); printf(" "); for(i=0;i<MAXLEN;i++) //打印列数名 printf("%4d",i); printf("\n\n"); for(i=0;i<MAXLEN;i++){ printf("%2d",i); //打印行名 for(j=0;j<MAXLEN;j++) printf("%4d",maze[i][j]); //输出迷宫//当前位置的标记 printf("\n\n"); }}Status Pass(MazeType &maze,PosType curpos){ if(maze[curpos.r][curpos.c]==1) //可通 return TRUE; else return FALSE; }Status FootPrint(MazeType &maze,PosType curpos,int curstep){ maze[curpos.r][curpos.c]=curstep; //记录可通足迹 return OK; }PosType NextPos(PosType curpos,int i){ PosType 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,PosType curpos){ maze[curpos.r][curpos.c]=-1; //-1表示曾走过但不通 return OK;}Status MazePath(MazeType &maze,PosType start,PosType end){ //若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底到栈顶),并返回TRUE;否则返回FALSE SqStack S; InitStack(S); //初始化栈 PosType curpos=start; //设置"当前位置"为"入口位置" int curstep=1; //探索第一步 SElemType e; do{ if(Pass(maze,curpos)){ //当前位置可以通过,即未曾走过的通道块 FootPrint(maze,curpos,curstep); //留下足迹 e.ord=curstep; e.seat=curpos; e.di=1; Push(S,e); //加入路径 if(curpos.r==end.r && curpos.c==end.c) return TRUE; //到达出口 curpos=NextPos(curpos,1); //下一位置是当前位置的东邻 curstep++; //探索下一步 } else{ //当前位置不通 if(!StackEmpty(S)){ Pop(S,e); curstep--; while(e.di==4 && !StackEmpty(S)){ MarkPrint(maze,e.seat); //留下不能通过的标记,并退一步 Pop(S,e); curstep--; }//while if(e.di<4){ e.di++; //换下一个方向探索 Push(S,e); curstep++; curpos=NextPos(e.seat,e.di); //设定当前位置是该新方向上的相邻 } } } }while(!StackEmpty(S)); return FALSE; }5. 主函数:#include <stdio.h>#include "maze.h" void main(){ MazeType maze; PosType start,end; InitMaze(maze); //初始化并创建迷宫 start.r=1; start.c=1; //迷宫入口坐标 end.c=MAXLEN-2;end.r=MAXLEN-2; //迷宫出口坐标 PrintMaze(maze); if(MazePath(maze,start,end)){ printf("存在从入口到出口的迷宫路径!\n"); PrintMaze(maze); //打印路径**/ }else printf("迷宫路径不存在!\n"); }【实验总结】【实验心得】
栈的运用---迷宫
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。