迷宫:1-->通路 非1-->死路
简单迷宫0 0 0 0 0 0
0 0 1 0 0 0
0 0 1 0 0 0
0 0 1 1 1 0
0 0 1 0 1 1
0 0 1 0 0 0
求解:①可以采用循环的方式。需要用到栈,从入口开始,往四个方向走,依次将走过的坐标点--入栈;如果走到“死路”,就出栈;--循环;最后栈中保存的就是出迷宫的路线。
求解:②可以采用递归的方式。每走一步,就把剩下的迷宫看成以下一步为入口的“新迷宫”,将走整个迷宫,化成走一个个“小迷宫”,这就是递归。走到出口,就“一路”返回。
多通路迷宫:通路间(不)带环
0 0 0 0 0 0
0 1 1 1 1 1
0 1 0 0 0 0
0 1 0 0 0 0
0 1 1 1 1 1
0 1 0 0 0 0
求解:还是采用递归的方式:将当前步--入栈,然后向四周走;当四周都不能走时---出栈。
(1)为解决“带环”问题----找到最短出迷宫路径:在判断下一步可以(下一步的数大于当前的数)走后,就把下一步的数改为当前的数+1;这样在再次进入“环”后,不会在环里一直“转圈”。
(2)解决多通路问题:在找到一条“出路后”,不是直接退出,而是把每一条路都走一遍;所以开始从入口进,最后又会从入口出。
下面是代码:
maze.h
#include <malloc.h> #include <stdio.h> #include <stdlib.h> #include <assert.h> #define ROW 4 #define COL 4 int Maze[ROW][COL]; typedef struct Position { int _x; int _y; }Position; typedef struct Stack { Position* _pos; int _top; // 表示有效元素个数 表示栈顶位置 int _capacity; // 底层空间的总大小 }Stack; void StackInit(Stack* s); // 入栈 void StackPush(Stack* s, Position pos); // 出栈 void StackPop(Stack* s); // 获取栈顶元素 //pPos StackTop(Stack* s); // 有效元素的个数 int StackSize(Stack* s); // 检测栈是否为空 int StackEmpty(Stack* s); //打印栈 void PrintfStack(Stack s); //清空栈 void clearstack(Stack* s); ///迷宫问题函数 //判断入口是否有效 int IsEnterRight(Position enter); //判断是否是出口 int IsExit(Position cur,Position enter); //判断next是否可走 int IsNextPass(Position cur,Position next); //保存路径 void saveshortpath(Stack* shortpath,Stack* path); //走迷宫 void passmaze(Position enter); //循环(栈)和递归走迷宫函数 //void passmaze(Position enter,Stack* shortpath); //走复杂迷宫函数
maze.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "maze.h" //////////////////////////////////////////////////// //////////////////////////////////////////////////// int Maze[ROW][COL]= { {0,0,1,0}, {0,1,1,1}, {0,1,0,0}, {0,1,0,0}, }; void StackInit(Stack* s) { s->_pos=(Position*)malloc(sizeof(Position)*3); s->_capacity=3; s->_top=0; } // 入栈 void StackPush(Stack* s,Position pos) { Position* tmp; int newCapacity=s->_capacity*2; if(NULL==s) //未初始化,退出 return; if(s->_top==s->_capacity) //如果栈已满,就扩容 { tmp=(Position*)realloc(s->_pos,newCapacity*sizeof(Position)); if(NULL==tmp) { printf("扩容失败\n"); return; } s->_pos=tmp; s->_capacity=newCapacity; } s->_pos[s->_top]._x=pos._x; s->_pos[s->_top]._y=pos._y; s->_top++; } // 出栈 void StackPop(Stack* s) { if(NULL==s) return; if(0==s->_top) return; else s->_top--; } // 获取栈顶元素 Position StackTop(Stack* s) { if(NULL==s) exit(EXIT_FAILURE); return s->_pos[s->_top-1]; } // 有效元素的个数 int StackSize(Stack* s) { if(NULL==s) return -1; return s->_top; } // 检测栈是否为空 int StackEmpty(Stack* s) { if(NULL==s) exit(EXIT_FAILURE); if(0==s->_top) return 1; else return 0; } //打印栈 void PrintfStack(Stack s) { int i=0; if(0==s._top) return; printf("迷宫出口:"); for (;i<s._top;i++) { printf("(%d %d)-->",s._pos[i]._x,s._pos[i]._y); } printf("\n"); } //清空栈 void clearstack(Stack* s) { s->_top=0; } //判出口 int IsExit(Position cur,Position enter) { if((cur._x!=enter._x && cur._y!= enter._y)&& ( 0==cur._x || ROW-1==cur._x || 0==cur._y || COL-1==cur._y) ) //cur在边界即为出口(cur入口要排除在外) return 1; return 0; //cur暂不是出口 } //判入口是否有效 int IsEnterRight(Position enter) { if(0==enter._x || ROW-1==enter._x || 0==enter._y || COL-1==enter._y) //enter在"边界"即为有效 return 1; return 0; } // 对简单迷宫进行求解----只有一条通路,迷宫不带环 //---- 用循环的方式求解简单迷宫问题 #if 0 void passmaze(Position enter) { Stack s; Position cur,next; StackInit(&s); if(!IsEnterRight(enter)) //判断入口是否有效 { printf("enter error!\n"); return; } StackPush(&s,enter); //把入口入栈 while (!StackEmpty(&s)) //栈不为空,就继续 { cur=StackTop(&s); Maze[cur._x][cur._y]=2; if(IsExit(cur,enter)) //判断当前位置是否是出口 { PrintfStack(s); return; } //上 next=cur; next._x-=1; if(1==Maze[next._x][next._y]) { StackPush(&s,next); //next为 1 ,可以走-->入栈 continue; } //左 next=cur; next._y-=1; if(1==Maze[next._x][next._y]) { StackPush(&s,next); //next为 1 ,可以走-->入栈 continue; } //右 next=cur; next._y+=1; if(1==Maze[next._x][next._y]) { StackPush(&s,next); //next为 1 ,可以走-->入栈 continue; } //下 next=cur; next._x+=1; if(1==Maze[next._x][next._y]) { StackPush(&s,next); //next为 1 ,可以走-->入栈 continue; } else { Maze[cur._x][cur._y]=3; StackPop(&s); //next这一步走错了,回退到上一步-->出栈 } } printf("没有出口!\n"); } #endif // 用递归的方式求解简单迷宫问题 #if 1 int _passmaze(Position enter,Position cur) { Position next; if(1==Maze[cur._x][cur._y]) { Maze[cur._x][cur._y]=2; if(IsExit(cur,enter)) //判断当前位置是否是出口 return 1; //上 next=cur; next._x-=1; if(_passmaze(enter,next)) return 1; //左 next=cur; next._y-=1; if(_passmaze(enter,next)) return 1; //右 next=cur; next._y+=1; if(_passmaze(enter,next)) return 1; //下 next=cur; next._x+=1; if(_passmaze(enter,next)) return 1; Maze[cur._x][cur._y]=3; } return 0; } void passmaze(Position enter) { if(!IsEnterRight(enter)) //判断入口是否有效 { printf("enter error!\n"); return; } _passmaze(enter,enter); } #endif //对复杂迷宫进行求解---迷宫中可能有多条通路,多条路径有可能构成环 #if 0 void _passmaze(Position enter,Position cur,Stack* path,Stack* shortpath) { Position next; if(StackEmpty(path)) Maze[cur._x][cur._y]=2; StackPush(path,cur); //把入口入栈 if(IsExit(cur,enter)) //判断当前位置是否是出口 { if(StackEmpty(shortpath) || StackSize(path)<StackSize(shortpath)) saveshortpath(shortpath,path); StackPop(path); return; } //上 next=cur; next._x-=1; if(IsNextPass(cur,next)) { Maze[next._x][next._y]=Maze[cur._x][cur._y]+1; _passmaze(enter,next,path,shortpath); } //左 next=cur; next._y-=1; if(IsNextPass(cur,next)) { Maze[next._x][next._y]=Maze[cur._x][cur._y]+1; _passmaze(enter,next,path,shortpath); } //右 next=cur; next._y+=1; if(IsNextPass(cur,next)) { Maze[next._x][next._y]=Maze[cur._x][cur._y]+1; _passmaze(enter,next,path,shortpath); } //下 next=cur; next._x+=1; if(IsNextPass(cur,next)) { Maze[next._x][next._y]=Maze[cur._x][cur._y]+1; _passmaze(enter,next,path,shortpath); } StackPop(path); //next这一步走错了,回退到上一步-->出栈 } void passmaze(Position enter,Stack* shortpath) { Stack path; if(!IsEnterRight(enter)) //判断入口是否有效 { printf("enter error!\n"); return; } StackInit(&path); _passmaze(enter,enter,&path,shortpath); } //判断next是否可走 int IsNextPass(Position cur,Position next) { if((1==Maze[next._x][next._y]) || (Maze[cur._x][cur._y]<Maze[next._x][next._y])) return 1; return 0; } //保存路径 void saveshortpath(Stack* shortpath,Stack* path) { int i=0; assert(path); if(0==path->_top) return; clearstack(shortpath); for (;i<path->_top;i++) { shortpath->_pos=path->_pos; } shortpath->_top=i; } #endif
test.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "maze.h" int main() { Position enter; Stack shortpath; int i=0,j=0; StackInit(&shortpath); enter._x=3; enter._y=1; //passmaze(enter,&shortpath); passmaze(enter); for (i=0;i<ROW;i++) { for (j=0;j<COL;j++) { printf("%d ",Maze[i][j]); } printf("\n"); } PrintfStack(shortpath); return 0; }