[英]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.