You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 20:23:21