Javascript JS:给定二维数组中的一个点和一个距离,哪些坐标是可移动的?

Javascript JS:给定二维数组中的一个点和一个距离,哪些坐标是可移动的?,javascript,arrays,multidimensional-array,2d,tiles,Javascript,Arrays,Multidimensional Array,2d,Tiles,给定任意大小的二维数组,如下所示: var board = [ [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0] ]; …以及该数组中的给定[y][x]点,例如: board[3][4] …以及它可以移动的给定数量的空间(上/下/左/右,而不是

给定任意大小的二维数组,如下所示:

var board = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
];
…以及该数组中的给定[y][x]点,例如:

board[3][4]
…以及它可以移动的给定数量的空间(上/下/左/右,而不是对角),如:

…函数如何在2D数组中循环并仅创建可能移动的坐标的列表

(以下是阵列中给定坐标(*)和周围可移动坐标的可视示例。)

参考:
(我以前问过这个问题,但我不明白如何输入坐标和接收坐标列表)

使用递归和访问链接的列表/散列。迈出一步,把你的旅行能力降低一倍,并把你所看到的东西的清单传递出去。将您当前的位置添加到已访问的地点列表中。在每个方向上走一步(使用递归),传递一个比给定值少一步的“steps left”值


这里有一个答案;唯一的问题是,它永远不会再访问一个细胞,即使用很长的路去那里。您可以通过以下两种方法来克服这一问题:一种是通过检测访问的单元是否通过比您到达该单元所需的步骤更多的步骤到达该单元。

迭代所有坐标(或者如果区域较大,则迭代子集
x-d,y-d
x+d,y+d

对于这些字段,计算距离-在您的情况下,计算为
dx-dy
,并且每当您找到距离>0的点时,都要使用它执行任何操作。否则,忽略它。就这样


与洪水填充方法相比,您可以获得简单的代码,并且不会增加额外的查找表开销。

这是我能想到的最简单的解决方案,它涉及从上到下和从左到右的工作,只迭代允许移动的坐标,所以应该非常快:

function getPossibleMoves(x, y) {
    var r, c, cMax, 
        distance = 3,
        rows = board.length,
        cols = board[0].length, 
        rMax = Math.min(y + distance + 1, rows),
        ret  = [],
        yOff;

    // Start at the first row with a permissible move
    for (r = Math.max(y - distance, 0); r < rMax; r++) {
        yOff = Math.abs(r - y);

        // Work out where we should stop looping for this row
        cMax = Math.min(x + distance - yOff + 1, cols);

        // Start at the first column with a permissible move
        for (c = Math.max(x - distance + yOff, 0); c < cMax; c++) {
            // If it's not the current position, add it to the result
            if (x != c || y != r)
                ret.push([c, r]);
        }
    }
    return ret;
}
函数getPossibleMoves(x,y){ var r,c,cMax, 距离=3, 行=board.length, cols=线路板[0]。长度, rMax=数学最小值(y+距离+1,行), ret=[], 约夫; //以允许的移动从第一行开始 对于(r=Math.max(y-距离,0);r 为了给你一个更好的主意,我制作了一个演示,让你可以调整所有不同的变量,例如电路板大小、距离等


工作演示:

对于一般情况,这是一个有效的算法,但由于问题中描述的世界仅由二维笛卡尔网格组成,因此只需要两个for循环。我想他真的是在问如何返回坐标列表。基本上是一个有额外限制的洪水填充?对于这样一个简单的问题,我想这是一种沉重的解决办法。@Kos,你说得对;不确定我为什么要走递归路径:)为了提高效率,你应该在原点附近用+-d限制迭代。有没有这样的函数可以指给我看?这在很大程度上取决于具体情况:“旅行者”可以对角移动吗?电路板上是否有“墙”(例如,上面有“1”的单元无法通过?没有直接的对角线移动;一个单元必须来回移动(2次移动)才能到达对角线瓷砖。可能有墙,但我正在考虑执行此“距离菱形”功能首先获取附近所有可能的可移动瓷砖,并为所有非障碍物提供悬停效果,然后使用寻路功能移动到单击的坐标。这让我高兴得想哭。太完美了!你救了我的命,谢谢,谢谢!
0 0 0 0 0 0 0 0
0 0 0 3 0 0 0 0
0 0 3 2 3 0 0 0
0 3 2 1 2 3 0 0
3 2 1 * 1 2 3 0
0 3 2 1 2 3 0 0
0 0 3 2 3 0 0 0
0 0 0 3 0 0 0 0
function getPossibleMoves(x, y) {
    var r, c, cMax, 
        distance = 3,
        rows = board.length,
        cols = board[0].length, 
        rMax = Math.min(y + distance + 1, rows),
        ret  = [],
        yOff;

    // Start at the first row with a permissible move
    for (r = Math.max(y - distance, 0); r < rMax; r++) {
        yOff = Math.abs(r - y);

        // Work out where we should stop looping for this row
        cMax = Math.min(x + distance - yOff + 1, cols);

        // Start at the first column with a permissible move
        for (c = Math.max(x - distance + yOff, 0); c < cMax; c++) {
            // If it's not the current position, add it to the result
            if (x != c || y != r)
                ret.push([c, r]);
        }
    }
    return ret;
}