迭代地为所有相邻的相同图块着色

时间:2014-02-07 14:51:23

标签: javascript algorithm

我尝试创建一个油漆桶工具。我需要找到我点击的点的所有相邻点,如果颜色与原始颜色相同,则更改颜色。颜色需要在相同颜色的所有点上传播。传播只能在4个方向上进行(无对角线)。

我可以轻松递归地执行此操作,但遗憾的是,当地图太大时我收到错误:

Uncaught RangeError: Maximum call stack size exceeded

这是重现问题的基本示例,我想将其转换为迭代方式:

// Fill the map
var map = [];
for (var x = 0; x < 500; x++){
    var row = [];
    for (var y = 0; y < 500; y++){
        row.push(1);
    }
    map.push(row);
}

var paintTile = function(x, y){
    // If X or Y is out of map range
    if (x < 0 || x >= 500 || y < 0 || y >= 500){
        return
    }

    // If this tile is already painted in new color
    if (map[x][y] == 0){
        return;
    }

    // Draw tile with new color
    map[x][y] = 0;

    // Paint all adjacent tiles
    paintTile(x - 1, y);
    paintTile(x + 1, y);
    paintTile(x, y - 1);
    paintTile(x, y + 1);
};

paintTile(0, 0);

在这个例子中,所有地图都填充了“1”(假设它是白色),我将它们转换为“0”(黑色),但是我得到了这个stack size错误。

此致

3 个答案:

答案 0 :(得分:3)

你的意思是洪水填充算法吗?

来自http://en.wikipedia.org/wiki/Flood_fill

Flood-fill (node, target-color, replacement-color):
 1. Set Q to the empty queue.
 2. If the color of node is not equal to target-color, return.
 3. Add node to Q.
 4. For each element N of Q:
 5.     If the color of N is equal to target-color:
 6.         Set w and e equal to N.
 7.         Move w to the west until the color of the node to the west of w no longer matches target-color.
 8.         Move e to the east until the color of the node to the east of e no longer matches target-color.
 9.         For each node n between w and e:
10.             Set the color of n to replacement-color.
11.             If the color of the node to the north of n is target-color, add that node to Q.
12.             If the color of the node to the south of n is target-color, add that node to Q.
13. Continue looping until Q is exhausted.
14. Return.

答案 1 :(得分:1)

保留您需要处理的图块列表以及已处理的图块。将您的第一个磁贴放入ToBeProcessed列表,然后重复循环,直到您的待处理列表为空。

在每个循环上首先检查是否要重新着色此图块。如果您没有,请将其从ToBeProcessed中删除,然后转到循环的下一个循环。如果是,则进行正常处理(即改变颜色)。然后将相邻的图块添加到ToBeProcessed列表中,如果它们不在已处理的列表上(或已经在ToBeProcessed列表中)。

然后在循环迭代结束时从ToBeProcessed列表中删除当前项。

答案 2 :(得分:0)

以下是有关该主题的视频:https://www.youtube.com/watch?v=LvacRISl99Y

我没有使用复杂的逻辑来跟踪先前验证过的相邻空间,而是有一个2D数组来记录所有验证过的空间。从已验证的数组中读取2至3条指令:如果已验证pixel [23,23],然后填充它并检查它的邻居。