洪水填充算法详解

文章目录三、实现 四、应用 五、总结
效果:
一、前言
当象一个容器中注水时,无论容器的结构如何复杂,注入的水总是能够绕过障碍物填满整个区域 。有一种算法叫做洪水填充算法,它是一种图像处理算法,用于填充封闭区域 。它的工作原理类似于在图像上泼洒颜料,使一个种子像水流一样蔓延,填充连通的区域,直到遇到边界或其他障碍物为止 。我们可以将洪水填充算法比喻为在涂色本上填色的过程 。假设我们有一个空白的涂色本,上面有很多小格子,每个格子可以涂上不同的颜色 。现在,我们想要将某个格子以及和它相连通的所有相同颜色的格子都涂上另一种颜色 。非常有趣,下面让我们来一起学习一下洪水填充算法的原理 。
二、思路
红色: 起点 。
绿色: 可到达的点 。
黑色: 障碍物 。
2.1 起点
这个起点我们可以理解为出水口,扩散的起点 。一般都选择中心点作为起点 。
2.2 检查起点四周
检查起点的 上 下 左 右四个方向是否存在障碍物 。如果不是障碍物,则为绿色(表示可到达的点)并存入待检查队列中,如果存在障碍物,颜色不变,不存入待检查队列 。
2.3 填充相邻点
将待检查队列中的点,填充为红色,并检查它的四周是否存在可到达的点:
2.4 继续扩散
循环2.2、 2.3 步骤继续检查扩散 。
2.7 结束
当待检查队列中没有节点时,证明已经检查并扩散完毕了 。
图中的两个白色的节点,是不可到达的点 。
三、实现
为了更加直观看到洪水填充算法的执行过程,我们使用和HTML来实现 。完整代码如下:
3.1 HTML + 代码
Canvas Grid with Obstacles>body {margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #f0f0f0;}canvas {border: 1px solid black;}#showTable {width: 200px;height: 150px;border: 1px solid black;padding: 10px;}

总数量: id="totalSquares">2,250,000
障碍物数量: id="obstacleCount">0
>const canvas = document.getElementById("gridCanvas");const ctx = canvas.getContext("2d");const size = 10;//网格大小const gridSize = 150; // 网格数量const totalSquares = gridSize * gridSize;const centerPoint = { x: Math.floor(gridSize / 2), y: Math.floor(gridSize / 2) };const totalSquaresDisplay = document.getElementById("totalSquares");const obstacleCountDisplay = document.getElementById("obstacleCount");const detectedCountDisplay = document.getElementById("detectedCount");let obstacles = [];function drawSquare(x, y, color) {ctx.fillStyle = color;ctx.fillRect(x, y, size, size);}//随机生成障碍物function randomObstruction() {obstacles = [];//先清空之前生成的障碍物ctx.clearRect(0, 0, canvas.width, canvas.height); drawGrid(); // Redraw the grid linesconst obstacleCount = Math.floor(Math.random() * 301) + 10000;for (let i = 0; i < obstacleCount; i++) {const x = Math.floor(Math.random() * gridSize) * size;const y = Math.floor(Math.random() * gridSize) * size;obstacles.push({ x, y });drawSquare(x, y, "black");}obstacleCountDisplay.textContent = obstacleCount;}//洪水填充function startDetect() {const detectedSet = new Set();const queue = [];const dx = [0, 1, 0, -1];const dy = [-1, 0, 1, 0];let detectedCount = 0;function isValid(x, y) {return x >= 0 && x < gridSize && y >= 0 && y < gridSize;}queue.push(centerPoint);detectedSet.add(`${centerPoint.x},${centerPoint.y}`);while (queue.length > 0) {const { x, y } = queue.shift();let canExpand = true;//上下左右四个方向for (let i = 0; i