Chapter 7

Decisions - if and switch

Introduction

We all make decisions in daily life. We wear a coat if it is raining. We buy a CD if we have enough money. Decisions are also central to computer programs. The computer tests a value and according to the result, takes one course of action or another. Decisions are used a lot in programs. Whenever the program has a choice of actions and decides to take one action or the other, an if statement is used to describe the situation.

We have seen that a computer program is a series of instructions to a computer. The computer obeys the instructions one after another in sequence. Often we want the computer to carry out a test on some data and then take one of a choice of actions depending on the result of the test. For example, we might want the computer to test someoneís age and then tell them either that they may vote or that they are too young. This is sometimes called selection. It uses a statement (or instruction) called the if statement, the central subject of this chapter.

if statements are so important that they are used in every programming language that has ever been invented.

This chapter explains:

Along the way, this chapter also explains:


The if statement

The voting checker program

Our first example is a voting checker program. Users enter their ages using the scrollbar and the program decides whether they can vote or not. The screen is shown in Figure 7.1.

Voting checker applet

We want the program to take different actions depending on whether the value is less than or greater than 18. As in the last chapter, we write the program as a collection of methods ñ init, paint and adjustmentValueChanged. Method init creates the scrollbar. Method adjustmentValueChanged is invoked whenever the scrollbar value is changed (by the mouse). Method paint displays the decision about voting rights.

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

public class Voting extends Applet implements AdjustmentListener {
    private Scrollbar bar;
    private int age = 0;
    public void init() {
        bar = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 100);
        add(bar);
        bar.addAdjustmentListener( this);
    }
    public void paint(Graphics g) {
    if (age > 17)
        g.drawString ("You may vote", 50, 50);
    g.drawString("Age is " + age, 50, 70);
    }
    public void adjustmentValueChanged(AdjustmentEvent event) {
        age = bar.getValue();
        repaint();
    }
}

The if statement tests the value of the variable age. If the value is greater than 17, the statement immediately below the if is carried out. Then the next statement is executed. On the other hand, if the age is not greater than 17, the associated statement is ignored and the next statement is executed.

One way of visualizing an if statement is as a flowchart (Figure 7.2). This shows the above if statement in graphical form.

Flowchart for if

There are two parts to the if statement:

All programs have a sequence of actions. A sequence is still evident here:

1. An age is input from the scrollbar.

2. Then a test is done.

3. If appropriate, a message is output to say that the person can vote.

4. Finally, the statement to output the personís age is (always) executed.

Very often we want not just one, but a complete sequence of actions carried out if the result of the test is true:

if (age > 17) {
    g.drawString ("congratulations! ", 50, 50);
    g.drawString ("you may vote", 50, 70);
}
g.drawString ("Age is " + age, 50, 90);

The sequence of statements to be carried out if the test is true is enclosed in curly brackets. Each statement is followed by a semicolon.

The rule is: when just one statement is to be done as part of the if, it need not be enclosed in curly brackets (but it can be if you like.)

Indentation

Notice that the lines have been indented to reflect the structure of this piece of program. (Indentation means using spaces to push the text over to the right.) Although indentation is not essential (it is not a mandatory part of the Java language), it is highly desirable so that the (human) reader of a program can understand it easily. All good programs (whatever the language) have indentation and all good programmers use it.

You can create indentation using the space bar on your keyboard or with the aid of the tab key. An indentation of four spaces is generally considered to give good readability and this is used throughout this book.

Very often in a program we want to specify two sequences of actions ñ those that are carried out if the condition is true and those that are carried out if the condition is false:

if (age > 17) {
    g.drawString ("congratulations! ", 50, 50);
    g.drawString ("you may vote", 50, 70);
} else {
    g.drawString ("sorry ", 50, 50);
    g.drawString ("you may not vote", 50, 70);
}
g.drawString ("Age is " + age, 50, 90);

There are three parts to this if statement:

The new element here is the word else, which introduces the second part of the if statement. Notice how the indentation helps considerably in emphasizing the intention of the program. Also, each statement is followed by a semicolon.

Again we can visualize an if...else statement as a flowchart, as shown in Figure 7.3.

Flowchart for if...else


Comparison operators

The program fragments above (excluding the self-test question) used only greater than (>), which is one of several comparison operators. Here is a complete list:

> means greater than
< means less than
== means equals
!= means not equal to
<= means less than or equal to
>= means greater than or equal to

The odd one out in this list is the test for equality, which is two equals signs, rather than one. It is a common mistake to use just one equals sign in a test. So remember that:

x = y;

means that x becomes equal to y. But the expression:

x == y

means a test to see whether x is equal to y.

Choosing the appropriate operator often has to be done with great care. In the program to test whether someone can vote, the appropriate test should probably be:

if (age >= 18)
    g.drawString("you can vote", 50, 50);

Note that it is usually possible to write conditions in either of two ways. The following two program fragments achieve exactly the same result, but use different conditions:

if (age >= 18)
    g.drawString("you may vote", 50, 50);
else
    g.drawString("sorry", 50, 50);
g.drawString("good-bye", 50, 70);

achieves the same end as:

if (age < 18)
    g.drawString("sorry", 50, 50);
