我尝试创建一个油漆桶工具。我需要找到我点击的点的所有相邻点,如果颜色与原始颜色相同,则更改颜色。颜色需要在相同颜色的所有点上传播。传播只能在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
错误。
此致
答案 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],然后填充它并检查它的邻居。