簡體   English   中英

迷宮(遞歸除法)算法設計

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

遞歸除法算法的問題是牆不被視為單元格的成員。 所有的“單元格”基本上都包含空白,牆壁將放置在它們周圍。

所以當我嘗試在我的情況下實現這個算法時,我得到了這樣的結果:(黑色方塊是牆壁,白色方塊是空的,紅色方塊是入口)在此處輸入圖片說明

我的 JSFiddle 位於此處。

本質上,用戶將從紅色方塊開始,必須穿過迷宮並找到可以打開門(即紅色方塊)的鑰匙才能逃脫,因此必須可以訪問迷宮中的所有空白。

有沒有人對我如何重寫這個算法有什么想法,以確保總是有一條從紅色方塊到迷宮中任何其他空間的路徑? 理想情況下,路徑的寬度永遠不會超過一平方。

代碼:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM