Размещение комнаты в лабиринте с использованием алгоритма Прима

Я пытаюсь разместить комнаты на экране ASCII, а затем использую алгоритм Прима, чтобы " заполнить "пространство между комнатами лабиринтом, но без фактического проникновения в комнаты". Я возился несколько часов и не могу придумать, как помешать моему алгоритму проникнуть в мои комнаты.

Может кто-нибудь помочь мне? Я очень потерян. Я практикую технику генерации карт, и это мой 5-й по счету. Нет, я не хочу делать это по-другому, я просто хочу сделать это по-другому - но правильно.

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

Примечание. Все, что делает противоположный метод, - это выяснение, какая ячейка является «родительской», и определение направления на основе этого. Таким образом, если значение x родительской ячейки равно 7, а значение x дочернего элемента равно 6, то он знает, что это новый дочерний элемент.

start = new Point(x,y, null);
map[start.x][start.y] = Tile.STAIRS_DOWN;

for(int nx = -1; nx <= 1; nx++){
    for(int ny = -1; ny <= 1; ny++){
        if((nx == 0 && ny == 0) || (nx != 0 && ny != 0)){
            continue;
        }
        try{
            if(map[start.x + nx][start.y + ny] == Tile.FLOOR){
                continue;
            }
            frontier.add(new Point(start.x+nx, start.y + ny, start));
        }
        catch(Exception e){
            continue;
        }
    }
}

Point last = null;
while(!frontier.isEmpty()){
    Point cu = frontier.remove(RandomGen.rand(0, frontier.size() - 1));
    Point op = cu.opposite();
    try{
        if((map[cu.x][cu.y] == Tile.WALL) && (map[op.x][op.y] == Tile.WALL)){
            for (int bx = -1; bx <= 1; bx++)
                for (int by = -1; by <= 1; by++) {
                    boolean failed = false;
                    if (bx == 0 && by == 0 || bx != 0 && by != 0)
                        continue;
                    try {
                        if(map[op.x + bx][op.y + by] == Tile.FLOOR){
                            break;
                        }
                        last = op;
                        if(!failed){
                        map[cu.x][cu.y] = Tile.FLOOR;
                        map[op.x][op.y] = Tile.FLOOR;
                        frontier.add(new Point(op.x + bx, op.y + by, op));
                        }
                    }
                    catch(Exception e){
                        continue;
                    }
                }
        }
    }
    catch(Exception e){}
}

Без комнат

С комнатами


person K. Kennedy    schedule 17.03.2017    source источник
comment
Алгоритм Прима (я предполагаю, что вы используете его со случайными весами) находит дерево на графе. Чтобы избежать нежелательных ребер, вы должны сделать так, чтобы они отсутствовали в исходном графе. Т.е. вы должны включать только те края, которые не разбиваются на комнаты. Тогда Прим не сможет дать вам нежелательного преимущества.   -  person Gene    schedule 17.03.2017
comment
@Gene, поскольку это тайловая карта, и мне каждый раз приходится проходить на 2 тайла вперед, кажется, действительно сложно не проникнуть в комнаты. Как я могу это изменить?   -  person K. Kennedy    schedule 17.03.2017
comment
Вы делаете обычную ошибку новичков, пытаясь сопоставить проблему со структурой данных, вместо того, чтобы найти правильную структуру данных для проблемы. Перестаньте думать о комнатах и ​​переездах. Прим - это графы. Подумайте о графе узлов и ребер, покрывающем сетку с допустимыми ребрами (то есть теми, которые не проникают в комнаты), которые соответствуют допустимым ходам. Нарисуйте несколько, чтобы детали у вас в голове. Теперь, когда вы понимаете графики, спроектируйте структуру данных, которая их эффективно представляет. Это может быть (возможно, не) 2-мерный массив значений перечисления. Теперь запустите Prim.   -  person Gene    schedule 17.03.2017
comment
@Gene Я попробую и вернусь к вам! Я студент и еще не изучал теорию графов, так что я вроде ... лажаю самостоятельно. Я делаю это, потому что хочу практиковать теорию графов, поэтому, если я делаю это задом наперед, это плохо. Спасибо.   -  person K. Kennedy    schedule 17.03.2017
comment
@Gene Хорошо, я еще не реализовал это, но я почти уверен, что нашел решение моей проблемы, используя метод, который вы описали. Я думаю, что проблема с моим кодом в том, что я добавляю плитку СЛЕДУЮЩУЮ к своим точкам на границе, тогда как я должен добавлять плитку +1 от нее, потому что между ними должна быть сплошная стена. По сути, мой пограничный вызов неверен.   -  person K. Kennedy    schedule 17.03.2017


Ответы (1)


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

person K. Kennedy    schedule 17.03.2017