diff --git a/pogodinda/lab2/main.py b/pogodinda/lab2/main.py new file mode 100644 index 0000000..8f3330c --- /dev/null +++ b/pogodinda/lab2/main.py @@ -0,0 +1,56 @@ +import sys +import os +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) + +from src.maze_builder import TextFileMazeBuilder +from src.maze_solver import MazeSolver +from src.pathfinding import BFSStrategy, DFSStrategy, AStarStrategy, DijkstraStrategy +from src.observer import ConsoleView +from src.commands import Player, MoveCommand + + +def demo(): + print("=" * 70) + print("ПОИСК ВЫХОДА ИЗ ЛАБИРИНТА") + print("=" * 70) + + # 1. Загрузка лабиринта + print("\n[1] Загрузка лабиринта из файла") + builder = TextFileMazeBuilder() + maze = builder.build_from_file("data/demo_maze.txt") + print(maze) + print(f"Старт: ({maze.start.x}, {maze.start.y})") + print(f"Выход: ({maze.exit.x}, {maze.exit.y})") + + # 2. Сравнение алгоритмов (Strategy) + print("\n[2] Сравнение алгоритмов") + strategies = [BFSStrategy(), DFSStrategy(), AStarStrategy(), DijkstraStrategy()] + + for strategy in strategies: + solver = MazeSolver(maze, strategy) + stats = solver.solve("demo") + print(f"{strategy.get_name():10} | {stats.time_ms:8.4f} мс | " + f"посещено: {stats.visited_cells:3} | длина: {stats.path_length}") + + # 3. Observer + print("\n[3] Паттерн Observer") + solver = MazeSolver(maze, AStarStrategy()) + console = ConsoleView() + solver.add_observer(console) + solver.solve("demo") + print(f"События: {console.events}") + + # 4. Command + print("\n[4] Паттерн Command") + player = Player(maze.start) + console.render(maze, player.current_cell) + + cmd = MoveCommand(player, maze, 'S') + cmd.execute() + print(f"После S: {player}") + + cmd.undo() + print(f"После undo: {player}") + +if __name__ == "__main__": + demo() \ No newline at end of file diff --git a/pogodinda/lab2/report.md b/pogodinda/lab2/report.md new file mode 100644 index 0000000..22579ad --- /dev/null +++ b/pogodinda/lab2/report.md @@ -0,0 +1,68 @@ +# Лабораторная работа 2: Поиск выхода из лабиринта + +## 1. Цель +Разработать гибкую, расширяемую программу для загрузки лабиринта из файла, поиска пути от старта до выхода с возможностью выбора алгоритма, визуализации процесса и экспериментального сравнения алгоритмов. В ходе работы необходимо применить минимум 3 паттерна проектирования из списка GoF, обосновать их выбор и продемонстрировать преимущества такой архитектуры. + +## 2. Паттерны + +| Паттерн | Где | Зачем | +|---------|-----|-------| +| Builder | `maze_builder.py` | Загрузка лабиринта из файла | +| Strategy | `pathfinding.py` | Смена алгоритмов (BFS, DFS, A*, Дейкстра) | +| Observer | `observer.py` | Уведомления о событиях поиска | +| Command | `commands.py` | Перемещение игрока с undo | + +## 3. Алгоритмы + +- **BFS** — кратчайший путь, но медленный +- **DFS** — быстрый, но путь не оптимальный +- **A*** — баланс скорости и оптимальности +- **Дейкстра** — для взвешенных графов + +## 4. Результаты + +### Таблица: посещённые клетки + +| Лабиринт | BFS | DFS | A* | Дейкстра | +|:--------:|:---:|:---:|:--:|:--------:| +| 10×10 | 52 | 49 | 47 | 52 | +| 50×50 | 514 | 326 | 491 | 511 | +| 100×100 | 1989 | 1509 | 1909 | 1987 | +| Пустой | 398 | 399 | 324 | 396 | +| Без выхода | 0 | 0 | 0 | 0 | +| Взвешенный | 145 | 111 | 139 | 143 | + +### Время (мс) + +| Лабиринт | BFS | DFS | A* | Дейкстра | +|:--------:|:---:|:---:|:--:|:--------:| +| 10×10 | 0.107 | 0.068 | 0.142 | 0.146 | +| 50×50 | 1.141 | 0.690 | 1.509 | 1.482 | +| 100×100 | 7.667 | 5.207 | 8.254 | 8.480 | + +### Длина пути + +| Лабиринт | BFS | DFS | A* | Дейкстра | +|:--------:|:---:|:---:|:--:|:--------:| +| 10×10 | 25 | 31 | 25 | 25 | +| Пустой | 35 | **187** | 35 | 35 | + +## 5. Графики + +![maze_comparison.png](results/maze_comparison.png) + +![visited_cells.png](results/visited_cells.png) + +![time_comparison.png](results/time_comparison.png) + +## 6. Анализ + +- **DFS** быстрее всех, но в пустом лабиринте путь в 5.3 раза длиннее оптимального +- **A*** — лучший баланс: кратчайший путь + меньше посещённых клеток +- **BFS** и **Дейкстра** на невзвешенных графах работают одинаково + +## 7. Вывод + +- Паттерны сделали код **гибким** и **расширяемым** +- **A*** — оптимальный выбор для большинства задач +- **Дейкстра** нужен только для взвешенных графов diff --git a/pogodinda/lab2/src/__init__.py b/pogodinda/lab2/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pogodinda/lab2/tests/__init__.py b/pogodinda/lab2/tests/__init__.py new file mode 100644 index 0000000..e69de29