import heapq from typing import Optional from source.models.base import Cell, Maze from source.strategy.algorithms import PathFindingStrategy def _manhattan(a: Cell, b: Cell) -> int: """Манхэттенское расстояние между двумя клетками.""" return abs(a.x - b.x) + abs(a.y - b.y) class AStarStrategy(PathFindingStrategy): """Алгоритм A* с манхэттенской эвристикой.""" def find_path(self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None) -> list[Cell]: if start is None: start = self._find_start(maze) if exit is None: exit = self._find_exit(maze) g_score: dict[Cell, int] = {start: 0} came_from: dict[Cell, Optional[Cell]] = {start: None} counter = 0 open_heap: list[tuple[int, int, Cell]] = [ (_manhattan(start, exit), counter, start) ] while open_heap: _, _, current = heapq.heappop(open_heap) if current is exit: return self._reconstruct_path(came_from, exit) for neighbor in maze.get_neighbors(current.x, current.y): tentative_g = g_score[current] + 1 if tentative_g < g_score.get(neighbor, float("inf")): g_score[neighbor] = tentative_g came_from[neighbor] = current f = tentative_g + _manhattan(neighbor, exit) counter += 1 heapq.heappush(open_heap, (f, counter, neighbor)) return []