进入"最大呼叫堆栈"递归函数的错误

时间:2015-05-14 06:29:52

标签: javascript recursion

我正在制作高度地图编辑器。基本上它是一个数字网格,您可以通过+/- 1更改任何位置。编辑器然后确保在任何触摸的8个图块之间只能存在1的差异。

我使用递归函数执行此操作。基本上它看着它的8个邻居并根据需要调整它们。如果有任何调整,请在所有8个邻居上调用该函数。

我在弄乱了一段时间后出现Uncaught RangeError: Maximum call stack size exceeded错误,我无法看到他们来自哪里。我正在做检查,以确保我不会尝试访问不存在的网格位置......

功能如下:

var moveDown = function (x, y) {
    var updated = false;
    if (x-1 >= 0 && Math.abs(grid[x][y] - grid[x-1][y]) > 1) {
        grid[x-1][y] -= 1;
        updated = true;
    }
    if (x-1 < size && Math.abs(grid[x][y] - grid[x+1][y]) > 1) {
        grid[x+1][y] -= 1;
        updated = true;
    }
    if (y-1 >= 0 && Math.abs(grid[x][y] - grid[x][y-1]) > 1) {
        grid[x][y-1] -= 1;
        updated = true;
    }
    if (y+1 < size && Math.abs(grid[x][y] - grid[x][y+1]) > 1) {
        grid[x][y+1] -= 1;
        updated = true;
    }
    if (x-1 >= 0 && y-1 >= 0 && Math.abs(grid[x][y] - grid[x-1][y-1]) > 1) {
        grid[x-1][y-1] -= 1;
        updated = true;
    }
    if (x-1 >= 0 && y+1 < size && Math.abs(grid[x][y] - grid[x-1][y+1]) > 1) {
        grid[x-1][y+1] -= 1;
        updated = true;
    }
    if (x+1 < size && y-1 >= 0 && Math.abs(grid[x][y] - grid[x+1][y-1]) > 1) {
        grid[x+1][y-1] -= 1;
        updated = true;
    }
    if (x+1 < size && y+1 < size && Math.abs(grid[x][y] - grid[x+1][y+1]) > 1) {
        grid[x+1][y+1] -= 1;
        updated = true;
    }

    if (updated) {
        if (x-1 >= 0) { moveDown(x-1, y); }
        if (x+1 < size) { moveDown(x+1, y); }
        if (y-1 >= 0) { moveDown(x, y-1); }
        if (y+1 < size) { moveDown(x, y+1); }
        if (x-1 >= 0 && y-1 >= 0) { moveDown(x-1, y-1); }
        if (x-1 >= 0 && y+1 < size) { moveDown(x-1, y+1); }
        if (x+1 < size && y-1 >= 0) { moveDown(x+1, y-1); }
        if (x+1 < size && y+1 < size) { moveDown(x+1, y+1); }
    }
}

我有一个小提琴here。看起来我可以内联它,所以我也这样做了。

&#13;
&#13;
var size = 15
var grid;
var active = {x: -1, y: -1};

var moveDown = function (x, y) {
    var updated = false;
    if (x-1 >= 0 && Math.abs(grid[x][y] - grid[x-1][y]) > 1) {
        grid[x-1][y] -= 1;
        updated = true;
    }
    if (x-1 < size && Math.abs(grid[x][y] - grid[x+1][y]) > 1) {
        grid[x+1][y] -= 1;
        updated = true;
    }
    if (y-1 >= 0 && Math.abs(grid[x][y] - grid[x][y-1]) > 1) {
        grid[x][y-1] -= 1;
        updated = true;
    }
    if (y+1 < size && Math.abs(grid[x][y] - grid[x][y+1]) > 1) {
        grid[x][y+1] -= 1;
        updated = true;
    }
    if (x-1 >= 0 && y-1 >= 0 && Math.abs(grid[x][y] - grid[x-1][y-1]) > 1) {
        grid[x-1][y-1] -= 1;
        updated = true;
    }
    if (x-1 >= 0 && y+1 < size && Math.abs(grid[x][y] - grid[x-1][y+1]) > 1) {
        grid[x-1][y+1] -= 1;
        updated = true;
    }
    if (x+1 < size && y-1 >= 0 && Math.abs(grid[x][y] - grid[x+1][y-1]) > 1) {
        grid[x+1][y-1] -= 1;
        updated = true;
    }
    if (x+1 < size && y+1 < size && Math.abs(grid[x][y] - grid[x+1][y+1]) > 1) {
        grid[x+1][y+1] -= 1;
        updated = true;
    }
    
    if (updated) {
        if (x-1 >= 0) { moveDown(x-1, y); }
        if (x+1 < size) { moveDown(x+1, y); }
        if (y-1 >= 0) { moveDown(x, y-1); }
        if (y+1 < size) { moveDown(x, y+1); }
        if (x-1 >= 0 && y-1 >= 0) { moveDown(x-1, y-1); }
        if (x-1 >= 0 && y+1 < size) { moveDown(x-1, y+1); }
        if (x+1 < size && y-1 >= 0) { moveDown(x+1, y-1); }
        if (x+1 < size && y+1 < size) { moveDown(x+1, y+1); }
    }
}



