【问题标题】:Delete enemy from vector array从向量数组中删除敌人
【发布时间】:2018-07-14 14:29:12
【问题描述】:

这是我在这个网站上的第一个问题。我学了一年编程,总能在项目中找到问题的答案。我知道这是一个非常简单的问题,这里有一个代码:

#include "stdafx.h"
#include "Wave.h"

Wave::~Wave()
{
}

void Wave::setEnemyCount(int count) {
    nemyCount = count;
}

bool Wave::createWave() {
    for (int i = 0; i < enemyCount; i++) {
        enemyArray.push_back(Enemy());
    }

    for (int i = 0; i < enemyArray.size(); i++) {
        int randomPositionX = rand() % 150 + 10;
        int randomPositionY = rand() % 50 + 10;

        if (!enemyArray.at(i).init(randomPositionX, randomPositionY)) {
            std::cout << "Create wave(init enemies) - failed\n";
            return false;
        }
    }

    return true;
}

void Wave::drawWave(Window* window) {
    window->setCursor({ 0, 2 });
    window->setColor(Window::Color::RED);
    std::cout << "Enemies: " << enemyArray.size();
    window->setColor(Window::Color::WHITE);

    for (int i = 0; i < enemyArray.size(); i++) {
        enemyArray.at(i).draw(window);
        //std::cout << i;
    }
}

void Wave::update(Bullet* bullet, Player* player) {

    for (int i = 0; i < enemyArray.size(); i++) {
        if (player->checkShoot()) {
            if ((bullet->getPositionX() >= enemyArray.at(i).getPositionX() && bullet->getPositionX() <= enemyArray.at(i).getPositionX() + 5)) {
                if ((bullet->getPositionY() >= enemyArray.at(i).getPositionY() && bullet->getPositionY() <= enemyArray.at(i).getPositionY() + 5)) {
                    player->addScore(10);
                    enemyArray.erase(enemyArray.begin() + i);
                }
            }
        }
    }

    if (enemyArray.size() <= 0) {
        std::cout << "WAVE COMPLETE";
        Sleep(2000);
        enemyCount += 5;
        createWave();
    }
}

int Wave::getEnemyCount() const {
    return enemyCount;
}

碰撞工作正确,但是当子弹碰到索引的敌人时,例如:5,代码总是删除最后一个索引的敌人,所以我可以删除每个敌人只射击索引为 5 或 1 或 7 的敌人。

【问题讨论】:

  • 向量的大小不能小于零。实际上size返回的大小是unsigned,所以不能小于零。因此使用小于的比较是错误的。
  • 只要子弹没有碰到两个具有连续索引的敌人,代码看起来是正确的。请显示minimal reproducible example,包括示例输入/输出。
  • 至于您的问题,请考虑擦除元素时的向量索引。向量中 next 元素的新索引是多少?您删除的元素之后的元素?试着在一张方格纸上画出向量,每个方格都是一个元素。然后“擦除”一个元素并将剩余的元素移动以填充被擦除元素的洞。
  • 我知道,但这并不重要。我在循环中有问题。这就是所有方法,我认为更好的方法是粘贴所有代码:)。
  • minimal reproducible example 请。所有代码都不是最少的。

标签: c++ arrays vector erase


【解决方案1】:

当您执行enemyArray.erase(...) 时,您不应增加i,因为您将跳过一个元素。

所以你应该像这样重写循环:

for (int i = 0; i < enemyArray.size();) {
    if (player->checkShoot()) {
        if ((bullet->getPositionX() >= enemyArray.at(i).getPositionX() && bullet->getPositionX() <= enemyArray.at(i).getPositionX() + 5)) {
            if ((bullet->getPositionY() >= enemyArray.at(i).getPositionY() && bullet->getPositionY() <= enemyArray.at(i).getPositionY() + 5)) {
                player->addScore(10);
                enemyArray.erase(enemyArray.begin() + i);
                continue;
            }
        }
    }
    ++i;
}

或者,使用更惯用的风格:

for (auto it = enemyArray.begin(), end = enemyArray.end();it!=end;) {
    if (player->checkShoot()) {
        if ((bullet->getPositionX() >= it->getPositionX() && bullet->getPositionX() <= it->getPositionX() + 5)) {
            if ((bullet->getPositionY() >= it->.getPositionY() && bullet->getPositionY() <= it->getPositionY() + 5)) {
                player->addScore(10);
                enemyArray.erase(it);
                continue;
            }
        }
    }
    ++it;
}

当然,如果你想一次移除一个敌人,你应该在删除元素后在循环中break 而不是continue

为了完整起见,如果你想移除所有被子弹触及的敌人,你也可以使用std::remove_if,它比上面的2个循环更优化,因为当移除多个元素时它会减少元素的移动。

【讨论】:

  • 我试过用这个,当子弹碰到一个敌人时,程序会同时移除几个敌人。
  • 不,它不起作用。我无法将所有代码粘贴到编辑器中:(,他不知道什么是代码,什么是文本:D.
  • @KewinWoźny 我只能鼓励你调试你的游戏,例如打印变量的状态来看看发生了什么,问题出在哪里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-27
  • 2015-08-09
  • 1970-01-01
相关资源
最近更新 更多