создание случайных и уникальных векторов в pygame - PullRequest
0 голосов
/ 09 июля 2020

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

Вот функция, которую я придумал:

def create_cells(number_of_cells):
    cell_grid = []
    cell_grid.append(pygame.math.Vector2(0,0))

    while len(cell_grid) < number_of_cells: 
        new_cell = random.choice(cell_grid).xy 
        new_cell[random.choice((0,1))] += random.choice((-1,1)) 
        for existing_cell in cell_grid: 
            if new_cell != existing_cell:
                cell_grid.append(new_cell)

    return cell_grid

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

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

1 Ответ

2 голосов
/ 09 июля 2020

Редактировать 2: Я добавил объяснение ошибки OP в конце под «Редактировать 2».

Это не касается ошибки, о которой вы спрашиваете, но я собираюсь предложить лучший подход к ваша проблема.

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

На самом деле, вероятно, имеет смысл отслеживать открытые соседние ячейки, а не свободные края, но это более или менее то же самое,

Я что-то упустил из-за проблемы, которая мешает этому?

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

Редактировать 2: Я взглянул на ваш код, и эта часть проблемная. c:

        for existing_cell in cell_grid: 
            if new_cell != existing_cell:
                cell_grid.append(new_cell)

Во-первых, вы НЕ должны перебирать список и одновременно изменять этот список. Это может испортить итерацию. Особенно плохо, если вы удаляете элементы из списка, но также плохо, если вы добавляете в него. В этом случае вы, когда я запускал свой код, добавляли new_cell в конец списка cell_grid, а затем for l oop, когда он дошел до конца, проверил cell_grid против самого себя.

Во-вторых, вы не проверяете, есть ли new_cell в списке перед его добавлением.

Вы проверяете, не совпадает ли он с каждой записью в списке, и добавляете его каждый раз, когда это не так. . Скажем, на третьем проходе у вас есть (0, 0) и (1, 0) в списке, и он выбирает new_cell из (0, -1). Он сравнит его с (0, 0), увидит, что это не то, и добавит (0, -1) в список, а затем сравнит его с (1, 0), увидит, что это не тот, и снова добавит (0, -1) в список. По мере того, как список становится больше, он будет добавлять в список еще больше копий new_cell.

Большая проблема заключается в том, что он добавит запись, даже если она уже есть в списке, поскольку она будет добавьте его для каждой записи, которая не является совпадением, и не будет добавлять ее только для сравнений, которые являются совпадениями. Давайте продолжим предыдущий пример, где теперь он имеет new_cell = [(0, 0), (1, 0), (0, -1), (0, -1)] и теперь выбирает new_cell из (0, 0). Он будет соответствовать первой записи и не будет добавлять ее, но затем продолжит просмотр остальных записей, не совпадающих, и добавит ее 4 раза для каждой из этих записей.

Есть ли причина, по которой вы не просто делают:

        if new_cell not in cell_grid: 
            cell_grid.append(new_cell)

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...