Страницы

Поиск по вопросам

среда, 24 октября 2018 г.

Генерация 3-х мерного лабиринта

Я бы хотел реализовать генерацию трехмерного лабиринта, что-то вроде этого

Ничего путного по этой теме найти не удалось. Есть у кого идеи на эту тему?


Ответ

Для начала, определимся с тем, что же такое лабиринт, т.е. дадим первое определение лабиринта, которое впоследствии мы чуть-чуть модифицируем. Я буду рассматривать двумерный случай. Трёхмерный во всех его вариациях строится ровно так же.
Определение. Лабиринтом на плоскости будем называть связный неориентированный граф без петель, у каждой вершины которого не более 4 ребёр.
Довольно легко провести аналогию решётки-лабиринта nxm и лабиринта. Как это сделать? Достаточно рассмотреть клетку и заметить, что у каждой клетки есть 4 соседа (не берём граничные случаи):

Теперь можно убрать, например, одного соседа. Обычная ситуация в лабиринте:

Каждую клетку можно ассоциировать с вершиной. Наличие соседа - связывать с ребром. В таком случае, довольно очевидно, что определение более или менее корректное. С первого взгляда непонятно: для каждого ли лабиринта можно подобрать решётку-лабиринт, ровно как и наоборот. Здесь уже необходимо строгое доказательство, которое приводить смысла много не имеет.
Вообще говоря, для порождения самого лабиринта, строить граф в явном виде не обязательно. Я лишь заострил внимание на этом, дабы дать волю Вашей фантазии. Построение графа может быть полезно при более детальном изучении вопроса. Вам может быть важно, чтобы лабиринт обладал какими-нибудь свойствами. Может быть Вам захочется ввести некую "плотность" или разветвлённость лабиринта. В таком случае на помощь могут прийти именно графы.
Определение. Границей решётки или просто границей назовём такую вершину, координата которой на решётке равна: (x, m), или (n,x), или (1,x), или (n,x), где х -- любое число из промежутков [1,n] или [1,m].
Теперь же, перейдём к генерации лабиринта. Сделаем это так. Зададим матрицу nxm. Выберем одну точку на одной из границ. После этого запустим из этой точки обход в глубину в пределах решётки.
Для каждой точки лабиринта будем по очереди выбирать каждое из 4х направлений и случайным образом, с вероятность p, принимать решение, есть ли проход в этом направлении или его нет. Будем его выполнять до тех пор, пока суммарное количество точек на границе будет не более k. Как только это произойдёт, мы прекращаем наше выполнение действий.
Делая действия таким образом, можно получить очень неравномерный лабиринт. Поэтому можно критерий останова чуть-чуть изменить. Будем его выполнять процесс до тех пор, пока суммарное количество точек на границе будет не более k и на каждой из границ (всего границы, разумеется, 4), будет не менее k_i точек.
Теперь нам нужно выбрать выбрать начало и конец. Можно, конечно, взять любые 2 точки на границе, но в таком случае, может случиться, что путь от начала в конец окажется тривиальным (т.е. слишком простым и коротким). Для того, чтобы этого избежать, следует выбирать начальную и конечную точки на расстоянии друг от друга не менее чем d
Таким образом мы построили алгоритм генерации лабиринта с параметрами: k, k_i (4 шт), p, d
Советую обратить внимание на такую вещь как теория перколяции. В этой теории реализуется процесс, который я описал выше.
У меня валяются три реализации перколяционного процесса на питоне, матлабе и плюсах. Вы можете на них взгялнуть здесь: 1, 2, 3

Комментариев нет:

Отправить комментарий