/// <summary> /// Wyszukuje najkrótszą ścieżkę pomiędzy dwoma polami. /// Implementacja algorytmu A*. /// </summary> /// <param name="fields">Tablica pól z zadeklarowną dostępnością. Muszą dziedziczyć po klasie PathFindableField</param> /// <param name="start">Pole startowe</param> /// <param name="destination">Pole końcowe</param> /// <param name="minIndexLimit">Minimalne indeksy pól branych pod uwagę przy wyznaczaniu ścieżki</param> /// <param name="maxIndexLimit">Maksymalne indeksy pól branych pod uwagę przy wyznaczaniu ścieżki</param> /// <seealso cref="PathFindableField"/> /// <exception cref="ArgumentNullException" /> /// <exception cref="ArgumentOutOfRangeException" /> /// <returns>Najkrótsza ścieżka (stos)</returns> internal static Stack <Vector2Int> FindPath(bool[][] fields, Vector2Int start, Vector2Int destination, Vector2Int minIndexLimit, Vector2Int maxIndexLimit) { #if DEBUG CheckArguments(fields, start, destination, minIndexLimit, maxIndexLimit); #endif var openSet = new FastPriorityQueue <AStarPosition>((maxIndexLimit.x - minIndexLimit.x) * (maxIndexLimit.y - minIndexLimit.y)); var startNode = new AStarNode(); InitializeAstarNodes(fields, out AStarNode[][] nodes); InitializeParents(fields, out Vector2Int[][] parents); AddToOpenSet(openSet, nodes, startNode, start); while (openSet.Count > 0) { var actualNodePosition = openSet.Dequeue(); // znaleziono ścieżkę if (actualNodePosition.position == destination) { return(CombinePath(actualNodePosition.position, start, nodes, parents)); } AddToClosedSet(nodes, actualNodePosition.position); foreach (var neighborPosition in GetNeighbors(fields, nodes, actualNodePosition.position, minIndexLimit, maxIndexLimit)) { if (IsInClosedSet(neighborPosition, nodes)) { continue; } var actualG = nodes[actualNodePosition.position.x][actualNodePosition.position.y].g + 1; if (IsInOpenSet(neighborPosition, nodes)) { var neighbor = nodes[neighborPosition.x][neighborPosition.y]; if (actualG < neighbor.g) { parents[neighborPosition.x][neighborPosition.y] = actualNodePosition.position; neighbor.g = actualG; openSet.UpdatePriority(actualNodePosition, neighbor.F); } } else { parents[neighborPosition.x][neighborPosition.y] = actualNodePosition.position; nodes[neighborPosition.x][neighborPosition.y].g = actualG; nodes[neighborPosition.x][neighborPosition.y].h = HexHelper.GetDistance(neighborPosition, destination); nodes[neighborPosition.x][neighborPosition.y].state = AStarNode.States.InOpenSet; openSet.Enqueue(new AStarPosition(neighborPosition), nodes[neighborPosition.x][neighborPosition.y].F); } } } return(new Stack <Vector2Int>()); }
/// <summary> /// Wyszukuje najkrótszą ścieżkę pomiędzy dwoma polami. /// Implementacja algorytmu A*. /// </summary> /// <param name="fields">Tablica pól z zadeklarowną dostępnością. Muszą dziedziczyć po klasie PathFindableField</param> /// <param name="start">Pole startowe</param> /// <param name="destination">Pole końcowe</param> /// <param name="minIndexes">Minimalne indeksy pól branych pod uwagę przy wyznaczaniu ścieżki</param> /// <param name="maxIndexes">Maksymalne indeksy pól branych pod uwagę przy wyznaczaniu ścieżki</param> /// <seealso cref="PathFindableField"/> /// <exception cref="ArgumentNullException" /> /// <exception cref="ArgumentOutOfRangeException" /> /// <returns>Najkrótsza ścieżka (stos)</returns> internal static Stack <Vector2Int> FindPath(bool[][] fields, Vector2Int start, Vector2Int destination, Vector2Int minIndexes, Vector2Int maxIndexes) { #if DEBUG CheckArguments(fields, start, destination, minIndexes, maxIndexes); #endif Node[][] nodes = InitializeAstarNodes(fields); var openSet = new FastPriorityQueue <Node>((maxIndexes.x - minIndexes.x) * (maxIndexes.y - minIndexes.y)); var startNode = new Node(start); AddToOpenSet(openSet, nodes, startNode); while (openSet.Count > 0) { var actualNode = openSet.Dequeue(); // znaleziono ścieżkę if (actualNode.position == destination) { return(CombinePath(actualNode)); } AddToClosedSet(nodes, actualNode); foreach (var neighborPosition in GetNeighbors(fields, nodes, actualNode.position, minIndexes, maxIndexes)) { if (IsInClosedSet(neighborPosition, nodes)) { continue; } var actualG = actualNode.g + 1; if (IsInOpenSet(neighborPosition, nodes)) { var neighbor = nodes[neighborPosition.x][neighborPosition.y]; if (actualG < neighbor.g) { neighbor.parent = actualNode; neighbor.g = actualG; openSet.UpdatePriority(neighbor, neighbor.F); } } else { var neighbor = new Node(neighborPosition) { parent = actualNode, g = actualG, }; neighbor.h = HexHelper.GetDistance(neighbor.position, destination); AddToOpenSet(openSet, nodes, neighbor); } } } return(new Stack <Vector2Int>()); }