forked from UNN/2026-rff_mp
204 lines
6.3 KiB
Python
204 lines
6.3 KiB
Python
|
|
"""Главный файл программы"""
|
|||
|
|
|
|||
|
|
import sys
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
from builders import TextFileMazeBuilder
|
|||
|
|
from solver import MazeSolver
|
|||
|
|
from strategies import BFSStrategy, DFSStrategy, AStarStrategy
|
|||
|
|
from visualization import ConsoleView
|
|||
|
|
from commands import MoveCommand
|
|||
|
|
from models import Player
|
|||
|
|
from experiments import ExperimentRunner
|
|||
|
|
|
|||
|
|
|
|||
|
|
def create_test_maze_files():
|
|||
|
|
"""Создание тестовых лабиринтов"""
|
|||
|
|
Path("mazes").mkdir(exist_ok=True)
|
|||
|
|
|
|||
|
|
# Лабиринт 1: Маленький запутанный (10×10)
|
|||
|
|
small_maze = [
|
|||
|
|
"##########",
|
|||
|
|
"#S #",
|
|||
|
|
"# ####### #",
|
|||
|
|
"# # #",
|
|||
|
|
"##### # # #",
|
|||
|
|
"# # #",
|
|||
|
|
"# ### ### #",
|
|||
|
|
"# # #",
|
|||
|
|
"# #### E#",
|
|||
|
|
"##########"
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# Лабиринт 2: Простой прямой путь (10×10)
|
|||
|
|
simple_maze = [
|
|||
|
|
"##########",
|
|||
|
|
"#S #",
|
|||
|
|
"# #",
|
|||
|
|
"# #",
|
|||
|
|
"# #",
|
|||
|
|
"# #",
|
|||
|
|
"# #",
|
|||
|
|
"# #",
|
|||
|
|
"# E#",
|
|||
|
|
"##########"
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# Лабиринт 3: Без выхода (10×10)
|
|||
|
|
no_exit_maze = [
|
|||
|
|
"##########",
|
|||
|
|
"#S #",
|
|||
|
|
"# ####### #",
|
|||
|
|
"# # #",
|
|||
|
|
"##### # # #",
|
|||
|
|
"# # #",
|
|||
|
|
"# ### ### #",
|
|||
|
|
"# # #",
|
|||
|
|
"# #######",
|
|||
|
|
"##########"
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# Лабиринт 4: Спиральный
|
|||
|
|
spiral_maze = [
|
|||
|
|
"##########",
|
|||
|
|
"#S #",
|
|||
|
|
"# ####### #",
|
|||
|
|
"# # # #",
|
|||
|
|
"# # ### # #",
|
|||
|
|
"# # # # #",
|
|||
|
|
"# # ### # #",
|
|||
|
|
"# # # #",
|
|||
|
|
"# #######E#",
|
|||
|
|
"##########"
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
with open("mazes/small_maze.txt", "w", encoding="utf-8") as f:
|
|||
|
|
f.write('\n'.join(small_maze))
|
|||
|
|
with open("mazes/simple_maze.txt", "w", encoding="utf-8") as f:
|
|||
|
|
f.write('\n'.join(simple_maze))
|
|||
|
|
with open("mazes/no_exit_maze.txt", "w", encoding="utf-8") as f:
|
|||
|
|
f.write('\n'.join(no_exit_maze))
|
|||
|
|
with open("mazes/spiral_maze.txt", "w", encoding="utf-8") as f:
|
|||
|
|
f.write('\n'.join(spiral_maze))
|
|||
|
|
|
|||
|
|
print("Созданы тестовые лабиринты в папке mazes/")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def interactive_mode():
|
|||
|
|
"""Интерактивный режим с ручным управлением"""
|
|||
|
|
print("\n" + "=" * 50)
|
|||
|
|
print("Интерактивный режим")
|
|||
|
|
print("=" * 50)
|
|||
|
|
|
|||
|
|
builder = TextFileMazeBuilder()
|
|||
|
|
view = ConsoleView()
|
|||
|
|
|
|||
|
|
maze_file = input("Введите путь к файлу (по умолчанию: mazes/small_maze.txt): ")
|
|||
|
|
if not maze_file:
|
|||
|
|
maze_file = "mazes/small_maze.txt"
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
maze = builder.build_from_file(maze_file)
|
|||
|
|
view.update("maze_loaded", {"maze": maze})
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"Ошибка: {e}")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
print("\nСтратегии:")
|
|||
|
|
print("1. BFS (кратчайший путь)")
|
|||
|
|
print("2. DFS (быстрый, но не оптимальный)")
|
|||
|
|
print("3. A* (оптимальный с эвристикой)")
|
|||
|
|
|
|||
|
|
choice = input("Выберите (1-3): ")
|
|||
|
|
strategies = {
|
|||
|
|
"1": BFSStrategy(),
|
|||
|
|
"2": DFSStrategy(),
|
|||
|
|
"3": AStarStrategy()
|
|||
|
|
}
|
|||
|
|
strategy = strategies.get(choice, BFSStrategy())
|
|||
|
|
|
|||
|
|
print(f"\nВыбрана стратегия: {strategy.name}")
|
|||
|
|
|
|||
|
|
solver = MazeSolver(maze, strategy)
|
|||
|
|
path, stats = solver.solve()
|
|||
|
|
|
|||
|
|
if path:
|
|||
|
|
view.update("path_found", {"path": path, "maze": maze})
|
|||
|
|
print(f"\n{stats}")
|
|||
|
|
else:
|
|||
|
|
view.update("path_not_found", {})
|
|||
|
|
print("Путь не найден!")
|
|||
|
|
|
|||
|
|
# Демонстрация Command (пошаговое движение)
|
|||
|
|
print("\n" + "-" * 30)
|
|||
|
|
print("Демонстрация паттерна Command (пошаговое движение)")
|
|||
|
|
print("-" * 30)
|
|||
|
|
|
|||
|
|
if path:
|
|||
|
|
player = Player(maze.start)
|
|||
|
|
print("\nПошаговое движение по найденному пути (Enter - следующий шаг, q - выход):")
|
|||
|
|
|
|||
|
|
for i, cell in enumerate(path[1:], 1):
|
|||
|
|
cmd = MoveCommand(player, cell)
|
|||
|
|
cmd.execute()
|
|||
|
|
view.render(maze, player.current_cell, path[:i+1])
|
|||
|
|
print(f"Шаг {i}/{len(path)-1}")
|
|||
|
|
|
|||
|
|
key = input("Нажмите Enter для продолжения или 'q' для выхода: ")
|
|||
|
|
if key.lower() == 'q':
|
|||
|
|
break
|
|||
|
|
|
|||
|
|
if player.current_cell == maze.exit:
|
|||
|
|
print("\n🎉 Вы достигли выхода!")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def experiment_mode():
|
|||
|
|
"""Экспериментальный режим сравнения алгоритмов"""
|
|||
|
|
print("\n" + "=" * 50)
|
|||
|
|
print("Экспериментальное сравнение алгоритмов")
|
|||
|
|
print("=" * 50)
|
|||
|
|
|
|||
|
|
create_test_maze_files()
|
|||
|
|
|
|||
|
|
runner = ExperimentRunner()
|
|||
|
|
maze_files = [
|
|||
|
|
"mazes/small_maze.txt",
|
|||
|
|
"mazes/simple_maze.txt",
|
|||
|
|
"mazes/no_exit_maze.txt",
|
|||
|
|
"mazes/spiral_maze.txt"
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
results = runner.run_all_experiments(maze_files, runs=10)
|
|||
|
|
|
|||
|
|
print("\n" + "=" * 50)
|
|||
|
|
print("Сводная таблица результатов:")
|
|||
|
|
print("=" * 50)
|
|||
|
|
print(f"{'Лабиринт':<15} {'Стратегия':<10} {'Ср. время (мс)':<15} {'Длина пути':<12} {'Найден':<8}")
|
|||
|
|
print("-" * 65)
|
|||
|
|
|
|||
|
|
for r in results:
|
|||
|
|
status = "✓" if r['path_found'] else "✗"
|
|||
|
|
print(f"{r['maze']:<15} {r['strategy']:<10} {r['avg_time_ms']:<15.3f} {r['path_length']:<12} {status:<8}")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def main():
|
|||
|
|
print("\n" + "=" * 50)
|
|||
|
|
print("Лабораторная работа: Поиск выхода из лабиринта")
|
|||
|
|
print("Паттерны: Builder, Strategy, Observer, Command")
|
|||
|
|
print("=" * 50)
|
|||
|
|
|
|||
|
|
print("\n1. Интерактивный режим (ручное управление)")
|
|||
|
|
print("2. Экспериментальный режим (сравнение алгоритмов)")
|
|||
|
|
|
|||
|
|
choice = input("\nВыберите (1-2): ")
|
|||
|
|
|
|||
|
|
if choice == "1":
|
|||
|
|
interactive_mode()
|
|||
|
|
elif choice == "2":
|
|||
|
|
experiment_mode()
|
|||
|
|
else:
|
|||
|
|
print("Неверный выбор!")
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
main()
|