Skip to content

Commit 4953541

Browse files
feat: implemented flood fill recursion algorthim
1 parent f0b4e46 commit 4953541

File tree

4 files changed

+178
-1
lines changed

4 files changed

+178
-1
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export function floodFill(mat, x, y, targetColor, newColor, steps = []) {
2+
const rows = mat.length;
3+
const cols = mat[0].length;
4+
5+
if (x < 0 || y < 0 || x >= rows || y >= cols) return;
6+
if (mat[x][y] !== targetColor) return;
7+
8+
steps.push({ x, y });
9+
10+
mat[x][y] = newColor;
11+
12+
floodFill(mat, x + 1, y, targetColor, newColor, steps);
13+
floodFill(mat, x - 1, y, targetColor, newColor, steps);
14+
floodFill(mat, x, y + 1, targetColor, newColor, steps);
15+
floodFill(mat, x, y - 1, targetColor, newColor, steps);
16+
17+
return steps;
18+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import React, { useState } from "react";
2+
import { floodFill } from "@/algorithms/Recursion/FloodFill";
3+
export default function FloodFillVisualizer() {
4+
const rows = 20;
5+
const cols = 20;
6+
7+
const generateGrid = () => {
8+
const grid = [];
9+
for (let i = 0; i < rows; i++) {
10+
const row = [];
11+
for (let j = 0; j < cols; j++) {
12+
row.push(Math.random() > 0.3 ? 1 : 0);
13+
}
14+
grid.push(row);
15+
}
16+
return grid;
17+
};
18+
19+
const [grid, setGrid] = useState(generateGrid());
20+
const [speed, setSpeed] = useState(200);
21+
const [isRunning, setIsRunning] = useState(false);
22+
23+
const source = { x: 0, y: 0 };
24+
25+
const startFloodFill = () => {
26+
if (isRunning) return;
27+
28+
const mat = grid.map((row) => [...row]);
29+
const steps = [];
30+
floodFill(grid.map((row) => [...row]), source.x, source.y, 1, 2, steps);
31+
32+
animateFill(steps);
33+
};
34+
35+
const animateFill = (steps) => {
36+
let i = 0;
37+
setIsRunning(true);
38+
39+
const interval = setInterval(() => {
40+
if (i >= steps.length) {
41+
clearInterval(interval);
42+
setIsRunning(false);
43+
return;
44+
}
45+
46+
const { x, y } = steps[i];
47+
setGrid((prev) => {
48+
const newGrid = prev.map((row) => [...row]);
49+
newGrid[x][y] = 2;
50+
return newGrid;
51+
});
52+
53+
i++;
54+
}, speed);
55+
};
56+
57+
return (
58+
<div style={{ textAlign: "center", marginTop: "30px" }}>
59+
<h2>Recursive Flood Fill Visualization</h2>
60+
<div style={{ margin: "20px 0" }}>
61+
<label style={{ fontWeight: "bold" }}>Speed: </label>
62+
<input
63+
type="range"
64+
min="50"
65+
max="800"
66+
value={speed}
67+
onChange={(e) => setSpeed(Number(e.target.value))}
68+
style={{ width: "300px" }}
69+
/>
70+
<div>{speed} ms per step</div>
71+
</div>
72+
<div
73+
style={{
74+
display: "inline-grid",
75+
gridTemplateColumns: `repeat(${cols}, 25px)`,
76+
gap: "2px",
77+
marginTop: "20px",
78+
}}
79+
>
80+
{grid.map((row, r) =>
81+
row.map((cell, c) => {
82+
let color = "#dfe6e9";
83+
84+
if (r === source.x && c === source.y) {
85+
color = "#ff7675";
86+
} else if (cell === 2) {
87+
color = "#3498db";
88+
} else if (cell === 1) {
89+
color = "#b2bec3";
90+
}
91+
92+
return (
93+
<div
94+
key={`${r}-${c}`}
95+
style={{
96+
width: 25,
97+
height: 25,
98+
borderRadius: 4,
99+
border: "1px solid #ccc",
100+
backgroundColor: color,
101+
transition: "background-color 0.25s",
102+
}}
103+
/>
104+
);
105+
})
106+
)}
107+
</div>
108+
<div style={{ marginTop: "30px" }}>
109+
<button
110+
disabled={isRunning}
111+
onClick={startFloodFill}
112+
style={{
113+
padding: "10px 20px",
114+
background: isRunning ? "#b2bec3" : "#0984e3",
115+
color: "white",
116+
border: "none",
117+
cursor: isRunning ? "not-allowed" : "pointer",
118+
borderRadius: "5px",
119+
marginRight: "10px",
120+
}}
121+
>
122+
Start Flood Fill
123+
</button>
124+
125+
<button
126+
disabled={isRunning}
127+
onClick={() => setGrid(generateGrid())}
128+
style={{
129+
padding: "10px 20px",
130+
background: "#6c5ce7",
131+
color: "white",
132+
border: "none",
133+
cursor: "pointer",
134+
borderRadius: "5px",
135+
}}
136+
>
137+
Reset Grid
138+
</button>
139+
</div>
140+
</div>
141+
);
142+
}

src/pages/Recursion/FloodFill.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from "react";
2+
import FloodFillVisualizer from "@/components/Recursion/FloodFill";
3+
4+
export default function FloodFillPage() {
5+
return (
6+
<div>
7+
<FloodFillVisualizer />
8+
</div>
9+
);
10+
}

src/pages/Recursion/RecursionPage.jsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import NQueens from "./NQueens";
55
import Sudoku from "./sudokuSolver";
66
import TowerOfHanoi from "./towerOfHanoi";
77
import SubsetSum from "./SubsetSum";
8+
import FloodFillPage from "./FloodFill";
89
export default function RecursionPage() {
910
const [selectedAlgo, setSelectedAlgo] = useState("");
1011
const [sidebarOpen, setSidebarOpen] = useState(true);
@@ -41,7 +42,12 @@ export default function RecursionPage() {
4142
<SubsetSum />
4243
</div>
4344
);
44-
45+
case "FloodFill":
46+
return(
47+
<div className="w-full p-4 overflow-auto">
48+
<FloodFillPage />
49+
</div>
50+
)
4551
default:
4652
return (
4753
<div className="flex flex-col items-center justify-center text-center p-6 min-h-screen bg-gray-900 text-gray-300">
@@ -87,6 +93,7 @@ export default function RecursionPage() {
8793
<option value="SudokuSolver">Sudoku Solver</option>
8894
<option value="TowerofHanoi">Tower of Hanoi</option>
8995
<option value="SubsetSum">Subset Sum</option>
96+
<option value="FloodFill">Flood Fill</option>
9097
</select>
9198

9299
<button

0 commit comments

Comments
 (0)