用阵列检测运动范围

时间:2018-05-26 20:12:37

标签: javascript html arrays html5 path-finding

我有一个像这样的维度数组:

    0, 0, 0, 0, 0, 0, 0,
    0, 1, 1, 1, 1, 1, 0,
    0, 0, 0, 0, 0, 1, 1,
    0, 0, 0, 0, 0, 0, 0,
    1, 0, 0, 0, 0, 1, 1,
    0, 1, 0, 1, 1, 1, 0,
    0, 1, 0, 1, 0, 0, 0,

图例:0 =空地板,1 =挡住通道的墙,2 =起点,3 =可以从起点到达的地板。 如果值为0,则可以水平,垂直和对角移动。 示例地图数组是7x7,示例移动范围是3,但这些参数可能是15x9甚至是6。 我想要做的是获得一个维度数组,从这个选择点显示可能的移动范围(示例范围是3步,如果位置有0,如左下角所示,对角线可以在墙之间传递):

    0, 0, 0, 0, 0, 0, 0,
    3, 1, 1, 1, 1, 1, 0,
    3, 3, 3, 3, 3, 1, 1,
    3, 3, 3, 2, 3, 3, 3,
    1, 3, 3, 3, 3, 1, 1,
    3, 1, 3, 1, 1, 1, 0,
    0, 1, 3, 1, 0, 0, 0,

这是更简单的版本,因为如果范围可以限制为在一维掩模数组中可能不同的指定形状(例如此示例(0 =外部范围)),那将是很好的:

    0, 0, 0, 1, 0, 0, 0,
    0, 0, 1, 1, 1, 0, 0,
    0, 1, 1, 1, 1, 1, 0,
    1, 1, 1, 1, 1, 1, 1,
    0, 1, 1, 1, 1, 1, 0,
    0, 0, 1, 1, 1, 0, 0,
    0, 0, 0, 1, 0, 0, 0,

在这种情况下,结果将是这样的:

    0, 0, 0, 0, 0, 0, 0,
    0, 1, 1, 1, 1, 1, 0,
    0, 3, 3, 3, 3, 1, 1,
    3, 3, 3, 2, 3, 3, 3,
    1, 3, 3, 3, 3, 1, 1,
    0, 1, 3, 1, 1, 1, 0,
    0, 1, 0, 1, 0, 0, 0,

代码:

<div id="results" style="font-family: monospace; font-weight: bold; font-size: 24pt; background-color: #000000; color: #FFFFFF;">
</div>
<script>
var map=[0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,1,0,1,1,1,0,0,1,0,1,0,0,0,];
var mask=[0,0,0,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,];

function path_create(map,width,height,point,range,mask)
{
// map = pure map with 0 as floor and 1 as wall
// width, height = size of map
// point = starting point to calculate movement range
// range = number of moves from starting point to each direction of horizontal, vertical, and diagonal
// mask = (optional) if possible to do, array mask (0 is not in range) can change range for diagonal moves with special shapes like circle or rhombus
var matrix=[];
return matrix;
// one dimension array where 0 is no range, and 1 is ok
}

function path_show(matrix,width,height)
{
var v="";
for(var i=0; i<matrix.length; i++)
{
if(i!=0 && i%7==0){v=v+"<br>";}
v=v+matrix[i]+" ";
}
document.getElementById('results').innerHTML=v;
}

path_show(path_create(map,7,7,25,3,mask));
//path_show(path_create(map,7,7,16,3,mask));
</script>

1 个答案:

答案 0 :(得分:0)

基本上你可以集成掩码数组并在找到不应该使用的单元格时提前退出。

此提案使用矩阵而不是线性数组,因为检查相邻单元格更容易解决。

然后它会为可能的方向采用数组,并使用

检查提前退出
if (!mask[i][j] || array[i][j] === 1 || !steps || reach[i][j] >= steps) {
    return;
}

,其中

  • !mask[i][j]检查面具,
  • array[i][j] === 1检查墙,
  • !steps检查剩余的步骤或
  • reach[i][j] >= steps其中单元格的步骤大于剩余步骤,这可以防止检查已经检查过的步骤,并防止将更短的剩余步骤视为可能。

在上述所有情况下,进一步处理将停止。

&#13;
&#13;
function check(i, j, steps) {
    var directions = [{ x: 0, y: -1 }, { x: -1, y: -1 }, { x: -1, y: 0 }, { x: -1, y: 1 }, { x: 0, y: 1 }, { x: 1, y: 1 }, { x: 1, y: 0 }, { x: 1, y: -1 }];

    if (!mask[i][j] || array[i][j] === 1 || !steps || reach[i][j] >= steps) {
        return;
    }

    reach[i][j] = steps;
    directions.forEach(({ x, y }) => {
        x += i;
        y += j;
        if (x < 0 || x >= width || y < 0 || y >= height) {
            return;
        }
        check(x, y, steps - 1);
    });
}

function out(array) {
    document.getElementById('out').innerHTML += array.map(a => a.join('  ')).join('\n') + '\n\n';
}

function getMatrix(raw, width) {
    var array = [],
        i = 0;

    while (i < raw.length) {
        array.push(raw.slice(i, i += width));
    }
    return array;
}

var width = 7,
    height = 7,
    rawData = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0],
    rawMask = [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
    array = getMatrix(rawData, width),
    mask = getMatrix(rawMask, width),
    reach = Array.from({ length: height }, _ => Array.from({ length: width }).fill(0)),
    max = 3,
    result;

array[3][3] = 2;
check(3, 3, max + 1);
result = reach.map((a, i) => a.map((b, j) => b === max + 1 ? 2 : b ? 3 : array[i][j]));

out(array);
out(reach);
out(result);
&#13;
<pre id="out"></pre>
&#13;
&#13;
&#13;