二维迷宫之中,找出出口,并且输出路径。数据结构中的迷宫求解问题。
程序中,建立二维数组为迷宫,0为墙壁,1为可以通行的道路。
PosType为坐标(结构体);
算法的基本思想是:若当前位置“可通”,则纳入“当前路径”,并继续朝“下一位置”探索,即切换“下一位置”为“当前位置”,如此重复直到出口,若当前位置“不可通过”,则应顺着“来向”退回到“前一块道块”,然后朝着“来向”之外的其他方向继续探索。若4个方向都不可通过,则应从“当前路径”上删除该通道块。
#include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR -1 #define FALSE 0 #define TRUE 1 #define OVERFLOW -2 #define STACK_INIT_SIZE 100 //初始分配增量 #define STACKINCREMENT 10 //分配增量 //重定义: typedef int Status; typedef int MazeType; //迷宫 typedef struct{ //坐标的重定义 int x; int y; }PosType; typedef struct{ int ord; //通道块在路径上的“序号” PosType seat; //通道块在迷宫中的“坐标位置” int di; //从此通道块走向下一通道块的“方向” }SElemType; typedef struct{ SElemType * base; SElemType * top; int stacksize; //当前已经分配的储存空间,以元素为单位 }SqStack; //函数定义: Status InitStack(SqStack &S); //构造一个空栈 Status Push(SqStack &S,SElemType e); //插入元素e为新的栈顶元素 Status StackEmpty(SqStack S); //若S为空栈,则返回TRUE,否则返回FAKSE Status Pop(SqStack &S,SElemType &e); //若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR Status Pass(PosType curpos); //当前位置可以通过,即是未曾走到过的通道块 PosType NextPos(PosType curpos, int &n); //返回下一个坐标, void FootPrint(PosType curpos); //记录足迹 void MarkPrint(PosType curpos); //留下不能同的标记,并返回上一步 Status shownumbers(SqStack S); //打印栈元素 Status MazePath(MazeType maze,PosType start,PosType end,SqStack &S); //前进函数,则求的一条存放在栈中,并返回TRUE,否则返回FALSE //全局变量 //迷宫(二维数组) MazeType maze[10][10] = { {0,0,0,0,0,0,0,0,0,0}, //0 {0,1,1,0,1,1,1,0,1,0}, //1 {0,1,1,0,1,1,1,0,1,0}, //2 {0,1,1,1,1,0,0,1,1,0}, //3 {0,1,0,0,0,1,1,1,1,0}, //4 {0,1,1,1,0,1,1,1,1,0}, //5 {0,1,0,1,1,1,0,1,1,0}, //6 {0,1,0,0,0,1,0,0,1,0}, //7 {0,0,1,1,1,1,1,1,1,0}, //8 {0,0,0,0,0,0,0,0,0,0}, //9 }; //函数实现 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 StackEmpty(SqStack S) { if(S.base == S.top) return TRUE; else return FALSE; } Status Push(SqStack &S,SElemType e) { if(S.top - S.base >= S.stacksize) { S.base = (SElemType *)realloc(S.base,(S.stacksize + STACKINCREMENT)*sizeof(SElemType)); if(!S.base) exit(OVERFLOW); S.top = S.base + S.stacksize; S.stacksize += STACKINCREMENT; } *S.top++ = e; return OK; } Status Pop(SqStack &S,SElemType &e) { if(S.base == S.top) return ERROR; e = *--S.top; return OK; } Status Pass(PosType curpos) { if(maze[curpos.y][curpos.x] == 1) return OK; else return FALSE; } PosType NextPos(PosType curpos,int &n) { //东-1,西-2,南-3,北-4 switch(n) { case 1: //东 curpos.x++; if(maze[curpos.y][curpos.x] !=2) break; curpos.x--; case 2: //南 curpos.y++; n = 2; if(maze[curpos.y][curpos.x] !=2) break; curpos.y--; case 3: //西 curpos.x--; n=3; if(maze[curpos.y][curpos.x] !=2) break; curpos.x++; case 4: //北 curpos.y--; n=4; if(maze[curpos.y][curpos.x] == 2) { curpos.y++; maze[curpos.y][curpos.x] = 0; } break; } return curpos; } Status MazePath(MazeType maze,PosType start,PosType end,SqStack &S) { // SqStack S; PosType curpos; SElemType e; // InitStack(S); curpos = start; //设定当前位置为入口位置 int curstep = 1; //探索第一步 do { if(Pass(curpos)) //当前位置可以通过,即是未曾走到过的通道块 { FootPrint(curpos); //留下足迹 e.ord = curstep;e.di = 1;e.seat = curpos; Push(S,e); //加入路径 if(curpos.x == end.x && curpos.y == end.y) return (TRUE); //到达终点(出口) curpos = NextPos(curpos,e.di); //下一个位置是当前位置的东临 curstep++; //探索下一步 } else //当前位置不能通过 { if(!StackEmpty(S)) { Pop(S,e); while(e.di == 4 && !StackEmpty(S)) //当前位置4个方向都测试无法通过的情况下 { MarkPrint(e.seat);Pop(S,e); //留下不能通过的标记,并退回一步 } if(e.di < 4) { e.di++; //换一个方向探索 Push(S,e); curpos = NextPos(e.seat,e.di); //设定当前位置是该新方向上的相邻快 } } } }while(!StackEmpty(S)); return (FALSE); } void FootPrint(PosType curpos) { maze[curpos.y][curpos.x] = 2; //设2为通过的路径 } void MarkPrint(PosType curpos) { maze[curpos.y][curpos.x] = 0; //通不过的用墙壁0代替 } Status shownumbers(SqStack S) { int numbers = 1; if(S.top == S.base) { printf("栈为空栈,无法打印\n"); exit(-1); } while(S.base < S.top) { S.top--; printf("序号 %d: 坐标:%4d%4d\n",numbers,S.top->seat.x+1,S.top->seat.y+1); numbers++; } } //启动函数 int main() { for(int i=0;i<10;i++) { for(int j=0;j<10;j++) printf("%4d",maze[i][j]); printf("\n"); } SqStack S; //建立栈 InitStack(S); // PosType start; //入口 PosType end; //出口 start.x = 1;start.y = 1; //入口坐标 end.x = 8;end.y = 8; //出口坐标 if(MazePath(maze[10][10],start,end,S)) { printf("------------------------------------------\n"); printf(" 成功找到路径!\n"); shownumbers(S); } return 0; }
直接上的代码,中间有注释。运用栈来实现,也可以运用递归回溯法。