2017-06-10 13 views
3

船と衝突したときに両方を削除しようとしています。 これを行うには、2つの高度なfor-loopを繰り返し実行しており、交差するときにそれらを削除しようとします。残念ながら、それらを反復処理しているfor-loopsを編集しているのは良い考えではなく、ConcurrentModificationExceptionをスローします。そのため、Iteratorを使用しているようです。Javaを反復処理中に配列からオブジェクトを削除する

public void collision() 
{ 
    Iterator<Ship> itShips = Ship.ships.iterator(); 
    Iterator<Projectile> itProj = Projectile.projectiles.iterator(); 

    while (itShips.hasNext()) { 
     Ship ship = itShips.next(); 

     while (itProj.hasNext()) { 
      Projectile proj = itProj.next(); 

      if (ship.c != proj.c) { 
       Rectangle.Float r1 = ship.getBounds(); 
       Rectangle.Float r2 = proj.getBounds(); 

       if (r1.intersects(r2)) { 
        itProj.remove(); 
        itShips.remove(); 
        break; 
       } 
      } 
     } 
    } 
} 

問題はConcurrentModificationExceptionが、私は私のアップデータを呼び出す場所に移動しているようだということです。私はイテレータのためにそれらのfor-loopsを交換しようとしましたが、動作するようには見えず、同じ例外がスローされましたが、今はupdate()メソッドにスローされます。

public void update() 
{ 
    Iterator<Ship> it1 = Ship.ships.iterator(); 
    while (it1.hasNext()) { 
     Ship s = it1.next(); 
     s.update(game); 
    } 

    Iterator<Projectile> it2 = Projectile.projectiles.iterator(); 
    while (it2.hasNext()) { 
     Projectile p = it2.next(); 
     p.update(game); 
    } 
} 

私のゲームオブジェクトの更新方法や保存方法を変更する必要がありますか?または私は間違った方法でオブジェクトの削除をしていますか?あなたは、いくつかの変数に衝突したものを保存することができます

答えて

0

それはまだ私のupdate()メソッドでエラーを与えたので、私は配列にcollidedObjectsを保存します。これらの配列を使って、元のShipとProjectile配列からそれらを削除できます。これを行うには、オブジェクトを比較して削除するupdate()メソッド内の別のメソッドを呼び出します。

public void collision() 
{ 
    Ship shipToRemove = null; 
    Projectile projToRemove = null; 

    outerLoop: 
    for (Ship ship : Ship.ships) { 
     for (Projectile proj : Projectile.projectiles) { 
      if (ship.c != proj.c) { 

       Rectangle.Float r1 = ship.getBounds(); 
       Rectangle.Float r2 = proj.getBounds(); 

       if (r1.intersects(r2)) { 
        shipToRemove = ship; 
        projToRemove = proj; 
        playSound(); 
        break outerLoop; 
       } 
      } 
     } 
    } 
    projALToRemove.add(projToRemove); 
    shipALToRemove.add(shipToRemove); 
} 

public void update() 
{ 

    for (Ship ship : Ship.ships) { 
     ship.update(game); 
    } 
    for (Projectile proj : Projectile.projectiles) { 
     proj.update(game); 
    } 
    deleteAfterCollision(); 
} 

public void deleteAfterCollision() 
{ 
    for (Ship ship : Ship.shipALToRemove) { 
     Ship.ships.remove(ship); 
    } 
    for (Projectile proj : Ship.projALToRemove) { 
     Projectile.projectiles.remove(proj); 
    } 
} 
2

あなたは、ループを終了した後、その後、リストからそれらを削除します。

Ship shipToRemove = null; 
Projectile projToRemove = null; 

Iterator<Ship> itShips = Ship.ships.iterator(); 
Iterator<Projectile> itProj = Projectile.projectiles.iterator(); 

while (itShips.hasNext()) { 
    Ship ship = itShips.next(); 

    while (itProj.hasNext()) { 
     Projectile proj = itProj.next(); 


     if (ship.c != proj.c) { 
      Rectangle.Float r1 = ship.getBounds(); 
      Rectangle.Float r2 = proj.getBounds(); 

      if (r1.intersects(r2)) { 
       shipToRemove = ship; 
       projToRemove = proj; 
       break; 
      } 
     } 
    } 
} 

Projectile.projectiles.remove(projToRemove); 
Ship.ships.remove(shipToRemove); 

それを行うべきです。

+0

この方法でも、私の更新方法でエラーが発生します。しかし、私はこの方法を繰り返した後、これらを削除するためにこれを使用することができるかもしれません。 – Muxor

+0

@Muxorあなたが役に立つ答えを見つけたら、それをアップヴォートする必要があります。 – ItamarG3

+0

同じ問題を抱えている人のために:私はこのアイデアを使用しましたが、それでもupdate()メソッドでエラーが表示されたため、少し変更する必要がありました。 collideObjectを直接削除するのではなく、配列に格納しました。私の更新メソッドでは、実際のオブジェクトが格納されている配列から、格納されているcollidedObjectsを削除するコードをいくつか入れました。 – Muxor

0

イテレータは繰り返し処理中にaddをサポートしていません。コレクションイテレータはexpectedModCountを使用して他のオブジェクトによって変更されているかどうかを確認します。set参照を使用して追加を行うとmodCount値が増加し、expectedModCountは変更されません。

最後に更新操作を追跡して実行する必要があります。

if (modCount != expectedModCount) 
       throw new ConcurrentModificationException(); 




public interface Iterator { 

    boolean hasNext(); 

    E next(); 

    void remove(); 
    } 
0

問題にアプローチするために機能的な方法は、filter非衝突船や発射にあります。このアプローチは、複数のオブジェクトを同時に変異させることによって生じる問題を回避する。私はShip.shipsProjectile.projectilesListオブジェクトであり、代わりにそのイテレータのそれと動作することを前提としています

List<Ship> ships = Ship.ships; 
List<Projectile> projs = Projectile.projectiles; 

Stream<Rectangle.Float> shipBounds = ships.stream().map(s -> s.getBounds()); 
Stream<Rectangle.Float> projBounds = projs.stream().map(p -> p.getBounds()); 

List<Ship> safeShips = ships 
     .stream() 
     .filter(s -> !projBounds.anyMatch(p -> p.intersects(s.getBounds()))) 
     .collect(Collectors.toList()); 

List<Projectile> safeProjs = projs 
     .stream() 
     .filter(p -> !shipBounds.anyMatch(s -> s.intersects(p.getBounds()))) 
     .collect(Collectors.toList()); 
関連する問題