Skip to content

Commit aa8107a

Browse files
author
Rory Sullivan
committed
Refactoring of algorithms.
1 parent 2fc5933 commit aa8107a

10 files changed

+127
-127
lines changed

algorithms/Graph.js

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import GraphNode from './GraphNode';
1+
import GraphNode from './GraphNode.js';
22

33
/**
44
* Makes a graph of nodes from our grid matrix. Grid matrix values of 0
@@ -7,15 +7,25 @@ import GraphNode from './GraphNode';
77
export default class Graph extends Array {
88
constructor(grid) {
99
super();
10+
11+
this.start = grid.start;
12+
this.end = grid.end;
13+
1014
for (let i = 0; i < grid.length; i += 1) {
11-
const row = grid[i];
15+
const gridRow = grid[i];
1216
const graphRow = [];
13-
for (let j = 0; j < row.length; j += 1) {
14-
const a = row[j];
17+
18+
for (let j = 0; j < gridRow.length; j += 1) {
19+
const tile = gridRow[j];
1520
const node = new GraphNode(i, j, this);
1621

17-
if (a === 1) {
22+
if (tile.isWall) {
1823
node.isWall = true;
24+
} else if (tile.isStart) {
25+
node.isStart = true;
26+
node.dStart = 0;
27+
} else if (tile.isEnd) {
28+
node.isEnd = true;
1929
}
2030

2131
graphRow.push(node);

algorithms/GraphNode.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default class GraphNode {
66
this.graph = parentGraph; // The graph containing this node
77
this.row = row;
88
this.col = col;
9-
this.d = Infinity; // current best known distance for this node.
9+
this.dStart = Infinity; // current best known distance from the start for this node.
1010
this.isWall = false;
1111
this.isStart = false;
1212
this.isEnd = false;

algorithms/aStar.js

+15-21
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,37 @@
1-
import Graph from './Graph';
2-
import hexDistanceBetween from './hexDistanceBetween';
1+
import Graph from './Graph.js';
2+
import hexDistanceBetween from './hexDistanceBetween.js';
33

44
export default class AStar {
5-
constructor(grid, startNode, endNode) {
5+
constructor(grid) {
66
this.graph = new Graph(grid);
7-
this.endNode = endNode;
87
this.path = [];
98
this.pathFound = false;
109
this.noPath = false;
1110
this.minDist = []; // Ordered list of nodes with the node of minimum
1211
// distance at position zero.
1312

14-
this.graph[startNode[0]][startNode[1]].isStart = true;
15-
this.graph[startNode[0]][startNode[1]].dStart = 0; // distance from start node
16-
this.graph[startNode[0]][startNode[1]].dEnd = hexDistanceBetween(
17-
startNode,
18-
endNode
19-
); // distance from end node
20-
this.graph[startNode[0]][startNode[1]].d =
21-
this.graph[startNode[0]][startNode[1]].dStart +
22-
this.graph[startNode[0]][startNode[1]].dEnd;
23-
this.addToMinDist(this.graph[startNode[0]][startNode[1]]);
24-
25-
this.graph[endNode[0]][endNode[1]].isEnd = true;
13+
this.graph[this.graph.start[0]][
14+
this.graph.start[1]
15+
].dEnd = hexDistanceBetween(this.graph.start, this.graph.end); // distance from end node
16+
this.graph[this.graph.start[0]][this.graph.start[1]].d = this.graph[
17+
this.graph.start[0]
18+
][this.graph.start[1]].dEnd;
19+
this.addToMinDist(this.graph[this.graph.start[0]][this.graph.start[1]]);
2620
}
2721

2822
/**
2923
* Increments a step of the algorithm.
3024
*/
3125
step() {
3226
if (this.pathFound) {
33-
return true;
27+
return false;
3428
}
3529

3630
if (this.minDist.length === 0) {
3731
// No path exists
3832
this.noPath = true;
3933
this.pathFound = true;
40-
return true;
34+
return false;
4135
}
4236

4337
let currentNode = this.minDist.shift();
@@ -55,18 +49,18 @@ export default class AStar {
5549
currentNode = previousNode;
5650
} while (!currentNode.isStart);
5751

58-
return true;
52+
return false;
5953
}
6054

