Lecture 6

  1. Random Number Generation
  2. Conditionals: a first example
  3. Boolean values
  4. Relational operators
  5. The Pong game
  6. Conditional behavior using the if-else
  7. Even more alternatives
  8. More on boolean expressions


Random Number Generation

Before we go on to discuss conditionals, let's look briefly at one more topic involving numbers. The topic we'll discuss is random number generation and, in particular, how to do it with the ObjectDraw library. This will be particularly helpful for Lab 2.

Recall our Scribble program from last week. Below is a slight modification of that program. The only difference is that we're scribbling in green.

    public class RandomColors extends WindowController{

        private Location lastPoint;
        private Color currentColor;     // current color for drawing
                        
        public void onMousePress(Location point) 
        // remembers the point of mouse press
        // sets a color for drawing
        {
                lastPoint = point;
                currentColor = Color.green;
        }
                
        public void onMouseDrag(Location point)
        // scribbles with the currently set color
        {
                (new Line(lastPoint, point, canvas)).setColor(currentColor);
                lastPoint = point;
        }          
}

We would like to change this program so that every time the user starts drawing (i.e., every time the mouse is pressed), the computer randomly chooses a color in which to draw.

Java's Color class provides constants for many common colors. Because they come from the Color class, when we write them in a Java program we must write them as Color.red, Color.blue, Color.green, and Color.black. We're not limited to these common colors, however. We can create colors of our own.

To create a color, we say


   new Color( r, g, b);

where r,g, and b are integers that refer to the amount of red, green, and blue we want to mix together to make a color. The integers we give need to be in the range 0-255. For example


   new Color(0, 0, 0);

gives us black.


   new Color(255, 255, 255);

gives us white.


   new Color(255, 0, 255);

gives us purple.

Now we know how to create new colors, but now we need to think about how we can do so randomly.

Our ObjectDraw library contains a class, RandomIntGenerator that can be used to randomly select integers. The constructor for this class allows us to choose the range of integers from which we'd like our random numbers to be selected. Suppose first and last represent integers with first <= last. If we write

    randGen = new RandomIntGenerator(first, last);

then the variable randGen (declared earlier to be of type RandomIntGenerator) will be able to generate numbers between first and last.

Once we have created the generator, we can ask it for new random numbers by sending it the message nextValue(). Thus if we evaluate randGen.nextValue(), we will get back an integer in the range between first and last, inclusive.

For our example above of creating random colors, we could write

    pickAColor = new RandomIntGenerator(0,255);

and then each time we evaluate pickAColor.nextValue() we will get a number in the range 0-255 that we can use as a random redness, greenness, or blueness value.

It is now easy to modify the program above to choose a color randomly. The begin method will create a RandomIntGenerator. Each time the onMousePress method is called, we will set the variable currentColor to be a newly created random color.

Demo. Scribbling in color


Conditionals: a first example

We now shift gears completely. Let's begin by looking at a program which allows the user to drag a box around the screen. If the user presses the mouse on the box and then drags the mouse around then, the box should move just as much as the mouse does.

Of course, there's more to it than this. We only want to move the box if the user actually pressed the mouse on the box. We need to be able to detect that, and we need to make sure that we only drag the box if the mouse was on the box.

Luckily, we have a method for graphic objects which allows us to detect whether a point is in the object.

    item.contains(point)

will have value true if point is in the bounding box of item, and has value false otherwise.

In order to write this program, we want to write something like:

    if item.contains(point) then
        move the box the appropriate amount

Let's see how we do this in Java.

Demo.MouseDrag

Note the parentheses around box.contains(point) and the curly braces around the statements to be executed if this is true.

Aside: if we use contains with an oval, it will only tell us if the point is inside the bounding rectangle, not within the oval!


Boolean values

While our box-dragging program works, it is not ideal, because every time we move the mouse, we check to see whether lastPoint is inside box. If it is in there the first time, it will be there each successive time. As a result, it would be better to check this once, and then simply remember the answer.

We can do this if we remember the answer in a variable. But what kind of variable can remember such an answer? Let's consider the expression


   box.contains(point)

This expression has a value of either true or false depending on whether box contains point or not. It can have no other values. These values (true and false) are called boolean values. So to remember the answer to whether the box contains the point, we declare a variable of type boolean.

Java's if statement determines whether or not to execute a block of code depending on the value of a boolean expression. Its syntax is:

   if (booleanExpression)
   {
      statements
   }

