11 KiB
Отчёт по лабораторной работе №2
Тема: Поиск выхода из лабиринта (объектно-ориентированная реализация с паттернами)
Студент: Соколов Н.Е.
Дата: 24.05.2026
1. Цель работы
Разработать гибкую, расширяемую программу для загрузки лабиринта из файла, поиска пути от старта до выхода с возможностью выбора алгоритма, визуализации процесса и экспериментального сравнения алгоритмов. В ходе работы необходимо применить минимум 3 паттерна проектирования из списка GoF, обосновать их выбор и продемонстрировать преимущества такой архитектуры.
2. Архитектура и паттерны
2.1 Общая схема классов
Ниже представлена диаграмма классов, отражающая основные компоненты программы и связи между ними: ┌─────────────────┐ ┌─────────────────┐ │ MazeBuilder │ │ PathFinding │ │ (interface) │ │ Strategy │ └────────┬────────┘ │ (interface) │ │ └────────┬────────┘ ▼ │ ┌─────────────────┐ ┌────────┼────────┬──────────────┐ │TextFileMaze │ │ ▼ ▼ ▼ │ Builder │ │ BFSStrategy DFSStrategy AStarStrategy └────────┬────────┘ └─────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ Maze │ ├─────────────────────────────────────────────────────────┤ │ - cells: Cell[][] │ │ - start: Cell │ │ - exit: Cell │ │ + getCell(x, y): Cell │ │ + getNeighbors(cell): List │ └─────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────┐ ┌─────────────────┐ │ MazeSolver │────▶│ SearchStats │ └─────────────────┘ └─────────────────┘ │ ▼ ┌─────────────────┐ ┌─────────────────┐ │ Observer │◀────│ ConsoleView │ │ (interface) │ └─────────────────┘ └─────────────────┘ │ ▼ ┌─────────────────┐ ┌─────────────────┐ │ Command │────▶│ MoveCommand │ │ (interface) │ └─────────────────┘ └─────────────────┘
2.2 Реализованные паттерны
| Паттерн | Где применён | Зачем |
|---|---|---|
| Builder | TextFileMazeBuilder |
Скрывает сложность создания лабиринта из файла (парсинг, валидация, установка старта/выхода). Легко добавить новый формат (JSON, бинарный) через новую реализацию MazeBuilder. |
| Strategy | BFSStrategy, DFSStrategy, AStarStrategy |
Алгоритмы поиска пути можно менять на лету через setStrategy(). Новый алгоритм добавляется без изменения остального кода. |
| Observer | ConsoleView (подписан на события MazeSolver) |
Отделяет отрисовку лабиринта и пути от логики поиска. Удобно заменить консольный вывод на GUI. |
| Command | MoveCommand |
Позволяет пошаговое движение игрока по найденному пути, отмену ходов, макрокоманды. |
3. Реализация алгоритмов поиска
3.1 BFS (поиск в ширину)
- Использует очередь (
deque). - Гарантирует нахождение кратчайшего пути по количеству шагов.
- Сложность O(V + E), где V — количество клеток, E — рёбра.
3.2 DFS (поиск в глубину)
- Использует стек (рекурсия или
list). - Быстрый, но не гарантирует кратчайший путь.
- Может «закопаться» вглубь, прежде чем найдет выход.
3.3 A* (звездочка)
- Использует приоритетную очередь (
heapq). - Эвристика: манхэттенское расстояние до выхода.
- Компромисс между скоростью и оптимальностью: почти всегда находит кратчайший путь, но быстрее BFS на больших лабиринтах.
4. Условия эксперимента
| Параметр | Значение |
|---|---|
| Количество лабиринтов | 4 |
| Стратегии | BFS, DFS, A* |
| Количество запусков на каждом лабиринте | 5 |
| Типы лабиринтов | small (5×5), medium (15×15), empty (20×20), no_exit (10×10) |
| Инструмент замера времени | time.perf_counter() |
| Метрики | Время (мс), длина пути (клеток) |
5. Результаты экспериментов
5.1 Время поиска пути (среднее за 5 запусков, мс)
| Лабиринт | BFS | DFS | A* |
|---|---|---|---|
| small (5×5) | 0.047 | 0.026 | 0.047 |
| medium (15×15) | 0.120 | 0.080 | 0.100 |
| empty (20×20) | 1.450 | 0.950 | 1.100 |
| no_exit (10×10) | 2.300 | 1.800 | 2.100 |
5.2 Длина найденного пути (клеток)
| Лабиринт | BFS | DFS | A* |
|---|---|---|---|
| small | 8 | 8 | 8 |
| medium | 25 | 32 | 25 |
| empty | 39 | 67 | 39 |
| no_exit | 0 | 0 | 0 |
5.3 Сводный график
График сгенерирован автоматически на основе maze_results.csv.
6. Анализ результатов
6.1 BFS
- Плюсы: всегда находит кратчайший путь.
- Минусы: медленнее DFS на больших лабиринтах из-за необходимости обходить все клетки по слоям.
- Вывод: лучший выбор, когда важна оптимальность пути.
6.2 DFS
- Плюсы: самый быстрый, потребляет мало памяти.
- Минусы: может найти очень длинный неоптимальный путь (например, в
emptyпуть в 67 клеток вместо 39). - Вывод: подходит для задач, где путь может быть любым, а скорость важнее.
6.3 A*
- Плюсы: почти идеальный компромисс: путь почти всегда кратчайший, скорость высокая.
- Минусы: требуется хорошая эвристика (у нас — манхэттенское расстояние).
- Вывод: рекомендуется для большинства практических задач поиска пути.
6.4 Лабиринт без выхода
- Все алгоритмы перебирают весь лабиринт (или его часть) и возвращают пустой путь.
- BFS и A* делают это системно, DFS может уйти вглубь и долго возвращаться.
7. Выводы
7.1 О реализации
- Паттерны действительно сделали код гибким и расширяемым.
- Builder изолировал загрузку — легко поменять формат файла.
- Strategy позволил сравнивать алгоритмы без изменения
MazeSolver. - Observer и Command добавили визуализацию и управление, не засоряя основную логику.
7.2 Рекомендации по выбору алгоритма
| Сценарий | Рекомендуемый алгоритм | Почему |
|---|---|---|
| Нужен кратчайший путь | BFS или A* | Оба находят оптимум, A* быстрее |
| Скорость важнее оптимальности | DFS | Самый быстрый |
| Лабиринт с известной эвристикой | A* | Лучший баланс |
| Лабиринт без выхода | BFS или A* | Предсказуемое перебор всех клеток |
7.3 Заключение
Лабораторная работа выполнена в полном объёме:
- ✅ Реализованы 4 паттерна проектирования.
- ✅ Программа загружает лабиринт из текстового файла.
- ✅ Реализованы 3 алгоритма поиска пути.
- ✅ Добавлена визуализация в консоли.
- ✅ Проведены эксперименты, результаты сохранены в CSV.
- ✅ Построены графики.
- ✅ Оформлен отчёт.
Программа готова к использованию и легко расширяется.
