直接貼代碼
#include<ctime> #include<conio.h> #include<iostream> #include<windows.h> #include<deque> #include<queue> #include<list> #include<vector> #include<algorithm> #include <ctime> #include <cstdlib> #include <stack> using namespace std; #define MAX 50 #define X_MAX MAX #define Y_MAX MAX int Map[X_MAX][Y_MAX]; #define MA 10 //迷宮的規模不能過小 //挖洞法造迷宮,為了包圍,只能為奇數行列,過小的地圖無法生成迷宮 #if MA<5 #undef MA #define MA 6 #endif #if !(MA%2) #define M (MA+1) #else #define M MA #endif using namespace std; //迷宮格子類型,記錄了是否被挖過 class Grid { public: //是否訪問 是否為空 bool cell, dig; int em; }; struct Node { int X, Y; bool operator==(const Node& n) { return (this->X == n.X) && (this->Y == n.Y); } }; Grid maze[M][M]; #pragma region 網上抄的一段挖洞法造迷宮,懶得自己弄 //用來存放路徑的棧 stack<int> row_s, col_s; //初始化迷宮格子 void Init() { for (int i = 0; i < M; i++) { for (int j = 0; j < M; j++) { maze[i][j].dig = false; if (i % 2 != 0 && j % 2 != 0) maze[i][j].cell = true; } } row_s.push(1); col_s.push(1); srand(static_cast<unsigned int> (time(0))); maze[1][0].cell = true; maze[M - 2][M - 1].cell = true; } //判斷周圍情況,沒有可挖的格子時返回-1 int DirRand() { vector <int> dirlist; //用來記錄可選擇的方向 int result = 0; int row = row_s.top(), col = col_s.top(); //0 up, 1 down, 2 left, 3 right if (row - 2 > 0 && !maze[row - 2][col].dig) dirlist.push_back(0); if (row + 2 < M - 1 && !maze[row + 2][col].dig) dirlist.push_back(1); if (col - 2 > 0 && !maze[row][col - 2].dig) dirlist.push_back(2); if (col + 2 < M - 1 && !maze[row][col + 2].dig) dirlist.push_back(3); if (dirlist.size() == 0) result = -1; else result = dirlist[rand() % ((int)dirlist.size())]; return result; } //制造迷宮 void GenMaze() { while (!row_s.empty() && !col_s.empty()) { int dir = DirRand(); int row = row_s.top(), col = col_s.top(); if (dir != -1) { //前進 if (dir == 0) { maze[row - 2][col].dig = maze[row - 1][col].dig = true; row_s.push(row - 2); col_s.push(col); } else if (dir == 1) { maze[row + 2][col].dig = maze[row + 1][col].dig = true; row_s.push(row + 2); col_s.push(col); } else if (dir == 2) { maze[row][col - 2].dig = maze[row][col - 1].dig = true; row_s.push(row); col_s.push(col - 2); } else if (dir == 3) { maze[row][col + 2].dig = maze[row][col + 1].dig = true; row_s.push(row); col_s.push(col + 2); } } else { row_s.pop(); col_s.pop(); //后退 } } } //輸出迷宮 void OutMaze() { //輸出迷宮 for (int i = 0; i < M; i++) { for (int j = 0; j < M; j++) { if (maze[i][j].em == 3) { printf("%2c", '*'); continue; } if (maze[i][j].cell || maze[i][j].dig) { printf("%2c", ' '); if (maze[i][j].em != 3) maze[i][j].em = true; } else { //為了保證對齊,牆壁和道路寬都是2個字符 cout << "■"; if (maze[i][j].em != 3) maze[i][j].em = false; } } cout << endl; } } //保存迷宮路徑 stack<Node> path; //已經查找的點 vector<Node> closelist; //查看該點是否查找過 返回1在 返回0不在 bool FindCloseList(Node n) { auto var = find(closelist.begin(), closelist.end(), n); return !(var == closelist.end()); } #pragma endregion //該函數可以摳出來放在自己程序,需要地圖地圖數組 起始坐標(beginX,beginY)終點坐標(endX,endY),結果保留在一個棧中 //有待優化 在迷宮有環的時候,找到的路徑不一定是最短的,問題先放在這,以后有時間再想辦法 //返回>1為找到 返回0為沒找到 int FindMaze(int beginX, int beginY, int endX, int endY) { int kbz = 1; //待查找的節點 stack<Node> lopenlist; //節點不在地圖范圍 if (beginX < 0 || beginY < 0 || beginX >= M || beginY >= M) return 0; //起始點加入尋找列表 closelist.push_back({ beginX,beginY }); //找到節點 if ((beginX == endX) && (beginY == endY)) { //將該節點添加到路徑 path.push({ beginX,beginY }); return 1; } #pragma region 查找目標節點周圍四個節點,如果要增加斜線功能,可以在此添加 //檢查(beginX,beginY+1)節點 if (beginY + 1 < M && maze[beginX][beginY + 1].em == 1) { //該節點沒找過 加入待查找節點列表 if (!FindCloseList({ beginX,beginY + 1 })) { lopenlist.push({ beginX,beginY + 1 }); } } //檢查(beginX,beginY-1)節點 if (beginY - 1 >= 0 && maze[beginX][beginY - 1].em == 1) { if (!FindCloseList({ beginX,beginY - 1 })) { lopenlist.push({ beginX,beginY - 1 }); } } //檢查(beginX-1,beginY)節點 if (beginX - 1 >= 0 && maze[beginX - 1][beginY].em == 1) { if (!FindCloseList({ beginX - 1,beginY })) { lopenlist.push({ beginX - 1,beginY }); } } //檢查(beginX+1,beginY)節點 if (beginX + 1 < M &&maze[beginX + 1][beginY].em == 1) { if (!FindCloseList({ beginX + 1,beginY })) { lopenlist.push({ beginX + 1,beginY }); } } #pragma endregion //遍歷每一個待查找的節點 while (!lopenlist.empty()) { //取出一個節點 int x = lopenlist.top().X; int y = lopenlist.top().Y; lopenlist.pop(); //遞歸查找 auto k = FindMaze(x, y, endX, endY); //找到就證明該節點為路徑點,加入路徑棧中 if (k) { path.push({ beginX,beginY }); return kbz + k; } } return 0; } int main() { //初始化 Init(); //制造迷宮 GenMaze(); //輸出迷宮 OutMaze(); //尋找路徑 if (!FindMaze(1, 0, M - 2, M - 1)) { cout << "沒找到出口"; return -1; } //依次從棧中取出每一個路徑 while (!path.empty()) { cout << "(" << path.top().X << "," << path.top().Y << ")"; maze[path.top().X][path.top().Y].em = 3; path.pop(); if (!path.empty()) cout << ","; } cout << endl; cout << "--------------------------------------------" << endl; OutMaze(); system("pause"); return 0; }