C語言動態走迷宮

weixin_33831673發表於2015-08-20

曾經用C語言做過的動態走迷宮程式,先分享程式碼如下:

程式碼如下:

  1 //標頭檔案
  2 #include<stdio.h>
  3 #include<windows.h>//Sleep(500)函式呼叫此標頭檔案
  4 #include<conio.h>//getch()函式呼叫此標頭檔案
  5 #include<stdlib.h>//system("cls")函式呼叫此標頭檔案
  6 
  7 //函式狀態碼定義
  8 /******************************/
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define OK 1
 12 #define ERROR 0
 13 #define INFEASIBLE -1
 14 #define OVERFLOW -2
 15 typedef int Status;
 16 #define STACK_INIT_SIZE 100
 17 #define STACKINCREMENT 10
 18 #define Pass 0 //可通過
 19 #define Wall 1 //
 20 #define Start 6 //起點
 21 #define End 7   //終點
 22 #define Back 8 //返回
 23 #define Exit 9 //出口:找到終點後標誌出來
 24 /******************************/
 25 
 26 //自定義資料型別
 27 /***************************************************/
 28 
 29 //自定義列舉型別
 30 enum direction{East=2,South,West,North};//2,3,4,5分別代表東、南、西、北
 31 /*+------------------------
 32 使用列舉型別來表示方向
 33 該列舉型別定義的變數只能取值 East,West,South,North
 34 且East=2,South=3,West=4,North=5
 35 本原始碼上面使用列舉型別,基本等效於下面
 36 #define East 2
 37 #define South 3
 38 #define West 4
 39 #define North 5
 40 +------------------------*/
 41 
 42 //自定義座標結構體
 43 typedef struct //迷宮x行,y列
 44 {
 45     int x;
 46     int y;
 47 }Position;//座標結構體
 48 
 49 //二維陣列構造迷宮,1代表牆,0代表可通過。
 50 int Map[10][10]={
 51     {1,6,1,1,1,1,1,1,1,1},
 52     {1,0,0,1,0,0,0,1,0,1},
 53     {1,0,0,1,0,0,0,1,0,1},
 54     {1,0,0,0,0,1,1,0,0,1},
 55     {1,0,1,1,1,0,0,0,0,1},
 56     {1,0,0,0,1,0,0,0,0,1},
 57     {1,0,1,0,0,0,1,0,0,1},
 58     {1,0,1,1,1,0,1,1,0,1},
 59     {1,1,0,0,0,0,0,0,0,7},
 60     {1,1,1,1,1,1,1,1,1,1}
 61 };
 62 
 63 //自定義結構體作為中間變數儲存當前臨時座標資訊
 64 typedef struct
 65 {
 66     int number;//記錄是第幾步
 67     Position seat;//通道塊在迷宮中的"位置座標"
 68     enum direction direc;
 69     //direction為列舉型別,用來表示從此通道走向下一通道的方向
 70     //direc只能取值 East,West,South,North
 71     //且East=2,South=3,West=4,North=5
 72 }SElemType;
 73 
 74 //自定義棧結構便於將上面結構體的臨時座標資訊放到棧記憶體儲
 75 typedef struct {
 76     SElemType *base;
 77     SElemType *top;
 78     int stacksize;
 79 }SqStack;//
 80 /*********************************************/
 81 
 82 //函式宣告
 83 /******************************************/
 84 
 85 void Welcome();//歡迎介面函式
 86 void printfMap();//列印迷宮函式
 87 Status findPath(SqStack &S,Position start,Position end);//迷宮尋路徑函式
 88 Status InitStack(SqStack &S);//初始化棧
 89 Status StackEmpty(SqStack S);//判斷棧是否為空
 90 Status Push(SqStack &S,SElemType e);//入棧
 91 Status Pop(SqStack &S,SElemType &e);//出棧
 92 enum direction Judge_direc(Position pos);//根據一個座標探索周圍座標返回可通行的座標
 93 Position change_seat(Position &pos,enum direction direc);//根據方向移動到下一個可通行的座標處
 94 Status change_Map(int mapid);
 95 
 96 /****************主函式開始***********************/
 97 
 98 //主函式
 99 int main()
