Создание сплошной формы с N плитками в 2D массиве - PullRequest
2 голосов
/ 08 июня 2019

Я делаю генератор астероидов, который создает двумерный массив bool с.Генератор принимает параметр int, size, который должен определять, сколько True ячеек будет в двумерном массиве.

Как я могу гарантировать, что в выходном массиве нет дыр ичто правильное количество ячеек True?

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

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

def create_shape(size, seed):
    # init rng with seed
    rng = random.Random(seed)
    # initial grid values empty and full mass left
    # make the grid size by size so any shape could fit
    grid = [[False for x in range(size)] for y in range(size)]
    mass_remaining = size
    # guarantee the center is something
    center = size // 2
    grid[center][center] = True
    mass_remaining -= 1 # remember to reduce available mass
    # generate random values
    for x in range(size):
        for y in range(size):
            # skip the already filled in center
            if x == y == center:
                continue
            # assign random value
            value = bool(rng.randint(0, 1))
            grid[y][x] = value
            # remember to reduce mass
            if value: 
                mass_remaining -= 1
    # smoothen things out with cellular automata neighbor checking
    for x in range(size):
        for y in range(size):
            # skip the center
            if x == y == center:
                continue
            # get neighbors
            # set neighbors is the count of neighbors set to True
            set_neighbors = 0
            for i in range(-1, 2):
                for j in range(-1, 2):
                    # skip counting self
                    if i == j == 0:
                        continue
                    nx, ny = x + i, y + j
                    if 0 <= nx < size and 0 <= ny < size:
                        # only get in-range cells
                        if grid[ny][nx]:
                            set_neighbors += 1
            # more than 3 -> become True, less than 3 -> become False
            if set_neighbors > 3:
                grid[y][x] = True
                mass_remaining -= 1
            elif set_neighbors < 3:
                grid[y][x] = False
                mass_remaining += 1
            else:
                # otherwise leave it the same
                pass
    # find out how well the mass is staying "in-budget"
    print(mass_remaining)
    return grid

Функция часто print s выделяет целый ряд различныхоставшиеся массовые количества, например, имеющие -14 в «долге» или имеющие 42 дополнительно.Я бы ожидал, что на выходе будет 0, если функция будет работать правильно.

Например, вывод, подобный этому ...

create_shape(8) ->

[ 0, 0, 0, 0, 0, 0,
  0, 1, 1, 0, 0, 0,
  0, 1, 1, 1, 0, 0,
  0, 1, 1, 1, 1, 0,
  0, 1, 1, 1, 1, 0 ]

... сплошной, но имеет слишком многоустановить плитки.

Ответы [ 2 ]

2 голосов
/ 08 июня 2019

Не существует однозначного ответа на вашу проблему, тем более что основная задача («создать 2D-фигуры астероидов») недостаточно конкретизирована и принципиально субъективна.Конечно, в принципе, вы всегда можете генерировать сплошную форму плитки N , например, начиная с верхнего левого угла и добавляя плитки слева направо и сверху вниз, пока у вас не будет N из них,но получающаяся форма, вероятно, не будет очень реалистичным или «симпатичным» астероидом.

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

  • Начните с одной центральной плитки и случайным образом добавьте новые плитки, которые соседствуют с существующими.Перед добавлением каждой плитки, убедитесь, что добавление ее не оставляет отверстия внутри астероида;если это так, выберите другую плитку.(Проверка связности, вероятно, будет самой дорогой частью этого алгоритма, хотя существуют различные способы его оптимизации. В частности, вы можете начать только с проверки существующих непосредственных соседей новой плитки; если все они являются смежными,новая плитка не может соединить две отдельные части ребра.)

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

  • Примените алгоритм смещение средней точки к кругу.То есть используйте алгоритм для генерации случайного массива радиусов (с одинаковым радиусом на каждом конце), а затем используйте эти радиусы как расстояния от произвольно выбранной центральной точки до поверхности вашего астероида, как если бы вы строили радарный график .Это не даст вам точную площадь плиток N , но вы всегда можете масштабировать радиусы вверх или вниз, пока не получите нужный размер.Результирующая форма всегда будет звездно-выпуклой , и, следовательно, не имеет отверстий.(Вероятно, это будет работать лучше всего для довольно больших N . Одним из преимуществ этой схемы является то, что она будет также довольно просто и эффективно обобщать трехмерные фигуры: просто начните с рандомизированного многогранника и примените среднюю точкусмещение к граням.)

  • Используйте любой алгоритм, который обычно генерирует астероид без отверстий.Затем проверьте, есть ли отверстия, и если да, перезапустите.Пока вероятность перезапуска достаточно мала, этот метод выборки отклонения будет достаточно эффективным.

0 голосов
/ 05 июля 2019

Нисходящий метод будет:

  • начните со случайным образом нарисованных заполненных эллипсов в растровом изображении, поэкспериментируйте, пока не получите желаемый результат, ячейки пока являются пикселями, пример: http://www.star.bris.ac.uk/~mbt/topcat/figures/plot2-layer-xyellipse.png
  • растровое растровое изображение в ваши ячейки и преобразование в 0, если пустой пиксель и 1, если заполнено
  • заполнить отверстия, используя метод обнаружения соседей
...