【資料結構】棧實現迷宮尋路問題
阿新 • • 發佈:2019-01-05
思路:
解決迷宮求解的問題,從入口出發,順某一方向向前探索,若能走通,則繼續往前走;否則沿原路退回,換一個方向再繼續探索,直至所有可能的通路都探索到為止。為了保證在任何位置上都能沿原路退回,所以需要用一個後進先出的結構來儲存從入口到當前位置的路徑。因此,在求迷宮通路的演算法中要應用“棧”的思想假設“當前位置”指的是“在搜尋過程中的某一時刻所在圖中某個方塊位置”,則求迷宮中一條路徑的演算法的基本思想是:若當前位置“可通”,則放入“當前路徑”,並繼續朝“下一位置”探索,即切換“下一位置”為“當前位置”,如此重複直至到達出口;若當前位置“不可通”,則應順著“來向”退回到“前一通道塊”,然後朝著除“來向”之外的其他方向繼續探索;若該通道塊的四周4個方塊均“不可通”,則應從“當前路徑”上刪除該通道塊。所謂“下一位置”指的是當前位置四周4個方向(上、下、左、右)上相鄰的方塊。假設以棧Stack記錄“當前路徑”,則棧頂中存放的是“當前路徑上最後一個通道塊”。由此,“放入路徑”的操作即為“當前位置入棧”;“從當前路徑上刪除前一通道塊”的操作即為“出棧”。
程式碼塊
maze.h
測試程式碼塊:#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include <cstdlib> #include <assert.h> #include <stack> using namespace std; #define N 10 struct pos { size_t _row; size_t _col; }; stack <pos> minstack; void GetMaze(int arr[][N],int size) { FILE* f = fopen("MAP.txt", "r"); if (NULL == f){ cout << "開啟檔案失敗" << endl; exit(-1); } for (int i = 0; i < size; ++i){ for (int j = 0; j < size;){ char ch = fgetc(f); if (ch == EOF){ cout << "讀取地圖失敗" << endl; exit(-1); } if (ch == '1' || ch == '0'){ arr[i][j] = ch - '0'; ++j; } } } fclose(f); } bool CheckIsAccess(int arr[][N],pos next) { assert(arr); if((next._row>=0)&&(next._row<=N)&&(next._col>=0)&&(next._col<=N)&&arr[next._row][next._col]==0) { return true; } else { return false; } } void PrintMaze(int arr[][N],int size) { for (int i=0;i<size;i++) { for (int j=0;j<size;j++) { cout<<arr[i][j]<<" "; } cout<<endl; } cout<<endl; } bool MazePath(int arr[][N],pos entry,stack<pos>& path) { //找到通路 path.push(entry); arr[entry._row][entry._col] = 2; while (!path.empty()) { pos cur = path.top(); pos next = cur; if (cur._row == N - 1 || cur._row == 0 || cur._col == N - 1 ){ //更新最短路徑 if (minstack.empty()) minstack = path; else if (path.size() < minstack.size()){ minstack = path; path.pop(); continue; } } //上 next._row -= 1; if (CheckIsAccess(arr, next)){ path.push(next); arr[next._row][next._col] = 2; continue; } next = cur; //下 next._row += 1; if (CheckIsAccess(arr, next)){ path.push(next); arr[next._row][next._col] = 2; continue; } next = cur; //左 next._col -= 1; if (CheckIsAccess(arr, next)){ path.push(next); arr[next._row][next._col] = 2; continue; } next = cur; //右 next._col += 1; if (CheckIsAccess(arr, next)){ path.push(next); arr[next._row][next._col] = 2; continue; } path.pop(); } if (path.empty()) //判斷是否找完所有路徑 return true; return false; }
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include <cstdlib> #include <assert.h> #include "maze.h" using namespace std; #define N 10 int main(){ int mazeMap[N][N] = { 0 }; GetMaze(mazeMap, N); PrintMaze(mazeMap, N); stack<pos> path; pos entry = {2,0}; //定義迷宮入口 bool ret = MazePath(mazeMap,entry,path); if (ret){ PrintMaze(mazeMap, N); while (!minstack.empty()){ cout << "<" << minstack.top()._row << "," << minstack.top()._col << ">" << endl;; minstack.pop(); } } system("pause"); return 0; }
地圖檔案
map.txt
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 1 1 1 1 1
1 1 0 1 0 1 1 1 1 1
1 1 0 1 0 0 0 1 1 1
1 1 0 1 1 1 0 1 1 1
1 1 0 1 1 1 0 1 1 1
1 1 0 0 1 1 0 1 1 1
1 1 1 1 1 1 0 1 1 1
1 1 1 1 1 1 0 1 1 1
執行結果圖