C++迷宫生成和BFS/DFS寻路

#include <iostream>
#include<graphics.h>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define W 801
#define S 801
#define X 1
struct point {
    int x, y;
};
void initMap(vector<vector<int>> &map) {
    if (map.size() > 0) {
        for (int i = 0; i < W; i++) {
            for (int j = 0; j < W; j++) {
                if (i % 2 == 0 || j % 2 == 0) map[i][j]=1;
                else map[i][j]=0;
            }
        }
    }
    for (int i = 0; i < W; i++) {
        map.push_back(vector<int>());
        for (int j = 0; j < W; j++) {
            if (i % 2 == 0 || j % 2 == 0) map[i].push_back(1);
            else map[i].push_back(0);
        }
    }
}
void displayMap(vector<vector<int>>& map) {
    for (int i = 0; i < W; i++) {
        map.push_back(vector<int>());
        for (int j = 0; j < W; j++) {
            if (map[i][j] == -1) setfillcolor(WHITE);
            else setfillcolor(BLACK);
            if(map[i][j]==-2)setfillcolor(RGB(0, 255, 0));
            solidrectangle(j * X, i * X, j * X + X, i * X + X);
        }
    }
}

void maze(vector<vector<int>>& map, int x, int y) {
    map[x][y] = -1;
    int dir[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };
    point p = { x,y };
    stack<point> s;
    s.push(p);
    while (!s.empty()) {
        p = s.top();
        s.pop();
        x = p.x;
        y = p.y;
        while (1) {
            bool end = true;
            for (int i = 0; i < 3; i++) {
                end = true;
                int seed;
                vector<int>temp;
                if (y + 2 < W && map[x][y + 2] == 0) temp.push_back(0);
                if (y - 2 > 0 && map[x][y - 2] == 0)temp.push_back(1);
                if (x + 2 < W && map[x + 2][y] == 0)temp.push_back(2);
                if (x - 2 > 0 && map[x - 2][y] == 0)temp.push_back(3);
                if (temp.size() > 0) {
                    seed = temp[rand() % temp.size()];
                }
                else break;
                int dx = dir[seed][0];
                int dy = dir[seed][1];
                int nx = x + 2 * dx;
                int ny = y + 2 * dy;
                if (nx > 0 && ny > 0 && nx < W && ny < W) {
                    if (map[nx][ny] != -1)
                    {
                        end = false;
                        x = nx;
                        y = ny;
                        map[x][y] = -1;
                        map[x - dx][y - dy] = -1;
                        p = { nx,ny };
                        s.push(p);
                        break;
                    }
                }
            }
            //  displayMap(map);
            if (end) break;
        }
    }
}

void findRoad(vector<vector<int>>& map, int sx, int sy, int ox, int oy) {
    map[sx][sy] = -2;
    int dir[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };
    point p = { sx,sy };
    stack<point> s;
    s.push(p);
    s.push(p);
    while (!s.empty()) {
        p = s.top();
        s.pop();
        sx = p.x;
        sy = p.y;
        while (true) {
            bool end = false;
            for (int i = 0; i < 3; i++) {
                vector<int>temp;
                int seed;
                if (sy + 1 < W && map[sx][sy + 1] == -1) temp.push_back(0);
                if (sy - 1 > 0 && map[sx][sy - 1] ==-1)temp.push_back(1);
                if (sx + 1 < W && map[sx + 1][sy] == -1)temp.push_back(2);
                if (sx - 1 > 0 && map[sx - 1][sy] ==-1)temp.push_back(3);
                if (temp.size() > 0) {
                    seed = temp[rand() % temp.size()];
                }else break;
                int dx = dir[seed][0];
                int dy = dir[seed][1];
                int nx = sx + dx;
                int ny = sy + dy;
                if (nx > 0 && ny > 0 && nx < W && ny < W) {
                    if (map[nx][ny] == -1)
                    {
                        end = true;
                        sx = nx;
                        sy = ny;
                        map[sx][sy] = -2;
                        setfillcolor(RGB(0,255,0));
                        solidrectangle(sy * X, sx * X, sy * X + X, sx * X + X);
                        //Sleep(100) 减缓寻路过程,其他对应地方也可以通过此方法延长运行时间。
                        if (sx == ox && sy == oy) return;
                        p = { nx,ny };
                        s.push(p);
                        break;
                    }
                }
            }
            if (!end) break;
        }
    }
}

int main()
{
    vector<vector<int>> map;
    srand(unsigned int(time(0)));
    //#include<graphics.h> 需要安装Easyx的图形库,方便查看地图的生成过程
    initgraph(S, S);
    setbkcolor(WHITE);
    srand(unsigned int(time(0)));
    cleardevice();
    while (1) {
        initMap(map);
        int a = rand() % (W - 2);
        int b = rand() % (W - 2);
        if (a % 2 == 0) a += 1;
        if (b % 2 == 0) b += 1;
        maze(map, a, b);
        displayMap(map);
        findRoad(map, 1, 1, W - 2, W - 2);
        displayMap(map);
        Sleep(1000);
    }
    system("pause");
    closegraph();
}

        这是第二次写这个函数,显然比上一次熟练多了。但是由于学习原因,没有进行优化,问题还是很多很多。假期再继续使用其他方法来实现,优化生成的速度。之前看过一个博主的视频,感觉迷宫的运用还是有很多的潜力,探索过程蛮有趣的。

以下是实际效果

        2023.8.19:单独的空间存放变化的单元格,减少重绘时间。用滑动窗口来处理创建迷宫时下一节点的选择问题,减少较长直通道的出现。

#include <iostream>
#include<graphics.h>
#include<vector>
#include<queue>
#include<stack>
using namespace std;

class Maze {
private:
    int width = 3;
    int height = 3;
    int size = 10;
    vector<vector<int>> map;
    vector<pair<pair<int, int>, int>> buffer;
    int buffer_size = 0;
    vector<pair<int, int>> sliding_queue;
    int sliding_queue_begin = 0;
    int sliding_queue_end = 0;

public:
    Maze(int _width, int _height, int _size);
    ~Maze() = default;
    int getWidth();
    int getHeight();
    void init();
    void create();
    void draw();
    void BFS(int sx, int sy, int ox, int oy);
    void DFS(int sx, int sy, int ox, int oy);
};

Maze::Maze(int _width, int _height,int _size) :width(_width), height(_height),size(_size) {
    width /= size;
    height /= size;
    if (width % 2 == 0) width -= 1;
    if (height % 2 == 0) height -= 1;
    map.resize(width, vector<int>(height));
    buffer.resize(width * height);
    sliding_queue.resize((width - 1) * (height - 1) / 4);
}

int Maze::getWidth()
{
    return this->width;
}

int Maze::getHeight()
{
    return this->height;
}

void Maze::init() {
    buffer_size = 0;
    for (int i = 0; i < map.size(); ++i) {
        for (int j = 0; j < map[i].size(); ++j) {
            if (i % 2 == 0 || j % 2 == 0) map[i][j] = 0;
            else map[i][j] = 1;
            buffer[buffer_size] = { {i,j},map[i][j] };
            ++buffer_size;
        }
    }
}

void Maze::draw() {
    BeginBatchDraw();
    for (int i = 0; i < buffer_size; ++i) {
        if (buffer[i].second == 0) {
            setfillcolor(RED);
        }
        else if (buffer[i].second == 1) {
            setfillcolor(GREEN);
        }
        else {
            setfillcolor(BLUE);
        }
        solidrectangle(buffer[i].first.first * size, buffer[i].first.second * size, (buffer[i].first.first + 1) * size, (buffer[i].first.second + 1) * size);
    }
    FlushBatchDraw();
}

void Maze::create() {
    buffer_size = 0;
    sliding_queue_begin = 0;
    sliding_queue_end = 1;
    sliding_queue[0] = { 1,1 };
    map[1][1] = -1;
    vector<pair<int, int>> next(4);
    int num = 0;
    while (sliding_queue_begin < sliding_queue_end) {
        int s0 = sliding_queue_begin + rand() % (sliding_queue_end - sliding_queue_begin);
        pair<int, int> cur = sliding_queue[s0];
        if (sliding_queue_begin + 1 < sliding_queue_end) {
            sliding_queue[s0] = sliding_queue[sliding_queue_begin + 1];
            sliding_queue[sliding_queue_begin + 1] = cur;
        }
        ++sliding_queue_begin;
        while (true) {
            if (cur.first > 2 && map[cur.first - 1][cur.second] == 0 && map[cur.first - 2][cur.second] == 1) {
                next[num] = { -1,0 };
                ++num;
            }
            if (cur.second > 2 && map[cur.first][cur.second - 1] == 0 && map[cur.first][cur.second - 2] == 1) {
                next[num] = { 0,-1 };
                ++num;
            }
            if (cur.first < map.size() - 3 && map[cur.first + 1][cur.second] == 0 && map[cur.first + 2][cur.second] == 1) {
                next[num] = { 1,0 };
                ++num;
            }
            if (cur.second < map[0].size() - 3 && map[cur.first][cur.second + 1] == 0 && map[cur.first][cur.second + 2] == 1) {
                next[num] = { 0,1 };
                ++num;
            }
            if (num < 1) break;
            int s = rand() % num;
            num = 0;
            map[cur.first + next[s].first][cur.second + next[s].second] = -1;
            map[cur.first + 2 * next[s].first][cur.second + 2 * next[s].second] = -1;
            cur = { cur.first + 2 * next[s].first,cur.second + 2 * next[s].second };
            sliding_queue[sliding_queue_end] = { cur.first,cur.second };
            ++sliding_queue_end;
        }
    }
    for (int i = 0; i < map.size(); ++i) {
        for (int j = 0; j < map[i].size(); ++j) {
            if (map[i][j] == -1) {
                buffer[buffer_size] = { {i,j} ,1 };
                ++buffer_size;
                map[i][j] = 1;
            }
        }
    }
}

void Maze::BFS(int sx, int sy, int ox, int oy) {
    buffer_size = 0;
    queue<pair<int, int>> next;
    next.push({ sx, sy});
    while (!next.empty()) {
        pair<int, int> cur = next.front();
        map[cur.first][cur.second] = -1;
        buffer[buffer_size]={{cur.first,cur.second},-1};
        ++buffer_size;
        if (ox == cur.first && oy == cur.second) break;
        next.pop();
        if (cur.first > 1 && map[cur.first - 1][cur.second] == 1) {
            next.push({ cur.first - 1,cur.second });
        }
        if (cur.second > 1 && map[cur.first][cur.second - 1] == 1 ) {
            next.push({ cur.first,cur.second - 1 });
        }
        if (cur.first < map.size() - 2 && map[cur.first + 1][cur.second] == 1 ) {
            next.push({ cur.first + 1,cur.second });
        }
        if (cur.second < map[0].size() - 2 && map[cur.first][cur.second + 1] == 1) {
            next.push({ cur.first,cur.second + 1 });
        }
    }
}

void Maze::DFS(int sx, int sy, int ox, int oy) {
    buffer_size = 0;
    stack<pair<int, int>> next;
    next.push({ sx, sy });
    while (!next.empty()) {
        pair<int, int> cur = next.top();
        map[cur.first][cur.second] = -1;
        buffer[buffer_size] = {{cur.first,cur.second},-1};
        ++buffer_size;
        if (ox == cur.first && oy == cur.second) break;
        next.pop();
        if (cur.first > 1 && map[cur.first - 1][cur.second] == 1) {
            next.push({ cur.first - 1,cur.second });
        }
        if (cur.second > 1 && map[cur.first][cur.second - 1] == 1) {
            next.push({ cur.first,cur.second - 1 });
        }
        if (cur.first < map.size() - 2 && map[cur.first + 1][cur.second] == 1) {
            next.push({ cur.first + 1,cur.second });
        }
        if (cur.second < map[0].size() - 2 && map[cur.first][cur.second + 1] == 1) {
            next.push({ cur.first,cur.second + 1 });
        }
    }
}

int main()
{
    srand(unsigned int(time(0)));
    initgraph(640, 480);
    Maze maze(getwidth(), getheight(), 4);
    while (true) {
        maze.init();
        maze.draw();
        maze.create();
        system("pause");
        maze.draw();
        maze.DFS(1, 1, maze.getWidth()-2, maze.getHeight()-2);
        maze.draw();
        system("pause");
    }
    system("pause");
    closegraph();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值