3层迷宫(内容由ai生成,注意辨别)
2026-08-01 15:02:54
发布于:广东
生成地图的算法:深度优先搜索(DFS)
生成原理(逐层)(由AI辅助生成,仅供参考,请自行辨别):
-
全墙初始化:每层地图先全部填满墙体
#。 -
DFS挖路:从起点
(1,1)开始,以步长2(跳跃式)随机访问相邻的奇数坐标格。- 每打通两个奇数格之间的偶数格墙体,形成通道。
- 递归进行,直到所有联通的奇数格都被访问,生成完美迷宫(任意两点间仅一条路径)。
-
结构设计:
- 楼层间用楼梯(
<>)连接,楼梯位置跨层对齐(上层终点 = 下层起点)。 - 使用 BFS 确保终点距离足够远,并在路径上放置钥匙(K)和门(D),保证钥匙在门前。
- 楼层间用楼梯(
-
游戏逻辑:
- 玩家(
@)通过 WASD 移动,拾取钥匙(keys++),消耗钥匙开门(keys--)。 - 通过楼梯切换楼层,最终抵达第3层的出口(
E)获胜。
- 玩家(
总结:用 DFS 生成各层单连通迷宫,BFS 规划路径并放置逻辑元素,实现跨层探索的解谜游戏。
这是代码:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <queue>
#include <algorithm>
#include <conio.h>
#include <windows.h>
using namespace std;
/* 三维迷宫参数 */
const int LAYERS = 3; // 层数
const int H = 17; // 高度(奇数)
const int W = 33; // 宽度(奇数)
char maze[LAYERS][H][W]; // 地图,字符含义见下
int playerX, playerY, playerZ; // 玩家位置 (x列, y行, z层)
int keys = 0; // 已持有钥匙数
/* 字符说明:
* '#' 墙/障碍物
* ' ' 路
* 'K' 钥匙
* 'D' 门(需钥匙才能通过)
* 'E' 出口(仅第3层)
* '>' 下行楼梯(通向下一层)
* '<' 上行楼梯(通向上一层)
* '@' 玩家(动态显示)
*/
struct Point {
int x, y;
Point() {}
Point(int a, int b) : x(a), y(b) {}
};
// 四个方向:上,右,下,左
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {-1, 0, 1, 0};
// 随机打乱方向,用于迷宫生成
void shuffleDir(int dirs[]) {
for (int i = 0; i < 4; ++i) dirs[i] = i;
for (int i = 0; i < 4; ++i) {
int j = rand() % 4;
swap(dirs[i], dirs[j]);
}
}
/* 递归深度优先生成迷宫 (从已设为路的起点开始) */
void dfsMaze(int z, int x, int y) {
int dirs[4];
shuffleDir(dirs);
for (int i = 0; i < 4; ++i) {
int nx = x + dx[dirs[i]] * 2;
int ny = y + dy[dirs[i]] * 2;
if (nx > 0 && nx < W - 1 && ny > 0 && ny < H - 1 && maze[z][ny][nx] == '#') {
// 打通中间墙
maze[z][y + dy[dirs[i]]][x + dx[dirs[i]]] = ' ';
maze[z][ny][nx] = ' ';
dfsMaze(z, nx, ny);
}
}
}
/* 生成一层的迷宫,全墙,从 (sx, sy) 开始挖路 */
void generateLayer(int z, int sx, int sy) {
for (int i = 0; i < H; ++i)
for (int j = 0; j < W; ++j)
maze[z][i][j] = '#';
maze[z][sy][sx] = ' ';
dfsMaze(z, sx, sy);
}
/* BFS 寻路,返回从 (sx,sy) 到 (ex,ey) 的路径坐标(含起止点) */
vector<Point> bfsPath(int z, int sx, int sy, int ex, int ey) {
vector<vector<bool> > visited(H, vector<bool>(W, false));
vector<vector<Point> > prev(H, vector<Point>(W, Point(-1, -1)));
queue<Point> q;
q.push(Point(sx, sy));
visited[sy][sx] = true;
while (!q.empty()) {
Point p = q.front(); q.pop();
if (p.x == ex && p.y == ey) break;
for (int i = 0; i < 4; ++i) {
int nx = p.x + dx[i];
int ny = p.y + dy[i];
if (nx >= 0 && nx < W && ny >= 0 && ny < H && !visited[ny][nx] && maze[z][ny][nx] != '#') {
visited[ny][nx] = true;
prev[ny][nx] = p;
q.push(Point(nx, ny));
}
}
}
vector<Point> path;
if (!visited[ey][ex]) return path; // 无路径
for (Point p = Point(ex, ey); p.x != -1; p = prev[p.y][p.x])
path.push_back(p);
reverse(path.begin(), path.end());
return path;
}
/* 在指定起点-终点路径上放置钥匙 K 和门 D(保证钥匙在门前) */
void placeKeyDoor(int z, Point start, Point end) {
vector<Point> path = bfsPath(z, start.x, start.y, end.x, end.y);
if (path.size() < 4) return; // 路径过短则放弃(实际不会发生)
// 钥匙位置:索引 [1, size-3];门位置:索引 [钥匙+1, size-2]
int keyIdx = rand() % (path.size() - 3) + 1;
int doorIdx = keyIdx + 1 + rand() % (path.size() - keyIdx - 2);
Point keyPos = path[keyIdx];
Point doorPos = path[doorIdx];
maze[z][keyPos.y][keyPos.x] = 'K';
maze[z][doorPos.y][doorPos.x] = 'D';
}
/* 从起点出发,在奇数坐标通路中选取一个距离 >= minDist 的点作为本层终点 */
Point selectEnd(int z, Point start, int minDist) {
// 先用 BFS 算距离
vector<vector<int> > dist(H, vector<int>(W, -1));
queue<Point> q;
q.push(start);
dist[start.y][start.x] = 0;
while (!q.empty()) {
Point p = q.front(); q.pop();
for (int i = 0; i < 4; ++i) {
int nx = p.x + dx[i];
int ny = p.y + dy[i];
if (nx >= 0 && nx < W && ny >= 0 && ny < H && maze[z][ny][nx] == ' ' && dist[ny][nx] == -1) {
dist[ny][nx] = dist[p.y][p.x] + 1;
q.push(Point(nx, ny));
}
}
}
// 收集奇数坐标的路格,要求距离 >= minDist
vector<Point> candidates;
for (int y = 0; y < H; ++y)
for (int x = 0; x < W; ++x)
if (maze[z][y][x] == ' ' && (x % 2 == 1) && (y % 2 == 1) &&
!(x == start.x && y == start.y) && dist[y][x] >= minDist)
candidates.push_back(Point(x, y));
// 若无满足条件的,退而求所有奇数路格(距离 >= 3 防止路径过短)
if (candidates.empty()) {
for (int y = 0; y < H; ++y)
for (int x = 0; x < W; ++x)
if (maze[z][y][x] == ' ' && (x % 2 == 1) && (y % 2 == 1) &&
!(x == start.x && y == start.y) && dist[y][x] >= 3)
candidates.push_back(Point(x, y));
}
// 仍无(极小概率),强制选距离最大的奇数路格
if (candidates.empty()) {
int maxDist = -1;
Point best = start;
for (int y = 0; y < H; ++y)
for (int x = 0; x < W; ++x)
if (maze[z][y][x] == ' ' && (x % 2 == 1) && (y % 2 == 1) &&
!(x == start.x && y == start.y) && dist[y][x] > maxDist) {
maxDist = dist[y][x];
best = Point(x, y);
}
return best;
}
return candidates[rand() % candidates.size()];
}
/* 生成全部三层,并保证每层从入口到出口有可行路径,且钥匙/门放置合理 */
void generateAll() {
srand(time(0));
const int MIN_DIST = 6; // 要求终点的路径长度至少为 7
// ------------- 第 1 层 -------------
Point start1(1, 1);
generateLayer(0, start1.x, start1.y);
Point end1 = selectEnd(0, start1, MIN_DIST);
maze[0][end1.y][end1.x] = '>'; // 下行楼梯
// 检验路径长度
while (bfsPath(0, start1.x, start1.y, end1.x, end1.y).size() < 4) {
generateLayer(0, start1.x, start1.y);
end1 = selectEnd(0, start1, MIN_DIST);
maze[0][end1.y][end1.x] = '>';
}
placeKeyDoor(0, start1, end1);
// ------------- 第 2 层 -------------
Point start2 = end1; // 与上层楼梯对齐
generateLayer(1, start2.x, start2.y);
maze[1][start2.y][start2.x] = '<'; // 上行楼梯
Point end2 = selectEnd(1, start2, MIN_DIST);
maze[1][end2.y][end2.x] = '>';
while (bfsPath(1, start2.x, start2.y, end2.x, end2.y).size() < 4) {
generateLayer(1, start2.x, start2.y);
maze[1][start2.y][start2.x] = '<';
end2 = selectEnd(1, start2, MIN_DIST);
maze[1][end2.y][end2.x] = '>';
}
placeKeyDoor(1, start2, end2);
// ------------- 第 3 层 -------------
Point start3 = end2;
generateLayer(2, start3.x, start3.y);
maze[2][start3.y][start3.x] = '<';
Point end3 = selectEnd(2, start3, MIN_DIST);
maze[2][end3.y][end3.x] = 'E'; // 出口
while (bfsPath(2, start3.x, start3.y, end3.x, end3.y).size() < 4) {
generateLayer(2, start3.x, start3.y);
maze[2][start3.y][start3.x] = '<';
end3 = selectEnd(2, start3, MIN_DIST);
maze[2][end3.y][end3.x] = 'E';
}
placeKeyDoor(2, start3, end3);
// 玩家初始位置
playerX = 1;
playerY = 1;
playerZ = 0;
keys = 0;
}
/* 绘制当前层 */
void draw() {
system("cls");
cout << "楼层 " << playerZ + 1 << " 钥匙数: " << keys << endl;
for (int y = 0; y < H; ++y) {
for (int x = 0; x < W; ++x) {
if (x == playerX && y == playerY)
cout << '@';
else
cout << maze[playerZ][y][x];
}
cout << endl;
}
cout << "WASD: 移动 | <: 下楼(要按q键) | >: 上楼 (要按e键) | K :钥匙(可以开门), D(门), 走到3楼的e(出口)就赢了";
}
/* 主游戏循环 */
int main() {
generateAll();
while (true) {
draw();
char ch = getch();
// 上楼
if (ch == 'q' || ch == 'Q') {
if (maze[playerZ][playerY][playerX] == '<' && playerZ > 0) {
playerZ--;
}
}
// 下楼
else if (ch == 'e' || ch == 'E') {
if (maze[playerZ][playerY][playerX] == '>' && playerZ < LAYERS - 1) {
playerZ++;
}
}
// 移动
else {
int nx = playerX, ny = playerY;
if (ch == 'w' || ch == 'W') ny--;
else if (ch == 's' || ch == 'S') ny++;
else if (ch == 'a' || ch == 'A') nx--;
else if (ch == 'd' || ch == 'D') nx++;
else continue;
if (nx < 0 || nx >= W || ny < 0 || ny >= H) continue;
char target = maze[playerZ][ny][nx];
if (target == '#') continue; // 墙
if (target == 'D') { // 门
if (keys > 0) {
keys--;
maze[playerZ][ny][nx] = ' ';
playerX = nx; playerY = ny;
}
}
else if (target == 'K') { // 钥匙
keys++;
maze[playerZ][ny][nx] = ' ';
playerX = nx; playerY = ny;
}
else if (target == 'E') { // 出口
if (playerZ == LAYERS - 1) {
system("cls");
cout << "Congratulations! You reached the exit!\n";
return 0;
} else {
playerX = nx; playerY = ny;
}
}
else { // 空地或楼梯
playerX = nx; playerY = ny;
}
}
}
return 0;
}
全部评论 1
2026-08-04 来自 广东
0发在灌水
2026-08-04 来自 广东
0















有帮助,赞一个