实习报告、题目:编制一个求解迷宫通路的程序班级:计算机04(2)姓名:王金锭学号:04120087完成日期:06.03.01一.需求分析:1.以二维数组Maze[m+2][n+2]表示迷宫,其中:Maze[0][j]和Maze[m+1][j](0<=j<=n+1)及Maze[i][0]Maze[i][n+1](0<=i<=m+1)为添加的一圈障碍.数组中以元素值为0表示通路,1表示障碍,限定迷宫的大小m,n<=10.2.用户以文件的形式输入迷宫的数据:文件中的第一行的数据为迷宫的行数m和列数n;从第二行至第m+1(每行n个数)为迷宫值,同一行中的两个数字之间用空白字符相隔。
3.迷宫的入口位置和出口位置可由用户随时设定。
4.若设定的迷宫存在通路,则以长方阵形式将迷宫及其通路输出到标准输出文件(即终端)上,其中,字符“#”表示障碍,字符“*”表示路径上的位置,字符“@”表示“死胡同”,即曾途径然而不能到达出口的位置,余者用空格符印出。
若设定的迷宫不存在通路,则报告相应信息。
5.本程序给出一条成功的通路,并且可以通过用户输入把所有的通路输出到指定的文件中。
6.测试数据见原题,当入口位置为(1,1),出口位置为(9,8)时,输出数据为:二.概要设计:1.设定栈的抽象数据类型定义:ADT Stack{数据对象:D={ai|ai∈IntSet,i=1,2….,n,n>=0}数据关系:{ai-1,ai|ai-1,ai∈D,i=1,2…..n}基本操作:InitStack(&S)操作结果:构造一个空栈。
DestroyStack(&S)初始条件:栈S已存在操作结果:将S清空为空栈。
ClearStack(&S)初始条件:栈S已存在。
操作结果:将S清为空栈。
StackLength(S)初始条件:栈S已存在。
操作结果:返回栈S的长度。
StackEmpty(S)初始条件:栈S已存在。
操作结果:若S为空栈,则返回TURE,否则返回FAULE。
GetTop(S,&e)初始条件:栈S已存在。
操作结果:若S不空,则以e返回栈顶元素。
Push(&S,e)初始条件:栈S存在。
操作结果:在栈S的栈顶插入新的栈顶元素e。
Pop(&S,e)初始条件:栈S已存在。
操作结果:删除S的栈顶元素,并以e返回其值。
StackTraverse(S,visit())初始条件:栈S已存在。
操作结果:从栈底到栈顶依次对S中的每个元素调用visit()。
}ADT Stack2. 求解迷宫中的一条通路的伪码算法 :设定当前位置的初值为入口位置;do{若当前位置可通,则{将当前位置插入栈顶;若该位置是出口位置,则结束;否则切换当前位置的东邻方块为新的当前位置;}否则{若栈不空且栈顶位置尚有其他方向未被搜索,则设定新的当前位置为沿顺时针方向旋转找到的栈顶苇子后的下一个相邻块;若栈不空但粘顶位置的四周均不可通,则{删去栈顶位置;若栈不空,则重新测试新的栈顶位置,直至找到一个可通的相邻块或出栈至空栈;}}}while(栈不空);{栈空说明没有路径存在}三.详细设计:typedef enum{Wall,Space,Thinked}TMazeElem;typedef struct{int x,y;}Coordinate;typedef struct {int iLength,iHeight;TMazeElem pMaze[MAX_MAZE_SIZE][MAX_MAZE_SIZE];Coordinate in,out;}TMaze;typedef struct{Coordinate pos;int di;}PathElem;void ClearMaze(TMaze *maze)//清空迷宫void PrintMaze(TMaze *maze)//输出迷宫bool SaveMaze(TMaze *maze,char *fname)//保存到文件fname迷宫bool LoadMaze(TMaze *maze,char *fname,char *errMsg)//从文件中输入迷宫void FindMazePath_B(TMaze *maze,char *fname)//用回溯法探索迷宫的所有解,并且把解写入文件名为fname 的文件3.主函数和其他函数的源代码int Number = 0;/*迷宫的解的个数*/typedef int bool;#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX_MAZE_SIZE 100#define MAX_STACK_SIZE 500extern int Number;typedef enum{Wall,Space,Thinked}TMazeElem;typedef struct{int x,y;}Coordinate;typedef struct {int iLength,iHeight;TMazeElem pMaze[MAX_MAZE_SIZE][MAX_MAZE_SIZE];Coordinate in,out;}TMaze;typedef struct{Coordinate pos;int di;}PathElem;void ClearMaze(TMaze *maze){/*清空迷宫*/int i ,j;for (i = 0; i < MAX_MAZE_SIZE; i++)for (j = 0; j < MAX_MAZE_SIZE; j++)maze->pMaze[i][j] = Wall;maze->iLength = 0;maze -> iHeight = 2;}/*clearmaze*/void PrintMaze(TMaze *maze){/*输出迷宫*/int x,y;for (x = 0; x < maze->iHeight; x++){printf("\n");for (y = 0; y < maze->iLength;y++){if (x == maze->in.x && y == maze->in.y){printf("e");continue;}if (x == maze->out.x && y == maze->out.y){printf("x");continue;}switch( maze->pMaze[x][y]){case Wall: printf("#");break;case Space: printf(" ");break;case Thinked: printf("*");break;}/*switch*/}/*for y*/}/*for x*/printf("\nin:(%d,%d)out:(%d,%d)\n",maze->in.x,maze->in.y,maze->out.x,maze->out.y);}/*PrintMaze*/bool SaveMaze(TMaze *maze,char *fname){/*保存到文件fname迷宫*/int x,y;FILE *fp;fp = fopen(fname,"a");if (fp == NULL){printf("\nCan't open or to creat!%s.",fname);return ERROR;}fputc('\n',fp);for (x = 0; x < maze->iHeight; x++){for (y = 0; y < maze->iLength;y++){if (x == maze->in.x && y == maze->in.y){fprintf(fp,"E");continue;}if (x == maze->out.x && y == maze->out.y){fprintf(fp,"X");continue;}switch( maze->pMaze[x][y]){case Wall: fprintf(fp,"1");break;case Space: fprintf(fp,"0");break;case Thinked: fprintf(fp,"2");break;}/*switch*/}/*for y*/fprintf(fp,"\n");}/*for x*/fprintf(fp,"\入口:(%d,%d) 出口:(%d,%d)",maze->in.x,maze->in.y,maze->out.x,maze->out.y);fclose(fp);}/*SaveMaze*/bool LoadMaze(TMaze *maze,char *fname,char *errMsg){/*从文件中输入迷宫*/FILE *fp;char ch;bool error = FALSE,begin = FALSE,end = FALSE,in = FALSE,out = FALSE;int x = 1,y = 1;ClearMaze(maze);maze->iLength = maze->iHeight = 2;fp = fopen(fname,"r");if ( fp == NULL ){strcpy(errMsg,"Can't open your maze txt!.");return ERROR;}while( !feof(fp) && error == FALSE && end == FALSE){ch = fgetc(fp);if ( ch == '[' && begin == FALSE){begin = TRUE;continue;}if (begin == FALSE) continue;if( y >= MAX_MAZE_SIZE || x >= MAX_MAZE_SIZE ) {error = TRUE;strcpy(errMsg,"Y our file is too large.");}switch(tolower(ch)){case '[': error = TRUE;strcpy(errMsg,"There is too much [");break;case ']': end = TRUE;maze->iHeight ++;break;case ',': maze->iHeight ++;x ++;if ( y > maze->iLength) maze->iLength = y;y = 1;break;case 'e': if (in == TRUE){error = TRUE;strcpy(errMsg,"There is too much entrance.");}else{in = TRUE;maze->pMaze[x][y] = Space;maze->in.x = x;maze->in.y = y++ ;}break;case 'x': if (out == TRUE){error = TRUE;strcpy(errMsg,"There is too much outpath.");}else {out = TRUE;maze->pMaze[x][y] = Space;maze->out.x = x;maze->out.y = y ++;}break;case '0': maze->pMaze[x][y++] = Space;break;case '1': y++;}/*switch*/}/*while*/if ( error == TRUE) return ERROR;if ( in == FALSE || out == FALSE){strcpy(errMsg,"There is no entrance or outpath.");return ERROR;}maze ->iLength += 1;return OK;}/*loadmaze*/static Coordinate Offset[] = {{1,0},/*左*/{0,1},/*下*/{-1,0},/*右*/{0,-1}/*上*/};void FindMazePath_B(TMaze *maze,char *fname){/*用回溯法探索迷宫的所有解,并且把解写入文件名为fname 的文件*/ PathElem pPath[MAX_STACK_SIZE];int iTop = 0;Coordinate cur;PathElem e;bool find;e.pos = maze->in;e.di = 0;pPath[iTop++] = e;maze->pMaze[e.pos.x][e.pos.y] = Thinked;cur.x = maze->in.x + Offset[0].x;cur.y = maze->in.y + Offset[0].y;while( iTop > 0){find = FALSE;if (cur.x == maze->out.x && cur.y == maze->out.y){Number++;printf("\n已经找到%d个解.",Number);find = TRUE;PrintMaze(maze);SaveMaze(maze,fname);}/*当前位置不可通或者已经找到了解,则回溯或者探索下一个没有探索的位置*/ if ((maze->pMaze[cur.x][cur.y]) != Space || find == TRUE){e = pPath[iTop - 1];while ( e.di >= 3 && iTop > 0){/*堆栈顶的位置的4个方向已经全部探索*/maze->pMaze[e.pos.x][e.pos.y] = Space;/*标记该位置为空*/iTop--;/*堆栈顶的元素出堆栈*/e = pPath[iTop - 1];cur = e.pos;}/*while*//*堆栈顶的位置的4个方向还有其他方向没有被探索*/pPath[iTop-1].di++;e = pPath[iTop - 1];cur.x = e.pos.x + Offset[e.di].x;/*确定当前位置为堆栈顶的下一个没有探索的位置*/cur.y = e.pos.y + Offset[e.di].y;continue;}/*if*//*当前位置可通*/e.pos = cur;e.di = 0;pPath[iTop++] = e;/*把当前位置压入堆栈*/maze->pMaze[e.pos.x][e.pos.y] = Thinked;cur.x = e.pos.x + Offset[0].x;/*确定当前位置为前位置的下一个位置*/cur.y = e.pos.y + Offset[0].y;}/*while*/printf(" \n 探索结束");}/*FindMazePath_B*/void main(void){TMaze myMaze;char errMsg[40],mazefile[100],outfile[100],dbgfile[100];char ch;FILE *fp = fopen("explore.txt","w");printf("\n 输入迷宫文件:");gets(mazefile);if(LoadMaze(&myMaze,mazefile,errMsg) == ERROR){printf("\n%s",errMsg);printf("\n按任意键退出....");return;}printf("\n\t\t你输入的迷宫");PrintMaze(&myMaze);printf("\n输入一个输出文件来保存所有结果:");gets(outfile);FindMazePath_B(&myMaze,outfile);fclose(fp);printf("\n一共探索到%d个解。