所以我在Java中制作一个小游戏,在游戏中你有实体存储在LinkedList中。在tick方法中,我遍历实体' LinkedList如下:
->weekly()->mondays()->at('14:32');
渲染方法也是如此
@Override
public void tick(float delta) {
for (Entity e : entities) {
e.tick(delta);
}
player.tick(delta);
}
其中一个实体是一个名为Block的类。在Block类中,有一个函数在块接近时返回,在此函数中我也遍历实体' LinkedList和它在Block中的以下tick方法调用:
@Override
public void render(Graphics g) {
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, Game.WIDTH, Game.HEIGHT);
for(Entity e : entities) {
e.render(g);
}
player.render(g);
}
(顺便说一下,该函数在块的tick方法中调用并使用)
现在每次我运行游戏时,游戏都会启动并运行正常几毫秒,然后抛出此异常:
@Override
public void tick(float delta) {
if (color == Color.WHITE) {
if (getSurrounding(-32, -32) != null && getSurrounding(-32, -32).getColor() == Color.BLACK) {
if (getSurrounding(-32, -32).getStrength() < strength) {
getSurrounding(-32, -32).setStrength(-50);
}
}
}
if (!inGame.entities.isEmpty() && strength <= 0) {
inGame.entities.remove(this); // <------ REMOVING AN ELEMENT
}
}
public Block getSurrounding(int xOffset, int yOffset) {
for (Entity e : inGame.entities) {
if (e instanceof Block) {
if (x + xOffset == e.getX() && y + yOffset == e.getY()) {
return (Block) e;
}
}
}
return null;
}
(前两个代码示例位于InGame.java文件中,第36行是tick方法中的for循环) 现在我该如何阻止此错误?
答案 0 :(得分:3)
ConcurrentModificationException
通常涉及在循环中迭代列表时修改列表。
我的假设是你在迭代时删除一个元素。
为了阻止这种情况发生,我建议在变量处于循环中时保存要删除的对象(并且已满足某些条件),然后在循环完成后将其从列表中删除。
编辑:根据更新的问题,您将删除tick方法中的元素。我不会在这里执行此操作,但返回您要删除的元素,并仅在您不再迭代要删除的列表时将其删除。
可能的解决方案: 我会创建另一个方法来检查实体的强度并从tick方法调用它(这是为了保存tick方法必须返回一个要删除的对象),如下所示:
@Override
public void tick(float delta) {
Entity removeEntity = null;
for (Entity e : entities) {
e.tick(delta);
if(e.checkStrength()){
removeEntity = e;
break;
}
}
if(removeEntity != null){
entities.remove(removeEntity);
}
player.tick(delta);
}
在实体类中:
public boolean checkStrength(){
if (!inGame.entities.isEmpty() && strength <= 0) {
return true;
}
return false;
}
您知道这不是目前为止最好的解决方案,但应该让您解决现在遇到的问题。有空的时候一定要清理你的代码。
答案 1 :(得分:1)
您正在删除tick()
方法中的实体...在方法中,您仍在迭代外部tick方法中的实体...因为您正在修改{{{}内的列表1}},列表正在改变,导致下一次迭代失败...用inline方法将方法调用替换为e.tick()
可以更清楚地证明问题:
e.tick()
请注意,您已经注意到的是&#34;删除元素&#34;在最外层循环中,这是导致问题的原因。
编辑:建议的解决方案正如其他人所建议的那样,尝试这样的事情(只显示删除块):
@Override
public void tick(float delta) {
for (Entity e : entities) {
//e.tick(delta); --inline below
if (color == Color.WHITE) {
if (getSurrounding(-32, -32) != null && getSurrounding(-32, -32).getColor() == Color.BLACK) {
if (getSurrounding(-32, -32).getStrength() < strength) {
getSurrounding(-32, -32).setStrength(-50);
}
}
}
if (!inGame.entities.isEmpty() && strength <= 0) {
inGame.entities.remove(this); // <------ REMOVING AN ELEMENT
}
}
}
然后在调用函数中,在完成所有迭代后
List toRemove = new ArrayList() //somewhere earlier in the code
if (!inGame.entities.isEmpty() && strength <= 0) {
//inGame.entities.remove(this); // <------ REMOVING AN ELEMENT
toRemove.add(this);
}
return toRemove;
答案 2 :(得分:0)
使用迭代器的解决方案:
用以下内容替换第一个代码块:
public void tick(float delta) {
for (Iterator<Entity> iterator = entities.iterator(); iterator.hasNext();) {
boolean remove = e.tick(delta);
if(remove) {
iterator.remove();
}
}
player.tick(delta);
}
然后用其替换另一个tick
方法:
public boolean tick(float delta) {
if (color == Color.WHITE) {
if (getSurrounding(-32, -32) != null && getSurrounding(-32, -32).getColor() == Color.BLACK) {
if (getSurrounding(-32, -32).getStrength() < strength) {
getSurrounding(-32, -32).setStrength(-50);
}
}
}
if (!inGame.entities.isEmpty() && strength <= 0) {
return true;
}
return false;
}
这应该可以解决您的问题。方法返回类型必须更改,以便我们有一个指示器何时删除任何元素,何时不删除。每次tick
返回true时,相应的元素都将被删除