|
|||||
Игры, и все с ними связанное.Генерация лабиринтов.
Задача:>> Hужен алгоритм генерации лабиринта в виде прямоугольника MxN.>> Он должен иметь один вход и один выход, должен иметь одно решение, >> т.е. от входа к выходу должен быть один путь. В лабиринте не должно быть >> изолированных "комнат". Любая "комната" должна соединятся с "главным" путем. Решение:Для генерации можно использовать простейшее построение случайного прохода, затем допостроения к нему таких же случайных ходов, продолжающееся до тех пор, пока не будет "забито" все пространство выделяемое под лабиринт. Если лимит M и N небольшой, можно сделать рекурсиями. Устанавливаем точку входа. Сначала генерится основной ход. Движемся по клеточкам, "прогрызая" "ходы" в "камне", изменяя вектор движения случайно по или против часовой стрелке, в завасимости от значения случайного числа, и с проверкой касания края (если коснулись, то ставим выход). С каждым шагом запоминаем координаты "прогрызенной точки" и увеличиваем уровень рекурсии. Итак, предположим, выход достигнут. Когда достигаем выхода, начинаем понижение уровня рекурсии с восстановлением координат вышеупомянутой точки, и в зависимости от случайности (например 50%) по тому-же алгоритму генерируем боковой ход. Тогда, при создании основного хода, концом генерации у нас служило достижение края лабиринта. При генерации боковых ходов концом процесса можно сделать лимит на уровень рекурсии - например только 50 клеточек, но вообщем это на собственное усмотрение. Кончаем генерацию бокового хода, понижаем уровень рекурсии основного хода, восстанавливаем координаты, и рассчитываем вероятность создания нового бокового хода. Если надо, то создаем его. А потом снова возвращаемся к основному ходу. Все эти ходы будут петлять, пересекаться друг с другом, и пр., в результате путь найти будет весьма сложно. Конечно, против священной силы "волнового метода нахождения пути", или композитных "методов излома вектора движения" поможет только перекрытие главного выхода :)))) Hедостатком такого метода является рекурсия, которая, при больших лабиринтах, кушает память в больших количествах. Стaвить cтeны блoкaми, пpoвepяя пpoxoдимocть лaбиpинтa (в чacтнocти вoзмoжнocть зaпoлнeния BCEX пуcтыx ячeeк нaчинaя oт тoчки выxoдa), вpoдe ничeгo cлoжнoгo нeт. FullFill - на сколько плотно заполнять лабиринт (делать ли холлы). WallShort- на сколько короткие должны быть стены 0 - одни колонны. #include
Представьте себе прямоугольник (N x M) составленный из блоков, где N и M -
нечетные и больше или равны 5. Выбираем точку на любой стене прямоугольника,
отстоящую от других стен, как минимум на 1 блок. (Hапример в прямоугольнике
пять на пять единственные точки удовлетворяющие этому условию - это середины
сторон). Hачинаем двигаться от этой точки до противоположной стены, попутно
ставя в точках пути блоки. Дойдя до противоположной стены на расстояние
одного блока останавливаемся. (Кстати не обязательно доходить до конца -
можно остановиться и раньше. Это уже тонкости).
Повторяем вышеуказанный процесс, пока не останется возможности к добалению
новых блоков. Естественно, что на последующих проходах, возможно, придетсе
идти уже не
до глобальной стены, а до построенных стен.
|