Flood Fill算法异常:填充区域反向且无法多区域填充求助
Flood Fill算法实现异常求助
我跟着教程实现Flood Fill算法,代码和教程一致但运行异常:绘制的圆形外部被填充、内部留白,且无法填充多个图形。我是编程新手,核对教程后未发现差异,附上当前代码及效果截图,请求帮忙排查问题。
效果截图
- 问题/预期效果:

- 实际运行效果:

当前代码
let imageData; function setup() { createCanvas(1000, 1000); } function draw() { drawing(); } function drawing() { if (mouseIsPressed) { line(pmouseX, pmouseY, mouseX, mouseY); } } function keyPressed() { imageData = drawingContext.getImageData(0, 0, 1000, 1000); floodFilling(mouseX, mouseY); drawingContext.putImageData(imageData, 0, 0); } function floodFilling(x, y) { let fillStack = []; fillStack.push([x, y]); while (fillStack.length > 0) { let [x, y] = fillStack.pop(); if (!valid(x, y)) continue; if (isPixel(x, y)) continue; } } setPixel(x, y); fillStack.push([x + 1, y]); fillStack.push([x - 1, y]); fillStack.push([x, y - 1]); fillStack.push([x, y + 1]); } } //set color of pixel function setPixel(x, y) { let pixels = imageData.data; let i = (y * width + x) * 4; pixels[i] = 255; pixels[i + 1] = 0; pixels[i + 2] = 0; pixels[i + 3] = 255; } //make sure it has color function isPixel(x, y) { let pixels = imageData.data; let i = (y * width + x) * 4; return pixels[i + 3] > 0; } //make sure it is in bounds of canvas function valid(x, y) { return x >= 0 && x <= width - 1 && y >= 0 && y <= height - 1; }
问题排查与修复
1. 致命语法错误:括号匹配错误
你的floodFilling函数中,while循环的闭合括号位置完全错误,导致setPixel和入栈相邻点的代码被放到了循环外面,根本不会被执行。正确的循环结构应该把这些操作包裹在循环体内。
2. 逻辑判断缺陷
当前isPixel函数仅判断“像素有颜色(alpha通道>0)”就跳过,但画布的空白区域(包括圆形内部和外部)都是alpha=0,所以会把整个画布除绘制线条外的区域全部填充。解决这个问题需要先记录起始点的颜色,只填充与起始点颜色一致的区域。
修正后的代码
let imageData; function setup() { createCanvas(1000, 1000); } function draw() { drawing(); } function drawing() { if (mouseIsPressed) { line(pmouseX, pmouseY, mouseX, mouseY); } } function keyPressed() { imageData = drawingContext.getImageData(0, 0, width, height); // 获取起始点的颜色,用于后续判断 const startIndex = (mouseY * width + mouseX) * 4; const startColor = [ imageData.data[startIndex], imageData.data[startIndex + 1], imageData.data[startIndex + 2], imageData.data[startIndex + 3] ]; floodFilling(mouseX, mouseY, startColor); drawingContext.putImageData(imageData, 0, 0); } function floodFilling(x, y, startColor) { let fillStack = []; fillStack.push([x, y]); while (fillStack.length > 0) { let [x, y] = fillStack.pop(); // 先判断是否在画布范围内 if (!valid(x, y)) continue; // 判断当前像素是否和起始点颜色一致 if (!isSameColor(x, y, startColor)) continue; // 设置填充颜色 setPixel(x, y); // 将相邻像素入栈 fillStack.push([x + 1, y]); fillStack.push([x - 1, y]); fillStack.push([x, y - 1]); fillStack.push([x, y + 1]); } } // 设置像素颜色为红色 function setPixel(x, y) { let pixels = imageData.data; let i = (y * width + x) * 4; pixels[i] = 255; // R pixels[i + 1] = 0; // G pixels[i + 2] = 0; // B pixels[i + 3] = 255; // A } // 判断当前像素是否和起始点颜色一致 function isSameColor(x, y, targetColor) { let pixels = imageData.data; let i = (y * width + x) * 4; return ( pixels[i] === targetColor[0] && pixels[i + 1] === targetColor[1] && pixels[i + 2] === targetColor[2] && pixels[i + 3] === targetColor[3] ); } // 判断像素是否在画布范围内 function valid(x, y) { return x >= 0 && x < width && y >= 0 && y < height; }
修正说明
- 修复了
floodFilling函数的括号结构,确保核心逻辑在循环内执行。 - 添加了
isSameColor函数,替代原来的isPixel,只填充与点击起始点颜色一致的区域,这样点击圆形内部时只会填充内部空白,不会波及外部。 - 在
keyPressed中获取起始点颜色,传递给填充函数,保证填充的是目标区域。
内容的提问来源于stack exchange,提问作者ejb1004
相关产品推荐
相关产品推荐