else
    g.drawString ("you may vote ", 50, 50);
g.drawString("good-bye", 50, 70);

Although these two fragments achieve the same end result, the first is probably better than the second, because it spells out clearly the condition for eligibility to vote.


And, or, not

Often in programming we need to test two things at once. Suppose, for example, we want to test whether someone should pay a junior rate for a ticket:

if (age > 6 && age < 16)
    g.drawString ("junior rate", 50, 50);

The double ampersand (&&) is one of the "logical operators" and means "and".

Brackets can be used to improve the readability of these more complex conditions:

if ((age > 6) && (age < 16))
    g.drawString ("junior rate", 50, 50);

It might be very tempting to write:

if (age > 6 && < 18) // error!

but this is incorrect because the conditions have to be spelled out in full:

if (age > 6 && age < 18) // OK

The complete list of these logical operators is:

&& means and
|| means or
! means not

The || operator is actually two | characters, which are there on the keyboard but not used very much other than for this purpose.

The throw of the dice program

This example illustrates how to carry out a more complex series of tests. Two dice are thrown in a betting game and the program has to decide what the result is. We will create two scrollbars with a range of 1 to 6 to input the values of each of the two dice (Figure 7.4). To start with, let us make the rule that only a total score of six wins anything.

Applet for dice program

We saw how to use a scrollbar in Chapter 6. For this program, the two horizontal bars are set up so that:

1. The initial value of the scroll bar is 1.

2. The amount the value is changed if the area between the slider and the end of the range is clicked is 1.

3. The minimum value is 1.

4. The maximum value is 6.

The program is:

import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Dice1 extends Applet implements AdjustmentListener {
    private Scrollbar die1, die2;
    private int value1 = 1, value2 = 1;
    public void init() {
        die1 = new Scrollbar(Scrollbar.HORIZONTAL, 1, 1, 1, 6);
        add(die1);
        die1.addAdjustmentListener(this);
        die2 = new Scrollbar(Scrollbar.HORIZONTAL, 1, 1, 1, 6);
        add(die2);
        die2.addAdjustmentListener(this);
    }
    public void paint(Graphics g) {
        int total;
        total = value1 + value2;
        g.drawString("total is "+total, 50, 50);
        if (total==6)
            g.drawString ("you have won!", 50, 60);
    }
    public void adjustmentValueChanged(AdjustmentEvent event) {
        value1 = die1.getValue();
        value2 = die2.getValue();
        repaint();
    }
}

To illustrate how to use the else option, we could write;

if (total == 6)
    g.drawString ("you have won!", 50, 50);
else
    g.drawString ("you have lost!", 50, 50);

Now we will alter the rules and see how to rewrite the program. Suppose that any pair of values wins, i.e. two ones, two twos etc. Then the if statement is:

if (die1 == die2)
    g.drawString ("you have won", 50, 50);

Now let's suppose that you win if you get 2 or 7:

if ( (total == 2) || (total == 7) )
    g.drawString ("you have won", 50, 50);

The pair of symbols || which you will find on your keyboard means or. Notice that we have enclosed each of the conditions with brackets. These brackets aren't strictly necessary in Java, but they help a lot to clarify the meaning of the condition to be tested.

The ! operator, meaning not, gets a lot of use in programming, even though in English the use of a negative can suffer from lack of clarity. Here is an example of the use of not:

if (! (age > 18))
    g.drawString("too young", 100, 100);

This means: test to see if the age is greater than 18. If the result is true, make it false. If it is false, make it true. Then, if the outcome is true, display the message. This can, of course, be written more simply without the not (!) operator.


Nested ifs

Look at the following program fragment:

if (age > 6)
    if (age < 16)
        g.drawString("junior rate", 50, 50);
    else
        g.drawString("adult rate ", 50, 50);

You will see that the second if statement is completely contained within the first. (The indentation helps to make this clear.) This is called nesting. Nesting is not the same as indentation ñ it is just that the indentation makes the nesting very apparent. The meaning of this nested code is as follows:

The overall effect of this piece of program is:

It is common to see nesting in programs, but a program like this has a complexity which makes it slightly difficult to understand. Often it is possible to write a program more simply using the logical operators. Here, for example, the same result as above is achieved without nesting:

if ((age > 6) && (age<16))
    g.drawString("junior rate", 50, 50);
if (age >= 16)
    g.drawString("adult rate", 50, 50);

We now have two pieces of program that achieve the same end result, one with nesting and one without. Some people argue that it is hard to understand nesting, therefore such a program is prone to errors and that therefore nesting should be avoided.

Other people counter by saying that the second piece of program will always have to perform two tests, whatever the data, and that this is wasteful of computer time.

This is a matter of program style. The best advice is probably to try to write programs that are as simple as possible for the majority of readers.

The Tom and Jerry program

In this program we create two scrollbars, one called Tom, the other called Jerry. The program compares the values and reports on which one is set to the larger value. The screen is shown in Figure 7.5.

Applet for Tom & Jerry

The library method fillRect is used to draw a solid rectangle whose width across the screen is equal to the value obtained from the corresponding scrollbar.

