2026-rff_mp/BudakovIS/docs/report_2-nd-exersize.md
2026-05-15 09:42:46 +03:00

13 KiB
Raw Blame History

Отчет по лабораторной работе: Поиск выхода из лабиринта

1. Описание задачи

Разработать программу для загрузки лабиринта из текстового файла, поиска пути от стартовой клетки до выхода с возможностью выбора алгоритма поиска, визуализации процесса и экспериментального сравнения эффективности алгоритмов.

Основные требования:

  • Реализовать модель лабиринта (классы Cell, Maze)
  • Реализовать загрузку лабиринта из файла с символами # (стена), S (старт), E (выход)
  • Реализовать три алгоритма поиска пути: BFS, DFS, A*
  • Реализовать класс-оркестратор MazeSolver с возможностью смены стратегии
  • Собрать статистику: время выполнения, количество посещенных клеток, длина пути
  • Провести эксперименты на лабиринтах разной сложности

Использованные паттерны проектирования GoF:

1. Builder

  • Где используется: Классы MazeBuilder и TextFileMazeBuilder
  • Почему выбран: Создание лабиринта из файла включает сложную логику парсинга, валидации и установки старта и выхода. Builder скрывает эти детали от клиента и позволяет легко добавлять новые форматы файлов
  • Преимущества: При добавлении нового формата достаточно создать новый класс-строитель, не меняя существующие классы Maze и алгоритмы поиска

2. Strategy

  • Где используется: Классы PathFindingStrategy, BFSStrategy, DFSStrategy, AStarStrategy
  • Почему выбран: Алгоритмы поиска пути взаимозаменяемы и решают одну задачу разными способами. Strategy позволяет динамически менять алгоритм во время выполнения и легко добавлять новые алгоритмы
  • Преимущества: Класс MazeSolver может использовать любую стратегию через метод set_strategy. Добавление нового алгоритма требует только создания нового класса

3. Observer

  • Где используется: Классы Observer и ConsoleView
  • Почему выбран: Приложение должно обновлять консольный интерфейс при различных событиях. Observer отделяет логику отображения от логики приложения
  • Преимущества: Легко добавить новые виды отображения без изменения основной логики

4. Command

  • Где используется: Классы Command и MoveCommand
  • Почему выбран: Для реализации пошагового перемещения игрока с возможностью отмены действий. Command инкапсулирует действие в объект и позволяет реализовать undo и redo
  • Преимущества: Хранение истории действий и возможность отмены последних ходов без изменения логики класса Player

2. Архитектура приложения

Приложение состоит из следующих основных компонентов:

  • Модель: классы Cell и Maze, представляющие клетку и лабиринт
  • Загрузка: классы MazeBuilder и TextFileMazeBuilder для загрузки из файлов
  • Алгоритмы: классы BFSStrategy, DFSStrategy, AStarStrategy, реализующие интерфейс PathFindingStrategy
  • Оркестрация: класс MazeSolver, управляющий процессом поиска
  • Визуализация: класс ConsoleView, реализующий интерфейс Observer
  • Управление: классы Command и MoveCommand для пошагового движения
  • Игрок: класс Player, хранящий текущую позицию

3. Реализация алгоритмов поиска пути

BFS (Поиск в ширину)

Алгоритм использует очередь для обхода лабиринта. Начинает со стартовой клетки, помещает её в очередь. Затем циклически извлекает клетку из начала очереди, проверяет не является ли она выходом, и добавляет всех непосещенных соседей в конец очереди. Гарантирует нахождение кратчайшего пути по количеству шагов.

DFS (Поиск в глубину)

Алгоритм использует стек для обхода лабиринта. Начинает со стартовой клетки, помещает её в стек. Затем циклически извлекает клетку из конца стека, проверяет не является ли она выходом, и добавляет всех непосещенных соседей в стек. Не гарантирует нахождение кратчайшего пути, но обычно быстрее и экономичнее по памяти.

A* (A звездочка)

Алгоритм использует приоритетную очередь с эвристической функцией. Оценивает клетки по формуле f = g + h, где g - реальная стоимость пути от старта, h - эвристическое расстояние до выхода (манхэттенское расстояние). Всегда находит кратчайший путь при допустимой эвристике и обычно быстрее BFS.

4. Экспериментальная часть

Тестовые лабиринты

