2026-rff_mp/strategies/astar_strategy.py

67 lines
2.6 KiB
Python
Raw Normal View History

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))