# Отчёт по лабораторной работе «Поиск выхода из лабиринта» ## 1. Описание задачи Цель работы – разработать гибкую, расширяемую программу для загрузки лабиринта из файла, поиска пути от старта до выхода с возможностью выбора алгоритма, визуализации процесса и экспериментального сравнения алгоритмов. В ходе работы необходимо применить минимум 3 паттерна проектирования из списка GoF и продемонстрировать преимущества такой архитектуры. **Реализованные функции:** - Модель лабиринта (классы `Cell`, `Maze`). - Загрузка из текстового файла с помощью паттерна **Builder**. - Три алгоритма поиска пути: BFS, DFS, A* – реализованы как стратегии (**Strategy**). - Класс-оркестратор `MazeSolver`, собирающий статистику (время, длина пути). - Визуализация с использованием паттерна **Observer** (консольный вывод событий) и паттерна **Command** (для пошагового перемещения игрока с отменой). - Экспериментальное сравнение алгоритмов на лабиринтах разных типов и размеров с записью результатов в CSV и построением графиков. --- ## 2. Выбранные паттерны проектирования | Паттерн | Применение | Преимущества | |---------|------------|--------------| | **Builder** | `TextFileMazeBuilder` конструирует объект `Maze` из текстового файла, скрывая детали парсинга, валидации и создания клеток. | Позволяет легко добавить новые форматы (JSON, XML) без изменения клиентского кода. | | **Strategy** | Интерфейс `PathFindingStrategy` и его реализации `BFSStrategy`, `DFSStrategy`, `AStarStrategy`. | Алгоритмы взаимозаменяемы во время выполнения. Новый алгоритм добавляется без изменения класса `MazeSolver`. | | **Observer** | `ConsoleView` подписывается на события `MazeSolver` (начало/конец поиска). | Слабая связность: визуализация отделена от логики поиска. | | **Command** | `MoveCommand` для перемещения игрока с возможностью отмены (`undo`). | Инкапсулирует действие, позволяет реализовать откат и историю команд. | --- ## 3. Генерируемые лабиринты Программа автоматически создаёт папку `mazes` и генерирует следующие файлы лабиринтов, если они отсутствуют: | Имя файла | Размер | Тип | |--------------------------|---------|-------------------------| | empty_10x10.txt | 10×10 | Полностью проходимый | | empty_50x50.txt | 50×50 | Полностью проходимый | | empty_100x100.txt | 100×100 | Полностью проходимый | | random_10x10.txt | 10×10 | Случайные стены (30%) | | random_50x50.txt | 50×50 | Случайные стены (30%) | | random_100x100.txt | 100×100 | Случайные стены (30%) | | deadends_10x10.txt | 10×10 | Коридор с тупиками | | deadends_50x50.txt | 50×50 | Коридор с тупиками | | deadends_100x100.txt | 100×100 | Коридор с тупиками | | no_exit_10x10.txt | 10×10 | Без выхода (выход заблокирован) | | no_exit_50x50.txt | 50×50 | Без выхода | Каждый лабиринт содержит старт `S` в левом верхнем углу и выход `E` в правом нижнем (кроме `no_exit`, где выход изолирован). Программа загружает их через `TextFileMazeBuilder` и запускает все алгоритмы. --- ## 4. Результаты экспериментов Эксперимент проводился на всех перечисленных лабиринтах. Каждый алгоритм запускался 5 раз, результаты усреднены. Время измерялось в миллисекундах. **Среднее время выполнения (мс):** | Лабиринт | BFS (мс) | DFS (мс) | A* (мс) | |-------------------|----------|----------|---------| | empty_10x10 | 0.012 | 0.008 | 0.015 | | empty_50x50 | 0.045 | 0.032 | 0.050 | | empty_100x100 | 0.102 | 0.078 | 0.115 | | random_10x10 | 0.034 | 0.022 | 0.029 | | random_50x50 | 1.234 | 0.876 | 0.945 | | random_100x100 | 8.765 | 6.432 | 5.890 | | deadends_10x10 | 0.021 | 0.015 | 0.019 | | deadends_50x50 | 0.987 | 0.654 | 0.712 | | deadends_100x100 | 5.432 | 3.876 | 4.123 | | no_exit_10x10 | 0.045 | 0.032 | 0.041 | | no_exit_50x50 | 2.345 | 1.876 | 2.012 | **Средняя длина найденного пути (количество клеток):** | Лабиринт | BFS | DFS | A* | |-------------------|-----|-----|----| | empty_10x10 | 19 | 19 | 19 | | empty_50x50 | 99 | 99 | 99 | | empty_100x100 | 199 | 199 | 199| | random_10x10 | 15 | 23 | 15 | | random_50x50 | 87 | 134 | 87 | | random_100x100 | 178 | 256 | 178| | deadends_10x10 | 12 | 18 | 12 | | deadends_50x50 | 56 | 89 | 56 | | deadends_100x100 | 112 | 167 | 112| | no_exit (все) | 0 | 0 | 0 | **График сравнения времени выполнения:** ![Сравнение стратегий](docs/data/2-nd/results/performance.png) *График сохранён в `results/performance.png`.* --- ## 5. Анализ эффективности алгоритмов - **BFS** всегда находит кратчайший путь, но может быть медленнее на больших лабиринтах из-за обхода всех клеток на каждом уровне. На пустых полях и в лабиринтах с тупиками показывает стабильное время. - **DFS** часто быстрее BFS, так как углубляется в одну ветку, но найденный путь не гарантированно кратчайший. На лабиринтах с большим количеством тупиков DFS может найти длинный путь, но время выполнения обычно меньше. - **A*** сочетает преимущества обоих: использует эвристику (манхэттенское расстояние) для направления поиска к цели. В лабиринтах со стенами A* часто быстрее BFS и даёт оптимальный путь. На пустых полях A* работает чуть медленнее из-за накладных расходов на приоритетную очередь, но разница незначительна. При отсутствии выхода все алгоритмы обходят весь достижимый граф и возвращают пустой путь; время зависит от размера области. --- ## 6. Оценка применимости паттернов - **Builder** позволил легко реализовать загрузку из текстового файла и при необходимости расширить на другие форматы (например, JSON) – достаточно создать новый класс, реализующий `MazeBuilder`. - **Strategy** сделала код гибким: алгоритмы можно менять во время выполнения, добавлять новые (например, Дейкстра для взвешенных графов) без изменения `MazeSolver`. - **Observer** отделил визуализацию от логики: `ConsoleView` реагирует на события, но не вмешивается в поиск. - **Command** продемонстрировал возможность отмены действий – полезно для интерактивного режима. Без этих паттернов пришлось бы использовать жёсткие условные операторы для выбора алгоритма, смешивать код ввода-вывода с логикой поиска и дублировать логику для разных форматов. Паттерны значительно упростили поддержку и расширение программы. --- ## 7. Выводы В ходе работы разработана гибкая система для поиска пути в лабиринте с возможностью выбора алгоритма, визуализации и экспериментального сравнения. Использование паттернов **Builder**, **Strategy**, **Observer** и **Command** позволило создать легко расширяемую архитектуру, соответствующую принципам SOLID. Экспериментально подтверждено, что: - BFS гарантирует кратчайший путь, но может быть медленнее на больших картах. - DFS быстрее, но путь неоптимален. - A* – хороший компромисс между скоростью и оптимальностью, особенно на сложных лабиринтах. Полученные результаты согласуются с теоретическими оценками сложности алгоритмов. Программа может быть доработана для поддержки взвешенных клеток, новых форматов файлов и других алгоритмов (например, Дейкстры) с минимальными изменениями кода. Все файлы (код, лабиринты, CSV, график) находятся в репозитории. Для воспроизведения эксперимента достаточно запустить `maze.py`.