import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class TomAndJerry extends Applet implements AdjustmentListener {
    private Scrollbar tom, jerry;
    private int tomValue = 0, jerryValue = 0;
    public void init() {
        Label toms = new Label ("Tom:");
        add(toms);
        tom = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 100);
        add(tom);
        tom.addAdjustmentListener( this);
        Label jerrys = new Label ("Jerry:");
        add(jerrys);
        jerry = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 100);
        add(jerry);
        jerry.addAdjustmentListener( this);
    }
    public void paint(Graphics g) {
        g.drawString("Tom", 5, 70);
        g.fillRect(40, 60, tomValue, 10);
        g.drawString("Jerry", 5, 85);
        g.fillRect(40, 75, jerryValue, 10);
        if (tomValue > jerryValue)
            g.drawString("Tom is bigger ", 50, 50);
        else
            g.drawString("Jerry is bigger", 50, 50);
    }
    public void adjustmentValueChanged(AdjustmentEvent event) {
        tomValue = tom.getValue();
        jerryValue = jerry.getValue();
        repaint();
    }
}

This is fine, but again illustrates the importance of care when you use if statements. In this program, what happens when the two values are equal? The answer is that the program declares Jerry to be bigger - which is clearly not the case. We really need to enhance the program to spell things out more clearly:

if (tomValue == jerryValue)
    g.drawString ("They are equal ", 50, 50);
else
    if (tomValue > jerryValue)
        g.drawString("Tom is bigger ", 50, 50);    else
        g.drawString("Jerry is bigger", 50, 50);

This is another illustration of nested if statements. There are two if statements. The second if is written within the else part of the first if statement. The indentation, while not required, is enormously helpful in visualizing how the ifs are meant to work.


Case studies using if

The amplifier display program

Some stereo amplifiers have a display that shows the volume being created. The display waxes and wanes according to the volume at any point in time. Sometimes the display has an indicator that shows the maximum value that is currently being output. This program displays the numerical value of the maximum value that the scroll bar is set to, (see Figure 7.6).

Applet for Max program

import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Max extends Applet implements AdjustmentListener {
    private Scrollbar volumeControl;
    private int max = 0;
    private int volume = 0;
    public void init() {
        volumeControl = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 100);
        add(volumeControl);
        volumeControl.addAdjustmentListener( this);
    }
    public void paint(Graphics g) {
        if (volume > max)
            max = volume;
        g.drawString("Maximum value is " + max, 50, 50);
    }
    public void adjustmentValueChanged(AdjustmentEvent event) {
        volume = volumeControl.getValue();
        repaint();
    }
}

Using buttons

We saw in an earlier chapter how to create and use scroll bars within a program. Now we look at how to use buttons. Figure 7.7 shows a window with a button in it.

Applet for Button count program

A button has a label on it - the label is "Press here" in Figure 7.7. The user can position the mouse over a button and click on it, just like pressing a real button on a stereo or a lift. Buttons are used a lot in graphical user interface (GUI) programs. If you use a word processor, it undoubtedly uses buttons to select options and functions (like cut, paste, select bold), as well as to change the size of the window. So buttons are an important aspect of programming.

As with scrollbars, use of buttons is accomplished using methods in one of the Java libraries, the AWT (Abstract Window Toolkit) library.

Program Button count

We will start out using only a single button, with a label on it called "Press here". When we press the button, by clicking on it with the mouse button, we will get the program to display the number of times the button has been pressed. This will test that the button and our Java code is working properly. When the program is running, the window is shown in Figure 7.7.

To create a button on the screen, we must first specify that the class implements ActionListener.

Then we declare a button among the variables at the start of the program:

private Button tester;

This declares a variable of type Button, which we have chosen to call tester. The method init is invoked when the program starts, and within init we must write the statement to create the button with the required label on it:

tester = new Button("Press here");

Next, we add the button to the window:

add(tester);add(tester);

Finally we register as a listener to button events:

tester.addActionListener(this);

In total, there are six steps to setting up a button:

  1. State that the class implements ActionListener
  2. Declare a button variable, giving it a name.
  3. Create a new button, giving it a label.
  4. Add the button to the window.
  5. Inform the button that this object will respond to button events, using addActionListener
  6. Provide a method called actionPerformed to be invoked when a button click event occurs

When we use scroll bars, we need to provide a method called adjustmentValueChanged to handle the event, but with buttons we have to provide a different method, called actionPerformed. The program code is:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonCount extends Applet implements ActionListener {
    private Button tester;
    private int count = 0;
    public void init(){
        tester = new Button("Press here");
        add(tester);
        tester.addActionListener(this);
    }
    public void actionPerformed(ActionEvent event) {
        count++;
        repaint();
    }
    public void paint(Graphics g) {
        g.drawString("Number of button presses is " + count, 10, 50);
    }
}

When the event happens the browser (or applet viewer) invokes actionPerformed, providing a set of information in the parameter event . The most useful item is the method getSource(), which enables us to detect which component caused the event.

In this particular program, only one kind of event can occur - someone clicking the mouse on the button. So in the method actionPerformed we can safely assume that any event is the button and therefore increment the count.

The count, initially zero, is displayed by the method paint.