100 {
101     Position start,end;
102     int n;
103     SqStack S;
104     InitStack(S);//初始化棧
105     Welcome();//呼叫歡迎介面函式
106     start.x=0;//0
107     start.y=1;//1
108     printf("請選擇地圖:\n\n");
109     change_Map(0);
110     printf("\t\t預設地圖0\n\n");
111     printfMap();
112     change_Map(1);
113     printf("\t\t備選地圖1\n\n");
114     printfMap();
115     printf("選擇預設地圖請輸入0,備選地圖請輸入1:\n");
116     printf("您的選擇:");
117     scanf("%d",&n);
118     system("cls");
119     switch(n)
120     {
121         case 0:
122         {
123             change_Map(0);printf("初始迷宮如下所示:\n\n");
124             end.x=8;end.y=9;
125             printfMap();
126             printf("按任意鍵繼續!");
127             getch();
128             system("cls");
129             break;
130         }
131          case 1:
132         {
133                 change_Map(1);printf("初始迷宮如下所示:\n\n"); 
134                 end.x=0;
135                 end.y=8;
136                 printfMap();
137                 printf("按任意鍵繼續!");
138                 getch();
139                 system("cls");
140                 break;
141         }
142     }
143     findPath(S,start,end);
144     printf("\n\n按下任意鍵退出系統!\n");
145     getch();
146     
147     return 0;
148 }
149 /***************主函式結束***********************/
150 //列印迷宮
151 void printfMap()
152 {
153     int i,j;
154     for(i=0;i<10;i++)
155     {
156         printf("\t");
157         for(j=0;j<10;j++)
158             switch(Map[i][j]){
159             case Pass:printf("");break;//可通過0
160             case Wall:printf("");break;//牆1
161             case East:printf("");break;//東2
162             case South:printf(""); break;//南3
163             case West:printf("");break;//西4
164             case North:printf("");break;//北5
165             case Start:printf("");break;//起點6
166             case End:printf("");break;//終點7
167             case Back:printf("Θ");break;//返回8
168             case Exit:printf("To");break;//出口9
169         }
170         printf("\n");
171     }
172     printf("\n");
173 }
174 
175 //走迷宮
176 Status findPath(SqStack &S,Position start,Position end){
177     Position curpos;//當前座標
178     SElemType elem;//路徑相關資訊結構體
179     int step=1;//記錄步驟數
180     curpos=start;//開始座標    
181     while(1){
182         if(curpos.x==start.x&&curpos.y==start.y)//此段程式碼只執行一次
183         {
184             elem.number=1;
185             elem.direc=Judge_direc(curpos);//判斷下一個位置是什麼方向
186             elem.seat=curpos;
187             step++;
188             Push(S,elem);//第一個起點無條件入棧 
189         }    
190         
191         Map[curpos.x][curpos.y]=(int)elem.direc;//鎖定當前位置
192         curpos=change_seat(curpos,elem.direc);//移動到下一個位置,根據方向改變座標位置
193         if(Map[curpos.x][curpos.y]==End)//找到終點,退出迴圈
194         {
195             elem.seat=curpos;
196             elem.number=step;
197             Push(S,elem);
198             Map[curpos.x][curpos.y]=Exit;
199             system("cls");
200             printf("\n");
201             printfMap();
202             printf("\n\t恭喜您,迷宮路徑已經找到!\n\n");
203             printf("路徑座標為:\n\n");
204             while(!StackEmpty(S))
205             {
206                 Pop(S,elem);//出棧
207                 curpos=elem.seat;
208                 printf("(%d,%d)\t",curpos.x,curpos.y);
209             }
210             break;
211         }
212         if(Map[curpos.x][curpos.y]==Pass)//如果當前路可通
213         {
214             elem.number=step;
215             elem.seat=curpos;
216             elem.direc=Judge_direc(curpos);
217             Push(S,elem);//將當前座標入棧
218             step++;
219         }
220         else//如果當前位置不通
221         {
222             Pop(S,elem);
223             curpos=elem.seat;
224             step=elem.number-1;
225             Map[curpos.x][curpos.y]=Back;//表示四個都不通,標記走過了
226             do
227             {
228                 Pop(S,elem);//出棧
229                 curpos=elem.seat;                
230                 /************while迴圈開始*****************/
231                 while(elem.direc<=4)
232                 {
233                     elem.direc=(enum direction)(elem.direc+1);
234                     curpos=change_seat(curpos,elem.direc);//移動到下一個位置,根據方向改變座標位置
235                     if(Map[curpos.x][curpos.y]==Pass)
236                     {
237                         break;
238                     }
239                 };
240                 /************while迴圈結束*****************/
241                 if(Map[curpos.x][curpos.y]==Pass)
242                 {
243                     curpos=elem.seat;
244                     elem.number=step;
245                     elem.seat=curpos;
246                     Push(S,elem);
247                     step++;
248                     break;
249                 }
250                 else
251                 {
252                     curpos=elem.seat;
253                     Map[curpos.x][curpos.y]=Back;    
254                 }
255                 printf("正在遍歷查詢...\n\n");
256                 printfMap();
257                 Sleep(1000);
258                 system("cls");
259             }while(!StackEmpty(S));//直到棧為空跳出迴圈        
260         }
261         printf("正在遍歷查詢...\n\n");
262         printfMap();
263         Sleep(1000);
264         system("cls");
265     }
266     return OK;    
267 }
268 
269 //改變座標
270 Position change_seat(Position &pos,enum direction direc){
271     switch(direc)
272     {
273     case East:  pos.y=pos.y+1;break;//2
274     case South: pos.x=pos.x+1;break;//3
275     case West:  pos.y=pos.y-1;break;//4
276     case North: pos.x=pos.x-1;break;//5
277     }
278     return pos;
279 }
280 //判斷下一個位置方向
281 enum direction Judge_direc(Position pos)
282 {
283     enum direction judge;
284     if(Map[pos.x][pos.y+1]==Pass||Map[pos.x][pos.y+1]==End)
285         judge=East;
286     else
287     {
288         if(Map[pos.x+1][pos.y]==Pass||Map[pos.x+1][pos.y]==End)
289             judge=South;
290         else
291         {
292             if(Map[pos.x][pos.y-1]==Pass||Map[pos.x][pos.y-1]==End)
293                 judge=West;
294             else
295             {
296                 if(Map[pos.x-1][pos.y]==Pass||Map[pos.x-1][pos.y]==End)
297                     judge=North;
298             }
299         }
300     }
301     return judge;            
302 }
303 
304 Status change_Map(int mapid)
305 {
306         if(mapid==0)//預設地圖
307         {
308             Map[0][8]=Wall;
309             Map[8][9]=End;
310         }
311         if(mapid==1)//其他地圖
312         {
313             Map[8][9]=Wall;
314             Map[0][8]=End;
315         }
316         return OK;
317 }
318 
319 //初始化棧
320 Status InitStack(SqStack &S){
321     S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
322     if(!S.base)exit(OVERFLOW);
323     S.top=S.base;
324     S.stacksize=STACK_INIT_SIZE;
325     return OK;
326 }
327 
328 //判斷棧是否為空
329 Status StackEmpty(SqStack S){
330     if(S.top==S.base)
331         return TRUE;
332     else
333         return FALSE;
334 }
335 //入棧
336 Status Push(SqStack &S,SElemType e){
337     if(S.top-S.base>=S.stacksize){
338         S.base=(SElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
339         if(!S.base)exit(OVERFLOW);
340         S.top=S.base+S.stacksize;
341         S.base+=STACKINCREMENT;
342     }
343     *S.top++=e;
344     return OK;
345 }
346 
347 //出棧
348 Status Pop(SqStack &S,SElemType &e){
349     if(S.top==S.base)return ERROR;
350     e=*--S.top;
351     return OK;
352 }
353 //去棧頂元素
354 Status GetTop(SqStack S,SElemType &e){
355     
356     if(S.top==S.base)return ERROR;
357     
358     e=*(S.top-1);  //注意top指向待插入位置
359     
360     return OK;
361     
362 }
363 
364 //歡迎介面函式
365 void Welcome(){
366     system("title 迷宮求解程式");//設定視窗標題
367     system("mode con cols=80 lines=40");  //視窗寬度高度
368     system("color a");//設定文字顏色,所在標頭檔案
369     printf("★**************************************************************★\n");
370     printf("★                                                              ★\n");
371     printf("★                     歡迎使用迷宮求解程式                     ★\n");
372     printf("★                                                              ★\n");
373     printf("★    檔名稱:資料結構期末實驗                                ★\n");
374     printf("★                                                              ★\n");
375     printf("★    專案名稱:迷宮求解程式                                    ★\n");
376     printf("★                                                              ★\n");
377     printf("★    建立時間:2014-11-28                                      ★\n");
378     printf("★                                                              ★\n");
379     printf("★    最後修改時間:2014-12-2                                   ★\n");
380     printf("★                                                              ★\n");
381     printf("★**************************************************************★\n");
382     printf("按任意鍵繼續!\n");
383     getch();//暫停函式,所在標頭檔案<conio.h>
384     system("cls");//清屏函式
385 }

 

相關文章