C ++ двойной цикл итератора для обнаружения столкновений - PullRequest
2 голосов
/ 25 апреля 2011

Перво-наперво, я очень новичок в C ++! Итак, у меня есть стандартный список объектов, представляющих элементы в двухмерном пространстве, и я хочу сделать базовое обнаружение столкновений. Моя первая идея (исходящая в основном из Java-фона ...) состоит в том, чтобы сравнивать каждый объект с каждым другим объектом, вызывая функцию для проверки пересечения каждой пары или объектов. В Java это было бы просто: взять первый элемент ArrayList, сравнить его со вторым, третьим и т. Д., Затем взять второй элемент, сравнить его с третьим, четвертым и т. Д. Это подход, который я использовал с проблема в C ++, но я использую итератор (а не прямой доступ к элементам, как я бы сделал в Java), но итераторы предназначены для линейного использования, верно? Так что прямой доступ не подходит.

Итак, мой вопрос, как мне выполнить этот алгоритм? Я также вполне уверен, что это не лучший способ (очень простой) обнаружения столкновений, поэтому любые советы по этому поводу также приветствуются. Вот мой (нерабочий) код.

for (list<Box>::iterator p = mBoxes.begin(); p != mBoxes.end(); p++) {
    for (list<Box>::iterator q = mBoxes.begin() + p); q != mBoxes.end(); q++) {
        if (p->isIntersecting(q)) {
            p->changeDirection();
            q->changeDirection();
        }
    }
}

Это должно проиллюстрировать метод, который я пытаюсь использовать, но, конечно, моя попытка mBoxes.begin() + p не работает!

Ответы [ 3 ]

5 голосов
/ 25 апреля 2011

РЕДАКТИРОВАТЬ: Ответ на несколько комментариев.

for (list<Box>::iterator p = mBoxes.begin(); p != mBoxes.end(); ++p) {
    for (list<Box>::iterator q = p); q != mBoxes.end(); ++q) {
        if (p==q) continue;
        if (p->isIntersecting(*q)) {
            p->changeDirection();
            q->changeDirection();
        }
    }
}
1 голос
/ 26 апреля 2011

Класс списка является связанным списком, вы не можете напрямую индексировать его.Кроме того, итераторы не являются индексами, + просто не имеет никакого смысла.

Однако, теоретически, вы должны иметь возможность скопировать итератор, если вы измените q = mboxes.begin () + p на q= p он должен установить q в качестве итератора, указывающего на то же место p, и это может просто решить вашу проблему.

for (list<Box>::iterator p = mBoxes.begin(); p != mBoxes.end(); p++) {
  for (list<Box>::iterator q = p, q++; q != mBoxes.end(); q++) {
    if (p->isIntersecting(q)) {
        p->changeDirection();
        q->changeDirection();
    }
  }
}

q ++ должен просто пропустить текущий элемент, чтобы вы не сравнивалипредмет против себя.

0 голосов
/ 26 апреля 2011

Примерно так должно работать:

for (int p = 0; p < mBoxes.size(); ++p)
{
    for (int q = 0; q < mBoxes.size(); ++q)
    {
        if (p == q)
        {
            // don't compare for collision against itself
            continue;
        }
        if (mBoxes[p]->isIntersecting(mBoxes[q]))
        {
            mBoxes[p]->changeDirection();
            mBoxes[q]->changeDirection();
        }
    }
}

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

...