Suppose we had a program that uses two buttons. For example, sometimes you see people at the roadside carrying out a census of road usage. Let us suppose that they are using a computer to record how many cars and how many trucks are passing. The program will display two buttons - one marked truck and the other marked car. It also displays the total number of cars and trucks. When an event occurs, it could either be the truck button or the car button that has been pressed. So we need to use if statements in conjunction with the method getSource to distinguish between them:

public void actionPerformed(ActionEvent event) {
    if (event.getSource() == truckButton)
        truckCount++;
    if (event.getSource() == carButton)
        carCount++;
    repaint();
}

So, in general, when there are two or more buttons, we need to use if statements to identify the source of an event. What about a program that uses both buttons and scrollbars? There is no extra problem here ñ we can use actionPerformed and adjustmentValueChanged in the same program. The class header becomes:

public class ButtonAndBar extends Applet implements ActionListener, AdjustmentListener

Boolean variables

All of the types of variable that we have met so far are designed to hold numbers. Now we meet a new kind of variable. It is a special type of variable, called a boolean, that can only hold either the value true or the value false. The words boolean, true and false are reserved in Java and cannot be used for any other purpose. This type of variable is named after the 19th century British mathematician George Boole who made a large contribution towards the development of mathematical logic, in which the ideas of true and false play a central role.

We can declare a variable of type boolean like this:

boolean finished;

and we can assign either of the values true and false:

finished = true;

Equally importantly, we can test the value of a boolean in an if statement:

if (finished)
    g.drawString("Good bye", 10, 10);

The value of finished is tested, and if it is true the accompanying statement is executed. An alternative, but slightly more cumbersome, way of writing the same test is:

if (finished == true)
    g.drawString("Good bye", 10, 10);

Boolean variables are used in programming to keep a record of the state of some action. Suppose we want to display the message "OUCH" the first time that a button is pressed (see Figure 7.8).

Applet for

We will use a boolean variable to say whether or not the button had been pressed. The variable, named clickedYet, has the value false if the button has not yet been clicked and true if it has been clicked. Initially, the value must be false. When the button is clicked, it must be made true. When the method paint sees that clickedYet is true, it displays the required message:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonOuch extends Applet implements ActionListener {
    private Button tester;
    private boolean clickedYet = false;
    public void init() {
        tester = new Button("Press here");
        add (tester);
        tester.addActionListener(this);
    }
    public void paint(Graphics g) {
        if (clickedYet)
            g.drawString ("OUCH", 100, 50);
    }
    public void actionPerformed(ActionEvent event) {
        clickedYet = true;
        repaint();
    }
}

A method can return a boolean value. For example, suppose we need a method to check whether three numbers are in numerical order:

public boolean inOrder (int a, int b, int c) {
    if ((a <= b) && (b <= c))
        return true;
    else
        return false;
}

Random numbers

We will return to the dice-throwing program discussed earlier. Instead of inputting the dice values via the scrollbars, we will change the program so that the computer decides the die values randomly. We will create a button, labelled "Throw". When it is clicked, the program will get two random numbers and use them as the die values (Figure 7.9).

Applet for 2 dice

Creating random numbers is a very common thing to want to do in game programs of all kinds. If the game behaved the same way every time you played it, it would be very boring. Randomness creates variety, whether it is the arrival of aliens, the bounce of a ball or the layout of a maze.

To get a random number in Java, we invoke a library method. There are a number of methods, including one named random, which is in the maths library. The method random returns a random number, a double in the range 0.0 up to but not including 1.0. What we need for our purpose is an integer in the range 1 to 6. So we need to convert the numbers that random produces into the ones that we want:

1. random creates numbers evenly distributed int the range 0.0 to 0.999999 If we multiply by 6, we will get random numbers evenly distributed in the range 0.0 to 5.999

2. If we now convert the floating point number to an integer using the cast operator (int), we will get the integers 0 to 5. Remember that (int) truncates the floating point number, so that for example 5.7 becomes 5.

3. Finally we add 1 to get random integers in the range 1 to 6.

The complete formula is thus:

die = (int)(Math.random() * 6)+1;

Transforming the size of random numbers in a manner similar to this is often necessary.

The program to throw two dice looks like this:

import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Dice2 extends Applet implements ActionListener {
    private Button throwDice;
    private boolean thrown = false;
    public void init() {
        throwDice = new Button("Throw");
        add(throwDice);
        throwDice.addActionListener(this);
    }
    public void actionPerformed(ActionEvent event) {
        thrown = true;
        repaint();
    }
    public void paint(Graphics g) {
        int die1, die2;
        if (thrown) {
            die1 = (int)(Math.random() * 6) + 1;
            die2 = (int)(Math.random() * 6) + 1;
            g.drawString("The dice are " + die1 + " and " + die2, 20, 40);
            if (die1 == die2)
                g.drawString("a win", 20, 60);
            else
                g.drawString("sorry" , 20, 60);
        }
    }
}

The random numbers that are obtained using the library method random are not truly random. Because a computer is a machine that can only carry out a well-defined series of actions, a computer cannot create random numbers. What it does instead is to create what look like random numbers - numbers that are indistinguishable from random numbers. These are called pseudo-random numbers. These are created as a series. The next number is created from the last, and so on. A formula is used to derive one value from the next in such a way that the next number seems to be random.

There are some other random number methods, one of which is called nextInt. When invoked it produces an integer random number in the complete range of the type int. This method is in a package called jav.util (util is short for utilities), and to use it another import statement must appear at the head of the program, along with the others:

import java.util.*;

Case stuies using buttons

The Little and Large program

In this program we create two buttons. The program draws a circle. Clicking on one button makes the circle bigger; the other makes it smaller (Figure 7.10).

Applet for Little & Large program

When the user clicks the mouse, the browser (or applet viewer) detects the event. It then invokes the method called actionPerformed that we have written to handle the event. We must provide this method (if we want to respond to events) as part of the program we write. The method must carries out tests to identify which particular event happened - which button was pressed.

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class LittleAndLarge extends Applet implements ActionListener {
    private int diameter = 20;
    private Button little, large;
    public void init() {
        little = new Button("Little");
        add(little);
        little.addActionListener(this);
        large = new Button("Large");
        add(large);
        large.addActionListener(this);
    }
    public void paint(Graphics g) {
        g.drawOval(25,25, diameter, diameter);
    }
    public void actionPerformed(ActionEvent event) {
        if (event.getSource() == little)
            diameter = diameter - 10;
        if (event.getSource() == large)
            diameter = diameter + 10;
        repaint();
    }
}

The library method drawOval needs as its first two parameters the x- and y-coordinates of the top left of a rectangle that just encloses the oval. The third parameter is the width of the oval and the last parameter is the height of the oval. (If the width and height are the same we get a circle.)

The safe program

This program represents the combination lock on a safe. The program displays three buttons, one for each of the digits 1, 2 and 3 (Figure 7.11).

Applet for Safe program

The user has to press three buttons, in an attempt to guess the combination correctly.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Safe extends Applet implements ActionListener {
    private int guess = 0;
    private int combination = 321;
    private Button one, two, three, again;
    public void init() {
        one = new Button("1");
        add(one);
        one.addActionListener(this);
        two = new Button("2");
        add(two);
        two.addActionListener(this);
        three = new Button("3");
        add(three);
        three.addActionListener(this);
        again = new Button("Try Again");
        add(again);
        again.addActionListener(this);
    }
    public void paint(Graphics g) {
        if (guess == combination)
            g.drawString("Unlocked", 50, 50);
        else
            g.drawString("Locked", 50, 50);
    }
    public void actionPerformed(ActionEvent event) {
        if (event.getSource() == one)
            guess = guess*10 + 1;
        if (event.getSource() == two)
            guess = guess*10 + 2;
        if (event.getSource() == three)
            guess = guess*10 + 3;
        if (event.getSource() == again)
            guess = 0;
        repaint();
    }
}

It might be frustrating to play with this program because you could try for a very long time before you got the correct combination. A less frustrating game is set as an exercise at the end of the chapter.


switch

The switch statement is another way of doing a lot of if statements. But it is actually not used very often and, if you wish, you can skip this section. We have included an explanation of the switch statement for completeness, and when you feel confident about programming you may want to come back and read all about it.

If you find that you are writing a lot of if statements together, it may be worth rewriting them as a switch statement. For example, suppose we need a piece of program to display a date. Suppose that the day of the week is represented by an integer called day, which has one of the values 1 to 7, representing the days Monday to Sunday. We could write:

if (day == 1)
    g.drawString ("Monday", 50, 50);
else
    if (day == 2)
        g.drawString ("Tuesday", 50, 50);
    else
        if (day == 3)
            g.drawString ("Wednesday", 50, 50);
        else
            if (day == 4)
                g.drawString ("Thursday", 50, 50);
            else
                if (day == 5)
                    g.drawString ("Friday", 50, 50);
                else
                    if (day == 6)
                        g.drawString ("Saturday", 50, 50);
                    else
                        if (day == 7)
                            g.drawString ("Sunday", 50, 50);

Notice that we have chosen to indent them, one from the other, so that successive lines march rightwards across the page. An alternative style would be to write the else's underneath each other. (See Chapter 22 for a further discussion of the style of a series of nested if statements.)

Now although this piece of coding is fairly neat, clear and well-structured, there is an alternative that has the same effect using the switch statement:

switch (day) {
    case 1 : g.drawString ("Monday", 50, 50); break;
    case 2 : g.drawString ("Tuesday", 50, 50); break;
    case 3 : g.drawString ("Wednesday", 50, 50); break;
    case 4 : g.drawString ("Thursday", 50, 50); break;
    case 5 : g.drawString ("Friday", 50, 50); break;
    case 6 : g.drawString ("Saturday", 50, 50); break;
    case 7 : g.drawString ("Sunday", 50, 50); break;
}

This now shows the symmetry of what is to happen more clearly than the equivalent series of if statements.

The word break means go to the end of the switch statement

Notice the brackets around the variable that acts as the control for the switch statement. Notice also the colon following each occurrence of the value of the variable. Curly brackets enclose the complete set of options.

A switch statement like this can be visualized as a flowchart in Figure 7.12.

