2026-rff_mp/smirnovad/lab2/docs/data/main.py

128 lines
4.1 KiB
Python
Raw Normal View History

2026-05-17 13:50:47 +00:00
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()