#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();
}