所以,我正在做一个坦克必须用子弹击落飞机的游戏。我有一个平面的ArrayList及其所有属性,我还有一个包含所有项目符号,它们的角度和坐标的ArrayList。
我在屏幕上显示所有平面的for
循环,并更改了它们的坐标。在for
循环内部,我创建了另一个环绕所有子弹的for
循环。这是我显示子弹并更改其y和x坐标的位置。
对于ArrayList中的每个平面,有一个变量可以计算它与屏幕上所有项目符号的距离。我做到这一点,当子弹与飞机接触时,子弹和飞机都是他们的ArrayLists remove
。然而,大约10-20%的时间,一架击中1架飞机的子弹移走了所有其他飞机,下一波飞机进来了。
有谁知道我的问题是什么?
以下是我的一些代码:
if(thisArrayList.size() > 0){
for(int x = 0; x < thisArrayList.size(); x ++){
if(thisArrayList.get(x)[4] == 1.0 && thisArrayList.get(x)[0] >= -50){
g2d.drawImage(plane10, (int) (thisArrayList.get(x)[0] - 50), (int) (thisArrayList.get(x)[3] - 50), null);
}else if(thisArrayList.get(x)[4] == 2.0 && thisArrayList.get(x)[0] >= -50){
g2d.drawImage(plane20, (int) (thisArrayList.get(x)[0] - 50), (int) (thisArrayList.get(x)[3] - 50), null);
}else if(thisArrayList.get(x)[4] == 3.0 && thisArrayList.get(x)[0] >= -50){
g2d.drawImage(plane30, (int) (thisArrayList.get(x)[0] - 50), (int) (thisArrayList.get(x)[3] - 50), null);
}
thisArrayList.get(x)[0] += thisArrayList.get(x)[2];
g2d.setFont(new Font("Source Sans Pro Black", 15, 15));
g2d.setColor(Color.WHITE);
g2d.drawString(((thisArrayList.get(x)[1])).toString(), (int) (thisArrayList.get(x)[0] - 10), (int) (thisArrayList.get(x)[3] + 7));
if(thisArrayList.get(x)[0] >= Main.widthOfScreen + 50 && thisArrayList.get(x)[3] == 100){
thisArrayList.get(x)[3] = 205.0;
thisArrayList.get(x)[0] = -60.0;
}else if(thisArrayList.get(x)[0] >= Main.widthOfScreen + 50 && thisArrayList.get(x)[3] != 100){
if(thisArrayList.size() == 1){
isDone = "yes";
Panel.waveNum ++;
isVisible = false;
thisArrayList = new ArrayList<Double[]>();
}else{
thisArrayList.remove(x);
}
}
try{
for(int i = 0; i < BulletTracker.bullets.size(); i ++){
//double dist = 100;
if(BulletTracker.bullets.size() > 0 && thisArrayList.size() > 0){
if(BulletTracker.bullets.size() > 0 && thisArrayList.size() > 0 && thisArrayList.get(x)[0] >= -50){
try{
thisArrayList.get(x)[5] = Math.sqrt(((BulletTracker.bullets.get(i)[1] - thisArrayList.get(x)[0]) * (BulletTracker.bullets.get(i)[1] - thisArrayList.get(x)[0]))
+ ((BulletTracker.bullets.get(i)[2] - thisArrayList.get(x)[3]) * (BulletTracker.bullets.get(i)[2] - thisArrayList.get(x)[3])));
}catch(Exception e){
thisArrayList.get(x)[5] = 50.0;
}
}else{
thisArrayList.get(x)[5] = 100.0;
}
if(thisArrayList.get(x)[5] <= 50){
thisArrayList.get(x)[1] -= 10;
if(thisArrayList.get(x)[1] <= 0){
if(thisArrayList.size() != 1){
thisArrayList.remove(x);
}else{
isDone = "yes";
Panel.waveNum ++;
isVisible = false;
thisArrayList = new ArrayList<Double[]>();
}
}
BulletTracker.bullets.remove(i);
}
}
}
}catch(Exception e){
System.out.println("Sorry. There was an error.");
isDone = "yes";
Panel.waveNum ++;
isVisible = false;
thisArrayList = new ArrayList<Double[]>();
}
顺便说一句,thisArrayList
是平面的ArrayList,thisArrayList.get(x)[5]
是每个平面与所有子弹的距离。有很多不需要的try和catch语句以及我从未删除的不需要的代码。
答案 0 :(得分:1)
我不确定,但看起来你的thisArrayList.remove
内循环遍历thisArrayList
。
请看以下示例:
for(int x = 0; x < thisArrayList.size(); x++) {
final int element = thisArrayList.get(x);
if(condition) {
thisArrayList.remove(x);
}
}
如果满足条件,则删除元素,但由于您仍处于for循环中,因此执行以下操作:
假设我们有thisArrayList = { 1, 2, 3 }
{ 1, 3 }
x < thisArrayList.size()
为false 你知道它要去哪里......
问题是你应该尽量避免同时删除和迭代列表,因为它会导致跳过元素。
正确的解决方案是标记要移除的元素
它可以通过外部列表完成,例如List<int> toBeRemoved
要删除索引。
toBeRemoved
toBeRemoved
并小心删除项目或者你可以这样做:
if(condition) {
thisArrayList.remove(x);
--x;
continue;
}
它将确保您不会跳过任何元素。
无论如何,迭代和删除同时更好的解决方案是使用迭代器:
Iterator<Integer> i = thisArrayList.iterator();
while (i.hasNext()) {
int s = i.next(); // must be called before you can call i.remove()
// Do something
i.remove();
}
通过使用迭代器,您可以确保迭代每个元素,并且不会发生任何不良事件。
使用迭代器是一种很好的做法(不是每次都有,但在这种情况下!)