2015-08-28 4 views
-1

У меня есть вектор объектов .. монстров. и у меня есть функция «стрелять». Я хочу, чтобы, когда я убил одного из монстров, объект, который нужно удалить. Я пробовал разные способы, но не добился успеха. Вот как я создал объекты:Удалить объект из вектора объектов

void AdaugareMonstru(vector<monstru>& Nmonstru){ 
    int i = 0; 
     srand(time(0)); 
     int a, b; 
     for (i; i < 4; i++){ 
      a = (rand() % 5)+1; 
      b = (rand() % 8)+1; 

      while (a == 1 && b == 1){ 
       a = (rand() % 5)+1; 
       b = (rand() % 8)+1; 
      } 
      monstru newMonstru(a,b); 
      Nmonstru.push_back(newMonstru); 
     } 
    } 

А вот функция, где я нашел монстр перед моим «героем» и я убью его ... или not..cuz я не знаете, как удалить его: D Я думаю, что есть проблема с моим объявлением функции «trage», но я не могу понять это.

void trage(vector<monstru>& monstru, vector< vector<char> > map,int x,int y,int face){ 
     if (face == 1) 
     { 
      for (int i = y; i < 10; i++){ 
       if (monstru[0].GetX() == x && monstru[0].GetY() == i){ 
        monstru[0].SetX(0); 
        monstru[0].SetY(0); 
        cout << "Ai ucis un monstru" << endl; 
       } 
       if (monstru[1].GetX() == x && monstru[0].GetY() == i){ 
        monstru[1].SetX(0); 
        monstru[1].SetY(0); 
        cout << "Ai ucis un monstru" << endl; 
       } 
       if (monstru[2].GetX() == x && monstru[0].GetY() == i){ 
        monstru[2].SetX(0); 
        monstru[2].SetY(0); 
        cout << "Ai ucis un monstru" << endl; 
       } 
       if (monstru[3].GetX() == x && monstru[0].GetY() == i){ 
        monstru[3].SetX(0); 
        monstru[3].SetY(0); 
// Instead of setting X and Y to 0 i want to delete the whole object. 
        monstru.erase(1); // doesn't work... no wonder:D 
        delete monstru[0]; // doesn't work either. 
        cout << "Ai ucis un monstru" << endl; 
       } 
      } 
     } 
    } 
+2

Сначала никогда не используйте delete, если вы не использовали новый. Во-вторых, вам нужен итератор для монстра, которого вы хотите стереть, и именно этот итератор вы передаете 'erase()' – NathanOliver

+1

monstru.erase (monstru.begin() + i); должен работать, но вы должны изучить лучшие способы найти монстра перед персонажем. – user4581301

+0

Похоже, что это работает. Я не мог придумать лучшего способа найти то, что находится перед моим персонажем, даже то, что я использовал, хуже ... больнее попробовать. спасибо: D –

ответ

0

Как вы можете видеть here, monstru.erase() нужен итератор. вам нужно сделать что-то вроде

monstru.erase(monstru.begin() + index) 

с индексом окопа монстра вы whant «убить» в векторе

также, в первом фрагменте, do..while может быть лучше

1

Ключевое слово delete на самом деле не имеет отношения к std::vector.
Используется для удаления памяти, выделенной с помощью оператора new,
, который, по-видимому, не является тем, что вы здесь сделали.

Чтобы удалить элемент из вектора, вы должны использовать monstru.erase(monstru.begin() + n); который удаляет n-й элемент из вектора.

Я думаю, что вы намеревались удалить монстр, который соответствует вашему if-statement из vector. Но тогда вы должны позаботиться о том, чтобы напрямую не обращаться к monstru[3], так как пока неясно, существует ли он в настоящее время. Таким образом, вы должны обобщить свой код с for цикла, что даже делает его более удобным для чтения, а также меньше, как приятный побочный эффект):

void trage(vector<monstru>& monstru, vector< vector<char> > map,int x,int y,int face){ 
    if (face == 1) 
    { 
     for (int i = y; i < 10; i++){ 
      for (int m = 0; m < monstru.size(); m++){ 
       //use index 'm' here: 
       if (monstru[m].GetX() == x && monstru[0].GetY() == i){ 
        monstru.erase(monstru.begin() + m); 
        cout << "Ai ucis un monstru" << endl; 
       } 
      } 
     } 
    } 
} 
+0

Правильная идея, но есть немного точки для внешнего цикла, поскольку вы повторяете весь массив с внутренним циклом. – user4581301

2

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

В коде OP monstru.erase(monstru.begin() + i); убьет монстра.

Но есть лучшие способы найти монстра для убийства. Мальте Шмитц продемонстрировал подход грубой силы. Следующее немного менее жестокое.

Сначала добавьте функцию удобства для class monstru

bool isAt(int x, int y) const 
{ 
    return (mX == x && mY == y); 
} 

Где mX и mY являются расположение monstru в. Я не знаю их внутренних имен, поэтому я использую mX и mY в качестве владельцев мест.

Затем быстрое изменение функции прототипа trage частично для эстетики и частично для устранения конфликта имен позже. Использование одного и того же имени для нескольких вещей затрудняет поиск вещей.

Использование x в нескольких функциях круто. Использование двух вещей с именем x в одной и той же функции довольно опасно, даже если они имеют разные области, поэтому они не конфликтуют. Использование x x; переменная x типа x просто беспорядочна, поэтому vector<monstru> monstru следует очистить, чтобы предотвратить путаницу и завинчивания.

void trage(vector<monstru>& monstruList, 
      vector<vector<char> > &map, 
      int x, 
      int y, 
      int face) 
{ 
    if (face == 1) // not sure what this does, but I'm keeping it. 
    { 
     auto it = std::find_if(monstruList.begin(), 
           monstruList.end(), 
           [x,y](const monstru & monst) // lambda expression 
           { 
            return monst.isAt(x,y); 
           }); 

     if (it != monstruList.end()) 
     { 
      monstruList.erase(it); 
     } 
    } 
} 

lambda expression является своего рода встроенной анонимной функции. Но только вроде. Нет смысла переосмысливать его, так что читайте так: What is a lambda expression in C++11?

[x,y] говорит, что локальные переменные x и y «захватываются» и доступны внутри тела выражения лямбда.

(const monstru & monst) Список параметров, в частности, лямбда называется ссылкой на константу monstru, которую мы будем называть monst.

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

OP также должен изучить другие способы хранения местоположения монстра, такие как разреженная матрица или std :: map.

Смежные вопросы