【问题标题】:boolean flag not read in while loop (java)布尔标志未在while循环中读取(java)
【发布时间】:2011-12-22 23:02:43
【问题描述】:

我编写了一个程序来让球在屏幕上弹跳。如下编写的程序不起作用(球只是移出屏幕)。

但是,如果我在 while 循环中声明布尔变量 atHorizo​​ntalEdge 和 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;
}

【问题讨论】:

标签: java while-loop boolean infinite


【解决方案1】:

atHorizontalEdgeatVerticalEdge 可以在while 循环内部或外部声明,这并不重要。

重要的是,在循环开始之前,只计算一次

atHorizontalEdge =  (ball.getX() == getWidth() - BALL_SIZE) || ball.getX() == 0 ; 
atVerticalEdge = (ball.getY() == getHeight() - BALL_SIZE) || ball.getY() == 0 ;

因此,atHorizontalEdgeatVerticalEdge 从您的 run 方法的开始到结束都将具有相同的值(这是永远的)。

您显然希望在循环的每次迭代中都执行上述两行,因为它们不会自行更新...

while (true) {
   atHorizontalEdge =  (ball.getX() == getWidth() - BALL_SIZE) || ball.getX() == 0 ; 
   atVerticalEdge = (ball.getY() == getHeight() - BALL_SIZE) || ball.getY() == 0 ;
   ...
}


编辑:另外,最好检查一下 x 和 y 是否大于或等于宽度/高度,并且小于或等于 0 有两个原因:

  1. 如果您决定从 1 更改增量,您可以跳过该 exact 值并导致错误,但更重要的是:
  2. 您使用的是double,而数字的浮点表示可能与完全您正在比较它,所以== 可能会导致错误,并且球可能会越过边缘并继续前进。

即。 ball.getX() >= getWidth() ... ball.getX() <= 0

What Every Computer Scientist Should Know About Floating-Point Arithmetic

【讨论】:

  • 感谢您对双打会计的见解。很有帮助!
  • @user1031901 不用担心。正如我所提到的,通常最好在检查边界时使用>=<=,而不是==
【解决方案2】:

我认为,您应该在每次迭代后更新循环体中的atHorizontalEdgeatVerticalEdge


更新:

while循环体应该是这样的, ` //声明布尔变量来测试球的位置是否在边缘 boolean atHorizo​​ntalEdge = 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);

    }`

如果您在循环内定义atHorizontalEdgeatVerticalEdge,它之所以起作用,是因为每次迭代都会重新计算这两个变量(即更新)。

【讨论】:

  • @user1031901 没关系。很高兴这是有道理的。 :)
【解决方案3】:

问题不在于布尔值的声明在 while 循环之外。这是您在 while 循环之外检查边界。因此,您的条件永远不会更新,它只会检查球的原始状态。

【讨论】:

  • 哦,这很有意义。感谢您的快速响应!
猜你喜欢
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 2017-11-20
  • 2020-12-03
  • 2015-10-08
  • 2017-06-04
  • 2016-05-17
  • 2011-03-05
相关资源
最近更新 更多