0

[为澄清起见,“怪物”是一个 NPC 列表,当被“子弹”物体射击时会从列表中删除。]

启动错误:

W/System.err: java.util.ConcurrentModificationException
W/System.err:     at java.util.ArrayList$Itr.next(ArrayList.java:831)
W/System.err:     at com.companyname.product.GameplayScene.update(GameplayScene.java:113)
//...

我相信这意味着它正在尝试对列表中不存在的某些内容执行操作。所以我的问题是,我能否得到一些帮助来确定一个不存在的对象被调用的点,因为我似乎找不到它。我知道它在哪个类中,因为第一行为每个错误引用它。

        for (Bullet bullet : player.getList())
            if (npcManager.bulletCollide(bullet)) { //checks for a collision between all npcs and all bullets
                 player.getList().remove(bullet);//npc is removed in method above

        }

       if (!gameOver) {
        npcManager.update(); //updates movement of npcs
        if (npcManager.playerCollideNPC(player)) {
            //end game
        }
    }

    for (RectNPC NPC : npcManager.getList())
        if (obstacleManager.NPCCollide(NPC)) { //checks collision between npcs and other objects
            //
        }

        int i = 0;
        //checks collisions between NPCs themselves
        while (i < (Constants.NUMBER_ENEMIES - 1)) {
            if (npcManager.getList().size() <= 1)
                return;
            if (Rect.intersects(npcManager.getList().get(i).getRectangle(), npcManager.getList().get(i + 1).getRectangle()))
                npcManager.getList().get(i).setRectangle(200);
            i += 1;
        }
    }

(上图)我想问题将在于在更新中调用某些东西(如上所示),其中对象不再可用,我如何删除 NPC 是否有任何问题?

 public boolean bulletCollide(Bullet bullet) {
    for(RectNPC npc : monsters) {
        if(npc.bulletCollideNPC(bullet)) {
            monsters.remove(npc);
            monsters.add(0, new RectNPC(new Rect(100, 100, 200, 200), Color.rgb(255, 0, 0), 25));
            return true;
        }
    }
    return false;
}

(上)我要删除 NPC 的代码,我已经包括在内,因为它很有帮助 - 但是它确实做了它的意思,所以我不相信这是问题所在。


我的主要问题是,这里有什么东西会导致这个错误(游戏停止几帧并在顶部给出错误) - 或者我应该查看其他特定的东西/其他地方?我也知道我的一些语法不是很好,我很抱歉这是我的第一个 Java 项目。


当前迭代器:

for(Iterator<RectNPC> iterator = monsters.iterator(); iterator.hasNext();) {
        if(iterator.next().bulletCollideNPC(bullet)) {
            iterator.remove();
            monsters.add(0, new RectNPC(new Rect(100, 100, 200, 200), Color.rgb(255, 0, 0), 25));
            return true;
        }
    }

for (Iterator<Bullet> iterator = player.getList().iterator(); iterator.hasNext(); ) {
            if (npcManager.bulletCollide(iterator.next())) {
                iterator.remove();
                //
            }
        }
4

3 回答 3

2

在java中,你不能这样做for( T variable : collection ) { collection.remove( variable ); }换句话说,你不能从一个正在for循环迭代的集合中删除项目。这将导致一个ConcurrentModificationException. 谷歌“java fail-fast iterator”了解更多关于为什么和如何的信息。

你有两个选择:

  • 将所有要删除的怪物收集到一个临时列表中,然后在完成对主列表的迭代后,再次遍历临时列表以将它们从主列表中删除。关键是你不会从你正在迭代的同一个列表中删除。

  • 代替“foreach”(for)循环,使用一个实际的迭代器,当你想删除一个项目时,通过调用迭代器的remove()方法而不是包含集合的remove()方法来删除它。迭代器的remove()方法执行必要的技巧来防止 aConcurrentModificationException被抛出。

于 2017-03-28T22:26:46.173 回答
1

使用 Iterator 以安全的方式删除您的元素。

请注意, Iterator.remove 是在迭代期间修改集合的唯一安全方法;如果在迭代过程中以任何其他方式修改了基础集合,则行为未指定。来自Java SE 文档

static void filter(Collection<?> c) {
    for (Iterator<?> it = c.iterator(); it.hasNext(); )
        if (!cond(it.next()))
            it.remove();
}

例子

于 2017-03-28T22:38:46.823 回答
1

你的方法是做 3 件不同的事情。它返回一个布尔值,从列表中删除一个元素,然后添加一个元素。我会重组代码,让你有 3 种方法只做一件事。

您可以使用 Java 8 内部迭代器的强大功能作为起点

      monsters.removeIf(e -> e.bulletCollideNPC(bullet));
于 2017-03-28T22:36:55.170 回答