简体   繁体   中英

vector iterator incrementable when erasing element of vector in 2 for loops

I am currently programming a little game for the console with an 2D map. 2 Elements of my game are: destroying fields and an enemy, which spreads in a random direction (its getting bigger). These two "entities" are saved in a structure which contains two vectors (X and Y). I am now trying to erase an element of "_Enemy"(<-private instance of the structure in a class, same as "_DestroyedFields") if you destroy the field where the enemy is.

I tried a lot of different variations to do so and whats giving me the error least is this method (I already searched the internet for a while now an couldn't find a answer to my question):

for (std::vector<int>::iterator itEX = _Enemys.X.begin(), itEY = _Enemys.Y.begin();
     itEX != _Enemys.X.end() && itEY != _Enemys.Y.end();
     ++itEX, ++itEY) {
  for (std::vector<int>::iterator itX = _DestroyedFields.X.begin(), 
                                      itY = _DestroyedFields.Y.begin(); 
           itX != _DestroyedFields.X.end() && itY != _DestroyedFields.Y.end(); 
           ++itX, ++itY) {
    if (*itY == *itEY && *itX == *itEX){
        itEY = _Enemys.Y.erase(itEY);
        itEX = _Enemys.X.erase(itEX);
    }
  }
}

PS: sorry if my english isn't the best, im german ^^

PSS: if you wanna watch over my whole code, you can find it on Github: https://github.com/Aemmel/ConsoleGame1

After erasing using iterator it , you cannot use it further as it is invalidated. You should use a result of a call to erase which is new, valid iterator.

for( it = v.begin(); it != v.end();)
{
   //...   
   if(...)
   {
      it = v.erase( it); 
   }
   else
   {
      ++it;
   }
   ...
}

I fixed the bug with first: making a "simple structure"(struct Entity{int X; intY} and then std::vector [insert name here]) and then with adding an break; if the condition is true.

for (Uint itE = 0; itE < _Enemys.size(); ++itE){
        for (Uint it = 0; it<_DestroyedFields.size(); ++it){
            if (_Enemys.at(itE).Y == _DestroyedFields.at(it).Y 
                && _Enemys.at(itE).X == _DestroyedFields.at(it).X){
                _Enemys.erase(_Enemys.begin()+itE);
                break;
            }
        }
    }

With struct Position {int x; int y;}; struct Position {int x; int y;}; and some utility operators,
you may do one of the following: ( https://ideone.com/0aiih0 )

void filter(std::vector<Position>& positions, const std::vector<Position>& destroyedFields)
{
    for (std::vector<Position>::iterator it = positions.begin(); it != positions.end(); ) {
        if (std::find(destroyedFields.begin(), destroyedFields.end(), *it) != destroyedFields.end()) {
            it = positions.erase(it);
        } else {
            ++it;
        }
    }
}

Or, if input are sorted, you may use a 'difference':

std::vector<Position> filter2(const std::vector<Position>& positions, const std::vector<Position>& destroyedFields)
{
    std::vector<Position> res;
    std::set_difference(positions.begin(), positions.end(),
                        destroyedFields.begin(), destroyedFields.end(),
                        std::back_inserter(res));
    return res;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM