本以为Prime迷宫生成算法和图论的Prime算法有什么关联,貌似并没有。
Prime迷宫生成算法的原理:
(1)初始地图所有位置均设为墙
(2)任意插入一个墙体进墙队列
(3)判断此时墙体是否可以设置为路(判断依据在于上下左右四个位置是否只有一个位置是路)
(4)若设置为路,则将该位置周围(上下左右)的所有墙插入队列,接着执行(5);若无法设置为路,直接执行(5)
(5)从墙队列中删去当前位置所在节点
(6)若墙队列不为空,则从队列中随机选取一面墙重新执行(3),直到墙队列为空
看代码,非常简单:
static const int L = 44;
void CreateMaze() {
int Maze[L][L] = { 0 };
//最外围设置为路,可以有效的保护里面一层墙体,并防止挖出界
for (int i = 0; i < L; i++) {
Maze[i][0] = 1;
Maze[0][i] = 1;
Maze[L - 1][i] = 1;
Maze[i][L - 1] = 1;
}
//墙队列,包括X , Y
vector<int> X;
vector<int> Y;
//任取初始值
X.push_back(2);
Y.push_back(2);
//当墙队列为空时结束循环
while (X.size()) {
//在墙队列中随机取一点
int r = rand() % X.size();
int x = X[r];
int y = Y[r];
//判读上下左右四个方向是否为路
int count = 0;
for (int i = x - 1; i < x + 2; i++) {
for (int j = y - 1; j < y + 2; j++) {
if (abs(x - i) + abs(y - j) == 1 && Maze[i][j] > 0) {
++count;
}
}
}
if (count <= 1) {
Maze[x][y] = 1;
//在墙队列中插入新的墙
for (int i = x - 1; i < x + 2; i++) {
for (int j = y - 1; j < y + 2; j++) {
if (abs(x - i) + abs(y - j) == 1 && Maze[i][j] == 0) {
X.push_back(i);
Y.push_back(j);
}
}
}
}
//删除当前墙
X.erase(X.begin() + r);
Y.erase(Y.begin() + r);
}
//设置迷宫进出口
Maze[2][1] = 1;
for (int i = L - 3; i >= 0; i--) {
if (Maze[i][L - 3] == 1) {
Maze[i][L - 2] = 1;
break;
}
}
//画迷宫
for (int i = 0; i < L; i++){
for (int j = 0; j < L; j++) {
if (Maze[i][j] == 1) printf(" ");
else printf("国");
}
printf("\n");
}
}
代码要简单不少,但是个人觉得效果还不如深度优先迷宫算法,但是不得不承认prime迷宫赛诺菲生成的迷宫更让人眼花缭乱。
附:
一、回答 abs(x - i) + abs(y - j) == 1 看不懂的问题。
已知此时所在位置(x,y),我需要通过上下左右四个方向所在位置的状态来判断是否需要打通(x,y)位置的墙壁。
上下左右意味着(x-1,y);(x+1,y);(x,y-1);(x,y+1),意味着 abs(x - i) + abs(y - j) == 1。