迷宮自動生成以及基於DFS的自動尋路算法


直接貼代碼

#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;

}

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM