迷宫寻路-Easyx演示

文章介绍了如何用C++编程解决迷宫问题,通过一个5x5的二维数组表示迷宫,1表示墙壁,0表示通道。主要方法是使用广度优先搜索(BFS)和深度优先搜索(DFS)来寻找从起点到终点的路径。在BFS中,使用队列存储路径,而在DFS中,使用栈进行搜索。代码示例展示了这两种方法的实现,并提供了基于Easyx库的图形化演示。
摘要由CSDN通过智能技术生成

题目:定义一个二维数组 N*M ,如 5 × 5 数组下所示:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求找出从左上角到右下角的路线。入口点为[0,0],既第一格是可以走的路。

从入口开始,检测当前位置的四个方向是否存在可行的位置P,将P放入队列中,将当前位置存储的距离加1后,替换位置P的值。接着从队列中取出下一位置。重复同样的操作,直到下一个位置是出口即可停止。

寻找最短路径则比较简单,经过的位置都存储了距离入口的距离,从出口的距离逆向寻找距离递减的路径就是最短路径。最短路径可能不止一条。

0  1  0  0  0
0  1  1  1  0
0  0  0  0  0
0  1  1  1  0
0  0  0  1  0

---------------------------------------------------------------------------------------------------------------------------------

2  1  0  11 10
3  1  1   1   9
4  5  6   7   8                        --------------------->   10 9 8 7 6 5 4 3 2
5  1  1   1   9                                                                 |
6  7  8   1 10                                                                 |

                                                                                    V
                                                          2     3       4       5      6      7       8     9      10

                                                       (0,0),(1,0),(2,0),(2,1),(2,2),(2,3),(2,4),(3,4),(4,4)

#include <iostream>
#include <queue>
#include <vector>
using namespace std;
struct Pos {
    int x;
    int y;
};

bool findRoad(vector<vector<int>>&map, vector<Pos>&road) {
    if (map.size() < 1)return false;
    int endx = map.size() - 1;
    int endy = map[0].size() - 1;
    queue<Pos> que;
    que.push({ 0,0 });
    map[0][0] = 2;
    while (!que.empty()) {
        Pos front = que.front();
        que.pop();
        int cx = front.x;
        int cy = front.y;
        if (cx == endx && cy == endy) {//当前位置位于出口,此时已经找到路径
            cx = endx;
            cy = endy;
            road.push_back({ cx,cy });
            while (!(cx == 0 && cy == 0)) {
                if (cx - 1 >= 0 && map[cx - 1][cy] == map[cx][cy] - 1) { --cx; road.push_back({ cx,cy }); }
                else if (cx + 1 < map.size() && map[cx + 1][cy] == map[cx][cy] - 1) { ++cx; road.push_back({ cx,cy }); }
                else if (cy - 1 >= 0 && map[cx][cy - 1] == map[cx][cy] - 1) { --cy; road.push_back({ cx,cy }); }
                else if (cy + 1 < map[0].size() && map[cx][cy + 1] == map[cx][cy] - 1) { ++cy; road.push_back({ cx,cy }); };
            }
            return true;
        }
        int d = map[cx][cy];
        if (cx - 1 >= 0 && map[cx - 1][cy] == 0) { que.push({ cx - 1,cy }); map[cx - 1][cy] = d + 1; }
        if (cx + 1 < map.size() && map[cx + 1][cy] == 0) { que.push({ cx + 1,cy }); map[cx + 1][cy] = d + 1; }
        if (cy - 1 >= 0 && map[cx][cy - 1] == 0) { que.push({ cx,cy - 1 }); map[cx][cy - 1] = d + 1; }
        if (cy + 1 < map[0].size() && map[cx][cy + 1] == 0) { que.push({ cx,cy + 1 }); map[cx][cy + 1] = d + 1; };
    }
    return false;
}
int main() {
    int row, col;
    cin >> row >> col;
    int pos;
    vector<vector<int>> map(row, vector<int>(col));
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < col; ++j) {
            cin >> pos;
            map[i][j] = pos;
        }
    }
    vector<Pos> road;
    findRoad(map, road);
    for (auto it = road.rbegin(); it != road.rend(); ++it) cout << "(" << it->x << "," << it->y << ")" << endl;
}

上述是广度优先的寻路算法,每走一步都要回头看一下所过之地的其他路口;而深度优先则只要还能继续走就绝不回头。下图是广度优先和深度优先不同的搜索过程。算法的核心思想几乎一致,只是区别于所有的数据结构式栈还是队列,所取得下一个节点也就分为最早放入的和刚放入的。

 下面是基于Easyx写的一个演示代码,包括迷宫的生成和寻路。为了提高出图速度,一些地方耦合度较大,看起来可能会比较跳跃。

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

struct Position {
    int i;
    int j;
    int state;
};

enum State { WALL = -1, ROAD = 0, DISABLE = -2 };

class Maze {
private:
    int width = 3;
    int height = 3;
    int size = 10;
    int color_depth = 0;
    vector<vector<int>> map;
    vector<Position> buffer;
    vector<Position> road_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 drawRoad();
    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] = WALL;
            else map[i][j] = ROAD;
            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].state == WALL) {
            setfillcolor(RGB(60,60,60));
        }
        else if (buffer[i].state == ROAD) {
            setfillcolor(WHITE);
        }
        else {
            int g = 255-int(255.0f* map[buffer[i].i][buffer[i].j] / color_depth);
            setfillcolor(RGB(0,g,0));
        }
        solidrectangle(buffer[i].i * size, buffer[i].j * size, (buffer[i].i + 1) * size, (buffer[i].j + 1) * size);
    }
    FlushBatchDraw();
}

void Maze::drawRoad() {
    BeginBatchDraw();
    for (int i = 0; i < road_buffer.size(); ++i) {
        if(i==0||i==road_buffer.size()-1) setfillcolor(BLUE);
        else setfillcolor(RED);
        solidrectangle(road_buffer[i].i * size, road_buffer[i].j * size, (road_buffer[i].i + 1) * size, (road_buffer[i].j + 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] = DISABLE;
    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] == WALL && map[cur.first - 2][cur.second] == ROAD) {
                next[num] = { -1,0 };
                ++num;
            }
            if (cur.second > 2 && map[cur.first][cur.second - 1] == WALL && map[cur.first][cur.second - 2] == ROAD) {
                next[num] = { 0,-1 };
                ++num;
            }
            if (cur.first < map.size() - 3 && map[cur.first + 1][cur.second] == WALL && map[cur.first + 2][cur.second] == ROAD) {
                next[num] = { 1,0 };
                ++num;
            }
            if (cur.second < map[0].size() - 3 && map[cur.first][cur.second + 1] == WALL && map[cur.first][cur.second + 2] == ROAD) {
                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] = DISABLE;
            map[cur.first + 2 * next[s].first][cur.second + 2 * next[s].second] = DISABLE;
            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] == DISABLE) {
                buffer[buffer_size] = { i,j ,ROAD };
                ++buffer_size;
                map[i][j] = ROAD;
            }
        }
    }
}

