如何使Flood-fill功能以递归方式填充ASCII图像

时间:2019-04-05 15:40:18

标签: javascript recursion flood-fill

我需要使用FloodFill函数将ASCII图像星号轮廓内的所有点都变成星号。有人可以帮忙吗?

"use strict";

let bitmap = [
  "................**********........................",
  "...............*..........*.......................",
  "..........*****............*........*.............",
  ".........*.................*.......*.*....*****...",
  "........*................***......*...*.**.....**.",
  "....****.................*.......*.....*.........*",
  "..**......................*******................*",
  ".*...............................................*",
  ".*...............................................*",
  "*...........****.............................****.",
  "*..........*....*.........................***.....",
  ".*.........*....*.......................**........",
  "..***.......****.......................*..........",
  ".....****......................******..*..........",
  ".........**********************.....****.........."
];



const bitmap2string = bitmap => bitmap.join("\n");

console.log(bitmap2string(bitmap));

const showOnPosition = (x, y) => 
  bitmap[y].charAt(x);

const changeSymbol = (x, y, symbol) => 
  bitmap[y].substr(0, x) + symbol + bitmap[y].substr(x + 1);

const floodFill = (x, y) => 
  showOnPosition(x, y) !== "*" 
    ? bitmap.map((line, i) => (i === y ? changeSymbol(x, y, "*") : line)) 
    : bitmap;

我已经为以下代码编写了代码:

  • showOnPosition-检查数组的x,y坐标上当前的内容
  • changeSymbol-在任何给定位置更改符号
  • floodFill-检查当前位置上的内容,如果不是星号,则将其更改为星号,并在控制台中提供更新的数组。

现在,我要如何使所有这些递归地遍历图像(如右图),并用星号填充给定的轮廓。

结果应为: 使用带有任何坐标的FloodFill Function调用,例如console.log(floodFill(8,7)) it shows the following in the console

1 个答案:

答案 0 :(得分:2)

这是一个懒惰但简单的实现:

let bitmap = [
    "................**********........................",
    "...............*..........*.......................",
    "..........*****............*........*.............",
    ".........*.................*.......*.*....*****...",
    "........*................***......*...*.**.....**.",
    "....****.................*.......*.....*.........*",
    "..**......................*******................*",
    ".*...............................................*",
    ".*...............................................*",
    "*...........****.............................****.",
    "*..........*....*.........................***.....",
    ".*.........*....*.......................**........",
    "..***.......****.......................*..........",
    ".....****......................******..*..........",
    ".........**********************.....****.........."
];

// convert to an array of arrays
bitmap = bitmap.map(row => [...row]);
xsize = bitmap[0].length;
ysize = bitmap.length;

floodFill = (x, y) => {

    // check bounds
    if (y < 0 || y >= ysize) return;
    if (x < 0 || x >= xsize) return;

    // already painted?
    if (bitmap[y][x] === '*') return;

    // paint!
    bitmap[y][x] = '*';

    // fill neighbours
    floodFill(x - 1, y);
    floodFill(x + 1, y);
    floodFill(x, y - 1);
    floodFill(x, y + 1);
};

floodFill(7, 8);

// convert to string
bitmap = bitmap.map(row => row.join('')).join('\n');

document.write('<pre>' + bitmap);

此解决方案的问题是起点是任意的,并且很可能超出界限。更好的方法是逐行扫描矩阵并执行一种“光线跟踪”以确定点在内部还是外部。这将在线性时间内无递归运行。