Алгоритм генерации лабиринта без тупиков?

Я ищу алгоритм генерации лабиринта, который может генерировать лабиринты с тупиками, но только начало и конец. Вот так:

maze

изображение из http://www.astrolog.org/labyrnth/maze/unicursl.gif

где я могу найти или перейти к построению такого алгоритма генерации лабиринта?

8 ответов


похоже, вам нужна кривая заполнения псевдослучайного пространства (например, см. контекстные кривые заполнения пространства-EUROGRAPHICS ’2000 (формат PDF, 1.1 Мб))

посмотрите кривая заполнения пространства.

Я подозреваю, что вы могли бы применить некоторую случайность к построению одного из них, чтобы достичь того, что вы хотите.


Я бы sugest, чтобы начать с полностью черного (полного) квадрата и попытаться выкопать путь. Во время копания вы легко убедитесь, что нет тупиков, просто продолжайте идти. Используйте алгоритм поиска backtracking, depth first. Сделайте "случайное блуждание" - на каждом шаге случайным образом решите, сохранить ли направление или изменить его. Проверьте состояние тупика - если вы застряли, вы можете либо сказать: "Ну, я закончил, я в финише", или, если вы считаете, что лабиринт еще не выкопан достаточно, просто вернуться. Всегда помните, что вы делали раньше, и попробуйте случайно какое-то другое действие. Вероятно, используйте эвристику, чтобы предпочесть определенные направления, например, всегда держать некоторое свободное пространство перед уклонением от стены, попытаться сначала обойти стены и т. д. - таким образом, вы могли бы найти желаемое решение, которое заполняет весь квадрат гораздо быстрее.


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

концепция проста: учитывая внешние границы лабиринта, начальную и конечную точки, напишите функцию для генерации случайных блужданий из начальной точки, которые в конечном итоге заканчиваются в конечной точке. Условия были бы таковы, что наш "случайный ходок" может двигаться только вверх, вниз, вправо или влево от предыдущего квадрата и не может прийти в пределах одного квадрата ранее пройденного квадрата (это создает стены).

Как я вижу, здесь есть две алгоритмические проблемы. Во-первых, выяснение того, находимся ли мы в пределах одного квадрата от ранее пройденного квадрата (столкновения). Возможно, мы могли бы сохранить список пройденных квадратов (их координаты) и границ лабиринта, и для каждого нового квадрата оценить расстояние от каждого квадрата в списке. Хотя это звучит не очень эффективно.

другой задача на самом деле достигает конечной точки с нашим случайным блужданием. Если бы столкновения с ранее пройденными квадратами не были проблемой, мы были бы обязаны в конечном итоге достичь нашей конечной точки, но с ними у нас есть проблема, что мы могли бы отгородиться от конечной точки. Способ избежать этого-проверить и избежать ввода циклов. Если мы избегаем входить в петли, образованные пройденным путем и / или границами лабиринта, то мы поддерживаем возможный путь к конечной точке. Насколько на самом деле прикидываем, не попали ли мы в петлю... Это довольно сложно.

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


Я не думал об этом, просто идея:

  • сосредоточьтесь не на тропе, а на стенах
  • начните только с черного внешнего квадрата
  • постепенно добавлять блоки стены в произвольных положениях, прилегающих к существующим блокам стены, сохраняя условие, что остается путь от начала до конца
  • когда ни одна ячейка пути не имеет более двух соседей пути, вы сделали

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

вероятно, ему понадобится возможность вернуться, если он застрянет.

наверное, это не слишком эффективно.


Ahh-я нашел гораздо более простой способ создания одномерного лабиринта.

начните с пустой сетки и заполните ее небольшими петлями 2x2. Если сетка нечетная по четной, вам нужно будет смешать несколько петель 2x3, а если нечетная по нечетной, вам придется оставить один квадрат свободным-я обычно оставляю угол незаполненным.

далее, произвольно соедините петли вместе, чтобы сформировать большие петли-так (например)2 петли 2x2 становятся одним циклом 4x2. Продолжайте делать это, убедившись, что вы не присоединяйте петлю обратно к себе.

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

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

Если вы работаете над нечетным лабиринтом, используйте этот последний метод, чтобы червь один из ваших концов к незаполненному углу, чтобы завершить лабиринт.


Я думаю, что нашел другой метод, однако я еще не тестировал его широко.

см.https://twitter.com/tdhooper/status/340853820584230915/photo/1

слева направо:

  • создайте не-уникурсальный лабиринт, как описано здесь https://en.wikipedia.org/wiki/File:Prim_Maze.svg, я думаю, что это алгоритм прим

  • закрыть выход

  • нарисовать путь, который посещает каждую точку в лабиринте (т. е. попробуйте решить его)

  • сделайте этот путь стеной


когда 'прогулки' сохранить изменения, сделанные на каждом шаге в стек, так что вы можете смотреть х шагов вперед, а затем на каждом этапе таким образом, что вы можете не предпринимать никаких дальнейших шагов ( пошел в угол или спирали как пешком ) поп стека, пока у вас есть жизнеспособный пешеходная дорожка и продолжайте идти оттуда до тех пор, пока стек пуст ( я.е вы поп стек весь путь обратно, потому что на каждом предыдущем шаге не было никакой жизнеспособной соседа ). Затем примените преобразования к структуре данных maze.


Я работаю над этим в данный момент... Начиная с края, я случайно иду по квадратному массиву, отмечая ячейки длиной пути, когда я прохожу через них.

когда вы застряли (и вы будете), создайте Т-образный переход, образующий цикл с самым последним путем, который рядом с вами (но см. ниже). Затем я возвращаюсь по существующему пути на другую сторону Т-образного перехода и разрываю там петлю. Этот болтающийся хвост затем формирует вашу новую "голову" случайного блуждания (не забудьте пересчитать длину пути из источника пути), и вы можете продолжить.

эксперименты показывают, что, делая это, он не (Или еще не - см. ниже) попал в петлю создания новых хвостов, пока ваш новый "хвост" пойман, вы не просто безмозгло переформируете связь с клеткой, от которой вы только что отделились, если это самый последний-выберите второй самый последний в этом случае.

завершающий случай-это когда вы застреваете на элементе edge, и вы заполнили массив (длина вашего пути совпадает с площадью массива) - вы сделали. Ваша начальная точка ведет к конечной.

кажется, есть две возможные неэффективности и потенциальные икоты с этим (я сейчас играю с алгоритмом) - иногда вы заходите в угол, и единственный способ продолжить-это переформулировать петлевую связь с той, которую вы только что сломали. Затем последовательность возвращается через все петли, которые вы ранее сделали для точка, в которой вы изначально застрял. Если это не могу пойти куда-нибудь еще (это еще один угол), то вы будете просто подпрыгивать между ними. Есть способы обойти это, но это означает, что вы сохраняете какой-то список замкнутых ячеек, только очищая его, когда вы на самом деле кладете какой-то новый путь.

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