我知道这是一个经常被问到的问题,但我仍然坚持如何用我的代码解决它。
我的GUI上有一个按钮,允许我在图形窗口中添加额外的“海龟”,这会在游戏循环结构中向一个显示植绒行为的arraylist添加一只乌龟。我怎么能这样做,所以我可以添加尽可能多的海龟,而不显示这个错误?
游戏循环如下:
private void gameLoop()
{
while(true) //The order in which the turtles move, and when which algorithm is executed
{
for (int i = 0; i < turtles.size(); i++) //for each turtle, perform the set algorithm
{
(turtles.get(i)).unDrawTurtle();
(turtles.get(i)).update(1000);
hello.setText("X: " + (turtles.get(i)).getPositionX() + " Y: " + (turtles.get(i)).getPositionY());
}
for (int i = 0; i < turtles.size(); i++) //for each turtle, perform the set algorithm
{
(turtles.get(i)).cohesian(turtles); //MAKE BOIDS ATTRACT
}
for (int i = 0; i < turtles.size(); i++) //for each turtle, perform the set algorithm
{
(turtles.get(i)).drawTurtle();
}
for (int i = 0; i < turtles.size(); i++) //for each turtle, perform the set algorithm
{
(turtles.get(i)).wrapPosition((turtles.get(i)).getPositionX(), (turtles.get(i)).getPositionY());
}
//Here we are making sure the turtles are on the screen
Utils.pause(deltaTime/2);
}
以下是将海龟添加到ArrayList的按钮的代码:
addTurtleButton.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
turtles.add(new RandomTurtleB(canvas, 400, 300, currentSpeed, 0));
}
} );
removeTurtleButton.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
turtles.remove(turtles.size() - 1);
canvas.removeMostRecentLine();
canvas.removeMostRecentLine();
canvas.removeMostRecentLine();
canvas.removeMostRecentLine();
}
} );
在另一个类中是内聚方法,即添加海龟/更改ArrayList的内容:
public void cohesian(ArrayList<DynamicTurtle> turtles)
{
double flockingDistanceLimit = 50;
double numberOfFlockers = 0;
double combinedX = 0;
double combinedY = 0;
double averageCombinedX;
double averageCombinedY;
//ouble moveToFlock;
//double turnToFlock;
double distanceToPotentialFlock;
for (DynamicTurtle t : turtles) //SCAN FOR ALL TURTLES
{
if(this.getPositionX() != t.getPositionX() && this.getPositionY() != t.getPositionY()) //MAKE SURE TURTLE ISNT SCANNING ITS SELF
{
distanceToPotentialFlock = Math.sqrt(Math.pow((this.getPositionX()-t.getPositionX()),2 ) + Math.pow((this.getPositionY()-this.getPositionY()),2)); //FIND DISTANCE TO TURTLE
System.out.println("distanceToPotentialFlock: " + distanceToPotentialFlock); //PRINT TO SCREEN HOW FAR AWAY THE TURTLE IS
if(distanceToPotentialFlock < flockingDistanceLimit) //MAKE SURE THE FOUND TURTLE IS WITHIN RANGE
{
combinedX = combinedX + t.getPositionX(); //FIND SUMMATION OF X POSITIONS
combinedY = combinedY + t.getPositionY(); //FIND SUMMATION OF Y POSITIONS
numberOfFlockers++; //AS A FLOCKER HAS BEEN FOUND INCREMENT THE NUMBER OF FLOCKERS
System.out.println("distanceToPotentialFlock: " + distanceToPotentialFlock);
System.out.println("numberOfFlockers: " + numberOfFlockers);
if(numberOfFlockers > 0)
{
averageCombinedX = (combinedX / numberOfFlockers); //FIND AVERAGE X POSITION
averageCombinedY = (combinedY / numberOfFlockers); //FIND AVERAGE Y POSITION
System.out.println("XFLOCK: " + averageCombinedX + "YFLOCK: " + averageCombinedY);
double angleRad = Math.atan2(averageCombinedY, averageCombinedX);
double angleDeg = Math.toDegrees(angleRad);
// place in 0,360 range
if(angleDeg < 0)
{
angleDeg = 360 - (-angleDeg);
}
this.turn(angleDeg);
this.move(10);
}
}
}
}
我非常感谢帮助我解决这个问题的任何帮助。问候,詹姆斯。
答案 0 :(得分:0)
由于每次按下按钮时都要添加或删除主turtles
列表,因此会出现并发修改异常。您应该花一些时间阅读Java中的Event Dispatch Threads。
基本上,您实际上正在处理多线程应用程序,因为按钮的单击事件恰好在不同的线程上执行,并且将修改共享变量 - 当前不是线程的turtles
列表 - 安全数据结构。
有关上下文,请参阅SO query。因此,这里的一个解决方案是使用类似CopyOnWriteArrayList的线程安全数据结构。
这会慢吗?我的猜测是否定的 - 因为在你的应用程序中,与添加或删除它们相比,花费了大量时间来迭代海龟列表。 This SO query详细说明了CopyOnWriteArrayList
希望这能帮助您解决问题。