Map.cs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. namespace Day17;
  2. public class Map
  3. {
  4. private readonly Tile[,] _tiles;
  5. private readonly int _width;
  6. private readonly int _height;
  7. private Func<Path?, Tile, Vec, Path> _pathFactory;
  8. public Map(Tile[,] tiles, int width, int height)
  9. {
  10. _tiles = tiles;
  11. _width = width;
  12. _height = height;
  13. _pathFactory = (path, tile, vRun) => new Path(path, tile, vRun);
  14. }
  15. public void Print()
  16. {
  17. for (var y = 0; y < _height; y++)
  18. {
  19. for (var x = 0; x < _width; x++)
  20. {
  21. Console.Write(_tiles[x, y].Display);
  22. _tiles[x, y].ClearDisplay();
  23. }
  24. Console.WriteLine();
  25. }
  26. Console.WriteLine();
  27. }
  28. public int ShortestPath()
  29. {
  30. var goal = _tiles[_width - 1, _height - 1];
  31. var visited = new HashSet<string>();
  32. var queue = new PriorityQueue<Path, int>();
  33. queue.Enqueue(_pathFactory(null, _tiles[0, 0], new Vec(1, 0)), 0);
  34. queue.Enqueue(_pathFactory(null, _tiles[0, 0], new Vec(0, 1)), 0);
  35. while (queue.Count > 0)
  36. {
  37. var current = queue.Dequeue();
  38. var curKey = current.GetKey();
  39. if (!visited.Add(curKey))
  40. {
  41. continue;
  42. }
  43. foreach (var v in current.Next())
  44. {
  45. var pos = current.Tile.Position.Add(v);
  46. if (IsValid(pos))
  47. {
  48. var next = _pathFactory(current, Tile(pos), v);
  49. if (next.Tile == goal && next.CanStop())
  50. {
  51. var cost = Backtrack(next);
  52. return cost;
  53. }
  54. queue.Enqueue(next, next.Cost);
  55. }
  56. }
  57. }
  58. return -1;
  59. }
  60. public void SetUltraPathMode()
  61. {
  62. _pathFactory = (path, tile, vRun) => new UltraPath(path, tile, vRun);
  63. }
  64. private int Backtrack(Path path)
  65. {
  66. var sum = 0;
  67. while (path.Prev != null)
  68. {
  69. sum += path.Tile.Cost;
  70. path.Tile.SetDisplay(path.VRun.Arrow());
  71. path = path.Prev;
  72. }
  73. return sum;
  74. }
  75. private bool IsValid(Vec position)
  76. {
  77. return position.X >= 0 && position.X < _width && position.Y >= 0 && position.Y < _height;
  78. }
  79. private Tile Tile(Vec position)
  80. {
  81. return _tiles[position.X, position.Y];
  82. }
  83. }