平铺地图JavaScript中的算法填充封闭区域

Posted

技术标签:

【中文标题】平铺地图JavaScript中的算法填充封闭区域【英文标题】:Algorithm Fill Closed Area in Tile map JavaScript 【发布时间】:2020-03-21 04:36:56 【问题描述】:

对不起我的英语。

我有一个问题,下一步是什么:

例如,我有一张地图:

var map = 
    [[0,1,1,0,0,0,0,0,0,0],
    [0,1,0,1,0,1,1,0,0,0],
    [0,1,0,0,1,0,0,1,0,0],
    [0,1,0,0,0,0,0,0,1,0],
    [0,0,1,0,0,0,0,1,0,0],
    [0,0,0,1,0,0,0,1,1,0],
    [0,0,1,0,0,0,1,0,0,0],
    [0,1,0,0,0,0,0,1,0,0],
    [1,0,0,1,1,1,0,1,0,0],
    [0,1,1,0,0,1,1,1,0,0]];

其中包含一系列数字 0 和 1(例如)。我需要填写此地图上所有封闭的方框,例如使用数字 2。

例子:

var map = 
    [[0,1,1,0,0,0,0,0,0,0],
    [0,1,2,1,0,1,1,0,0,0],
    [0,1,2,2,1,2,2,1,0,0],
    [0,1,2,2,2,2,2,2,1,0],
    [0,0,1,2,2,2,2,1,0,0],
    [0,0,0,1,2,2,2,1,1,0],
    [0,0,1,2,2,2,1,0,0,0],
    [0,1,2,2,2,2,2,1,0,0],
    [1,2,2,1,1,1,2,1,0,0],
    [0,1,1,0,0,1,1,1,0,0]];

考虑到:

    正如本例中只有一个闭合图形,也可以有多个闭合图形 不会考虑地图的侧面 如果有任何用处,数字 1(将是实心)将 随着时间的推移生成,所以地图会不断变化 (就像数组中的笔划)

我找到了一个名为“Flood Fill”的方法,但是它取决于一个起点,在这种情况下它没有起点。这个想法是代码负责找到封闭区域并自动填充它们。

【问题讨论】:

【参考方案1】:

如果您没有起始坐标,识别要填充的每个 0 的一种方法是识别边缘上的每个 0。这些零中的每一个都应该被填充,并且最终与这些0相邻的每个0也不应该被填充。因此,如果您将边缘 0 作为“起点”并遍历它们的所有递归邻居,您将识别出每个坐标为 0 但不应填充。

然后,这很简单:只需遍历输入,对于每个 0,检查当前坐标是否在不应填充的那组坐标中。如果坐标在该集合中不是,则替换为 2。

var map = 
    [[0,1,1,0,0,0,0,0,0,0],
    [0,1,2,1,0,1,1,0,0,0],
    [0,1,2,2,1,2,2,1,0,0],
    [0,1,2,2,2,2,2,2,1,0],
    [0,0,1,2,2,2,2,1,0,0],
    [0,0,0,1,2,2,2,1,1,0],
    [0,0,1,2,2,2,1,0,0,0],
    [0,1,2,2,2,2,2,1,0,0],
    [1,2,2,1,1,1,2,1,0,0],
    [0,1,1,0,0,1,1,1,0,0]];
const height = map.length;
const width = map[0].length;

const edgeZerosCoords = new Set();
map.forEach((arr, row) => 
  arr.forEach((num, col) => 
    if (num === 0 && (row === 0 || col === 0 || row === width - 1 || col === height - 1)) 
      edgeZerosCoords.add(`$row_$col`);
    
  )
);
const doNotFillCoords = new Set();
const visited = new Set();
const checkCoord = (row, col) => 
  // Verify valid coord:
  if (row < 0 || col < 0 || row === width || col === height) return;
  const str = `$row_$col`;
  if (doNotFillCoords.has(str) || visited.has(str)) return;
  visited.add(str);
  const num = map[row][col];
  if (num !== 0) return;
  doNotFillCoords.add(str);
  checkCoord(row + 1, col);
  checkCoord(row - 1, col);
  checkCoord(row, col + 1);
  checkCoord(row, col - 1);
;
for (const str of edgeZerosCoords) 
  const [row, col] = str.split('_').map(Number);
  checkCoord(row, col)

map.forEach((arr, row) => 
  arr.forEach((num, col) => 
    const str = `$row_$col`;
    if (num === 0 && !doNotFillCoords.has(str)) 
      map[row][col] = 2;
    
  )
);
console.log(JSON.stringify(map));

结果:

[
  [0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
  [0, 1, 2, 1, 0, 1, 1, 0, 0, 0],
  [0, 1, 2, 2, 1, 2, 2, 1, 0, 0],
  [0, 1, 2, 2, 2, 2, 2, 2, 1, 0],
  [0, 0, 1, 2, 2, 2, 2, 1, 0, 0],
  [0, 0, 0, 1, 2, 2, 2, 1, 1, 0],
  [0, 0, 1, 2, 2, 2, 1, 0, 0, 0],
  [0, 1, 2, 2, 2, 2, 2, 1, 0, 0],
  [1, 2, 2, 1, 1, 1, 2, 1, 0, 0],
  [0, 1, 1, 0, 0, 1, 1, 1, 0, 0]
]

【讨论】:

非常感谢,我就是这个意思

以上是关于平铺地图JavaScript中的算法填充封闭区域的主要内容,如果未能解决你的问题,请参考以下文章

地图平铺算法

图像填充算法

IfcFillAreaStyleTiles

《图像处理实例》 之 填充封闭区域

洪水覆盖算法(Flood Fill):颜色填充

用随机颜色填充封闭区域 - Haskell - 星期五