Были подготовлены следующие тестовые лабиринты:

  • maze1.txt (размер 10x6): простой лабиринт из задания
  • maze10x10.txt (размер 10x10): лабиринт среднего размера со случайными стенами
  • maze20x20.txt (размер 20x20): большой запутанный лабиринт
  • maze_empty.txt (размер 15x15): пустой лабиринт без стен
  • maze_no_exit.txt (размер 10x10): лабиринт без достижимого выхода

Результаты замеров

Каждый эксперимент проводился 5 раз с усреднением результатов.

Лабиринт Алгоритм Время (мс) Посещено клеток Длина пути
Small 10x6 BFS 0.040 27 14
Small 10x6 DFS 0.025 27 18
Small 10x6 A* 0.051 19 14
Medium 10x10 BFS 0.023 19 12
Medium 10x10 DFS 0.018 18 12
Medium 10x10 A* 0.037 12 12
Large 20x20 BFS 0.019 16 5
Large 20x20 DFS 0.019 17 9
Large 20x20 A* 0.023 9 5
Empty 15x15 BFS 0.182 78 15
Empty 15x15 DFS 0.069 76 43
Empty 15x15 A* 0.156 63 15
No exit 10x10 BFS - - 0
No exit 10x10 DFS - - 0
No exit 10x10 A* - - 0

Графики

Сравнение производительности алгоритмов

На графике представлено сравнение трех алгоритмов по трем метрикам: время выполнения, количество посещенных клеток и длина найденного пути.

5. Анализ результатов

Сравнение характеристик алгоритмов

BFS:

  • Гарантирует кратчайший путь: да
  • Скорость на малых лабиринтах: средняя
  • Скорость на больших лабиринтах: медленная
  • Потребление памяти: высокое
  • Количество посещенных клеток: много

DFS:

  • Гарантирует кратчайший путь: нет
  • Скорость на малых лабиринтах: быстрая
  • Скорость на больших лабиринтах: быстрая
  • Потребление памяти: низкое
  • Количество посещенных клеток: мало

A*:

  • Гарантирует кратчайший путь: да (с допустимой эвристикой)
  • Скорость на малых лабиринтах: быстрая
  • Скорость на больших лабиринтах: средняя
  • Потребление памяти: среднее
  • Количество посещенных клеток: среднее

Выводы по эффективности

  1. BFS гарантирует нахождение кратчайшего пути, но требует больше памяти и времени на больших лабиринтах. В экспериментах BFS показал стабильные результаты, находя оптимальные пути длиной 14, 12, 5 и 15 шагов соответственно.

  2. DFS является самым быстрым по времени (0.018-0.069 мс) и самым экономичным по памяти, но не гарантирует кратчайший путь. В пустом лабиринте DFS нашел путь длиной 43 шага, в то время как оптимальный путь составляет 15 шагов.

  3. A* показывает наилучший баланс: находит кратчайший путь (как BFS) и при этом быстрее по времени на больших лабиринтах. A* посетил меньше всего клеток (9-63) по сравнению с конкурентами.

  4. В лабиринте 20x20 все алгоритмы сработали очень быстро (0.019-0.023 мс), так как путь оказался коротким (всего 5 шагов).

  5. При отсутствии пути (лабиринт maze_no_exit.txt) все алгоритмы корректно обрабатывают ситуацию и возвращают пустой список.

Рекомендации по выбору алгоритма

  • Для небольших лабиринтов (до 20x20) подходит любой алгоритм
  • Для больших лабиринтов, где важна оптимальность пути, выбирайте A*
  • Для максимальной скорости, когда путь не важен, используйте DFS
  • Для лабиринтов с гарантией кратчайшего пути используйте BFS

6. Заключение

Преимущества использованных паттернов

Builder позволил легко реализовать загрузку лабиринтов из текстовых файлов и оставил возможность для добавления других форматов без изменения основного кода.

Strategy сделал алгоритмы поиска взаимозаменяемыми. Добавление нового алгоритма (например, Дейкстры) потребовало бы только создания нового класса.

Observer отделил логику отображения от логики приложения, что упростило добавление новых видов визуализации.

Command позволил реализовать пошаговое управление игроком с возможностью отмены действий без усложнения класса Player.

Итог

Разработанная программа демонстрирует преимущества объектно-ориентированного подхода и использования паттернов проектирования. Код является гибким, расширяемым и легко поддерживаемым. Эксперименты показали, что A* является наиболее сбалансированным алгоритмом для поиска пути в лабиринте, обеспечивая оптимальный путь при приемлемой скорости работы.