Вектор выходит за пределы - PullRequest
0 голосов
/ 07 декабря 2018

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

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

Вот мой вектор:

vector<Piece*> pieces;
pieces.push_back(&b);
pieces.push_back(&r);
pieces.push_back(&q);
pieces.push_back(&b2);
pieces.push_back(&r2);
pieces.push_back(&q2);

, и этот цикл я повторяю, используя:

while (pieces.size() > 1) {
    cout << "-------------- Round " << round << " --------------" << endl;
    round++;
    cout << pieces.size() << " pieces left" << endl;
    i = 0;
    while (i < pieces.size()) {
        pieces.at(i)->move(board.getMaxLength());
        j = 0;
        while (j < pieces.size()) {
            if (pieces.at(i) != pieces.at(j) && col.detectCollision(pieces.at(i), pieces.at(j))) {
                cout << pieces.at(i)->getName() << " has slain " << pieces.at(j)->getName() << endl << endl;
                pieces.at(i)->setKills(pieces.at(i)->getKills() + 1);
                pieces.erase(pieces.begin() + j);
            }
            else {
                j++;
            }
        }
        i++;
    }
}

Решение

pieces.erase(pieces.begin() + j);
break;

Ответы [ 3 ]

0 голосов
/ 07 декабря 2018

Ваша логика нуждается в небольшом уточнении.

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

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

i++;
* 1007 безоговорочно выполняется безоговорочно. Она не должна выполняться, если вы удаляете кусок по той же причине, по которой не выполняется j ++: вы перепрыгнете кусок.
0 голосов
/ 08 декабря 2018

У меня очень сильное чувство, что эта строка кода:

i++;

- это ваш преступник, в котором отсутствует либо необходимое условие разрыва, либо другая условная проверка, которая отсутствует в ваших циклах.Поскольку это относится к условиям ваших вложенных циклов while, поскольку они основаны на текущем размере вашего вектора и не обновляются соответствующим образом.

while (pieces.size() > 1) {
    // ...
    while (i < pieces.size()) {
        // ...
        while (j < pieces.size()) {
              // ...
        }
    }
} 

Это связано с тем, что вы вызываете это внутрисамый внутренний вложенный цикл:

 pieces.erase(pieces.begin() + j);

Вы находитесь во вложенном цикле while и, если выполняется определенное условие, вы стираете объект в этом месте индекса в вашем векторе, пока вывсе еще находятся во внутреннем цикле while, от которого вы никогда не прерветесь или не проверите, является ли индекс по-прежнему действительным.

Изначально вы вводите цикл while с вектором, который имеет 6 записей, и вызываете стирание на нем в рамках вложенного цикла, и теперь ваш вектор имеет 5 записей.

Это может нанести ущерб вашим циклам, потому что ваши счетчики индекса i & j были установлены в соответствии с исходной длиной вашего вектора размером 6, но теперь вектор был уменьшен доразмером 5, пока вы все еще находитесь во внутреннем самом вложенном цикле, из которого вы никогда не ломаетесь и не проверяете, действительны ли индексы.На следующей итерации эти значения теперь становятся недействительными, поскольку вы никогда не выходите из циклов, чтобы сбросить индексы в соответствии с новым размером вашего вектора, и не проверяете, являются ли они действительными.


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

int main() {
    std::vector<std::string> words{ "please", "erase", "me" };

    std::cout << "Original Size: " << words.size() << '\n';
    for (auto& s : words)
        std::cout << s << " ";
    std::cout << '\n';

    words.erase(words.begin() + 2);

    std::cout << "New Size: " << words.size() << '\n';
    for (auto& s : words)
        std::cout << s << " ";
    std::cout << '\n';

    return 0;
}

-Output-

Original Size: 3
please erase me
New Size: 2
please erase
0 голосов
/ 07 декабря 2018

Вы должны сохранить локально pieces.at(i) и использовать эту локальную переменную везде, где вы используете pieces.at(i).

Чтобы избежать как элементов из связанных, так и логических проблем, вы можете использовать std::list.

Кроме того, вы должны использовать std::vector<Piece*> только в том случае, если это не принадлежащие указатели, в противном случае вам следует использовать умные указатели, вероятно unique_ptr.

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