2026-rff_mp/ivantsovma/maze/strategies/astar_strategy.py

67 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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