[英]Maze (recursive division) algorithm design
我目前正在开发一个随机迷宫生成器,它将迷宫存储在一个名为grid
的二维数组中。 稍后将使用它来生成一个真正的 3D 迷宫,然后用户可以穿过它。
在做了一些研究之后,我尝试使用递归除法算法创建这个迷宫生成器,但是由于迷宫格式的性质,这对我来说并不真正有效。
据我了解,递归分割方法不会将墙壁视为细胞。
例如,我的网格看起来像这样:
a b c d e f g h
1 - - - - - - - -
2 | | | | |
3 | | |
4 | - - | - |
5 | | | |
6 | - | - |
7 x |
8 - - - - - - - -
我试图在这里说明的一点是,我试图创建的网格将表示如下:
w w w w w w w w
w w w w w
w w w
w w w w w w
w w w w
w w w w w
g w
w w w w w w w w
其中“w”是一堵墙,“g”是入口/出口。 所以墙壁被放置到网格中,例如grid[1][2] == 'w'
递归除法算法的问题是墙不被视为单元格的成员。 所有的“单元格”基本上都包含空白,墙壁将放置在它们周围。
所以当我尝试在我的情况下实现这个算法时,我得到了这样的结果:(黑色方块是墙壁,白色方块是空的,红色方块是入口)
本质上,用户将从红色方块开始,必须穿过迷宫并找到可以打开门(即红色方块)的钥匙才能逃脱,因此必须可以访问迷宫中的所有空白。
有没有人对我如何重写这个算法有什么想法,以确保总是有一条从红色方块到迷宫中任何其他空间的路径? 理想情况下,路径的宽度永远不会超过一平方。
var grid;
function generate(dimensions, numDoors) {
//numDoors is unused right now
grid = new Array();
for (var i = 0; i < dimensions; i++) {
grid[i] = new Array();
for (var j = 0; j < dimensions; j++) {
grid[i][j] = "";
}
}
addOuterWalls();
var ent = addEntrance();
addInnerWalls(true, 1, grid.length - 2, 1, grid.length - 2, ent);
}
function addOuterWalls() {
for (var i = 0; i < grid.length; i++) {
if (i == 0 || i == (grid.length - 1)) {
for (var j = 0; j < grid.length; j++) {
grid[i][j] = "w";
}
} else {
grid[i][0] = "w";
grid[i][grid.length - 1] = "w";
}
}
}
function addEntrance() {
var x = randomNumber(1, grid.length - 1);
grid[grid.length - 1][x] = "g";
return x;
}
function addInnerWalls(h, minX, maxX, minY, maxY, gate) {
if (h) {
if (maxX - minX < 2) {
return;
}
var y = randomNumber(minY, maxY);
addHWall(minX, maxX, y);
addInnerWalls(!h, minX, maxX, minY, y-1, gate);
addInnerWalls(!h, minX, maxX, y + 1, maxY, gate);
} else {
if (maxY - minY < 2) {
return;
}
var x = randomNumber(minX, maxX);
addVWall(minY, maxY, x);
addInnerWalls(!h, minX, x-1, minY, maxY, gate);
addInnerWalls(!h, x + 1, maxX, minY, maxY, gate);
}
}
function addHWall(minX, maxX, y) {
var hole = randomNumber(minX, maxX);
for (var i = minX; i <= maxX; i++) {
if (i == hole) grid[y][i] = "";
else grid[y][i] = "w";
}
}
function addVWall(minY, maxY, x) {
var hole = randomNumber(minY, maxY);
for (var i = minY; i <= maxY; i++) {
if (i == hole) grid[i][x] = "";
else grid[i][x] = "w";
}
}
function randomNumber(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function display() {
document.getElementById("cnt").innerHTML = "";
for (var i = 0; i < grid.length; i++) {
var output = "<div>";
for (var j = 0; j < grid.length; j++) {
output += "<b " + grid[i][j] + "></b>";
}
output += "</div>";
document.getElementById("cnt").innerHTML += output;
}
}
generate(30, 1, 1);
display();
只在偶数单元格中放置墙壁,在奇数单元格中放置门,并使“尺寸”为奇数。 http://jsfiddle.net/tPm3s/1/
Code:
var grid;
function generate(dimensions, numDoors) {
grid = new Array();
for (var i = 0; i < dimensions; i++) {
grid[i] = new Array();
for (var j = 0; j < dimensions; j++) {
grid[i][j] = "";
}
}
addOuterWalls();
var ent = addEntrance();
addInnerWalls(true, 1, grid.length - 2, 1, grid.length - 2, ent);
}
function addOuterWalls() {
for (var i = 0; i < grid.length; i++) {
if (i == 0 || i == (grid.length - 1)) {
for (var j = 0; j < grid.length; j++) {
grid[i][j] = "w";
}
} else {
grid[i][0] = "w";
grid[i][grid.length - 1] = "w";
}
}
}
function addEntrance() {
var x = randomNumber(1, grid.length - 1);
grid[grid.length - 1][x] = "g";
return x;
}
function addInnerWalls(h, minX, maxX, minY, maxY, gate) {
if (h) {
if (maxX - minX < 2) {
return;
}
var y = Math.floor(randomNumber(minY, maxY)/2)*2;
addHWall(minX, maxX, y);
addInnerWalls(!h, minX, maxX, minY, y-1, gate);
addInnerWalls(!h, minX, maxX, y + 1, maxY, gate);
} else {
if (maxY - minY < 2) {
return;
}
var x = Math.floor(randomNumber(minX, maxX)/2)*2;
addVWall(minY, maxY, x);
addInnerWalls(!h, minX, x-1, minY, maxY, gate);
addInnerWalls(!h, x + 1, maxX, minY, maxY, gate);
}
}
function addHWall(minX, maxX, y) {
var hole = Math.floor(randomNumber(minX, maxX)/2)*2+1;
for (var i = minX; i <= maxX; i++) {
if (i == hole) grid[y][i] = "";
else grid[y][i] = "w";
}
}
function addVWall(minY, maxY, x) {
var hole = Math.floor(randomNumber(minY, maxY)/2)*2+1;
for (var i = minY; i <= maxY; i++) {
if (i == hole) grid[i][x] = "";
else grid[i][x] = "w";
}
}
function randomNumber(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function display() {
document.getElementById("cnt").innerHTML = "";
for (var i = 0; i < grid.length; i++) {
var output = "<div>";
for (var j = 0; j < grid.length; j++) {
output += "<b " + grid[i][j] + "></b>";
}
output += "</div>";
document.getElementById("cnt").innerHTML += output;
}
}
generate(31, 1, 1);
display();
我对JavaScript的了解不多(最好是Python),但是我认为您应该使用深度优先搜索算法。 首先会生成一个单元格网格,每个单元格对应一个列表。 它从左上角开始,并随机选择一个未访问的相邻单元格并擦除墙。 它会一直这样做,直到陷入死胡同为止;如果是这样,它将回溯被访问的单元,并在其中一个单元有未访问的相邻单元进入时停止。 重复这些步骤,直到迷宫中的所有单元都已被访问,并且迷宫完成。 如果要解决迷宫问题,请添加一个存储墙信息的数组。 另外,您可以在此迷宫中选择任意2个点,并且只有一条路径可以连接它们。 希望这会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.