Advertisement
Korotkodul

Задача №2 Выход есть!

Mar 28th, 2025 (edited)
443
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.62 KB | None | 0 0
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from IPython.display import display, clear_output
  4. from IPython.display import HTML
  5. from matplotlib.animation import FuncAnimation
  6. import time
  7. from queue import Queue
  8.  
  9. def find_shortest_path(
  10.     maze: np.ndarray,
  11.     start: tuple[int, int],
  12.     end: tuple[int, int]
  13. ):
  14.   parent = np.full((maze.shape[0], maze.shape[1], 2), [-1, -1])
  15.   parent[start[0]][start[1]] = start
  16.   visited = np.zeros(maze.shape)
  17.   visited[start[0]][start[1]] = 1
  18.   level = np.full(maze.shape, -1)
  19.   level[start[0]][start[1]] = -1
  20.   queue = Queue()
  21.   queue.put(start)
  22.   while not queue.empty():
  23.       node = queue.get()
  24.       level[node[0]][node[1]] = level[parent[node[0]][node[1]][0]][parent[node[0]][node[1]][1]] + 1
  25.       #print ("node: ", node)
  26.       dx = [0, 1, 0, -1]
  27.       dy = [-1,0, 1, 0]
  28.       neighbors = []
  29.       for i in range(4):
  30.         x = node[0] + dx[i]
  31.         y = node[1] + dy[i]
  32.         if 0 <= x < maze.shape[0] and 0 <= y < maze.shape[1] and maze[x][y] and not visited[x][y]:
  33.           neighbors.append(tuple((x, y)))
  34.       for neighbor in neighbors:
  35.           if not visited[neighbor[0]][neighbor[1]]:
  36.               visited[neighbor[0]][neighbor[1]] = 1
  37.               queue.put(neighbor)
  38.               parent[neighbor[0]][neighbor[1]] = [node[0], node[1]]
  39.   """print("visited")
  40.  print(visited)
  41.  #print("parent")
  42.  #print(parent)"""
  43.   if end != start and level[end[0]][end[1]] == -1:
  44.     return False, False
  45.   path = [np.array([end[0], end[1]])]
  46.   nd = end
  47.   while not (nd[0] == start[0] and nd[1] == start[1]):
  48.     nd = parent[nd[0]][nd[1]]
  49.     path.append(nd)
  50.   return path, level
  51.  
  52.  
  53. def visualize_grid(size_x, size_y, coordinates, grid_data, level):
  54.     fig, ax = plt.subplots(figsize=(size_y, size_x))  # Изменение порядка, size_x — строки, size_y — столбцы
  55.  
  56.     # Настройка осей
  57.     ax.set_xticks(np.arange(size_y))  # Координаты по оси X (по столбцам)
  58.     ax.set_yticks(np.arange(size_x))  # Координаты по оси Y (по строкам)
  59.     ax.set_xticklabels(np.arange(size_y))  # Подписи для оси X
  60.     ax.set_yticklabels(np.arange(size_x))  # Подписи для оси Y
  61.  
  62.     # Жирные линии для сетки между клетками (толщина линии увеличена)
  63.     ax.set_xticks(np.arange(size_y + 1) - 0.5, minor=True)  # Для рисования сетки
  64.     ax.set_yticks(np.arange(size_x + 1) - 0.5, minor=True)  # Для рисования сетки
  65.     ax.grid(which="minor", color="black", linestyle='-', linewidth=6)  # Жирная сетка (толщина линии увеличена в 3 раза)
  66.  
  67.     # Отображаем сетку по краям (границы)
  68.     ax.spines['top'].set_linewidth(6)  # Верхняя граница (толщина линии увеличена)
  69.     ax.spines['right'].set_linewidth(6)  # Правая граница (толщина линии увеличена)
  70.     ax.spines['bottom'].set_linewidth(6)  # Нижняя граница (толщина линии увеличена)
  71.     ax.spines['left'].set_linewidth(6)  # Левая граница (толщина линии увеличена)
  72.  
  73.     # Убираем подписи с осей, потому что они уже на координатах
  74.     ax.tick_params(which="both", bottom=False, left=False, labelbottom=False, labelleft=False)
  75.  
  76.     plt.xlim(-0.5, size_y - 0.5)
  77.     plt.ylim(size_x - 0.5, -0.5)  # Инвертируем ось Y, чтобы (0, 0) была в верхнем левом углу
  78.     ax.set_aspect('equal')
  79.  
  80.     # Отображаем клетки в зависимости от значений в grid_data
  81.     for i in range(size_x):  # Идем сверху вниз по оси X (строки)
  82.         for j in range(size_y):  # И слева направо по оси Y (столбцы)
  83.             color = 'blue' if grid_data[i, j] == 1 else 'white'
  84.             ax.add_patch(plt.Rectangle((j - 0.5, i - 0.5), 1, 1, color=color))  # Заполняем клетки
  85.  
  86.     # Раскрашиваем клетки в розовый цвет, если они находятся в списке координат
  87.     for x, y in coordinates:
  88.         ax.add_patch(plt.Rectangle((y - 0.5, x - 0.5), 1, 1, color='pink'))  # Розовые клетки (x по Y, y по X)
  89.  
  90.     # Добавление координат для оси X снизу (сдвигаем выше)
  91.     for i in range(size_y):
  92.         ax.text(i, -0.8, str(i), ha='center', va='center', fontsize=12)  # Подписи снизу
  93.  
  94.     # Добавление координат для оси Y слева (сдвигаем влево)
  95.     for j in range(size_x):
  96.         ax.text(-0.8, j, str(j), ha='center', va='center', fontsize=12)  # Подписи слева
  97.  
  98.     # Список для хранения текстовых объектов
  99.     text_objects = []
  100.  
  101.     # Функция обновления для анимации
  102.     def update(frame):
  103.         nonlocal text_objects
  104.         # Очищаем старые текстовые объекты только после того, как отрисованы все цифры
  105.         if frame == len(np.unique(level)) - 1:
  106.             for text in text_objects:
  107.                 text.remove()
  108.             text_objects.clear()  # Очищаем список после удаления старых цифр
  109.  
  110.         # Выбираем цифры, которые будут отрисовываться
  111.         unique_values = np.unique(level)  # Получаем уникальные значения в level
  112.         unique_values = unique_values[unique_values != -1]  # Убираем -1, чтобы не отображать его
  113.  
  114.         # Перемещаемся по уровням и рисуем соответствующие цифры
  115.         value = unique_values[frame % len(unique_values)]  # Выбираем очередное значение для отображения
  116.         for i in range(size_x):
  117.             for j in range(size_y):
  118.                 if level[i, j] == value:
  119.                     text = ax.text(j, i, str(value), ha='center', va='center', fontsize=12, color='red', fontweight='bold')
  120.                     text_objects.append(text)  # Сохраняем объект текста
  121.  
  122.         # Возвращаем список текстовых объектов
  123.         return text_objects
  124.  
  125.     # Создаём анимацию
  126.     anim = FuncAnimation(fig, update, frames=len(np.unique(level)) - 1, interval=1000, repeat=True)
  127.     # Сохраняем анимацию в файл
  128.     return anim
  129.  
  130. def animate_wave_algorithm(
  131.     maze: np.ndarray,
  132.     start: tuple[int, int],
  133.     end: tuple[int, int],
  134.     save_path: str = ""
  135. ): #  -> FuncAnimation:
  136.     path, level = find_shortest_path(maze, start, end)
  137.     if not path:
  138.       print("NO PATH FROM START TO END")
  139.       exit(0)
  140.     anim = visualize_grid(maze.shape[0], maze.shape[1], path, maze, level)
  141.     return anim
  142.  
  143.  
  144. maze = np.array([
  145.     [0, 0, 0, 0, 0, 0, 0, 0],
  146.     [0, 1, 1, 1, 1, 1, 0, 0],
  147.     [1, 1, 0, 1, 0, 1, 0, 0],
  148.     [1, 1, 1, 1, 1, 1, 0, 0],
  149.     [0, 1, 0, 0, 0, 1, 1, 1],
  150.     [1, 1, 1, 1, 1, 1, 0, 0],
  151.     [0, 0, 0, 0, 0, 1, 1, 1],
  152. ])
  153.  
  154.  
  155.  
  156.  
  157.  
  158. start = (2, 0)
  159. end = (6, 7)
  160.  
  161. way = find_shortest_path(maze, start, end)
  162.  
  163.  
  164. save_path = "labyrinth.gif"  # Укажите путь для сохранения анимации
  165. animate_wave_algorithm(maze, start, end, "")
  166.  
  167. animation = animate_wave_algorithm(maze, start, end, save_path)
  168. HTML(animation.to_jshtml())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement