forked from UNN/2026-rff_mp
67 lines
2.6 KiB
Python
67 lines
2.6 KiB
Python
import heapq
|
||
from typing import List, Dict
|
||
from .path_finding_strategy import PathFindingStrategy
|
||
|
||
class AStarStrategy(PathFindingStrategy):
|
||
"""A* поиск с эвристикой (манхэттенское расстояние)"""
|
||
|
||
def __init__(self):
|
||
self._visited_count = 0
|
||
|
||
@property
|
||
def name(self) -> str:
|
||
return "AStar"
|
||
|
||
def _heuristic(self, cell, exit_cell) -> int:
|
||
"""Манхэттенское расстояние между клетками"""
|
||
return abs(cell.x - exit_cell.x) + abs(cell.y - exit_cell.y)
|
||
|
||
def find_path(self, maze, start, exit_cell) -> List:
|
||
"""Находит путь с помощью A*"""
|
||
if not start or not exit_cell:
|
||
return []
|
||
|
||
# Приоритетная очередь (F-значение, ID для уникальности, клетка)
|
||
open_set = []
|
||
heapq.heappush(open_set, (0, id(start), start))
|
||
|
||
# Откуда пришли в каждую клетку
|
||
came_from = {}
|
||
|
||
# Стоимость пути от старта до клетки (G-значение)
|
||
g_score = {start: 0}
|
||
|
||
# Оценочная стоимость (F-значение = G + H)
|
||
f_score = {start: self._heuristic(start, exit_cell)}
|
||
|
||
self._visited_count = 0
|
||
|
||
while open_set:
|
||
_, _, current = heapq.heappop(open_set)
|
||
self._visited_count += 1
|
||
|
||
# Нашли выход
|
||
if current == exit_cell:
|
||
return self._reconstruct_path(came_from, exit_cell)
|
||
|
||
# Проверяем всех соседей
|
||
for neighbor in maze.get_neighbors(current):
|
||
tentative_g = g_score[current] + 1
|
||
|
||
if neighbor not in g_score or tentative_g < g_score[neighbor]:
|
||
came_from[neighbor] = current
|
||
g_score[neighbor] = tentative_g
|
||
f = tentative_g + self._heuristic(neighbor, exit_cell)
|
||
f_score[neighbor] = f
|
||
heapq.heappush(open_set, (f, id(neighbor), neighbor))
|
||
|
||
# Путь не найден
|
||
return []
|
||
|
||
def _reconstruct_path(self, came_from: Dict, current) -> List:
|
||
"""Восстанавливает путь от старта до exit"""
|
||
path = [current]
|
||
while current in came_from:
|
||
current = came_from[current]
|
||
path.append(current)
|
||
return list(reversed(path)) |