Small refactoring for better readabilty

This commit is contained in:
2026-02-02 09:28:05 +01:00
parent 01f66d4b8f
commit 17a787b0f1
2 changed files with 50 additions and 33 deletions

View File

@@ -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">

View File

@@ -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,14 +117,7 @@ export class PathfindingService {
const tentativeGScore = currentNode.distance + 1; // Distance from start to neighbor
if (tentativeGScore < neighbor.distance) {
neighbor.previousNode = currentNode;
neighbor.distance = tentativeGScore;
neighbor['distance'] = this.calculateHeuristic(neighbor, endNode);
neighbor['fScore'] = neighbor.distance + neighbor['distance'];
if (!openSet.includes(neighbor)) {
openSet.push(neighbor);
}
this.updateNeighborNode(neighbor, currentNode, tentativeGScore, endNode, openSet);
}
}
}
@@ -129,6 +125,26 @@ export class PathfindingService {
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);
neighbor['fScore'] = neighbor.distance + neighbor['distance'];
if (!openSet.includes(neighbor)) {
openSet.push(neighbor);
}
}
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 {
// Manhattan distance heuristic
return Math.abs(node.row - endNode.row) + Math.abs(node.col - endNode.col);