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

像素网格递归填充函数实现方案咨询

嘿,我来帮你搞定这个像素填充的需求!这本质上是简化版的洪水填充算法,正好匹配你描述的逻辑——点击一个像素,然后把相邻同色的都改成黑色,碰到不同颜色就停。下面我会结合两种常见的像素存储方式,给出具体实现方案:

核心实现思路

不管像素是怎么存储的,核心逻辑都一致:

  1. 先记录被点击像素的原始颜色,如果它已经是黑色,直接终止操作(避免无意义循环)
  2. 检查当前像素是否在网格范围内,且颜色和原始颜色一致
  3. 符合条件就把它改成黑色,然后继续处理上下左右四个相邻像素
  4. 如果像素颜色和原始颜色不同,或者超出网格边界,就停止当前分支的遍历

1. 基于二维数组的实现(最直观)

如果你的像素网格是用二维数组存储的(比如grid[y][x]对应坐标(x,y)的像素颜色),可以用下面的递归版本快速实现:

示例网格与函数代码

// 示例:3x3的像素网格,中间是红色,其余是蓝色
const pixelGrid = [
  ["blue", "blue", "blue"],
  ["blue", "red", "blue"],
  ["blue", "blue", "blue"]
];

function fillPixelGrid(grid, startX, startY) {
  const originalColor = grid[startY][startX];
  
  // 已经是黑色就直接返回
  if (originalColor === "black") return;

  // 递归处理单个像素的函数
  function fill(x, y) {
    // 边界检查:超出网格范围就终止
    if (x < 0 || x >= grid[0].length || y < 0 || y >= grid.length) return;
    // 颜色不同,终止当前分支
    if (grid[y][x] !== originalColor) return;

    // 修改为黑色
    grid[y][x] = "black";

    // 递归遍历上下左右
    fill(x - 1, y); // 左
    fill(x + 1, y); // 右
    fill(x, y - 1); // 上
    fill(x, y + 1); // 下
  }

  // 启动填充
  fill(startX, startY);
}

使用方式

// 点击中间的红色像素(坐标x=1, y=1)
fillPixelGrid(pixelGrid, 1, 1);
console.log(pixelGrid);
// 输出结果:中间的红色会被改成黑色,周围蓝色保持不变

2. 基于像素对象数组的实现

如果你的像素是存储在一维对象数组里(每个像素结构类似{ x: 0, y: 0, color: "#ff0000" }),可以先建立一个坐标映射表,方便快速查找相邻像素:

示例数据与函数代码

// 示例:一维像素对象数组
const pixels = [
  { x: 0, y: 0, color: "blue" },
  { x: 1, y: 0, color: "blue" },
  { x: 2, y: 0, color: "blue" },
  { x: 0, y: 1, color: "blue" },
  { x: 1, y: 1, color: "red" },
  { x: 2, y: 1, color: "blue" },
  { x: 0, y: 2, color: "blue" },
  { x: 1, y: 2, color: "blue" },
  { x: 2, y: 2, color: "blue" }
];

// 建立「x-y坐标」到像素对象的映射,方便快速查找
const pixelMap = {};
pixels.forEach(pixel => {
  pixelMap[`${pixel.x}-${pixel.y}`] = pixel;
});

function fillPixelObjects(pixelMap, startX, startY) {
  const startPixel = pixelMap[`${startX}-${startY}`];
  if (!startPixel) return; // 找不到起始像素,直接终止

  const originalColor = startPixel.color;
  if (originalColor === "black") return;

  function fill(x, y) {
    const currentPixel = pixelMap[`${x}-${y}`];
    // 像素不存在或颜色不符,终止当前分支
    if (!currentPixel || currentPixel.color !== originalColor) return;

    // 修改为黑色
    currentPixel.color = "black";

    // 遍历上下左右
    fill(x - 1, y);
    fill(x + 1, y);
    fill(x, y - 1);
    fill(x, y + 1);
  }

  fill(startX, startY);
}

使用方式

// 点击中间的红色像素(坐标x=1, y=1)
fillPixelObjects(pixelMap, 1, 1);
console.log(pixels);
// 输出结果:中间的红色像素会被改为黑色

进阶优化:避免递归栈溢出

如果你的像素网格特别大,递归版本可能会触发栈溢出问题。这时候可以改用迭代+队列的方式实现,逻辑和递归完全一致,但更稳定:

// 迭代版本的二维数组填充函数
function fillPixelGridIterative(grid, startX, startY) {
  const originalColor = grid[startY][startX];
  if (originalColor === "black") return;

  // 用数组模拟队列,存储待处理的像素坐标
  const queue = [[startX, startY]];
  // 标记已处理的像素,避免重复入队
  const processed = new Set();
  processed.add(`${startX}-${startY}`);

  while (queue.length > 0) {
    const [x, y] = queue.shift();
    grid[y][x] = "black";

    // 定义四个方向的偏移量
    const directions = [[-1,0], [1,0], [0,-1], [0,1]];
    for (const [dx, dy] of directions) {
      const newX = x + dx;
      const newY = y + dy;
      const key = `${newX}-${newY}`;
      
      // 检查边界、颜色、是否已处理
      if (
        newX >=0 && newX < grid[0].length &&
        newY >=0 && newY < grid.length &&
        grid[newY][newX] === originalColor &&
        !processed.has(key)
      ) {
        processed.add(key);
        queue.push([newX, newY]);
      }
    }
  }
}

内容的提问来源于stack exchange,提问作者saricden

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:16:20