void Maze::BFS(int sx, int sy, int ox, int oy) {
    buffer_size = 0;
    queue<Position> next;
    next.push({ sx, sy,2});
    while (!next.empty()) {
        Position cur = next.front();
        next.pop();
        map[cur.i][cur.j] = cur.state;
        buffer[buffer_size] = { cur.i,cur.j,DISABLE };
        ++buffer_size;
        if (ox == cur.i && oy == cur.j) {
            color_depth = map[ox][oy];
            int cx = ox;
            int cy = oy;
            road_buffer.clear();
            road_buffer.push_back({ cx,cy });
            while (!(cx == sx && cy == sy)) {
                if (cx > 1 && map[cx - 1][cy] == map[cx][cy] - 1) { --cx; road_buffer.push_back({ cx,cy }); }
                else if (cx < map.size() - 2 && map[cx + 1][cy] == map[cx][cy] - 1) { ++cx; road_buffer.push_back({ cx,cy }); }
                else if (cy > 1 && map[cx][cy - 1] == map[cx][cy] - 1) { --cy; road_buffer.push_back({ cx,cy }); }
                else if (cy < map[0].size() - 2 && map[cx][cy + 1] == map[cx][cy] - 1) { ++cy; road_buffer.push_back({ cx,cy }); };
            }
            break;
        }
        if (cur.i > 1 && map[cur.i - 1][cur.j] == ROAD) {
            next.push({ cur.i - 1,cur.j ,cur.state + 1 });
        }
        if (cur.j > 1 && map[cur.i][cur.j - 1] == ROAD) {
            next.push({ cur.i,cur.j - 1 ,cur.state + 1 });
        }
        if (cur.i < map.size() - 2 && map[cur.i + 1][cur.j] == ROAD) {
            next.push({ cur.i + 1,cur.j ,cur.state + 1 });
        }
        if (cur.j < map[0].size() - 2 && map[cur.i][cur.j + 1] == ROAD) {
            next.push({ cur.i,cur.j + 1,cur.state + 1 });
        }
    }
}

void Maze::DFS(int sx, int sy, int ox, int oy) {
    buffer_size = 0;
    stack<Position> next;
    next.push({ sx, sy ,2});
    while (!next.empty()) {
        Position cur = next.top();
        next.pop();
        map[cur.i][cur.j] = cur.state;
        buffer[buffer_size] = { cur.i,cur.j,DISABLE };
        ++buffer_size;
        if (ox == cur.i && oy == cur.j) {
            color_depth = map[ox][oy];
            int cx = ox;
            int cy = oy;
            road_buffer.clear();
            road_buffer.push_back({ cx,cy });
            while (!(cx == sx && cy == sy)) {
                if (cx > 1 && map[cx - 1][cy] == map[cx][cy] - 1) { --cx; road_buffer.push_back({ cx,cy }); }
                else if (cx < map.size() - 2 && map[cx + 1][cy] == map[cx][cy] - 1) { ++cx; road_buffer.push_back({ cx,cy }); }
                else if (cy > 1 && map[cx][cy - 1] == map[cx][cy] - 1) { --cy; road_buffer.push_back({ cx,cy }); }
                else if (cy < map[0].size() - 2 && map[cx][cy + 1] == map[cx][cy] - 1) { ++cy; road_buffer.push_back({ cx,cy }); };
            }
            break;
        }
        if (cur.i > 1 && map[cur.i - 1][cur.j] == ROAD) {
            next.push({ cur.i - 1,cur.j ,cur.state + 1 });
        }
        if (cur.j > 1 && map[cur.i][cur.j - 1] == ROAD) {
            next.push({ cur.i,cur.j - 1 ,cur.state + 1 });
        }
        if (cur.i < map.size() - 2 && map[cur.i + 1][cur.j] == ROAD) {
            next.push({ cur.i + 1,cur.j ,cur.state + 1 });
        }
        if (cur.j < map[0].size() - 2 && map[cur.i][cur.j + 1] == ROAD) {
            next.push({ cur.i,cur.j + 1,cur.state + 1 });
        }
    }
}


int main()
{
    srand(unsigned int(time(0)));
    HWND hwnd = initgraph(640, 480);
    SetWindowText(hwnd, L"Maze");
    Maze maze(getwidth(), getheight(), 2);
    while (true) {
        maze.init();
        maze.draw();
        maze.create();
        maze.draw();
        system("pause");
        maze.BFS(159, 105, maze.getWidth() - 2, maze.getHeight() - 2);
        maze.draw();
        system("pause");
        maze.drawRoad();
        system("pause");
    }
    system("pause");
    closegraph();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值