views:

136

answers:

4

I have been staring at this code all day now, but just can't get it right.

ATM I am just pushing codeblocks around without being able to concentrate anymore, with the due time being within almost an hour... So you guys are my last resort here.

I am supposed to create a few random balls on a canvas, those balls being stored within an ArrayList (I hope an ArrayList is suitable here: the alternative options to choose from were HashSet and HashMap). Now, whatever I do, I get the differently colored balls at the top of my canvas, but they just get stuck there and refuse to move at all. Apart from that I now get a ConcurrentModificationException, when running the code:

java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at BallDemo.bounce(BallDemo.java:109)

Line 109 being: bBall.draw();

Reading up on that exception, I found out that one can make sure ArrayList is accessed in a threadsafe manner by somehow synchronizing access. But since I have remember fellow students doing without synchronizing, my guess is, that it would actually be the wrong path to go.

Maybe you guys could help me get this to work, I at least need those stupid balls to move ;-)

   /**
 * Simulate random bouncing balls
 */
public void bounce(int count)
{
    int ground = 400;   // position of the ground line
    System.out.println(count);

    myCanvas.setVisible(true);

    // draw the ground
    myCanvas.drawLine(50, ground, 550, ground);


    // Create an ArrayList of type BouncingBalls
    ArrayList<BouncingBall>balls =  new ArrayList<BouncingBall>();

    for (int i = 0; i < count; i++){
        Random numGen = new Random(); 
        // Creating a random color. 
        Color col = new Color(numGen.nextInt(256), numGen.nextInt(256), numGen.nextInt(256));
        // creating a random x-coordinate for the balls
        int ballXpos = numGen.nextInt(550);


        BouncingBall bBall = new BouncingBall(ballXpos, 80, 20, col, ground, myCanvas);

        // adding balls to the ArrayList
        balls.add(bBall);
        bBall.draw();
        boolean finished = false;
    }

        for (BouncingBall bBall : balls){

            bBall.move();

    }
}

This would be the original unmodified method we got from our teacher, which only creates two balls:

    /**
 * Simulate two bouncing balls
 */
public void bounce()
{
    int ground = 400;   // position of the ground line

    myCanvas.setVisible(true);

    myCanvas.drawLine(50, ground, 550, ground);
    // draw the ground

    // crate and show the balls
    BouncingBall ball = new BouncingBall(50, 50, 16, Color.blue, ground, myCanvas);
    ball.draw();
    BouncingBall ball2 = new BouncingBall(70, 80, 20, Color.red, ground, myCanvas);
    ball2.draw();

    // make them bounce
    boolean finished =  false;
    while(!finished) {
        myCanvas.wait(50);           // small delay
        ball.move();
        ball2.move();
        // stop once ball has travelled a certain distance on x axis
        if(ball.getXPosition() >= 550 && ball2.getXPosition() >= 550) {
            finished = true;
        }
    }
    ball.erase();
    ball2.erase();
}

}

So I just modified my code as follows

public void bounce(int count)
    {
        int ground = 400;   // position of the ground line
        System.out.println(count);

        myCanvas.setVisible(true);

        // draw the ground
        myCanvas.drawLine(50, ground, 550, ground);


        // Create an ArrayList of type BouncingBalls
        ArrayList<BouncingBall>balls =  new ArrayList<BouncingBall>();
        Random numGen = new Random(); 
        for (int i = 0; i < count; i++){

            // Creating a random color. 
            Color col = new Color(numGen.nextInt(256), numGen.nextInt(256), numGen.nextInt(256));
            // creating a random x-coordinate for the balls
            int ballXpos = numGen.nextInt(550);


            BouncingBall bBall = new BouncingBall(ballXpos, 80, 20, col, ground, myCanvas);

            // adding balls to the ArrayList
            balls.add(bBall);
            bBall.draw();

        }
            boolean finished = false;
  while(!finished)
    {
        myCanvas.wait(50);           // small delay

        for(BouncingBall ball : balls)
        {
            ball.move();

            // once one ball has travelled the distance, they all have
            if(ball.getXPosition() >= 550)
                finished = true;
        }
    }

    for(BouncingBall ball : balls)
        ball.erase();
}

But that only moves the balls very shortly and then creates the same exception as above.

A: 

Are you being forced to use ONLY one of those three structures? An ArrayList barfing-out ConcurrentModificationExceptions is pretty much an engraved invitation to try replacing it with a CopyOnWriteArrayList.

BlairHippo
He really shouldn't need synchronization for this though, unless I'm missing part of the assignment. He's making an `ArrayList` of sprites and then looping over them repeatedly to move them around; it shouldn't be changing after the initial population
Michael Mrozek
yes, we are only supposed to chose from ArrayList, HashSet and HashMap.
elementz
Usually a ConcurrentModificationException is created by modifying a list while you are iterating it and does not imply a multi-threaded environment.
Kathy Van Stone
+3  A: 

You are missing the while(!finished) part.
With the for you are adding you are iterating only once through the balls, that's why you are not seeing them move.

Edit: The new version can be over really soon if the random X position of any ball (between 0 and 550) is near 550.

Guillermo Vasconcelos
hm. it seems I just don't see it right now. Doesn't my first for-loop add the balls to the ArrayList, and shouldn't `for (BouncingBall bBall : balls){ bBall.move(); }` make them move?
elementz
The second for loop (the BouncingBall loop) will only move them once and not until they hit the bound.
Poindexter
for (Bouncing bBall: balls) makes them move once, and immediately after they were created so you may not even see the single move.
Kathy Van Stone
@BlairHippo Calling bounce will recreate more balls and go into an infinite recursive loop.
Kathy Van Stone
@Kathy Van Stone, yeah that seems to be exactly the problem now, as I have modified the code after Justin Niessners example.
elementz
A: 
public void bount(int count)
{
    int ground = 400;

    myCanvas.setVisible(true);

    myCanvas.drawLine(50, ground, 550, ground);

    ArrayList<BouncingBall> balls =  new ArrayList<BouncingBall>(); 

    for(int i = 0; i < count; i++)
    {
        // set up colors and position
        BouncingBall newBall = new BouncingBall(ballXpos, 80, 
            20, col, ground, myCanvas);

        newBall.Draw();

        balls.Add();
    }

    boolean finished = false;

    while(!finished)
    {
        myCanvas.wait(50);           // small delay

        for(BouncingBall ball : balls)
        {
            ball.Move();

            // once one ball has travelled the distance, they all have
            if(ball.getXPosition() >= 550)
                finished = true;
        }
    }

    for(BouncingBall ball : balls)
        ball.erase();
}
Justin Niessner
A: 

You should create the Random object before the for loop. see below.This may position your balls correctly

 Random numGen=new Random();

  for (int i = 0; i < count; i++){ 
           // Creating a random color.  
    Color col = new Color(numGen.nextInt(256), numGen.nextInt(256), numGen.nextInt(256)); 
    // creating a random x-coordinate for the balls 
    int ballXpos = numGen.nextInt(550); 


    BouncingBall bBall = new BouncingBall(ballXpos, 80
josephj1989
this didn't solve my ConcurrentException-problem though
elementz