var moveUp = function (x, y) {
    var updated = false;
    if (x-1 >= 0 && Math.abs(grid[x][y] - grid[x-1][y]) > 1) {
        grid[x-1][y] += 1;
        updated = true;
    }
    if (x-1 < size && Math.abs(grid[x][y] - grid[x+1][y]) > 1) {
        grid[x+1][y] += 1;
        updated = true;
    }
    if (y-1 >= 0 && Math.abs(grid[x][y] - grid[x][y-1]) > 1) {
        grid[x][y-1] += 1;
        updated = true;
    }
    if (y+1 < size && Math.abs(grid[x][y] - grid[x][y+1]) > 1) {
        grid[x][y+1] += 1;
        updated = true;
    }
    if (x-1 >= 0 && y-1 >= 0 && Math.abs(grid[x][y] - grid[x-1][y-1]) > 1) {
        grid[x-1][y-1] += 1;
        updated = true;
    }
    if (x-1 >= 0 && y+1 < size && Math.abs(grid[x][y] - grid[x-1][y+1]) > 1) {
        grid[x-1][y+1] += 1;
        updated = true;
    }
    if (x+1 < size && y-1 >= 0 && Math.abs(grid[x][y] - grid[x+1][y-1]) > 1) {
        grid[x+1][y-1] += 1;
        updated = true;
    }
    if (x+1 < size && y+1 < size && Math.abs(grid[x][y] - grid[x+1][y+1]) > 1) {
        grid[x+1][y+1] += 1;
        updated = true;
    }
    
    if (updated) {
        if (x-1 >= 0) { moveUp(x-1, y); }
        if (x+1 < size) { moveUp(x+1, y); }
        if (y-1 >= 0) { moveUp(x, y-1); }
        if (y+1 < size) { moveUp(x, y+1); }
        if (x-1 >= 0 && y-1 >= 0) { moveUp(x-1, y-1); }
        if (x-1 >= 0 && y+1 < size) { moveUp(x-1, y+1); }
        if (x+1 < size && y-1 >= 0) { moveUp(x+1, y-1); }
        if (x+1 < size && y+1 < size) { moveUp(x+1, y+1); }
    }
}



var init = function () {
    $('#board').mouseleave(function () {
        active.x = -1;
        active.y = -1;
    })
    .mousemove(function () {
        active.x = -1;
        active.y = -1;
    });
    $('#reset').click(function () {
        for(var x=0; x<size; x++) {
            for(var y=0; y<size; y++) {
                grid[x][y] = 1;
            }
        }
    });
    $(window).keydown(function (e) {
        if (e.keyCode === 119 || e.keyCode === 87) {
            // W
            grid[active.x][active.y] += 1;
            moveUp(active.x, active.y);
        }
        if (e.keyCode === 115 || e.keyCode === 83) {
            // S
            grid[active.x][active.y] -= 1;
            moveDown(active.x, active.y);
        }
    });
    
    grid = [];
    for(var x=0; x<size; x++) {
        grid[x] = [];
        var row = $('<div class="row">');
        for(var y=0; y<size; y++) {
            grid[x][y] = 1;
            var cell = $('<div id="C' + x + '_' + y + '" class="cell">');
            cell.data('x', x).data('y', y);
            cell.mousemove(function (e) {
                var $this = $(this);
                active.x = $this.data('x');
                active.y = $this.data('y');
                e.stopPropagation();
            });
            row.append(cell)
        }
        $('#board').append(row);
    }
    
    setInterval(function () {
        for(var x=0; x<size; x++) {
            for(var y=0; y<size; y++) {
                $('#C' + x + '_' + y).text(grid[x][y]);
            }
        }
        $('#info').text('x: ' + active.x + ' y: ' + active.y);
    }, 100);
};
init();
&#13;
#board {
    padding: 20px;
    z-index: -1;
}

.row {
    height: 25px;
}

.cell {
    position: relative;
    display: inline-block;
    width: 25px;
    height: 25px;
    border: 1px solid black;
    text-align: center;
    line-height: 25px;
    cursor: default;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="board"></div>
<div id="info"></div>
<p>
    Click on the board once to set focus. This lets the keyboard work. Press <strong>S</strong> to make a tile go down, press <strong>W</strong> to make a tile go up.
</p>
<button id="reset">Reset</button>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

Uncaught RangeError: Maximum call stack size exceeded当递归函数没有断点时会发生此错误。当您从该功能调用任何功能或类似的功能时。然后执行然后调用函数进入堆栈并且被调用函数进入内存执行。如果在递归之前没有返回语句或条件,则处理器堆栈将变满并抛出此错误消息。

在您的情况下,您从moveDown致电moveDown,但有一个条件始终为真且有责任再次致电moveDown,或与moveUp相同

只需使用断点进行调试,您就会得到错误的地方。