MACROBUTTON HtmlResAnchor Flowchart for switch program

More than one statement can follow an option. For example, one of the options could be:

case 4 : setColor(RED);
         g.drawString ("Thursday", 50, 50);
         break;

Several options can be grouped together, like this:

switch (day) {
    case 1 : case 2: case 3: case 4: case 5:
                 g.drawString("weekday", 50, 50); break;
    case 6 : case 7:
                 g.drawString ("weekend", 50, 50); break;
}

Another sometimes useful part of the switch statement is the default option. Suppose in the above example that the value of the integer denoting the day of the week is input from a scrollbar. Then there is the distinct possibility that the number entered will not be in the range 0 to 7. Any decent program needs to take account of this, in order to prevent something odd happening. The switch statement is very good at dealing with this situation, because we can supply a "catch-all" or default option that will be invoked if none of the others are valid:

switch (day) {
    case 1 : g.drawString ("Monday", 50, 50); break;
    case 2 : g.drawString ("Tuesday", 50, 50); break;
    case 3 : g.drawString ("Wednesday", 50, 50); break;
    case 4 : g.drawString ("Thursday", 50, 50); break;
    case 5 : g.drawString ("Friday", 50, 50); break;
    case 6 : g.drawString ("Saturday", 50, 50); break;
    case 7 : g.drawString ("Sunday", 50, 50); break;
    default : g.drawString ("illegal day", 50, 50); break;
}

If a default option is not written as part of a switch statement and if none of the cases corresponds to the actual value of the variable, then all the options are ignored.

The switch statement looks very useful, but unfortunately it is not as flexible as it could be. Suppose, for example, we want to write a piece of program to output two numbers, with the smallest first, followed by the larger. Using if statements, we have:

if (a > b)
    g.drawString(b + " greater than " +  a, 50, 50);
else
    if (b > a)
        g.drawString(a + " greater than " +  b, 50, 50);
    else
        g.drawString("they are equal", 50, 50);

We may be tempted to rewrite this using the switch statement as follows:

switch (?) { // beware! illegal Java
    case a>b : g.drawString(b + " greater than " + a, 50, 50); break;
    case b>a : g.drawString(a + " greater than " + b, 50, 50); break;
    case a == b : g.drawString ("they are equal", 50, 50); break;
}

but this is not allowed because, as indicated by the question mark, switch only works with a single integer or character variable as its subject.


Text fields

Text fields are another graphical user interface component for inputting information from the user of a program. Until now we have used scroll bars for the input of numbers - which is convenient and intuitive. But a text field allows a number to be input more directly than a scroll bar. (A text field can also be used to input textual information, as we shall see later.) For example, Figure 7.13 shows the window for a program that acts as the voting checker, which we presented at the beginning of this chapter.

Applet for voting checker

However, in this new version of the program the voter's age is entered into a text field. To enter a number into a text field the cursor is positioned within the field. Then the characters are keyed in. They can be altered as much as you like by using the backspace and delete keys. When the user is satisfied with the number, the enter key is pressed.

Here is the program that displays the text field, gets the number and checks it - the voting checker program:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
    public class AgeCheck extends Applet implements ActionListener { 
    private TextField ageField;
    private int age;
    public void init() {
        ageField = new TextField(10);
        add(ageField);
        ageField.addActionListener(this);
    }
    public void actionPerformed(ActionEvent event) {
        age = Integer.parseInt(ageField.getText());
        repaint();
    }
    public void paint(Graphics g) {
        g.drawString("Age is " + age, 50, 50);
        if (age >= 18)
            g.drawString("You can vote", 50, 100);
        else
            g.drawString("You cannot vote", 50, 100);
    }
}

Setting up a text field is similar to setting up a button. First we declare a variable of type Textfield:

private TextField ageField;

with a name chosen by the programmer. This is declared with any other variable at the top of the program. Next we create the text field when init is invoked:

ageField = new TextField(10);

The parameter for the method Textfield is the width, in characters, of the text field displayed on the screen.

Next, the text field is added to the window display:

add(ageField);

Finally, we tell the event handling mechanism to notify us when an event occurs:

ageField.addActionListener(this);

When the user of the program presses the enter key, the method actionPerformed is invoked by the applet viewer or the browser. We must provide such a method to handle the event. In this program there is only one possible event, so we have no need to distinguish it from any others. (Note that the methods associated with handling events from text fields are the same as those used with buttons.)

We can go on to process the data that was entered. The library method getText() does this, and in our case ageField.getText() inputs the characters from the text field. Finally we need to convert the characters into an integer number using the library method Integer.parseInt. A string of characters such as 123 may look like a number, but in fact is simply three characters ñ the character 1, the character 2 and the character 3. If we want to convert them into a number, we need to do so explicitly. The method parseInt is so called because the word parse means to scan or process some text. In summary, inputting an integer from a text field involves:

1. Use getText to input the text.

2. Use Integer.parseInt to convert the text to an integer.

If the characters entered into a text field are not digits - for example if they are letters or punctuation characters - then the program will stop with an error message. (There is a way to avoid this, but we will not see how until Chapter 16 on exception handling.)

