-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdijkstra.js
More file actions
66 lines (61 loc) · 2.28 KB
/
dijkstra.js
File metadata and controls
66 lines (61 loc) · 2.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Performs Dijkstra's algorithm; returns *all* nodes in the order
// in which they were visited. Also makes nodes point back to their
// previous node, effectively allowing us to compute the shortest path
// by backtracking from the finish node.
export function dijkstra(grid, startNode, finishNode) {
const visitedNodesInOrder = [];
startNode.distance = 0;
const unvisitedNodes = getAllNodes(grid);
while (!!unvisitedNodes.length) {
sortNodesByDistance(unvisitedNodes);
const closestNode = unvisitedNodes.shift();
// If we encounter a wall, we skip it.
if (closestNode.isWall) continue;
// If the closest node is at a distance of infinity,
// we must be trapped and should therefore stop.
if (closestNode.distance === Infinity) return visitedNodesInOrder;
closestNode.isVisited = true;
visitedNodesInOrder.push(closestNode);
if (closestNode === finishNode) return visitedNodesInOrder;
updateUnvisitedNeighbors(closestNode, grid);
}
}
function sortNodesByDistance(unvisitedNodes) {
unvisitedNodes.sort((nodeA, nodeB) => nodeA.distance - nodeB.distance);
}
function updateUnvisitedNeighbors(node, grid) {
const unvisitedNeighbors = getUnvisitedNeighbors(node, grid);
for (const neighbor of unvisitedNeighbors) {
neighbor.distance = node.distance + 1;
neighbor.previousNode = node;
}
}
function getUnvisitedNeighbors(node, grid) {
const neighbors = [];
const {col, row} = node;
if (row > 0) neighbors.push(grid[row - 1][col]);
if (row < grid.length - 1) neighbors.push(grid[row + 1][col]);
if (col > 0) neighbors.push(grid[row][col - 1]);
if (col < grid[0].length - 1) neighbors.push(grid[row][col + 1]);
return neighbors.filter(neighbor => !neighbor.isVisited);
}
function getAllNodes(grid) {
const nodes = [];
for (const row of grid) {
for (const node of row) {
nodes.push(node);
}
}
return nodes;
}
// Backtracks from the finishNode to find the shortest path.
// Only works when called *after* the dijkstra method above.
export function getNodesInShortestPathOrder(finishNode) {
const nodesInShortestPathOrder = [];
let currentNode = finishNode;
while (currentNode !== null) {
nodesInShortestPathOrder.unshift(currentNode);
currentNode = currentNode.previousNode;
}
return nodesInShortestPathOrder;
}