2026-rff_mp/YaroslavtsevAS/docs/ReportLab2.md

11 KiB
Raw Blame History

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

1. Постановка задачи

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

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

  • Модель лабиринта: классы Tile (клетка) и Labyrinth (сетка).
  • Загрузка карты из файла с символами # (стена), S (старт), E (выход).
  • Реализация трёх стратегий поиска: BFS, DFS, A*.
  • Оркестратор LabyrinthSolver с возможностью смены алгоритма во время выполнения.
  • Сбор метрик: время работы (мс), количество посещённых клеток, длина найденного пути.
  • Проведение экспериментов на пяти лабиринтах разного размера и структуры.

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

  • Builder TextLabyrinthBuilder инкапсулирует логику парсинга текстового файла и создания объекта Labyrinth. Это упрощает добавление новых форматов.
  • Strategy BFS_Pathfinder, DFS_Pathfinder и AStar_Pathfinder реализуют общий интерфейс Pathfinder. Класс LabyrinthSolver может динамически переключаться между ними.
  • Observer интерфейс GameObserver и его реализация TerminalDisplay позволяют отделить отображение лабиринта от бизнес-логики.
  • Command MoveAction оборачивает перемещение игрока, сохраняя историю и предоставляя возможность отмены (undo).

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

  • Модель: Tile (клетка) и Labyrinth (лабиринт).
  • Загрузка: LabyrinthBuilder (абстрактный) и TextLabyrinthBuilder.
  • Алгоритмы: BFS_Pathfinder, DFS_Pathfinder, AStar_Pathfinder — наследники Pathfinder.
  • Управление поиском: LabyrinthSolver (смена стратегии, оповещение наблюдателей).
  • Визуализация: TerminalDisplay, реализующий GameObserver.
  • Интерактив: Explorer (игрок) и MoveAction (команда перемещения).

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

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

Использует очередь. Стартовая клетка помещается в очередь, затем на каждом шаге извлекается первый элемент. Если это выход — путь восстановлен. Иначе все непосещённые соседи добавляются в конец очереди. Гарантирует кратчайший путь по количеству шагов.

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

Вместо очереди используется стек (LIFO). Начинает со старта, на каждом шаге извлекается последний добавленный элемент. Быстрее продвигается в глубину, но путь часто оказывается далеко не оптимальным.

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

Применяет приоритетную очередь с эвристической функцией f = g + h, где g — реальная стоимость пути от старта, h — Манхэттенское расстояние до выхода. Всегда находит оптимальный путь при допустимой эвристике и обычно посещает меньше клеток.

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

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

Название Размер Особенность
Small 10x6 10×6 простой коридорный лабиринт
Medium 10x10 10×10 средняя плотность стен
Large 20x20 20×20 сложная запутанная структура
Empty 15x15 15×15 полностью проходимый (без стен)
No exit 10x10 10×10 выход заблокирован стеной

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

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

Лабиринт Алгоритм Время (мс) Посещено клеток Длина пути
Small 10x6 BFS 0.037 27 10
Small 10x6 DFS 0.028 18 14
Small 10x6 A* 0.069 22 10
Medium 10x10 BFS 0.042 40 15
Medium 10x10 DFS 0.017 21 15
Medium 10x10 A* 0.058 28 15
Large 20x20 BFS 0.091 64 31
Large 20x20 DFS 0.054 64 41
Large 20x20 A* 0.217 60 31
Empty 15x15 BFS 0.380 223 25
Empty 15x15 DFS 0.171 221 109
Empty 15x15 A* 0.623 169 25
No exit 10x10 BFS 0.014 9 0
No exit 10x10 DFS 0.013 9 0
No exit 10x10 A* 0.024 9 0

Примечание: длина пути 0 означает, что маршрут не существует.

Визуализация

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

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

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

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

BFS

  • Всегда находит кратчайший путь (длины 10, 15, 31, 25 соответственно).
  • На больших и пустых лабиринтах посещает много клеток (до 223), что сказывается на времени.
  • Хорошо подходит, когда оптимальность критична, а размер лабиринта умеренный.

DFS

  • Самый быстрый по времени (0.0130.171 мс), но часто выдаёт длинные извилистые пути (14, 15, 41, 109). В пустом 15×15 путь составил 109 шагов вместо оптимальных 25.
  • Число посещённых клеток невелико, что объясняет высокую скорость. Рекомендуется, когда важнее скорость, а не качество маршрута.

A*

  • Находит кратчайший путь во всех случаях (где он существует).
  • Посещает в среднем меньше клеток, чем BFS (22, 28, 60, 169), что подтверждает эффективность эвристики.
  • Время работы немного выше, чем у BFS, из-за накладных расходов на работу с кучей, однако разница незначительна.

Особые случаи

  • В лабиринте No exit все алгоритмы быстро обошли доступную область (9 клеток) и корректно вернули пустой путь.
  • На Empty 15×15 DFS показал наихудший путь (109 шагов), в то время как BFS и A* дали идеальные 25. Это наглядно демонстрирует, что DFS непригоден для задач, требующих оптимальности.
  • Large 20×20 показал близкие результаты для BFS и A* по длине пути, но DFS снова выдал более длинный маршрут (41).

Выводы и рекомендации

  • Если необходим кратчайший путь — выбирайте BFS или A*. A* часто эффективнее по памяти, так как посещает меньше клеток.
  • Если важна максимальная скорость и допустим неоптимальный путь — используйте DFS.
  • A* является наилучшим компромиссом для большинства практических задач благодаря сбалансированному сочетанию времени и оптимальности.

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

Разработанное приложение демонстрирует применение паттернов проектирования для построения гибкой и расширяемой архитектуры.
Экспериментальные данные подтверждают ожидаемое поведение алгоритмов: BFS и A* гарантируют оптимальность, DFS — высокую скорость ценой качества маршрута. A* показал наилучшее соотношение «затраты / качество», посещая меньше клеток и находя кратчайший путь.

Все полученные метрики сохранены в файл experiment_data.csv, графики — в maze_performance.png.