Skip to content

Instantly share code, notes, and snippets.

@jvanmelckebeke
Created May 31, 2018 20:08
Show Gist options
  • Save jvanmelckebeke/cbc2bd06af59aeef35b979460922e07e to your computer and use it in GitHub Desktop.
Save jvanmelckebeke/cbc2bd06af59aeef35b979460922e07e to your computer and use it in GitHub Desktop.
module.exports = {
PathFinder: (grid, gridHeight, gridWidth) => {
/* grid;
gridHeight;
gridWidth;
startTile;
endTile;
/!** Array of the already checked tiles. *!/
closedList = [];
openList = [];*/
console.log('activated');
let openList = [];
let closedList = [];
let startTile, endTile;
function searchPath(start, end) {
startTile = start;
console.log(startTile);
endTile = end;
/** Path validation */
if (grid[start.y][start.x] === 0) {
console.log('The start tile in not walkable, choose different tile than', start, grid[start.y][start.x]);
return [];
}
if (grid[end.y][end.x] === 0) {
console.log('The end tile in not walkable, choose different tile than', end);
return [];
}
/** Start A* Algorithm */
/** Add the starting tile to the openList */
console.log('start', start, openList.push(start)); //expected output: start {x: 10, y: 9} 1 || real output: the same
console.log('openlist = ', openList); // expected output: [{x: 10, y: 9}] || real output: []
let currentTile;
while (openList.length > 0) {
console.log('openlist = ', openList);
//current node = node for open list with the lowest cost.
currentTile = getTileWithLowestTotal(openList);
//if the currentTile is the endTile, then we can stop searching
if (currentTile.x === end.x && currentTile.y === end.y) {
return shortestPath();
}
else {
//move the current tile to the closed list and remove it from the open list.
openList.splice(openList.indexOf(currentTile) - 1, 1);
// openList.filter(value => value.x !== currentTile.x && value.y !== currentTile.y);
closedList.push(currentTile);
// //Get all adjacent Tiles
let adjacentTiles = getAdjacentTiles(currentTile);
for (let adjacentTile of adjacentTiles) {
//Get tile is not in the open list
if (!openList.contains(adjacentTile)) {
//Get tile is not in the closed list
if (!closedList.contains(adjacentTile)) {
//move it to the open list and calculate cost
openList.push(adjacentTile);
//calculate the cost
adjacentTile.cost = currentTile.cost + 1;
//calculate the manhattan distance
adjacentTile.heuristic = manhattanDistance(adjacentTile);
// calculate the total amount
adjacentTile.total = adjacentTile.cost + adjacentTile.heuristic;
}
}
}
}
}
console.log('boo');
}
function getTileWithLowestTotal(openList) {
let tileWithLowestTotal = {};
let lowestTotal = 999999999;
/** Search open tiles and get the tile with the lowest total cost */
for (let openTile of openList) {
if (openTile.total <= lowestTotal) {
//clone lowestTotal
lowestTotal = openTile.total;
tileWithLowestTotal = openTile;
}
}
console.log('tilewithlowesttotal', tileWithLowestTotal);
return tileWithLowestTotal;
}
function getAdjacentTiles(current) {
let adjacentTiles = [];
let adjacentTile = {};
//Tile to left
if (current.x - 1 >= 0) {
adjacentTile = grid[current.x - 1][current.y];
if (adjacentTile === 1) {
adjacentTiles.push({x: current.x, y: current.y, cost: 1});
}
}
//Tile to right
if (current.x + 1 < gridWidth) {
adjacentTile = grid[current.x + 1][current.y];
if (adjacentTile === 1) {
adjacentTiles.push({x: current.x, y: current.y, cost: 1});
}
}
//Tile to Under
if (current.y + 1 < gridHeight) {
adjacentTile = grid[current.x][current.y + 1];
if (adjacentTile === 1) {
adjacentTiles.push({x: current.x, y: current.y, cost: 1});
}
}
//Tile to Above
if (current.y - 1 >= 0) {
adjacentTile = grid[current.x][current.y - 1];
if (adjacentTile === 1) {
adjacentTiles.push({x: current.x, y: current.y, cost: 1});
}
}
return adjacentTiles;
}
/** Calculate the manhattan distance */
function manhattanDistance(adjacentTile) {
return Math.abs((endTile.x - adjacentTile.x) + (endTile.y - adjacentTile.y));
}
function shortestPath() {
let startFound = false;
let currentTile = endTile;
let pathTiles = [];
//includes the end tile in the path
pathTiles.push(endTile);
while (!startFound) {
let adjacentTiles = getAdjacentTiles(currentTile);
//check to see what newest current tile.
for (let adjacentTile of adjacentTiles) {
//check if it is the start tile
if (adjacentTile.x === startTile.x && adjacentTile.y === startTile.y) {
return pathTiles;
}
//it has to be inside the closedList or openList
if (closedList.contains(adjacentTile) || openList.contains(adjacentTile)) {
if (adjacentTile.cost <= currentTile.cost && adjacentTile.cost > 0) {
//change the current tile.
currentTile = adjacentTile;
//Add this adjacentTile to the path list
pathTiles.push(adjacentTile);
//highlight way with yellow balls
break;
}
}
}
}
}
return {
searchPath: (start, end) => searchPath(start, end),
};
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment