import os from maze_builder import TextFileMazeBuilder from maze_solver import MazeSolver from strategies import BFSStrategy, DFSStrategy, AStarStrategy, DijkstraStrategy from observer import ConsoleView from command import Player, MoveCommand STRATEGIES = { "1": ("BFS", BFSStrategy), "2": ("DFS", DFSStrategy), "3": ("A*", AStarStrategy), "4": ("Dijkstra", DijkstraStrategy), } DIRECTION_MAP = { "w": (0, -1), "s": (0, 1), "a": (-1, 0), "d": (1, 0), } def choose_strategy(): print("\nВыберите алгоритм:") for key, (name, _) in STRATEGIES.items(): print(f" {key}. {name}") choice = input("Ваш выбор: ").strip() if choice not in STRATEGIES: print("Неверный выбор, используется BFS.") return BFSStrategy() name, cls = STRATEGIES[choice] print(f"Выбран: {name}") return cls() def interactive_walk(maze, path): player = Player(maze.start) view = ConsoleView() history: list[MoveCommand] = [] print("\n=== Ручное управление ===") print("W/A/S/D — движение, U — отмена, Q — выход") view.render(maze, path=path, player=player.current_cell) while True: cmd_input = input("Ход: ").strip().lower() if cmd_input == "q": break if cmd_input == "u": if history: history.pop().undo() view.render(maze, path=path, player=player.current_cell) else: print("Нет ходов для отмены.") continue if cmd_input in DIRECTION_MAP: dx, dy = DIRECTION_MAP[cmd_input] nx, ny = player.current_cell.x + dx, player.current_cell.y + dy if 0 <= nx < maze.width and 0 <= ny < maze.height: target = maze.get_cell(nx, ny) cmd = MoveCommand(player, target, maze) cmd.execute() history.append(cmd) view.render(maze, path=path, player=player.current_cell) if player.current_cell == maze.exit: print("🎉 Вы достигли выхода!") break else: print("За пределами лабиринта.") else: print("Неизвестная команда.") def main(): print("Решатель лабиринтов") mazes_dir = "mazes" if os.path.isdir(mazes_dir): files = [f for f in sorted(os.listdir(mazes_dir)) if f.endswith(".txt")] if files: print("\nДоступные лабиринты:") for i, f in enumerate(files, 1): print(f" {i}. {f}") choice = input("Выберите номер (или введите путь): ").strip() if choice.isdigit() and 1 <= int(choice) <= len(files): maze_path = os.path.join(mazes_dir, files[int(choice) - 1]) else: maze_path = choice else: maze_path = input("Путь к файлу лабиринта: ").strip() else: maze_path = input("Путь к файлу лабиринта: ").strip() builder = TextFileMazeBuilder() try: maze = builder.build_from_file(maze_path) print(f"\nЛабиринт загружен: {maze.width}×{maze.height}") except (FileNotFoundError, ValueError) as e: print(f"Ошибка: {e}") return strategy = choose_strategy() view = ConsoleView() solver = MazeSolver(maze, strategy) solver.add_observer(view) stats = solver.solve() print(f"\n── Статистика ──────────────────") print(f" Время: {stats.time_ms:.4f} мс") print(f" Посещено клеток: {stats.visited_cells}") print(f" Длина пути: {stats.path_length}") if stats.path: walk = input("\nЗапустить ручное управление? (y/n): ").strip().lower() if walk == "y": interactive_walk(maze, stats.path) if __name__ == "__main__": main()