迷宫求解
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 }