6155
for (let i = 0; i < currentNode.neighbours.length; i += 1) {
6256
const neighbour = currentNode.neighbours[i];
6357
checkedNodes.push(neighbour);
6458

6559
if (neighbour.dEnd === undefined) {
66-
neighbour.dStart = Infinity;
60+
neighbour.d = Infinity;
6761
neighbour.dEnd = hexDistanceBetween(
6862
[neighbour.row, neighbour.col],
69-
this.endNode
63+
this.graph.end
7064
);
7165
}
7266

algorithms/biasedAStar.js

+14-21
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import Graph from './Graph';
2-
import hexDistanceBetween from './hexDistanceBetween';
1+
import Graph from './Graph.js';
2+
import hexDistanceBetween from './hexDistanceBetween.js';
33

44
export default class BiasedAStar {
5-
constructor(grid, startNode, endNode) {
5+
constructor(grid) {
66
this.graph = new Graph(grid);
7-
this.endNode = endNode;
87
this.path = [];
98
this.pathFound = false;
109
this.noPath = false;
@@ -13,33 +12,27 @@ export default class BiasedAStar {
1312

1413
this.bias = 100;
1514

16-
this.graph[startNode[0]][startNode[1]].isStart = true;
17-
this.graph[startNode[0]][startNode[1]].dStart = 0; // distance from start node
18-
this.graph[startNode[0]][startNode[1]].dEnd = hexDistanceBetween(
19-
startNode,
20-
endNode
21-
); // distance from end node
22-
this.graph[startNode[0]][startNode[1]].d =
23-
this.graph[startNode[0]][startNode[1]].dStart +
24-
this.graph[startNode[0]][startNode[1]].dEnd * this.bias;
25-
this.addToMinDist(this.graph[startNode[0]][startNode[1]]);
26-
27-
this.graph[endNode[0]][endNode[1]].isEnd = true;
15+
this.graph[this.graph.start[0]][
16+
this.graph.start[1]
17+
].dEnd = hexDistanceBetween(this.graph.start, this.graph.end); // distance from end node
18+
this.graph[this.graph.start[0]][this.graph.start[1]].d =
19+
this.graph[this.graph.start[0]][this.graph.start[1]].dEnd * this.bias;
20+
this.addToMinDist(this.graph[this.graph.start[0]][this.graph.start[1]]);
2821
}
2922

3023
/**
3124
* Increments a step of the algorithm.
3225
*/
3326
step() {
3427
if (this.pathFound) {
35-
return true;
28+
return false;
3629
}
3730

3831
if (this.minDist.length === 0) {
3932
// No path exists
4033
this.noPath = true;
4134
this.pathFound = true;
42-
return true;
35+
return false;
4336
}
4437

4538
let currentNode = this.minDist.shift();
@@ -57,18 +50,18 @@ export default class BiasedAStar {
5750
currentNode = previousNode;
5851
} while (!currentNode.isStart);
5952

60-
return true;
53+
return false;
6154
}
6255

6356
for (let i = 0; i < currentNode.neighbours.length; i += 1) {
6457
const neighbour = currentNode.neighbours[i];
6558
checkedNodes.push(neighbour);
6659

6760
if (neighbour.dEnd === undefined) {
68-
neighbour.dStart = Infinity;
61+
neighbour.d = Infinity;
6962
neighbour.dEnd = hexDistanceBetween(
7063
[neighbour.row, neighbour.col],
71-
this.endNode
64+
this.graph.end
7265
);
7366
}
7467

algorithms/dijkstra.js

+12-16
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,41 @@
1+
import Graph from './Graph.js';
2+
13
/**
24
* An implementation of Dijksta's shortest path algorithm. This implementation
35
* finds the shortest path from a start node to an end node in a hexagonal grid
46
* where each node is separated by a distance of one.
57
*/
68

7-
/* global Graph */
8-
99
/**
1010
* Implements our Dijkstra algorithm. Inputs are our hexagonal grid matrix, an
1111
* array representing the start node position and an array representing the end
1212
* node position.
1313
*/
1414
export default class Dijkstra {
15-
constructor(grid, startNode, endNode) {
15+
constructor(grid) {
1616
this.graph = new Graph(grid);
1717
this.path = [];
1818
this.pathFound = false;
1919
this.noPath = false;
2020
this.minDist = []; // Ordered list of nodes with the node of minimum
2121
// distance from the start node at position zero.
2222

23-
this.graph[startNode[0]][startNode[1]].isStart = true;
24-
this.graph[startNode[0]][startNode[1]].d = 0;
25-
this.addToMinDist(this.graph[startNode[0]][startNode[1]]);
26-
27-
this.graph[endNode[0]][endNode[1]].isEnd = true;
23+
this.addToMinDist(this.graph[this.graph.start[0]][this.graph.start[1]]);
2824
}
2925

3026
/**
3127
* Increments a step of the algorithm.
3228
*/
3329
step() {
3430
if (this.pathFound) {
35-
return true;
31+
return false;
3632
}
3733

3834
if (this.minDist.length === 0) {
3935
// No path exists
4036
this.noPath = true;
4137
this.pathFound = true;
42-
return true;
38+
return false;
4339
}
4440

4541
let currentNode = this.minDist.shift();
@@ -57,21 +53,21 @@ export default class Dijkstra {
5753
currentNode = previousNode;
5854
} while (!currentNode.isStart);
5955

60-
return true;
56+
return false;
6157
}
6258

63-
const dPlus1 = currentNode.d + 1;
59+
const dPlus1 = currentNode.dStart + 1;
6460

6561
for (let i = 0; i < currentNode.neighbours.length; i += 1) {
6662
const neighbour = currentNode.neighbours[i];
6763
checkedNodes.push(neighbour);
6864

69-
if (neighbour.d > dPlus1) {
70-
neighbour.d = dPlus1;
65+
if (neighbour.dStart > dPlus1) {
66+
neighbour.dStart = dPlus1;
7167
neighbour.pathTo = currentNode;
7268

7369
if (this.minDist.includes(neighbour)) {
74-
this.minDist.sort((a, b) => a.d - b.d);
70+
this.minDist.sort((a, b) => a.dStart - b.dStart);
7571
} else {
7672
this.addToMinDist(neighbour);
7773
}
@@ -89,7 +85,7 @@ export default class Dijkstra {
8985

9086
addToMinDist(node) {
9187
for (let i = 0; i < this.minDist.length; i += 1) {
92-
if (node.d < this.minDist[i].d) {
88+
if (node.dStart < this.minDist[i].dStart) {
9389
this.minDist.splice(i, 0, node);
9490
return;
9591
}

grid/HexTile.js

+7-24
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,16 @@
22
* Object for storing information about our hexagons.
33
*/
44
export default class HexTile {
5-
constructor(
6-
gridPosition,
7-
hexSize,
8-
isWall = false,
9-
isStart = false,
10-
isEnd = false
11-
) {
5+
constructor(gridPosition, hexSize) {
126
[this.row, this.col] = gridPosition;
137

148
this.width = hexSize.width;
159
this.height = hexSize.height;
1610

17-
this.isWall = isWall;
18-
this.isStart = isStart;
19-
this.isEnd = isEnd;
11+
this.isStart = false;
12+
this.isEnd = false;
13+
this.isWall = false;
14+
this.fill = 'white';
2015

2116
if (this.col % 2 === 0) {
2217
this.xPos = (this.col / 2) * (this.width * 3);
@@ -28,22 +23,10 @@ export default class HexTile {
2823
}
2924
}
3025

31-
get fill() {
32-
if (this.isStart) {
33-
return 'green';
34-
}
35-
if (this.isEnd) {
36-
return 'red';
37-
}
38-
if (this.isWall) {
39-
return 'black';
40-
}
41-
return 'white';
42-
}
43-
4426
reset() {
45-
this.isWall = false;
4627
this.isStart = false;
4728
this.isEnd = false;
29+
this.isWall = false;
30+
this.fill = 'white';
4831
}
4932
}

main.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Grid from './grid/Grid.js';
44
import addStart from './userInterface/addStartEnd.js';
55
import { updateDisplay, drawBackground } from './userInterface/display.js';
66
import addWallBegin from './userInterface/addWalls.js';
7+
import animateAlgorithm from './userInterface/animateAlgorithm.js';
78

89
// Hexagons
910
window.hexSize = { width: 16 }; // Should be divisible by 2
@@ -33,6 +34,9 @@ function updateGridSize(w, h) {
3334
function reset() {
3435
animationCanvas.removeEventListener('mousedown', addWallBegin);
3536

37+
grid.start = undefined;
38+
grid.end = undefined;
39+
3640
grid.forEach((row) => {
3741
row.forEach((tile) => {
3842
tile.reset();
@@ -76,7 +80,15 @@ function resize() {
7680
function setup() {
7781
document.getElementById('resetButton').onclick = reset;
7882

79-
document.getElementById('dijkstraButton').onclick = reset;
83+
document.getElementById('dijkstraButton').onclick = () => {
84+
animateAlgorithm('dijkstra');
85+
};
86+
document.getElementById('aStarButton').onclick = () => {
87+
animateAlgorithm('aStar');
88+
};
89+
document.getElementById('biasedAStarButton').onclick = () => {
90+
animateAlgorithm('biasedAStar');
91+
};
8092

8193
const [w, h] = updateCanvasSize();
8294
updateGridSize(w, h);

userInterface/addStartEnd.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ function addEnd(event) {
1818

1919
grid.end = [x, y];
2020
grid[x][y].isEnd = true;
21-
22-
grid[x][y].isWall = false; // just in case they click on a wall
21+
grid[x][y].fill = 'red';
2322

2423
updateDisplay(animationContext);
2524

@@ -39,8 +38,7 @@ export default function addStart(event) {
3938

4039
grid.start = [x, y];
4140
grid[x][y].isStart = true;
42-
43-
grid[x][y].isWall = false; // just in case they click on a wall
41+
grid[x][y].fill = 'green';
4442

4543
updateDisplay(animationContext);
4644

0 commit comments

Comments
 (0)