from collections import deque import heapq import time # --- Модель --- class Cell: def __init__(self, x, y, is_wall=False, is_start=False, is_exit=False): self.x = x self.y = y self.is_wall = is_wall self.is_start = is_start self.is_exit = is_exit self.visited = False def is_passable(self): return not self.is_wall class Maze: def __init__(self, width, height): self.width = width self.height = height self.cells = [[Cell(x, y) for x in range(width)] for y in range(height)] self.start_cell = None self.exit_cell = None def get_cell(self, x, y): if 0 <= x < self.width and 0 <= y < self.height: return self.cells[y][x] return None def get_neighbors(self, cell): neighbors = [] directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] for dx, dy in directions: neighbor = self.get_cell(cell.x + dx, cell.y + dy) if neighbor and neighbor.is_passable(): neighbors.append(neighbor) return neighbors # --- Строитель class MazeBuilder: def buildFromFile(self, filename): with open(filename, 'r') as f: lines = f.readlines() height = len(lines) width = len(lines[0].strip()) maze = Maze(width, height) for y, line in enumerate(lines): for x, char in enumerate(line.strip()): cell = maze.get_cell(x, y) if char == '#': cell.is_wall = True elif char == 'S': cell.is_start = True maze.start_cell = cell elif char == 'E': cell.is_exit = True maze.exit_cell = cell if not maze.start_cell or not maze.exit_cell: raise ValueError("Лабиринт сломан") return maze class PathFindingStrategy: def findPath(self, maze, start, exit): raise NotImplementedError("Этот метод должен быть реализован в стратегии!") def _reconstruct_path(self, parents, current): path = [] while current: path.append(current) current = parents.get(current) return path[::-1] class BFSStrategy(PathFindingStrategy): def findPath(self, maze, start, exit): queue = deque([start]) parents = {start: None} start.visited = True while queue: current = queue.popleft() if current == exit: return self._reconstruct_path(parents, exit) for neighbor in maze.get_neighbors(current): if not neighbor.visited: neighbor.visited = True parents[neighbor] = current queue.append(neighbor) return [] class AStarStrategy(PathFindingStrategy): def _heuristic(self, a, b): return abs(a.x - b.x) + abs(a.y - b.y) def findPath(self, maze, start, exit): heap = [(0, start)] parents = {start: None} g_score = {start: 0} while heap: _, current = heapq.heappop(heap) if current == exit: return self._reconstruct_path(parents, exit) for neighbor in maze.get_neighbors(current): new_g = g_score[current] + 1 if new_g < g_score.get(neighbor, float('inf')): parents[neighbor] = current g_score[neighbor] = new_g f = new_g + self._heuristic(neighbor, exit) heapq.heappush(heap, (f, neighbor)) return [] class SearchStats: def __init__(self, time_ms, visited, length): self.time_ms = time_ms self.visited = visited self.length = length class MazeSolver: def __init__(self, maze): self.maze = maze self.strat = None def setStrategy(self, strategy): self.strat = strategy def solve(self): if not self.strat: return None t0 = time.perf_counter() path = self.strat.findPath(self.maze, self.maze.start_cell, self.maze.exit_cell) t1 = time.perf_counter() # Считаем посещенные ячейки visited_count = sum(c.visited for row in self.maze.cells for c in row) return SearchStats((t1 - t0) * 1000, visited_count, len(path)) if __name__ == "__main__": builder = MazeBuilder() try: path = r"C:\Users\vva26\2026-rff_mp\VolkovVA\docs\data\maze.txt" maze = builder.buildFromFile(path) solver = MazeSolver(maze) solver.setStrategy(BFSStrategy()) stats = solver.solve() print(f"BFS: {stats.time_ms:.2f}мс, посещено: {stats.visited}, путь: {stats.length}") except Exception as e: print(f"Ошибка: {e}")