55 lines
1.8 KiB
C#
55 lines
1.8 KiB
C#
namespace AdventOfCode.Core.Shared.A_Star
|
|
{
|
|
public class AStarGrid<T>(T[] data) : Grid<T>(data) where T : AStarNode
|
|
{
|
|
public int TileMoveCost { get; set; }
|
|
|
|
public int MinimalSteps(T start, T destination)
|
|
{
|
|
List<T> openNodes = [start];
|
|
List<T> closedNodes = [];
|
|
|
|
while(openNodes.Count != 0)
|
|
{
|
|
// get the lowest F-cost node
|
|
T current = openNodes.OrderBy(n => n.FCost).First();
|
|
openNodes.Remove(current);
|
|
closedNodes.Add(current);
|
|
|
|
if (current == destination)
|
|
{
|
|
//done
|
|
return 1;
|
|
}
|
|
|
|
var neighbors = GetNeighbors(current, false)
|
|
.Where(n => current.CanMoveTo(current));
|
|
|
|
// calc costs
|
|
foreach(T neighbor in neighbors)
|
|
{
|
|
long g = current.GCost + GetMoveCost(current, neighbor);
|
|
long h = neighbor.GetManhattanDistance(destination) * GetMoveCost(current, neighbor);
|
|
long f = g + h;
|
|
|
|
int openNodeIndex = openNodes.IndexOf(neighbor),
|
|
closedNodeIndex = closedNodes.IndexOf(neighbor);
|
|
|
|
if (openNodeIndex > 0 && openNodes[openNodeIndex].FCost > f)
|
|
{
|
|
openNodes[openNodeIndex].ParentNode = neighbor;
|
|
openNodes[openNodeIndex].GCost = g;
|
|
openNodes[openNodeIndex].HCost = h;
|
|
}
|
|
|
|
openNodes.Add(neighbor);
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
public virtual int GetMoveCost(T current, T neighbor) => TileMoveCost;
|
|
}
|
|
}
|