Путешествие по циклу for одновременно с удалением и вставкой - PullRequest
0 голосов
/ 25 октября 2011

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

Нормальное значение для разрывов цикла, как если бы удаление или рождение произошло, то индекс, в котором он находится в данный момент, перекошен. Что было бы лучшим решением? Хотя со счетчиком и условно, что размер> 0 или как-то иначе?

Ответы [ 3 ]

5 голосов
/ 25 октября 2011

Вы можете подождать, пока вы закончите итерацию для добавления / удаления элементов:

entities_to_add = new Array;
entities_to_remove = new Array;

function tick():
    for each entity in world:
        //general entity behavior goes here
        if entity.wants_to_reproduce:
            entities_to_add.append(entity.make_baby())
        if entity.wants_to_die:
            entities_to_remove.append(entity)

function cleanup():
    for each entity in entities_to_remove:
        world.remove(entity)
    for each entity in entities_to_add:
        world.add(entity)
    entities_to_remove.clear()
    entities_to_add.clear()

function main():
    while(True):
        tick()
        cleanup()

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

1 голос
/ 31 октября 2011

Обычно в симуляции бывает две копии мира - одна для состояния во время t , другая для состояния во время t + & Delta; t .

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

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

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

0 голосов
/ 27 октября 2011
    ArrayList<Object> predators = new ArrayList<Object>();
    ArrayList<Object> preys = new ArrayList<Object>();
    for (Object predator : predators) {
      Object[] entities = preys.toArray();
      for (Object entity : entities) {
        if (entity.shouldReprodue()) {
            world.add(entity.baby());
        }
        if (entity.shouldDie()) {
            world.remove(entity);
        }
      }
    }

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

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