我写了一个程序来在屏幕上反弹球。下面写的程序不起作用(球只会离开屏幕)。
但是,如果我在while循环中声明布尔变量atHorizontalEdge和atVerticalEdge,它似乎可行。为什么会这样?由于为整个run()方法定义了布尔值,所以即使它在while循环之外,它不应该被while循环调用吗?
import acm.program.*;
import acm.graphics.*;
import java.awt.*;
public class BouncingBallv3 extends GraphicsProgram {
public void run() {
double x = (getWidth() - BALL_SIZE)/2 ; //sets the starting position of ball at center
double y = (getHeight() - BALL_SIZE)/2 ;
GOval ball = new GOval (x, y, BALL_SIZE, BALL_SIZE ); // creates a red ball at center of screen
ball.setFilled(true);
ball.setColor(Color.red);
add (ball);
double dx = 1; //increments by which the ball moves
double dy = 1;
//declares boolean variables to test if ball position is at an edge
boolean atHorizontalEdge = (ball.getX() == getWidth() - BALL_SIZE) || ball.getX() == 0 ;
boolean atVerticalEdge = (ball.getY() == getHeight() - BALL_SIZE) || ball.getY() == 0 ;
/* while loop keeps the ball moving in direction dx,dy
* if ball reaches a position at any edge, the direction dx or dy changes
*/
while (true) {
if (atHorizontalEdge) { //changes direction of ball if it hits a left/right wall
dx = -dx;
} else if (atVerticalEdge) { //changes direction of ball if it hits a top/bottom wall
dy = -dy;
}
ball.move(dx,dy);
pause (PAUSE_TIME);
}
}
private static final double BALL_SIZE = 50;
private static final int PAUSE_TIME = 5;
}
答案 0 :(得分:4)
问题不在于布尔的声明是在while循环之外。这是你在while循环之外检查你的边界。因此,您的状况永远不会更新,只会检查球的原始状态。
答案 1 :(得分:0)
我认为你应该在每次迭代后更新循环体中的atHorizontalEdge
和atVerticalEdge
。
更新:
while循环体应该是这样的, ` //声明布尔变量以测试球位置是否在边缘 boolean atHorizontalEdge = false; boolean atVerticalEdge = false;
/* while loop keeps the ball moving in direction dx,dy
* if ball reaches a position at any edge, the direction dx or dy changes
*/
while (true) {
atHorizontalEdge = (ball.getX() == getWidth() - BALL_SIZE) || ball.getX() == 0;
atVerticalEdge = (ball.getY() == getHeight() - BALL_SIZE) || ball.getY() == 0;
if (atHorizontalEdge) { //changes direction of ball if it hits a left/right wall
dx = -dx;
} else if (atVerticalEdge) { //changes direction of ball if it hits a top/bottom wall
dy = -dy;
}
ball.move(dx,dy);
pause (PAUSE_TIME);
}`
如果在循环内定义atHorizontalEdge
和atVerticalEdge
,它的工作原理是因为每次迭代都会重新计算(即更新)这两个变量。
答案 2 :(得分:0)
atHorizontalEdge
和atVerticalEdge
可以在while
循环内部或外部声明,这并不重要。
重要的是,在循环开始之前,以下只计算 :
atHorizontalEdge = (ball.getX() == getWidth() - BALL_SIZE) || ball.getX() == 0 ;
atVerticalEdge = (ball.getY() == getHeight() - BALL_SIZE) || ball.getY() == 0 ;
因此atHorizontalEdge
和atVerticalEdge
从run
方法的开头到结尾都会有相同的值(这是永久的)。
您显然希望在循环的每次迭代中都执行上述两行,因为它们不会自行更新...
while (true) {
atHorizontalEdge = (ball.getX() == getWidth() - BALL_SIZE) || ball.getX() == 0 ;
atVerticalEdge = (ball.getY() == getHeight() - BALL_SIZE) || ball.getY() == 0 ;
...
}
编辑另外,最好检查x和y是否大于或等于宽度/高度,是否小于或等于 0有两个原因:
double
,并且该数字的浮点表示可能不是完全您要比较的内容,因此==
会导致错误,球可能越过边缘继续前进。即。 ball.getX() >= getWidth() ... ball.getX() <= 0
What Every Computer Scientist Should Know About Floating-Point Arithmetic