# Стратегии поиска пути: BFS, DFS, A* (Strategy pattern) from collections import deque import heapq class PathFindingStrategy: def find_path(self, maze, start, exit_cell): raise NotImplementedError def _reconstruct_path(self, came_from, start, exit_cell): path = [] current = exit_cell while current is not None: path.append(current) current = came_from.get(current) path.reverse() return path def get_visited_count(self): return getattr(self, '_visited_count', 0) class BFSStrategy(PathFindingStrategy): def find_path(self, maze, start, exit_cell): queue = deque() queue.append(start) came_from = {start: None} visited = {start} while queue: current = queue.popleft() if current == exit_cell: self._visited_count = len(visited) return self._reconstruct_path(came_from, start, exit_cell) for neighbor in maze.get_neighbors(current): if neighbor not in visited: visited.add(neighbor) came_from[neighbor] = current queue.append(neighbor) self._visited_count = len(visited) return [] class DFSStrategy(PathFindingStrategy): def find_path(self, maze, start, exit_cell): stack = [start] came_from = {start: None} visited = {start} while stack: current = stack.pop() if current == exit_cell: self._visited_count = len(visited) return self._reconstruct_path(came_from, start, exit_cell) for neighbor in maze.get_neighbors(current): if neighbor not in visited: visited.add(neighbor) came_from[neighbor] = current stack.append(neighbor) self._visited_count = len(visited) return [] class AStarStrategy(PathFindingStrategy): def _heuristic(self, cell, exit_cell): return abs(cell.x - exit_cell.x) + abs(cell.y - exit_cell.y) def find_path(self, maze, start, exit_cell): heap = [] counter = 0 start_f = self._heuristic(start, exit_cell) heapq.heappush(heap, (start_f, counter, start)) counter += 1 came_from = {} g_score = {start: 0} f_score = {start: start_f} visited = set() while heap: current_f, _, current = heapq.heappop(heap) visited.add(current) if current == exit_cell: self._visited_count = len(visited) return self._reconstruct_path(came_from, start, exit_cell) if current_f > f_score.get(current, float('inf')): continue for neighbor in maze.get_neighbors(current): tentative_g = g_score[current] + 1 if tentative_g < g_score.get(neighbor, float('inf')): came_from[neighbor] = current g_score[neighbor] = tentative_g new_f = tentative_g + self._heuristic(neighbor, exit_cell) f_score[neighbor] = new_f heapq.heappush(heap, (new_f, counter, neighbor)) counter += 1 self._visited_count = len(visited) return []