Advertisement
Layvu

G3. Teleport maze

Apr 5th, 2023
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.18 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5.  
  6. namespace Maze
  7. {
  8.     class Program
  9.     {
  10.         static void Main()
  11.         {
  12.             // 'S' - начальная точка, 'E' - конечная точка, 'X' - стена, 'T' - телепорт
  13.             string[] maze =
  14.             {
  15.                 "SX   X    ",
  16.                 " X XXXXX X",
  17.                 "     TX   ",
  18.                 "XXXX XXX X",
  19.                 "  T      X",
  20.                 " XXX XXXTX",
  21.                 " X       E"
  22.             };
  23.  
  24.             var shortestPath = FindShortestPath(maze).Reverse().ToList();
  25.  
  26.             foreach (var point in shortestPath)
  27.                 Console.WriteLine($"({point.X}, {point.Y})");
  28.         }
  29.  
  30.         public static IEnumerable<Point> FindShortestPath(string[] maze)
  31.         {
  32.             var elements = FindElements(maze);
  33.             var start = elements['S'].First();
  34.             var end = elements['E'].First();
  35.             var teleports = elements.ContainsKey('T') ? elements['T'] : null;
  36.            
  37.             if (!elements.ContainsKey('S')) throw new ArgumentException("The maze does not have a start");
  38.             if (!elements.ContainsKey('E')) throw new ArgumentException("The maze does not have an end");
  39.  
  40.             var queue = new Queue<Point>();
  41.             var visited = new HashSet<Point>();
  42.             var parents = new Dictionary<Point, Point>();
  43.  
  44.             queue.Enqueue(start);
  45.             visited.Add(start);
  46.             while (queue.Count != 0)
  47.             {
  48.                 var currentPosition = queue.Dequeue();
  49.  
  50.                 if (currentPosition == end)
  51.                 {
  52.                     yield return currentPosition;
  53.                     while (currentPosition != start)
  54.                     {
  55.                         currentPosition = parents[currentPosition];
  56.                         yield return currentPosition;
  57.                     }
  58.                     break;
  59.                 }
  60.  
  61.                 for (var dx = -1; dx <= 1; dx++)
  62.                 for (var dy = -1; dy <= 1; dy++)
  63.                 {
  64.                     if (dx != 0 && dy != 0) continue;
  65.                     var nextPosition = new Point(currentPosition.X + dx, currentPosition.Y + dy);
  66.                     if (!CouldBeNewPoint(nextPosition, maze, visited)) continue;
  67.                    
  68.                     visited.Add(nextPosition);
  69.                     queue.Enqueue(nextPosition);
  70.                     parents[nextPosition] = currentPosition;
  71.                 }
  72.                
  73.                 if (teleports?.Count > 0 && teleports.Contains(currentPosition))
  74.                 {
  75.                     foreach (var teleportPair in teleports)
  76.                     {
  77.                         if (teleportPair != currentPosition && CouldBeNewPoint(teleportPair, maze, visited))
  78.                         {
  79.                             visited.Add(teleportPair);
  80.                             queue.Enqueue(teleportPair);
  81.                             parents[teleportPair] = currentPosition;
  82.                         }
  83.                     }
  84.                 }
  85.             }
  86.         }
  87.  
  88.         private static bool CouldBeNewPoint(Point point, string[] maze, HashSet<Point> visited)
  89.         {
  90.             var height = maze.Length;
  91.             var width = maze[0].Length;
  92.             return point.X >= 0 && point.X < width &&
  93.                    point.Y >= 0 && point.Y < height &&
  94.                    maze[point.Y][point.X] != 'X' &&
  95.                    !visited.Contains(point);
  96.         }
  97.  
  98.         private static Dictionary<char, List<Point>> FindElements(string[] maze)
  99.         {
  100.             var elementAndPositions = new Dictionary<char, List<Point>>();
  101.             for (var y = 0; y < maze.Length; y++)
  102.             for (var x = 0; x < maze[y].Length; x++)
  103.             {
  104.                 var currentPosition = maze[y][x];
  105.                 if (!elementAndPositions.ContainsKey(currentPosition))
  106.                     elementAndPositions[currentPosition] = new List<Point>();
  107.                 elementAndPositions[currentPosition].Add(new Point(x, y));
  108.             }
  109.             return elementAndPositions;
  110.         }
  111.     }
  112. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement