【问题标题】:Maze (recursive division) algorithm design迷宫(递归除法)算法设计
【发布时间】:2014-06-25 04:41:03
【问题描述】:

我目前正在开发一个随机迷宫生成器,它将迷宫存储在一个名为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'

递归除法算法的问题是墙不被视为单元的成员。所有的“单元”基本上都包含空白,并且墙壁将被放置在它们周围。

所以当我尝试在我的情况下实现这个算法时,我最终得到了这样的结果:(黑色方块是墙壁,白色方块是空的,红色方块是入口)

My JSFiddle is located here.

基本上,用户将从红色方块开始,必须穿过迷宫并找到可以打开门(即红色方块)的钥匙才能逃脱,因此迷宫中的所有空白都必须可以访问.

有人对我如何重写此算法以确保始终有一条从红色方块到迷宫中任何其他空间的路径有任何想法吗?理想情况下,路径的宽度永远不会超过一平方。

代码:

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();

【问题讨论】:

    标签: javascript algorithm recursion


    【解决方案1】:

    只在偶数的牢房中放置墙壁,在奇数的牢房中放置门,并使“尺寸”变得奇数。 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();
    

    【讨论】:

    • 这太完美了!那么你改变了什么?
    • 在 addInnerWalls 中参见 Math.floor(randomNumber(minY, maxY)/2)*2;和 var x = Math.floor(randomNumber(minX, maxX)/2)*2;,在 addHWall 见 var hole = Math.floor(randomNumber(minY, maxY)/2)*2+1;,在 addVWall var hole = Math.floor(randomNumber(minY, maxY)/2)*2+1;
    • 哇,原来是我的随机数不对? :P 谢谢!
    猜你喜欢
    • 2020-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多