Skip to content

Commit 6e783bb

Browse files
committed
Updated BFS to use new zustand store
1 parent f90edd7 commit 6e783bb

File tree

3 files changed

+76
-44
lines changed

3 files changed

+76
-44
lines changed

src/algorithms/pathfinding/BreadthFirstSearch.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Cell, getNeighbors, getOptimalPath } from "../utils/PathfindingUtils";
2-
import { sleep } from '../utils/SleepTime';
2+
import { useMazeStore } from '../../hooks/useMazeStore';
33

4-
// Define a function to perform breadth-first search on the maze
5-
export async function BreadthFirstSearch(maze: Cell[][], startCell: Cell, endCell: Cell, setMaze: (arr: Cell[][]) => void ): Promise<Cell[] | null> {
4+
// Define a generator function for breadth-first search on the maze
5+
function* bfsGenerator(startCell: Cell, endCell: Cell, maze: Cell[][]): Generator<Cell[][] | Cell[] | null, unknown> {
66
const queue: Cell[] = [];
77
const visited: boolean[][] = [];
88

@@ -27,7 +27,8 @@ export async function BreadthFirstSearch(maze: Cell[][], startCell: Cell, endCel
2727
}
2828
// Check if we have reached the end cell
2929
if (currentCell.row === endCell.row && currentCell.col === endCell.col) {
30-
return getOptimalPath(maze, startCell, endCell);
30+
const optimalPath = getOptimalPath(maze, startCell, endCell);
31+
return optimalPath;
3132
}
3233

3334
// Get the neighbors of the current cell
@@ -42,10 +43,32 @@ export async function BreadthFirstSearch(maze: Cell[][], startCell: Cell, endCel
4243
maze[neighbor.row][neighbor.col].prev = currentCell;
4344
}
4445
}
45-
await sleep(0);
46-
setMaze([...maze]);
46+
yield maze;
4747
}
4848

4949
// If we reach here, there is no path from start to end
50-
return null;
51-
}
50+
yield null;
51+
}
52+
53+
// Define a function to animate the breadth-first search
54+
export async function BreadthFirstSearch(startCell: Cell, endCell: Cell): Promise<Cell[] | null> {
55+
const { maze, setMaze, populateOptimalPath } = useMazeStore.getState();
56+
const generator = bfsGenerator(startCell, endCell, maze);
57+
58+
return new Promise((resolve) => {
59+
function step() {
60+
const result = generator.next();
61+
if (result.done) {
62+
const optimalPath = result.value as Cell[] | null;
63+
if (optimalPath) {
64+
populateOptimalPath(optimalPath);
65+
}
66+
resolve(optimalPath);
67+
} else {
68+
setMaze(result.value as Cell[][]);
69+
requestAnimationFrame(step);
70+
}
71+
}
72+
requestAnimationFrame(step);
73+
});
74+
}

src/pages/PathfindingVisualiser.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const PathfindingVisualiser: React.FC = () => {
2626
populateOptimalPath,
2727
} = useMazeStore();
2828