Thus we can say

    if ( box.contains(lastPoint))
    {
       box.move( point.getX() - lastPoint.getX(),
                 point.getY() - lastPoint.getY() );
       lastPoint = point;
    }

as we did in the example above. Or we can modify the program as in the following demo.

Demo.Better MouseDrag

In this better version, we declare a variable boxGrabbed, of type boolean. As soon as the mouse is pressed, we remember whether the box contains the point of press. Each time we do a mouse drag, we simply consider the value of boxGrabbed.


Relational operators

Java contains several relational (comparison) operators which result in values of type boolean. The operators include:

        < , > , ==, <=, >=, !=

Notice how we must use == in order to test for equality, because = has already been used for assignment. The symbol != stands for inequality.

Thus we can write x > 4, y != z+17, x+2 <= y. Depending on the values of the variables, each of these expressions will evaluate to either true or false. That is, each of these expressions evaluates to a value of type boolean.

We'll see examples of the use of these operators in the examples below.


The Pong game

The following demo allows you to play the classic Pong game. Go ahead and try it out. Use the mouse to move the paddle left or right. The object of the game is to keep the ball in the court.

Demo. An OK Pong game


Conditional behavior using the if-else

For now don't worry about the code that handles the animation of the ball. (We'll teach you how to do that in a couple of weeks.) Instead, focus on the paddle. In the demo you may have noticed that there's something not quite right with the paddle. It doesn't stay in the court.

How can we fix the program so that the paddle never moves out of the court? How can we detect that the mouse is about to move so far to the left that the paddle will go off the court? How can we then stop the paddle at the left edge of the court? The answer is to use relational operators and conditionals.

First, let's consider what we want to check for. We'll focus on the left edge of the court for now. If the mouse moves off the left edge of the court, then we'll move the paddle to the left edge of the court (rather than further to the left), otherwise, we'll move the paddle to where the mouse is:


    if (point.getX() < COURT_LEFT)
    {
       // move paddle to left edge ..
    }
    else
    {
       // move paddle to mouse ..
    }

Demo. The "half-fixed" Pong game

Notice that our partially fixed Pong program makes use of the relational operator <. It also shows us that we can specify more than one alternative in a conditional statement. In general, we can express this kind of conditional behavior using an if-else statement as follows:

    if (booleanExpression)
    {
       // stuff to do if booleanExpression is true
    } 
    else 
    {
       //stuff to do if booleanExpression is false
    }


Even more alternatives

Now let's really fix our Pong program. Let's make sure that paddle doesn't go over the right edge of the court either. To ensure that the paddle always stays within the walls of the court we want to do something like:

    if (point.getX() < COURT_LEFT)
    {
       // move paddle to left edge ..
    }
    else if (point.getX() < COURT_LEFT + COURT_WIDTH - PADDLE_WIDTH)
    {
       // move paddle to right edge ..
    }
    else
    {
       // move paddle to mouse ..
    }

Notice how we can make the else clause contain another if-else clause. In this way, we can stack up as many alternatives as we need to solve our problem.

Demo. The fixed Pong game


More on boolean expressions

In the final version of the Pong game, we first checked if the paddle was off of the left edge, then if it was off the right edge, and if neither of those was true then it must have been between the edges.

Suppose the first thing that we wanted to do was to check if it was between the edges? Because we need it to be inside the left edge and inside the right edge, we need to write an expression to determine if both of these are true. In Java we use && betwen two boolean expressions to indicate that both must be true.

In order to ensure that point is between the left and right edges of the court we would need to write a statement as below:

    if (point.getX() > COURT_LEFT && 
        point.getX() < COURT_LEFT + COURT_WIDTH - PADDLE_WIDTH)
    {...}

For the code in the if statement to be executed, it is necessary for the boolean expression to the left of the && (checking to see if point is to the right of COURT_LEFT) to be true as well as the expression on the right.

Unfortunately computer programming languages do not usually allow one to combine two inequalities as one, as in the expression 1 < x < 10. Instead one must write this out the long way as 1 < x && x < 10.

Just as Java uses && to represent the logical and operation, it uses || to represent the logical or. The operation || is used in Java to determine whether at least one of two expressions is true. Thus x < 5 || x > 20 will be true if x is less than 5 or if x is greater than 20. An expression of the form bexp1 || bexp2 will be true if either or both of bexp1 and bexp2 are true.