前言 :
老鼠走迷宮是堆疊在實際應用上一個很好的例子. 在一個實驗中, 老鼠被放進一個迷宮裡, 當老鼠走錯路時, 就會重走一次並把走過的路記起來, 避免走重複的路, 就這樣直到找到出口為止. 另外在迷宮移動尋找出口時, 電腦還必須判斷下一步該往哪一個方向移動, 此外還必須記錄能夠走的迷宮路徑, 如此才可以在迷宮走到死胡同時, 可以回頭來搜尋其它路徑. 在迷宮行進, 必須遵守以下三個原則 :
電腦模擬迷宮說明 :
在建立迷宮前, 我們先來了解如何在電腦中表現一個模擬迷宮的方式. 這時我們可以利用二維矩陣 MAZE[row][col], 並符合以下規則 :
下圖就是一個使用 10x12 二維陣列的模擬迷宮地圖表示圖 :
假設老鼠從左上角的 MAZE[1][1] 進入, 由右下角MAZE[8][10] 出來, 老鼠目前位置以 MAZE[x][y] 表示, 那麼我們可以將老鼠的移動方向表示如下 :
如上圖所示, 老鼠可以選擇的方向共有四個, 分別為東, 南, 西, 北. 但並非每個位置都可以移動, 必須視情況與目前位置來決定. 因此我們可以利用鏈結串列來記錄走過的位置, 並將走過的位置的陣列元素內容標示為 2, 然後將這個位置放入堆疊再進行下一次的選擇. 如果走到死巷子並且還沒走到終點, 那麼就必須退回到上一個位置, 並退回去, 直到回到上一個叉路後再選擇其他路. 由於每次加入新的位置必定會在堆疊的頂端, 因此堆疊頂端所指位置便是目前老鼠所在位置. 如此一直重複直到走到出口為止.
範例代碼 :
* Map.h 代碼 :
* Map.cpp 代碼 :
* 呼叫使用演算法代碼 :
執行函式 ch04_07 結果 :
老鼠走迷宮是堆疊在實際應用上一個很好的例子. 在一個實驗中, 老鼠被放進一個迷宮裡, 當老鼠走錯路時, 就會重走一次並把走過的路記起來, 避免走重複的路, 就這樣直到找到出口為止. 另外在迷宮移動尋找出口時, 電腦還必須判斷下一步該往哪一個方向移動, 此外還必須記錄能夠走的迷宮路徑, 如此才可以在迷宮走到死胡同時, 可以回頭來搜尋其它路徑. 在迷宮行進, 必須遵守以下三個原則 :
電腦模擬迷宮說明 :
在建立迷宮前, 我們先來了解如何在電腦中表現一個模擬迷宮的方式. 這時我們可以利用二維矩陣 MAZE[row][col], 並符合以下規則 :
下圖就是一個使用 10x12 二維陣列的模擬迷宮地圖表示圖 :
假設老鼠從左上角的 MAZE[1][1] 進入, 由右下角MAZE[8][10] 出來, 老鼠目前位置以 MAZE[x][y] 表示, 那麼我們可以將老鼠的移動方向表示如下 :
如上圖所示, 老鼠可以選擇的方向共有四個, 分別為東, 南, 西, 北. 但並非每個位置都可以移動, 必須視情況與目前位置來決定. 因此我們可以利用鏈結串列來記錄走過的位置, 並將走過的位置的陣列元素內容標示為 2, 然後將這個位置放入堆疊再進行下一次的選擇. 如果走到死巷子並且還沒走到終點, 那麼就必須退回到上一個位置, 並退回去, 直到回到上一個叉路後再選擇其他路. 由於每次加入新的位置必定會在堆疊的頂端, 因此堆疊頂端所指位置便是目前老鼠所在位置. 如此一直重複直到走到出口為止.
範例代碼 :
* Map.h 代碼 :
- #ifndef _MAP_FOR_MAZE
- #define _MAP_FOR_MAZE
- #include
- #define EAST MAZE[x][y+1]
- #define WEST MAZE[x][y-1]
- #define SOUTH MAZE[x+1][y]
- #define NORTH MAZE[x-1][y]
- struct pos{
- int x,y;
- struct pos* next;
- };
- typedef struct pos pnode;
- typedef pnode* plink;
- class Map{
- public:
- plink curPos;
- Map(){
- curPos = NULL;
- }
- ~Map(){
- //delete all curPos
- while(curPos) {
- plink top = curPos;
- curPos = curPos->next;
- delete top;
- }
- }
- virtual plink push(int x, int y);
- virtual plink pop(int* x, int* y);
- virtual int chkExit(int x,int y,int ex,int ey);
- };
- #endif
- #include "Map.h"
- plink Map::push(int x, int y) {
- if(curPos==NULL){
- curPos = new pnode;
- curPos->x = x;
- curPos->y = y;
- curPos->next = NULL;
- return curPos;
- } else {
- plink newnode = new pnode;
- newnode->x = x;
- newnode->y = y;
- newnode->next = curPos;
- curPos = newnode;
- return curPos;
- }
- }
- plink Map::pop(int* x, int* y){
- if(curPos == NULL){
- *x = -1;
- return NULL;
- } else {
- plink top = curPos;
- *x = curPos->x;
- *y = curPos->y;
- curPos = curPos->next;
- delete top;
- return curPos;
- }
- }
- int Map::chkExit(int x, int y, int ex, int ey){
- if(x==ex && y==ey){
- return 1;
- } else {
- return 0;
- }
- }
- const int ExitX = 8;
- const int ExitY = 10;
- int MAZE[10][12] = {1,1,1,1,1,1,1,1,1,1,1,1,
- 1,0,0,0,1,1,1,1,1,1,1,1,
- 1,1,1,0,1,1,0,0,0,0,1,1,
- 1,1,1,0,1,1,0,1,1,0,1,1,
- 1,1,1,0,0,0,0,1,1,0,1,1,
- 1,1,1,0,1,1,0,1,1,0,1,1,
- 1,1,1,0,1,1,0,1,1,0,1,1,
- 1,1,1,1,1,1,0,1,1,0,1,1,
- 1,1,0,0,0,0,0,0,1,0,0,1,
- 1,1,1,1,1,1,1,1,1,1,1,1};
- void ch04_07(bool b) {
- if(b) {
- int x=1, y=1;
- plink path = NULL;
- Map map;
- cout << "[列印出迷宮路徑]" << endl;
- for(int i=0; i<10; i++) {
- for(int j=0;j<12; j++)
- cout << MAZE[i][j] << " ";
- cout << endl;
- }
- // 開始走迷宮
- while(x<=ExitX && y<=ExitY){
- MAZE[x][y] = 2;
- if(NORTH==0) {
- x-=1;
- path = map.push(x,y);
- } else if(SOUTH==0) {
- x+=1;
- path = map.push(x,y);
- } else if(WEST==0) {
- y-=1;
- path = map.push(x,y);
- } else if(EAST==0) {
- y+=1;
- path = map.push(x,y);
- } else if(map.chkExit(x,y,ExitX,ExitY)==1){
- cout << "\t>>> 走出迷宮!" << endl;
- break;
- } else { // 走到死胡同
- MAZE[x][y] = 2;
- path = map.pop(&x, &y);
- }
- }
- cout << "[列印出迷宮路徑]" << endl;
- for(int i=0; i<10; i++) {
- for(int j=0;j<12; j++)
- cout << MAZE[i][j] << " ";
- cout << endl;
- }
- }
- }
執行函式 ch04_07 結果 :
範例代碼 (java) :
執行結果 :
執行結果 :
請問你寫的* 呼叫使用演算法代碼 是另一個cpp檔嗎?
回覆刪除還是也是Map.cpp的一部份?
Check "ch04_07" which is the partial code of "main.cpp". FYI
刪除你stack好特別喔竟然用link list實作,為何不直接使用STL的stack
回覆刪除Either way will work. Just to practice how to implement the stack. ^^
刪除圖片中的東應該是MAZE[x][y+1]
回覆刪除Thanks for the feedback! You are right.
刪除