29-
function initialiseMaze(width: number, height: number){
29+
function initialiseMaze(width: number, height: number) {
3030
generateMaze(width, height);
3131
const cellHeight = Math.floor((height - (26 + 64)) / 26);
3232
const cellWidth = Math.floor((width - 326) / 26);
@@ -75,7 +75,7 @@ const PathfindingVisualiser: React.FC = () => {
7575

7676
return (
7777
<div>
78-
<ControlPanel triggerAlgorithm={triggerAlgorithm} generateTable={() => {initialiseMaze(width, height)}} clearLatestRun={clearLatestRun}/>
78+
<ControlPanel triggerAlgorithm={triggerAlgorithm} generateTable={() => { initialiseMaze(width, height); }} clearLatestRun={clearLatestRun} />
7979
<MazeGrid handleMouseDown={handleMouseDown} handleMouseEnter={handleMouseEnter} handleMouseUp={handleMouseUp} />
8080
</div>
8181
);

src/utils/pathfindingAlgorithmHooks.ts

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect } from 'react';
1+
import { useState, useEffect, useRef } from 'react';
22
import { Cell } from '../algorithms/utils/PathfindingUtils';
33
import { BreadthFirstSearch } from '../algorithms/pathfinding/BreadthFirstSearch.ts';
44
import { Dijkstra } from '../algorithms/pathfinding/Dijkstra.ts';
@@ -27,49 +27,58 @@ const pathfindingAlgorithmHooks = ({
2727
setMaze,
2828
}: PathfindingAlgorithmHooksProps) => {
2929
const [algorithm, setAlgorithm] = useState<Algorithm | null>(null);
30+
const isRunningRef = useRef(false);
3031

3132
useEffect(() => {
32-
if (!algorithm) return;
33+
if (!algorithm || isRunningRef.current) return;
3334

35+
isRunningRef.current = true;
3436
const startCell = maze[startNode[0]][startNode[1]];
3537
const endCell = maze[endNode[0]][endNode[1]];
3638

37-
const algorithmMap: Record<Algorithm, () => Promise<void> | void> = {
38-
[Algorithm.BFS]: async () => {
39-
const optimalPath = await BreadthFirstSearch(maze, startCell, endCell, setMaze);
40-
if (optimalPath) populateOptimalPath(optimalPath);
41-
},
42-
[Algorithm.DIJKSTRA]: async () => {
43-
const optimalPath = await Dijkstra(maze, startCell, endCell, setMaze);
44-
if (optimalPath) populateOptimalPath(optimalPath);
45-
},
46-
[Algorithm.DFS]: async () => {
47-
const optimalPath = await DepthFirstSearch(maze, startCell, endCell, setMaze);
48-
if (optimalPath) populateOptimalPath(optimalPath);
49-
},
50-
[Algorithm.PRIMS_MAZE]: () => {
51-
primsMazeGeneration(maze, startCell, endCell, setMaze);
52-
},
53-
[Algorithm.DFS_MAZE]: () => {
54-
dfsMazeGeneration(startCell, endCell);
55-
},
56-
[Algorithm.KRUSKAL_MAZE]: () => {
57-
kruskalsMazeGeneration(maze, startCell, endCell, setMaze);
58-
},
59-
[Algorithm.RECURSIVE_DIVISION_MAZE]: () => {
60-
recursiveDivisionMazeGeneration(maze, startCell, endCell, setMaze);
61-
},
62-
[Algorithm.RECURSIVE_DIVISION_MAZE_HORIZONTAL_BIAS]: () => {
63-
recursiveDivisionMazeGeneration(maze, startCell, endCell, setMaze, 0.4);
64-
},
65-
[Algorithm.RECURSIVE_DIVISION_MAZE_VERTICAL_BIAS]: () => {
66-
recursiveDivisionMazeGeneration(maze, startCell, endCell, setMaze, 0.6);
39+
const runAlgorithm = async () => {
40+
const algorithmMap: Record<Algorithm, () => Promise<void> | void> = {
41+
[Algorithm.BFS]: async () => {
42+
const optimalPath = await BreadthFirstSearch(startCell, endCell);
43+
if (optimalPath) populateOptimalPath(optimalPath);
44+
},
45+
[Algorithm.DIJKSTRA]: async () => {
46+
const optimalPath = await Dijkstra(maze, startCell, endCell, setMaze);
47+
if (optimalPath) populateOptimalPath(optimalPath);
48+
},
49+
[Algorithm.DFS]: async () => {
50+
const optimalPath = await DepthFirstSearch(maze, startCell, endCell, setMaze);
51+
if (optimalPath) populateOptimalPath(optimalPath);
52+
},
53+
[Algorithm.PRIMS_MAZE]: () => {
54+
primsMazeGeneration(maze, startCell, endCell, setMaze);
55+
},
56+
[Algorithm.DFS_MAZE]: () => {
57+
dfsMazeGeneration(startCell, endCell);
58+
},
59+
[Algorithm.KRUSKAL_MAZE]: () => {
60+
kruskalsMazeGeneration(maze, startCell, endCell, setMaze);
61+
},
62+
[Algorithm.RECURSIVE_DIVISION_MAZE]: () => {
63+
recursiveDivisionMazeGeneration(maze, startCell, endCell, setMaze);
64+
},
65+
[Algorithm.RECURSIVE_DIVISION_MAZE_HORIZONTAL_BIAS]: () => {
66+
recursiveDivisionMazeGeneration(maze, startCell, endCell, setMaze, 0.4);
67+
},
68+
[Algorithm.RECURSIVE_DIVISION_MAZE_VERTICAL_BIAS]: () => {
69+
recursiveDivisionMazeGeneration(maze, startCell, endCell, setMaze, 0.6);
70+
}
71+
};
72+
73+
if (algorithm) {
74+
await algorithmMap[algorithm]?.();
75+
setAlgorithm(null);
76+
isRunningRef.current = false;
6777
}
6878
};
6979

70-
algorithmMap[algorithm]?.();
80+
runAlgorithm();
7181

72-
setAlgorithm(null);
7382
}, [algorithm, maze, startNode, endNode, clearLatestRun, populateOptimalPath, setMaze]);
7483

7584
const triggerAlgorithm = (algorithm: Algorithm) => {

0 commit comments

Comments
 (0)