69 lines
2.4 KiB
Python
69 lines
2.4 KiB
Python
from abc import ABC, abstractmethod
|
|
from typing import Optional
|
|
|
|
from source.models.base import Maze, Cell
|
|
|
|
|
|
class PathFindingStrategy(ABC):
|
|
"""Интерфейс стратегии поиска пути в лабиринте."""
|
|
|
|
@abstractmethod
|
|
def find_path(
|
|
self, maze: Maze, start: Cell = None, exit: Cell = None
|
|
) -> list[Cell]:
|
|
"""Найти путь от start до exit.
|
|
|
|
Args:
|
|
maze: Объект лабиринта.
|
|
start: Стартовая клетка.
|
|
exit: Целевая клетка.
|
|
|
|
Returns:
|
|
Список клеток пути (от start до exit включительно).
|
|
Пустой список, если путь не найден.
|
|
"""
|
|
|
|
def _validate(
|
|
self, maze: Maze, start: Optional[Cell], exit: Optional[Cell]
|
|
) -> tuple[Optional[Cell], Optional[Cell]]:
|
|
"""Подставляет start/exit из лабиринта если не переданы явно.
|
|
|
|
Raises:
|
|
ValueError: Если старт или выход не найдены.
|
|
"""
|
|
if start is None:
|
|
start = maze.start
|
|
if exit is None:
|
|
exit = maze.exit
|
|
|
|
if start is None:
|
|
raise ValueError("Стартовая клетка не найдена в лабиринте")
|
|
if exit is None:
|
|
raise ValueError("Выходная клетка не найдена в лабиринте")
|
|
|
|
return start, exit
|
|
|
|
def _reconstruct_path(
|
|
self, came_from: dict[Cell, Optional[Cell]], end: Cell
|
|
) -> list[Cell]:
|
|
"""Восстанавливает путь от старта до end, идя по came_from в обратном порядке.
|
|
|
|
Args:
|
|
came_from: Словарь {клетка: родитель}, где родитель старта = None.
|
|
end: Конечная клетка.
|
|
|
|
Returns:
|
|
Список клеток пути от старта до end включительно.
|
|
Пустой список, если end отсутствует в came_from.
|
|
"""
|
|
if end not in came_from:
|
|
return []
|
|
|
|
path: list[Cell] = []
|
|
current: Optional[Cell] = end
|
|
while current is not None:
|
|
path.append(current)
|
|
current = came_from[current]
|
|
path.reverse()
|
|
return path
|