1. 程式人生 > >迷宮求解 呼叫棧,及遞迴實現

迷宮求解 呼叫棧,及遞迴實現

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