| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- namespace Day17;
- public class Map
- {
- private readonly Tile[,] _tiles;
- private readonly int _width;
- private readonly int _height;
- private Func<Path?, Tile, Vec, Path> _pathFactory;
- public Map(Tile[,] tiles, int width, int height)
- {
- _tiles = tiles;
- _width = width;
- _height = height;
- _pathFactory = (path, tile, vRun) => new Path(path, tile, vRun);
- }
- public void Print()
- {
- for (var y = 0; y < _height; y++)
- {
- for (var x = 0; x < _width; x++)
- {
- Console.Write(_tiles[x, y].Display);
- _tiles[x, y].ClearDisplay();
- }
- Console.WriteLine();
- }
- Console.WriteLine();
- }
- public int ShortestPath()
- {
- var goal = _tiles[_width - 1, _height - 1];
- var visited = new HashSet<string>();
- var queue = new PriorityQueue<Path, int>();
- queue.Enqueue(_pathFactory(null, _tiles[0, 0], new Vec(1, 0)), 0);
- queue.Enqueue(_pathFactory(null, _tiles[0, 0], new Vec(0, 1)), 0);
- while (queue.Count > 0)
- {
- var current = queue.Dequeue();
- var curKey = current.GetKey();
- if (!visited.Add(curKey))
- {
- continue;
- }
- foreach (var v in current.Next())
- {
- var pos = current.Tile.Position.Add(v);
- if (IsValid(pos))
- {
- var next = _pathFactory(current, Tile(pos), v);
- if (next.Tile == goal && next.CanStop())
- {
- var cost = Backtrack(next);
- return cost;
- }
- queue.Enqueue(next, next.Cost);
- }
- }
- }
- return -1;
- }
- public void SetUltraPathMode()
- {
- _pathFactory = (path, tile, vRun) => new UltraPath(path, tile, vRun);
- }
- private int Backtrack(Path path)
- {
- var sum = 0;
- while (path.Prev != null)
- {
- sum += path.Tile.Cost;
- path.Tile.SetDisplay(path.VRun.Arrow());
- path = path.Prev;
- }
- return sum;
- }
- private bool IsValid(Vec position)
- {
- return position.X >= 0 && position.X < _width && position.Y >= 0 && position.Y < _height;
- }
- private Tile Tile(Vec position)
- {
- return _tiles[position.X, position.Y];
- }
- }
|