标签:des style blog io color ar os for sp
实验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) 曾走过但不通的地方也留下足迹,为-1 f) 关键算法:迷宫存在从入口到出口的通道,则求得一条存放在栈中,并返回ture g) 输出迷宫 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 10 typedef 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); //输出迷宫 #endif 3. 再建立一个头文件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 -2 typedef int Status; #endif 4. 将实现放在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,不可通过路径为-1 Status 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"); } 【实验总结】 【实验心得】
标签:des style blog io color ar os for sp
原文地址:http://www.cnblogs.com/lcpholdon/p/4074852.html