We will use text fields in later chapters to input floating-point numbers and to input character strings. The process is similar. In the case of floating-point numbers, various library methods are used to convert the characters into a number (see Chapter 12 on calculations). In the case of inputting a string, no conversion is necessary.

If a program uses two or more text fields, or a text field and a button, the method actionPerfromed that handles the events from these components needs to distinguish between the sources of an event, using if statements in the following manner;

public void actionPerformed(ActionEvent event) {
    if (event.getSource() == ageField)
        age = Integer.parseInt(ageField.getText());
    if (event.getSource() == yearField)
        year = Integer.parseInt(yearField.getText());
    repaint();
}

A text field can also be used to output (display) text, using the method setText as shown in the following code. Note that the text field needs to be sufficiently wide to accommodate the text.

TextField message = new TextField(25);
message.setText("Your message here");

A text field is used for the input (or output) of just one line of text. If you need to input (or output) several lines of text, a GUI component called a text area is what you need. These are described later in this book.


Grammar spot

The first kind of if statement has the structure:

if (condition)
    statement;

or

if (condition) {
    statement1;
    statement2;
}

The second type of if statement has the structure:

if (condition)
    statementA;
else
    statementB;

or

if (condition) {
    statement1;
    statement2;
} else {
    statement3;
    statement4;
}

Several aspects of using if statements require care:

The switch statement has slightly complicated grammar and must be used carefully. For example it uses colons and semicolons. The best approach is simply to copy a switch statement from a book or an existing program. Luckily, it is not something that you will use very often.


Programming pitfalls

Do not forget to enclose the condition being tested in an if statement in brackets like this:

if (a > b)...

Don't forget that, in a test, the test for equality is not = but ==, so

if (a = b)...

will not compile correctly, whereas:

if (a == b)...

is probably what you want to write. This is a very common error.

You might find that you have written an if statement like this:

if (a > 18 && < 25) ...

which is wrong. Instead, the && (meaning and) must link two complete conditions, preferably in brackets for clarity, like this:

if (a > 18) && (a < 25)) ...

Programming principles

The computer normally obeys instructions one-by-one in a sequence. An if statement or a switch statement causes the computer to test the value of some data and then take a choice of actions depending on the result of the test. This choice is sometimes called selection. The test of the data is sometimes called a condition.

The if statement comes in two flavours, one with an else part and one without. When you use an if statement with an else part, the two alternative actions are clearly distinguished. When you use an if statement without an else, the actions are only performed if the condition is true.

After an if statement is completed, the computer continues obeying the instructions in sequence.

A boolean variable can only have one of two values - true and false.


New language elements

Control structures for selection:

if, else 
switch, case, break, default Boolean variables.

Summary

if statements allow the programmer to control the sequence of actions by making the program carry out a test. Following the test, the computer carries out one of a choice of actions.

There are two varieties of the if statement, one with an else part and one without.

A boolean variable can take on either the value true or the value false.

The switch statement carries out a test, but provides for an unlimited set of outcomes. However, the switch statement is restricted to tests on integers.


Exercises

7.1 Random number Write a program to display a single random number each time a button labelled ênextë is pressed. The program should display:

1. the random number obtained by invoking Math.random, which is in the range 0.0 to 0.999...;

2. random integer in the range 1 to 10;

3. a random integer in the range 0 to 100;

4. a random boolean value (true or false).

7.2 Deal a card Write a program with a single button on it which, when clicked, randomly selects a single playing card. First use the random number generator method in the library to create a number in the range 1 to 4. Then convert the number to a suit (heart, diamond, club, spade). Next use the random number generator to create a random number in the range 1 to 13. Convert the number to an ace, 2, 3 etc. and finally output the value of the chosen card. (Hint: use switch as appropriate.)

7.3 Sorting Write a program to input numbers from three scroll bars, or text fields, and output them in increasing numerical size.

7.4 Cinema price Write a program to work out how much a person pays to go to the cinema. The program should input an age from the scrollbar or a text field and then decide on the following basis:

7.5 Betting A group of people are betting on the outcome of three throws of the dice. A person bets $1 on predicting the outcome of the three throws. Write a program that uses the random number method to simulate three throws of a die and displays the winnings according to the following rules:

7.6 The digital combination safe Write a program to act as the digital combination lock for a safe. Create three buttons, representing the numbers 1, 2 and 3. The user clicks on the buttons, attempting to guess the correct numbers (say 331121). The program remain unhelpfully quiet until the correct buttons are pressed. Then it congratulates the user with a suitable message. A button is provided to allow users to give up when they become frustrated.

Enhance the program so that it has another button which allows the user to change the safe's combination.

7.7 Rock, scissors, paper game This is a game for two humans to play. Each player simultaneously chooses one of rock, scissors or paper. Rock beats scissors, paper beats rock and scissors beats paper. If both players choose the same, it is a draw. Write a program to play the game. The player selects one of three buttons, marked rock, scissors or paper. The computer makes its choice randomly using the random number method. The computer also decides and displays who has won.

7.8 The calculator Write a program which simulates a simple desk calculator (Figure 7.14) that acts on integer numbers. It has one button for each of the 10 digits, 0 to 9. It has a button to add and a button to subtract. It has a clear button, to clear the display, and an equals (=) button to get the answer.

