Small refactoring for better readabilty
This commit is contained in:
@@ -9,11 +9,12 @@
|
||||
<mat-button-toggle [value]="NodeType.Wall">{{ 'PATHFINDING.WALL' | translate }}</mat-button-toggle>
|
||||
<mat-button-toggle [value]="NodeType.None">{{ 'PATHFINDING.CLEAR_NODE' | translate }}</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
|
||||
<button mat-raised-button color="primary" (click)="visualizeDijkstra()">{{ 'PATHFINDING.DIJKSTRA' | translate }}</button>
|
||||
<button mat-raised-button color="accent" (click)="visualizeAStar()">{{ 'PATHFINDING.ASTAR' | translate }}</button>
|
||||
<button mat-raised-button color="warn" (click)="resetBoard()">{{ 'PATHFINDING.RESET_BOARD' | translate }}</button>
|
||||
<button mat-raised-button color="warn" (click)="clearBoard()">{{ 'PATHFINDING.CLEAR_BOARD' | translate }}</button>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<button matButton="filled" class="primary" (click)="visualizeDijkstra()">{{ 'PATHFINDING.DIJKSTRA' | translate }}</button>
|
||||
<button matButton="filled" class="accent" (click)="visualizeAStar()">{{ 'PATHFINDING.ASTAR' | translate }}</button>
|
||||
<button matButton="filled" class="warn" (click)="resetBoard()">{{ 'PATHFINDING.RESET_BOARD' | translate }}</button>
|
||||
<button matButton="filled" class="warn" (click)="clearBoard()">{{ 'PATHFINDING.CLEAR_BOARD' | translate }}</button>
|
||||
</div>
|
||||
|
||||
<div class="legend">
|
||||
|
||||
@@ -6,8 +6,6 @@ import { Node, GRID_ROWS, GRID_COLS } from '../pathfinding.models';
|
||||
})
|
||||
export class PathfindingService {
|
||||
|
||||
|
||||
|
||||
// Helper function to get all unvisited neighbors of a given node
|
||||
getUnvisitedNeighbors(node: Node, grid: Node[][]): Node[] {
|
||||
const neighbors: Node[] = [];
|
||||
@@ -42,16 +40,23 @@ export class PathfindingService {
|
||||
this.sortNodesByDistance(unvisitedNodes);
|
||||
const closestNode = unvisitedNodes.shift() as Node;
|
||||
|
||||
// If we encounter a wall, skip it
|
||||
if (closestNode.isWall) continue;
|
||||
if (closestNode.isWall) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the closest node is at an infinite distance, we're trapped
|
||||
if (closestNode.distance === Infinity) return { visitedNodesInOrder, nodesInShortestPathOrder: [] };
|
||||
const isTrapped = closestNode.distance === Infinity;
|
||||
if (isTrapped)
|
||||
{
|
||||
return { visitedNodesInOrder, nodesInShortestPathOrder: [] };
|
||||
}
|
||||
|
||||
closestNode.isVisited = true;
|
||||
visitedNodesInOrder.push(closestNode);
|
||||
|
||||
if (closestNode === endNode) return { visitedNodesInOrder, nodesInShortestPathOrder: this.getNodesInShortestPath(endNode) };
|
||||
const reachedTheEnd = closestNode === endNode;
|
||||
if (reachedTheEnd) {
|
||||
return {visitedNodesInOrder, nodesInShortestPathOrder: this.getNodesInShortestPath(endNode)};
|
||||
}
|
||||
|
||||
this.updateUnvisitedNeighbors(closestNode, grid);
|
||||
}
|
||||
@@ -75,7 +80,6 @@ export class PathfindingService {
|
||||
aStar(grid: Node[][], startNode: Node, endNode: Node): { visitedNodesInOrder: Node[], nodesInShortestPathOrder: Node[] } {
|
||||
const visitedNodesInOrder: Node[] = [];
|
||||
startNode.distance = 0;
|
||||
// hueristic distance
|
||||
startNode['distance'] = this.calculateHeuristic(startNode, endNode);
|
||||
// fScore = gScore + hScore
|
||||
startNode['fScore'] = startNode.distance + startNode['distance'];
|
||||
@@ -83,29 +87,28 @@ export class PathfindingService {
|
||||
const openSet: Node[] = [startNode];
|
||||
const allNodes = this.getAllNodes(grid);
|
||||
|
||||
// Initialize all nodes' fScore to infinity except for the startNode
|
||||
for (const node of allNodes) {
|
||||
if (node !== startNode) {
|
||||
node['fScore'] = Infinity;
|
||||
node.distance = Infinity; // gScore
|
||||
}
|
||||
}
|
||||
|
||||
this.initNodesForAStar(allNodes, startNode);
|
||||
|
||||
while (openSet.length > 0) {
|
||||
openSet.sort((nodeA, nodeB) => nodeA['fScore'] - nodeB['fScore']);
|
||||
const currentNode = openSet.shift() as Node;
|
||||
|
||||
if (currentNode.isWall) continue;
|
||||
if (currentNode.isWall) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the closest node is at an infinite distance, we're trapped
|
||||
if (currentNode.distance === Infinity) return { visitedNodesInOrder, nodesInShortestPathOrder: [] };
|
||||
const isTrapped = currentNode.distance === Infinity;
|
||||
if (isTrapped)
|
||||
{
|
||||
return {visitedNodesInOrder, nodesInShortestPathOrder: []};
|
||||
}
|
||||
|
||||
|
||||
currentNode.isVisited = true;
|
||||
visitedNodesInOrder.push(currentNode);
|
||||
|
||||
if (currentNode === endNode) {
|
||||
const reachedTheEnd = currentNode === endNode;
|
||||
if (reachedTheEnd) {
|
||||
return { visitedNodesInOrder, nodesInShortestPathOrder: this.getNodesInShortestPath(endNode) };
|
||||
}
|
||||
|
||||
@@ -114,6 +117,15 @@ export class PathfindingService {
|
||||
const tentativeGScore = currentNode.distance + 1; // Distance from start to neighbor
|
||||
|
||||
if (tentativeGScore < neighbor.distance) {
|
||||
this.updateNeighborNode(neighbor, currentNode, tentativeGScore, endNode, openSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { visitedNodesInOrder, nodesInShortestPathOrder: [] };
|
||||
}
|
||||
|
||||
private updateNeighborNode(neighbor: Node, currentNode: Node, tentativeGScore: number, endNode: Node, openSet: Node[]) {
|
||||
neighbor.previousNode = currentNode;
|
||||
neighbor.distance = tentativeGScore;
|
||||
neighbor['distance'] = this.calculateHeuristic(neighbor, endNode);
|
||||
@@ -123,10 +135,14 @@ export class PathfindingService {
|
||||
openSet.push(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { visitedNodesInOrder, nodesInShortestPathOrder: [] };
|
||||
private initNodesForAStar(allNodes: Node[], startNode: Node) {
|
||||
for (const node of allNodes) {
|
||||
if (node !== startNode) {
|
||||
node['fScore'] = Infinity;
|
||||
node.distance = Infinity; // gScore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private calculateHeuristic(node: Node, endNode: Node): number {
|
||||
|
||||
Reference in New Issue
Block a user