迷宫求解 调用栈,及递归实现

迷宫求解
1. 首先要有一张迷宫地图,地图由两部分组成:

(1)一是迷宫中各处的位置坐标,

(2)二是迷宫各位置处的状态信息,即该处是墙还是路

1)迷宫地图是6*6的,即二维数组是6行6列的。(2)在迷宫中用0表示墙,用1表示路
给定一个地图
这里写图片描述
初始化地图

  3 #define ROW 6
  4 #define COL 6
  5 
  6 //定义一个仓库存储地图和路径
  7 typedef struct Warehouse
  8 {
  9     int map[ROW][COL];
 10 }Warehouse;
 11 
 12 //表示地图中的点的横列值
 13 typedef struct Point
 14 {
 15     int row;
 16     int col;
 17 }Point;
 18 //地图进行初始化
 19 void MapInit(Warehouse*house)
 20 {
 21     if(house==NULL)
 22     {
 23         return ;
 24     }
 25     int tmp[ROW][COL]=
 26     {
 27         {0,1,0,0,0,0},
 28         {0,1,1,1,0,0},
 29         {0,1,0,0,0,0},
 30         {0,1,1,0,0,0},
 31         {0,1,0,0,0,0},
 32         {0,1,0,0,0,0}
 33     };
 34     int row=0;
 35     for(;row<ROW;++row)
 36     {
 37         int col=0;
 38         for(;col<COL;++col)
 39         {
 40             //对地图中的点进行初始化
 41             house->map[row][col]=tmp[row][col];
 42         }
 43     }
 44 }

判断当前点能否落脚

 47 //判断能否落脚
 48 int CanStay(Warehouse* house, Point cur)
 49 {
 50     //落脚点在地图之外不能落脚
 51     if(cur.row<0||cur.row>ROW||cur.col<0||cur.col>COL)
 52     {
 53         return 0;
 54     }
 55     //约定,二维数组中值为1可以落脚
 56     if(house->map[cur.row][cur.col]==1)
 57     {
 58         return 1;
 59     }
 60     return 0;
 61 }

对落脚点进行标记

 63 //对落脚点进行标记
 64 void Mark(Warehouse* house,Point cur)
 65 {
 66     if(house==NULL)
 67     {
 68         return ;
 69     }
 70     //约定 落脚点值为2
 71     house->map[cur.row][cur.col]=2;
 72     return ;
 73 }    

判断当前点是否为出口

 75 //当前点是否为出口
 76 int IsExit(Point cur,Point entry)
 77 {
 78     //入口点不能为出口
 79     if(cur.row==entry.row&&cur.col==entry.col)
 80     {
 81         return 0 ;
 82     }
 83     if(cur.row==0||cur.row==ROW-1||cur.col==0||cur.col==COL-1)
 84     {
 85         return 1;
 86     }
 87     return 0;
 88 }   

从入口进入迷宫寻找出口

//根据入口点和迷宫地图找迷宫的出口
void Path(Maze* maze,Point entry);

方法一 递归实现
实现思想:

因为每经过一处,都要调用该递归函数,即将经过的位置入栈,但是该位置是否能走,还需要在进行判断。所以在递归函数函数中需要对各个位置进行判断:

(1)该位置能否落脚,如果不能落脚,就直接结束函数调用。

(2)如果能落脚,标记该位置(约定为2),表示走过。

(3)判断该位置是否是出口(规定出口在边界上),如果是出口打印信息并返回

(4)如果不是出口,在四周探索(约定顺时针,深度优先探索)。将四周点作为新的当前点出入递归函数,进行函数调用。

(5)当四周点都已经探索完了,说明探索结束。原路返回探索上一个岔路口的其他路线。此时,直接结束函数调用就表示将当前位置出栈了。

 90 //辅助函数判断是否为合法路径
 91 void _Path(Warehouse* house,Point cur, Point entry)
 92 {
 93     if(house==NULL)
 94     {
 95         return ;
 96     }
 97     printf("(%d%d)",cur.row,cur.col);
 98     //判断当前点是否能落脚
 99     if(CanStay(house,cur)==0)
100     {
101         return ;
102     }
103     //如果可以落脚进行标记
104     Mark(house,cur);
105     //判断当前点是否为出口
106     if(IsExit(cur,entry)==1)
107     {
108         printf("找到一条出口\n");
109         return ;
110     }
111     //如果不是出口对四周进行探索(例如顺时针)
112     Point up; 
113     cur.row-=1;
114     _Path(house,up,entry);
115 
116     Point right;
117     cur.col+=1;
118     _Path(house,right,entry);
119     
120     Point down;
121     cur.row+=1;
122     _Path(house,down,entry);
123 
124     Point left;
125     cur.col-=1;
126     _Path(house,left,entry);
127 }
128 
129 void Path(Warehouse* house, Point entry)
130 {
131     if(house==NULL)
132     {
133         return ;
134     }
135     _Path(house,entry,entry);
136     return ;
137 }

方法二 借用栈实现

Path函数的实现思路如下:

(1)定义一个栈保存走过的位置信息

(2)从入口点开始探索,是否落脚,若能落脚,标记并入栈

(3)取栈顶元素判断若栈为空,说明回溯结束没有出口

(4)若不为空则判断栈顶元素是否为出口点,若出口点直接打印返回

(5)若栈顶元素不是出口点,就顺时针探测该栈顶元素的四周。

(6)依次判断若落脚(则标记,并入栈)

(8)如果四周的点都探测完了还没找到出口,就出栈顶元素,继续探测上一个位置的四周点。

155 //方法二借用栈实现判断出口
156 void Pathstack(Warehouse* house,Point entry)
157 {
158     if(house==NULL)
159     {
160         return;
161     }
162 
163     //定义栈,对其初始化
164     SeqStack stack;
165     SeqStackInit(&stack);
166 
167     //若能落脚,标记,入栈
168     if(CanStay(house,entry)==0)
169     {
170         return ;
171     }
172     Mark(house,entry);
173     SeqStackPush(&stack,entry);
174 
175     //循环判断
176     while(1)
177     {
178 
179         Point cur;
180         int ret=SeqStackTop(&stack);
181         if(ret==-1)
182         {
183             printf("没有找到");
184             return ;
185         }
186         printf("(%d%d)\n",cur.row,cur.col);
187         if(IsExit(cur,entry)==1)
188         {
189             printf("找到一条出口");
190             return ;
191         }
192 
193        //如果不是出口,对四周探索(例如顺时针)
194        Point up;
195        up.row-=1;
196        if(CanStay(house,up)==1)
197        {
198            Mark(house,up);
199            SeqStackPush(&stack,up);
200            continue;
201        }
202         
203        Point right;
204        right.col+=1;
205        if(CanStay(house,right)==1)
206        {
207            Mark(house,right);
208            SeqStackPush(&stack,right);
209            continue;
210        }
211        
212        Point down;
213        down.row+=1;
214        if(CanStay(house,down)==1)
215        {
216            Mark(house,down);
217            SeqStackPush(&stack,down);
218            continue;
219        }
220         
221        Point left;
222        left.col-=1;
223        if(CanStay(house,left)==1)
224        {
225            Mark(house,left);
226            SeqStackPush(&stack,left);
227            continue;
228        }
229        SeqStackPop(&stack);
230     }
231 }

猜你喜欢

转载自blog.csdn.net/yu876876/article/details/81078549