|Sorry, I missed the number of balls.
But my other notes are still valid (out of bound array access and why not updating with small steps). For timing purposes (slower movement), wait outside the
I suggest to start with one ball to implement and check the border bouncing. To be realistic, the new directions should be calculated according to the collision angle.
Then proceed with two balls to make it simpler. For collison detection you need another loop (runing from currently processed ball index + 1 to number of balls) to check for collisions like with the borders. Upon a collision you have to set the collision position as new position for both balls and adjust the directions (which requires a flag / state that the other ball has been already processed within the current loop execution). Again, the new directions should be calculated according to the collision angles.
To check the code, you can suppress the drawing and print out the positions and changings instead. Or write them to a text file so that you can inspect it later. For testing it might be also helpful to stop after each step and continue after a key press. So you can check your calculations.