When the clear button is pressed the display is set to zero and the (hidden) total is set to zero.

When a digit button is pressed, the digit is added to the right of those already in the display (if any).

When the + button is pressed, the number in the display is added to the total (and similarly for the - button). The display is set equal to zero.

When the = button is pressed, the value of the total is displayed.

calculator applet

7.9 The elevator Write a program to simulate a very primitive elevator. The elevator is represented as a rectangle and there are two buttons ó one to make it move up the screen and one to make it move down.

7.10 Reaction timer Write a program that acts as a reaction timer. It uses the library method currentTimeMillis() which returns the current time in milliseconds as a long. A millisecond is one thousandth of a second. This method is invoked like this: long timeNow = System.currentTimeMillis();

When the program starts up the init method should create and display a button labelled êNow!ë and record the time. When the user hits (clicks on) the button, the program gets the time and displays how long it took the user to respond. (Times of less than 0.1 of a second are suspect and may have resulted from cheating!)

For interest, the time is measured from 1 January 1970 (the so-called epoch). It is called UTC (Coordinated Universal Time) and is essentially the same as Greenwich Mean Time (GMT).

7.11 Turtle graphics Turtle graphics is a way of making programming easy for young children. Imagine a pen fixed to the belly of a turtle. As the turtle crawls around a floor, the pen draws on the floor. The turtle can be issued with commands as follows:

Initially the turtle is at coordinates 0, 0 and facing to the right.

So, for example, we can draw a rectangle using the sequence

pen down
go forward 20 pixels
turn right 90 degrees
go forward 20 pixels
turn right 90 degrees
go forward 20 pixels
turn right 90 degrees
go forward 20 pixels

Write a program that behaves as the turtle, with one button for each of the commands. The number of pixels, n, to be moved is input via a scrollbar.


Self-test Questions

In the book, these are placed at the appropriate place in the text.

7.1 Do these two pieces of Java achieve the same end or not?

if (age > 18)
    g.drawString ("you may vote ", 50, 50);
if (age < 18)
    g.drawString ("you may not vote", 50, 50);

7.2 Alter the program so that a win is a total value of 2, 5 or 7.

7.3 Write if statements to test whether someone is eligible for full-time employment. The rule is that you must be 16 or above and younger than 65.

7.4 Rewrite the above if statement without using the not operator.

7.5 Write a program to input a salary from a scrollbar and determine how much tax someone should pay according to the following rules:

People pay no tax if they earn up to $10,000. They pay tax at the rate of 20% on the amount they earn over $10,000 but up to $50,000. They pay tax at 90% on any money they earn over $50,000.

7.6 Write a program that creates three scrollbars and displays the largest of the three values.

7.7 Write a program that displays the numerical value of the minimum value that the scroll bar is set to.

7.8 The Young and Beautiful holiday company restricts its clients to ages between 18 and 30. (Below 18 you have no money; after 30 you have too many wrinkles.) Write a program to test whether you are eligible to go on holiday with this company.

7.9 Write a method that converts the integers 1, 2, 3 and 4 into the words diamonds, hearts, clubs and spades respectively.

7.10 Write a method to convert integers as follows. If the number is in the range 1 to 5, return the string "weekday". If it is 6 or 7 return the string "weekend". Otherwise return the string "error".


Answers to Self-Test Questions

7.1

No, because they treat the age of 18 differently. The two if statements also create different messages.

7.2

if ((total == 2) || (total == 5) || (total == 7))
    g.drawString("you have won", 50, 50);

7.3

if (age >= 16)
    if (age < 65)
        g.drawString("Yes", 10, 10);

7.4

if (age <= 18)
    g.drawString("too young", 100, 100);

7.5

salary = bar.getvalueÜ();
int tax = 0;
if ((salary > 10000) && (salary <= 50000))
    tax = (salary - 10000)/5;
if (salary > 50000)
    tax = 8000 + ((salary - 50000) * 9 / 10);

7.6

int a = bar1.getvalueÜ();
int b = bar2.getvalueÜ();
int c = bar3.getvalueÜ();
int t;
if (b > c)
    t = b;
else
    t = c;
if (a > t)
    t = a;
g.drawString("largest value is " + t, 20, 20);

7.7 The essential part of this program is:

if (volume < min)
    min = volume;
g.drawString("Minimum value is " + min, 50, 50);

7.8

private boolean isTriangle(float a, float b, float c) {
if ((a + b) <= c)
    return false;
if ((b + c) <= a)
    return false;
if ((c + a) <= b)
    return false;
return true;
}

7.9

private String convert(int s) {
    String suit;
    switch(s) {
        case 1 : suit = "diamonds"; break;
        case 2 : suit = "hearts"; break;
        case 3 : suit = "clubs"; break;
        case 4 : suit = "spades"; break;
    }
    return suit;
}

7.10

private String checkDay(int day) (
    String status;
    switch (day) {
        case 1 : case 2 : case 3 : case 4 : case 5 :
            status = "Weekday"; break;
        case 6 : case 7 :
            status = "Weekend"; break;
        default : status = "error"; break;
    }
    return status;
}