Chapter 5

Going Around in Circles (Or, Using Loops)

IN THIS CHAPTER

check The thrill of while loops

check The rapture of infinite loops

check The splendor of do loops

check The joy of validating input

check The wonder of for loops

check The ecstasy of nested loops

So far, all the programs in this book have started, run quickly through their main method, and then ended. If Dorothy from The Wizard of Oz were using these programs, she’d probably say, “My, programs come and go quickly around here!”

In this chapter, you find out how to write programs that don’t come and go so quickly. They hang around by using loops, which let them execute the same statements more than once.

Loops are the key to writing one of the most common types of programs: programs that get input from the user, do something with it, get more input from the user and do something with that, and keep going this way until the user has had enough.

Put another way, loops are like the instructions on your shampoo: Lather. Rinse. Repeat.

Tip Like if statements, loops rely on conditional expressions to tell them when to stop looping. Without conditional expressions, loops would go on forever, and your users would grow old watching them run. So if you haven’t yet read Book 2, Chapter 4, I suggest that you do so before continuing much further.

Using Your Basic while Loop

The most basic of all looping statements in Java is while. The while statement creates a type of loop that’s called a while loop, which is simply a loop that executes continuously as long as some conditional expression evaluates to true. while loops are useful in all sorts of programming situations, so you use while loops a lot. (I tell you about other kinds of loops later in this chapter.)

The while statement

The basic format of the while statement is this:

while (expression)

statement

The while statement begins by evaluating the expression. If the expression is true, statement is executed. Then the expression is evaluated again, and the whole process repeats. If the expression is false, statement is not executed, and the while loop ends.

Note that the statement part of the while loop can either be a single statement or a block of statements contained in a pair of braces. Loops that have just one statement aren’t very useful, so nearly all the while loops you code use a block of statements. (Well, okay, sometimes loops with a single statement are useful. It isn’t unheard of — just not all that common.)

A counting loop

Here’s a simple program that uses a while loop to print the even numbers from 2 through 20 on the console:

public class EvenCounter

{

public static void main(String[] args)

{

int number = 2;

while (number <= 20)

{

System.out.print(number + " ");

number += 2;

}

System.out.println();

}

}

If you run this program, the following output is displayed in the console window:

2 4 6 8 10 12 14 16 18 20

The conditional expression in this program’s while statement is number <= 20. That means the loop repeats as long as the value of number is less than or equal to 20. The body of the loop consists of two statements. The first prints the value of number followed by a space to separate this number from the next one. Then the second statement adds 2 to number.

Figure 5-1 shows a flowchart for this program. This flowchart can help you visualize the basic decision-making process of a loop.

Flowchart for the basic decision-making process of a loop. The body of the loop consists of two statements the first prints the value of number followed by a space to separate this number from the next one; then the second statement adds 2 to number.

FIGURE 5-1: The flowchart for a while loop.

Breaking Out of a Loop

In many programs, you need to set up a loop that has some kind of escape clause. Java’s escape clause is the break statement. When a break statement is executed in a while loop, the loop ends immediately. Any remaining statements in the loop are ignored, and the next statement executed is the statement that follows the loop.

Suppose that you’re afraid of the number 12. (I’m not a doctor, and I don’t play one on TV, but I think the scientific name for this condition would be dodecaphobia.) You could modify the counting program shown in the preceding section so that when it gets to the number 12, it panics and aborts the loop:

public class Dodecaphobia

{

public static void main(String[] args)

{

int number = 2;

while (number <= 20)

{

if (number == 12)

break;

System.out.print(number + " ");

number += 2;

}

System.out.println();

}

}

When you run this program, the following line is displayed on the console:

2 4 6 8 10

Whew! That was close. Almost printed the number 12 there.

Looping Forever

One common form of loop is called an infinite loop. That’s a loop that goes on forever. You can create infinite loops many ways in Java (not all of them intentional), but the easiest is to just specify true for the while expression.

Here’s an example:

public class CountForever

{

public static void main(String[] args)

{

int number = 2;

while (true)

{

System.out.print(number + " ");

number += 2;

}

}

}

If you run this program, your console window quickly fills up with numbers and just keeps going. That’s great if you really like even numbers, but eventually you’ll tire of this loop and want it to stop. You can stop an infinite loop in any of three ways:

  • Turn off your computer.
  • Hit your computer with an ax or other heavy object.
  • Close the console window.

The last one is probably the one you want to go with.

Tip Obviously, infinite loops are something you want to avoid in your programs. So whenever you use a while expression that’s always true, be sure to throw in a break statement to give your loop some way to terminate. You could use an infinite loop with a break statement in the Dodecaphobia program:

public class Dodecaphobia2

{

public static void main(String[] args)

{

int number = 2;

while (true)

{

if (number == 12)

break;

System.out.print(number + " ");

number += 2;

}

System.out.println();

}

}

Here the loop looks as though it might go on forever, but the break statement panics out of the loop when it hits 12.

Letting the user decide when to quit

It turns out that infinite loops are also useful when you want to let the user be in charge of when to stop the loop. Suppose that you don’t know what numbers a user is afraid of, so you want to count numbers until the user says to stop. Here’s a program that does that:

import java.util.Scanner;

public class NumberPhobia

{

static Scanner sc = new Scanner(System.in);

public static void main(String[] args)

{

int number = 2;

String input;

while (true)

{

System.out.println(number + " ");

System.out.print

("Do you want to keep counting?"

+ " (Y or N)");

input = sc.next();

if (input.equalsIgnoreCase("N"))

break;

number += 2;

}

System.out.println("\nWhew! That was close.\n");

}

}

Here’s some typical console output from this program, for a user who has octophobia:

2

Do you want to keep counting? (Y or N)y

4

Do you want to keep counting? (Y or N)y

6

Do you want to keep counting? (Y or N)n

Whew! That was close.

Letting the user decide in another way

Another way to write a loop that a user can opt out of is to test the input string in the while condition. The only trick here is that you must first initialize the input string to the value that continues the loop. Otherwise, the loop doesn’t execute at all!

Here’s a variation of the NumberPhobia program named NumberPhobia2 that uses this technique:

import java.util.Scanner;

public class NumberPhobia2

{

static Scanner sc = new Scanner(System.in);

public static void main(String[] args)

{

int number = 2;

String input = "Y";

while (input.equalsIgnoreCase("Y"))

{

System.out.println(number + " ");

System.out.print

("Do you want to keep counting?"

+ " (Y or N)");

input = sc.next();

number += 2;

}

System.out.println("\nWhew! That was close.");

}

}

This program works almost the same way as the preceding version, but with a subtle difference. In the previous version, if the user says N after the program displays 6, the value of the number variable after the loop is 6 because the break statement bails out of the loop before adding 2 to number. But in this version, the value of number is 8.

Using the continue Statement

The break statement is rather harsh: It completely bails out of the loop. Sometimes that’s what you need — but just as often, you don’t really need to quit the loop; you just need to skip a particular iteration of the loop. The Dodecaphobia program presented earlier in this chapter stops the loop when it gets to 12. What if you just want to skip the number 12, so you go straight from 10 to 14?

To do that, you can use the break statement’s kinder, gentler relative, the continue statement. The continue statement sends control right back to the top of the loop, where the expression is immediately evaluated again. If the expression is still true, the loop’s statement or block is executed again.

Here’s a version of the Dodecaphobia program that uses a continue statement to skip the number 12 rather than stop counting altogether when it reaches 12:

public class Dodecaphobia3

{

public static void main(String[] args)

{

int number = 0;

while (number < 20)

{

number += 2;

if (number == 12)

continue;

System.out.print(number + " ");

}

System.out.println();

}

}

Run this program, and you get the following output in the console window:

2 4 6 8 10 14 16 18 20

Notice that I had to make several changes in this program to get it to work with a continue statement instead of a break statement. If I had just replaced the word break with continue, the program wouldn’t have worked, because the statement that added 2 to the number came after the break statement in the original version. As a result, if you just replace the break statement with a continue statement, you end up with an infinite loop when you reach 12, because the statement that adds 2 to number never gets executed.

To make this program work with a continue statement, I rearranged the statements in the loop body so that the statement that adds 2 to number comes before the continue statement. That way, the only statement skipped by the continue statement is the one that prints number to the console.

Unfortunately, this change affected other statements in the program. Because 2 is added to number before number is printed, I had to change the initial value of number from 2 to 0, and I had to change the while expression from number <= 20 to number < 20.

Running do-while Loops

A do-while loop (sometimes just called a do loop) is similar to a while loop, but with a critical difference: In a do-while loop, the condition that stops the loop isn’t tested until after the statements in the loop have executed at least once. The basic form of a do-while loop is this:

do

statement

while (expression);

Note that the while keyword and the expression aren’t coded until after the body of the loop. As with a while loop, the body for a do-while loop can be a single statement or a block of statements enclosed in braces.

Also, notice that the expression is followed by a semicolon. do-while is the only looping statement that ends with a semicolon.

Here’s a version of the EvenCounter program that uses a do-while loop instead of a while loop:

public class EvenCounter2

{

public static void main(String[] args)

{

int number = 2;

do

{

System.out.print(number + " ");

number += 2;

} while (number <= 20);

System.out.println();

}

}

Remember Here’s the most important thing to remember about do-while loops: The statement or statements in the body of a do-while loop always get executed at least once. By contrast, the statement or statements in the body of a while loop aren’t executed at all if the while expression is false the first time it’s evaluated.

Look at the flowchart in Figure 5-2 to see what I mean. You can see that execution starts at the top of the loop and flows through to the decision test after the loop’s body has been executed once. Then, if the decision test is true, control flies back up to the top of the loop. Otherwise, it spills out the bottom of the flowchart.

Flowchart for a do-while loop, depicting that execution starts at the top of the loop and flows through to the decision test after the loop’s body has been executed once.

FIGURE 5-2: The flowchart for a do-while loop.

Here are a few other things to be aware of concerning do-while loops:

  • You often can skip initializing the variables that appear in the expression before the loop, because the expression isn’t evaluated until the statements in the loop body have been executed at least once. But remember that any variables mentiond in the while expression must be within scope of the do statement itself; variables declared within the do loop can't be used in the while expression because they’re out of scope.
  • You can use break and continue statements in a do-while loop, just as you can in a while loop.
  • Some programmers like to place the brace that begins the loop body on the same line as the do statement and the while statement that ends the do-while loop on the same line as the brace that marks the end of the loop body. Whatever makes you happy is fine with me. Just remember that the compiler is agnostic when it comes to matters of indentation and spacing.

Validating Input from the User

do-while loops are especially useful for validating input by the user. Suppose you’re writing a program that plays a betting game, and you want to get the amount of the user’s bet from the console. The user can bet any dollar amount he wants (whole dollars only, though) but can’t bet more than he has in the bank, and he can’t bet a negative amount or zero. Here’s a program that uses a do-while loop to get this input from the user:

import java.util.Scanner;

public class GetABet

{

static Scanner sc = new Scanner(System.in);

public static void main(String[] args)

{

int bank = 1000; // assume the user has $1,000

int bet; // the bet entered by the user

System.out.println("You can bet between 1 and " + bank);

do

{

System.out.print("Enter your bet: ");

bet = sc.nextInt();

} while ( (bet <= 0) || (bet > bank) );

System.out.println("Your money's good here.");

}

}

Here the expression used by the do-while loop validates the data entered by the user, which means that it checks the data against some set of criteria to make sure the data is acceptable.

Remember The || operator performs an Or test. It returns true if at least one of the expressions on either side of the operator is true. So if the bet is less than or equal to zero (bet <= 0), or if the bet is greater than the money in the bank (bet > bank), this expression returns true.

Warning This type of validation testing checks only whether the user entered a valid number in an acceptable range. If the user entered something that isn’t a valid number, such as the word Buttercup or Humperdinck, the program chokes badly and spews forth a bunch of vile exception messages upon the console. You find out how to clean up that mess in Book 2, Chapter 8. (Actually, you can avoid this problem by using either a do loop or a while loop and the hasNextDouble method of the Scanner class, which I describe in Book 2, Chapter 2.)

If you want to display an error message when the user enters incorrect input, you have to use an if statement inside the loop, and this if statement must duplicate the expression that validates the input data. Thus the expression that does the validation has to appear twice. For example:

import java.util.Scanner;

public class GetABet2

{

static Scanner sc = new Scanner(System.in);

public static void main(String[] args)

{

int bank = 1000; // assume the user has $1,000

int bet; // the bet entered by the user

System.out.println ("You can bet between 1 and " + bank);

do

{

System.out.print("Enter your bet: ");

bet = sc.nextInt();

if ( (bet <= 0) || (bet > bank) )

System.out.println ("What, are you crazy?");

} while ( (bet <= 0) || (bet > bank) );

System.out.println("Your money's good here.");

}

}

Here, the if statement displays the message "What, are you crazy?" if the user tries to enter an inappropriate bet.

Tip You can avoid duplicating the expression that does the data validation by adding a boolean variable that’s set in the body of the do-while loop if the data is invalid, as in this example:

import java.util.Scanner;

public class GetABet3

{

static Scanner sc = new Scanner(System.in);

public static void main(String[] args)

{

int bank = 1000; // assume the user has $1,000

int bet; // the bet entered by the user

boolean validBet; // indicates if bet is valid

System.out.println("You can bet between 1 and " + bank);

do

{

System.out.print("Enter your bet: ");

bet = sc.nextInt();

validBet = true;

if ( (bet <= 0) || (bet > bank) )

{

validBet = false;

System.out.println("What, are you crazy?");

}

} while (!validBet);

System.out.println("Your money's good here.");

}

}

In this example, I use a boolean variable named validBet to indicate whether the user has entered a valid bet. After the user enters a bet, this variable is set to true before the if statement tests the validation criteria. Then, if the if statement finds that the bet is not valid, validBet is set to false.

Using the Famous for Loop

In addition to while and do-while loops, Java offers the for loop. You may have noticed that many of the loops presented so far in this minibook involve counting. It turns out that counting loops are quite common in computer programs, so the people who design computer programming languages (they’re called computer programming language designers) long ago concocted a special kind of looping mechanism that’s designed just for counting.

The basic principle behind a typical for loop is that the loop itself maintains a counter variable — that is, a variable whose value increases each time the body of the loop is executed. If you want a loop that counts from 1 to 10, you’d use a counter variable that starts with a value of 1 and is increased by 1 each time through the loop. Then you’d use a test to end the loop when the counter variable reaches 10. The for loop lets you set all this up in one convenient statement.

Understanding the formal format of the for loop

I would now like to inform you of the formal format of the for loop, so that you’ll know how to form it from now on. The for loop follows this basic format:

for (initialization-expression; test-expression; count-expression)

statement;

The three expressions in the parentheses following the keyword for control how the for loop works. The following paragraphs explain what these three expressions do:

  • The initialization expression is executed before the loop begins. Usually, you use this expression to initialize the counter variable. If you haven’t declared the counter variable before the for statement, you can declare it here too.
  • The test expression is evaluated each time the loop is executed to determine whether the loop should keep looping. Usually, this expression tests the counter variable to make sure that it is still less than or equal to the value you want to count to. The loop keeps executing as long as this expression evaluates to true. When the test expression evaluates to false, the loop ends.
  • The count expression is evaluated each time the loop executes. Its job is usually to increment the counter variable.

Figure 5-3 shows a flowchart to help you visualize how a for loop works.

Flowchart for a for loop. The initialization expression is executed before the loop begins; the test expression is evaluated each time the loop is executed; and the count expression is evaluated each time the loop executes.

FIGURE 5-3: The flowchart for a for loop.

Here’s a simple for loop that displays the numbers 1 to 10 on the console:

public class CountToTen

{

public static void main(String[] args)

{

for (int i = 1; i <= 10; i++)

System.out.println(i);

}

}

Run this program, and here’s what you see on the console:

1

2

3

4

5

6

7

8

9

10

This for loop has the following pieces:

  • The initialization expression is int i = 1. This expression declares a variable named i of type int and assigns it an initial value of 1.
  • The test expression is i <= 10. As a result, the loop continues to execute as long as i is less than or equal to 10.
  • The count expression is i++. As a result, each time the loop executes, the variable i is incremented.
  • The body of the loop is the single statement System.out.println(i). As a result, each time the loop executes, the value of the i variable is printed to the console.

Technical stuff I made up the terms I use to describe the three expressions in a for loop. Officially, Java calls them the ForInit expression, the expression, and the ForUpdate expression. Don’t you think my terms are more descriptive?

Scoping out the counter variable

If you declare the counter variable in the initialization statement, the scope of the counter variable is limited to the for statement itself. Thus, you can use the variable in the other expressions that appear within the parentheses and in the body of the loop, but you can’t use it outside the loop. This example code causes a compiler error:

public class CountToTenError

{

public static void main(String[] args)

{

for (int i = 1; i <=10; i++)

System.out.println(i);

System.out.println("The final value of i is " + i);

}

}

That’s because the last statement in the main method refers to the variable i, which has gone out of scope because it was declared within the for loop.

If you want to access the counter variable outside of the loop, you should declare the counter variable prior to the for statement, as in this example:

public class CountToTenErrorFixed

{

public static void main(String[] args)

{

int i;

for (i = 1; i <=10; i++)

System.out.println(i);

System.out.println("The final value of i is " + i);

}

}

Note that because the i variable is declared before the for statement, the initialization expression doesn't name the variable’s data type. When you run this program, the following appears in the console window:

1

2

3

4

5

6

7

8

9

10

The final value of i is 11

Counting even numbers

Earlier in this chapter, you saw a program that counts even numbers up to 20. You can do that with a for loop too. All you have to do is adjust the count expression. Here’s a version of the CountEven program that uses a for loop:

public class ForEvenCounter

{

public static void main(String[] args)

{

for (int number = 2; number <= 20; number += 2)

System.out.print(number + " ");

System.out.println();

}

}

Run this program, and sure enough, the console window displays the following:

2 4 6 8 10 12 14 16 18 20

Counting backward

No rule says for loops can only count forward. To count backward, you simply have to adjust the three for loop expressions. As usual, the initialization expression specifies the starting value for the counter variable. The test expression uses a greater-than test instead of a less-than test, and the count expression subtracts from the counter variable rather than adding to it.

For example:

public class CountDown

{

public static void main(String[] args)

{

for (int count = 10; count >= 1; count--)

System.out.println(count);

}

}

Run this program, and you see this result in the console window:

10

9

8

7

6

5

4

3

2

1

Tip If you grew up in the 1960s watching NASA launches religiously, as I did, you’ll appreciate this variation of the countdown program:

public class LaunchControl

{

public static void main(String[] args)

{

System.out.print ("We are go for launch in T minus ");

for (int count = 10; count >= 0; count--)

{

if (count == 8)

System.out.println("Ignition sequence start!");

else

System.out.println(count + "…");

}

System.out.println("All engines running!");

System.out.println("Liftoff! We have a liftoff!");

}

}

When you run it, here’s the output that’s displayed:

We are go for launch in T minus 10…

9…

Ignition sequence start!

7…

6…

5…

4…

3…

2…

1…

0…

All engines running!

Liftoff! We have a liftoff!

Can’t you just hear the voice of Paul Haney, the famous “Voice of Mission Control” for NASA in the 1960s? If you can’t, you’re not nearly as nerdy (or as old) as I am.

Using for loops without bodies

Some programmers get a kick out of writing code that is as terse as possible. I think Seinfeld did an episode about that. Jerry had a girlfriend who was a “terse-coder,” and he had to dump her because he couldn’t understand her code.

Anyway, terse-coders sometimes like to play with for statements in an effort to do away with the body of a for loop altogether. To do that, they take advantage of the fact that you can code any expression you want in the count expression part of a for statement, including method calls. Here’s a program that prints the numbers 1 to 10 on the console, using a for statement that has no body:

public class TerseCoder

{

public static void main(String[] args)

{

for (int i = 1; i <=10; System.out.println(i++));

}

}

Here the count expression is a call to System.out.println. The parameter to the println method cleverly uses the increment operator, so the variable is both printed and incremented in the same expression.

Warning Stay away from terse-coders! Seinfeld was right to dump her.

Ganging up your expressions

An obscure aspect of for loops is the fact that the initialization and count expressions can actually be a list of expressions separated by commas. This can be useful if you need to keep track of two counter variables at the same time. Here’s a program that counts from 1 to 10 and 10 to 1 at the same time, using two counter variables:

public class CountBothWays

{

public static void main(String[] args)

{

int a, b;

for (a = 1, b = 10; a <= 10; a++, b--)

System.out.println(a + " " + b);

}

}

If you run this program, here’s what you see in the console window:

1 10

2 9

3 8

4 7

5 6

6 5

7 4

8 3

9 2

10 1

Keep in mind these rules when you use more than one expression for the initialization and counter expressions:

  • In the initialization expression, you can’t declare variables if you use more than one expression. That’s why I declared the a and b variables before the for statement in the CountBothWays example.
  • The expressions in an expression list can be assignment statements, increment or decrement statements (such as a++), method calls, or object creation statements that use the new keyword to create an object from a class. Other types of statements, such as if statements or loops, are not allowed.
  • You can’t list more than one expression in the test expression. You can use compound conditions created with boolean operators, however, so you don’t need to use an expression list. Alternatively, you could craft a method that returns a boolean value and call that method as your test expression.

Technical stuff Here, just to prove that I can do it, is a version of the LaunchController program that uses a bodiless for loop:

public class ExpressionGanging

{

public static void main(String[] args)

{

System.out.print ("We are go for launch in T minus ");

for (int count = 10; count >= 0;

System.out.println((count == 8) ?

"Ignition sequence start!" :

count + "…"),

count-- );

System.out.println("All engines running!");

System.out.println("Liftoff! We have a liftoff!");

}

}

This program actually looks more complicated than it is. The count expression is a list of two expressions. First is a call to System.out.println that uses the ternary ?: operator to determine what to print. The ?: operator first evaluates the count variable to see if it equals 8. If so, the string "Ignition sequence start!" is sent to the println method. Otherwise, count + "…" is sent. The second expression simply increments the count variable.

I think you’ll agree that coding the for statement like this example is way out of line. It’s better to keep the expressions simple and do the real work in the loop’s body.

Omitting expressions

Yet another oddity about for loops is that all three of the expressions are optional. If you omit one or more of the expressions, you just code the semicolon as a placeholder so that the compiler knows what’s going on.

Omitting the test expression or the iteration expression is not common, but omitting the initialization expression is common. The variable you’re incrementing in the for loop may already be declared and initialized before you get to the loop, for example. In that case, you can omit the initialization expression, like this:

Scanner sc = new Scanner(System.in);

System.out.print("Where should I start? ");

int a = sc.nextInt();

for ( ; a >= 0; a--)

System.out.println(a);

This for loop simply counts down from whatever number the user enters to zero.

Warning If you omit the test expression, you’d better throw a break statement in the loop somewhere (as described earlier in the chapter in the “Breaking Out of a Loop” section). Otherwise you’ll find yourself in an infinite loop.

You can omit all three of the expressions if you want to, as in this example:

for(;;)

System.out.println("Oops");

This program also results in an infinite loop. There’s little reason to do this, however, because while(true) has the same effect and is more obvious.

Breaking and continuing your for loops

You can use a break in a for loop just as you can in a while or do-while loop. Here I revisit the Dodecaphobia program from earlier in the chapter, this time with a for loop:

public class ForDodecaphobia

{

public static void main(String[] args)

{

for (int number = 2; number <=20; number += 2)

{

if (number == 12)

break;

System.out.print(number + " ");

}

System.out.println();

}

}

As before, this version counts by 2 until it gets to 20. When it hits 12, however, it panics and aborts the loop, so it never actually gets to 14, 16, 18, or 20. The console output looks like this:

2 4 6 8 10

And here’s a version that uses a continue statement to skip 12 rather than abort the loop:

public class ForDodecaphobia2

{

public static void main(String[] args)

{

for (int number = 2; number <=20; number += 2)

{

if (number == 12)

continue;

System.out.print(number + " ");

}

System.out.println();

}

}

The console output from this version looks like this:

2 4 6 8 10 14 16 18 20

Nesting Your Loops

Loops can contain loops. The technical term for this is loop-de-loop. Just kidding. Actually, the technical term is nested loop, which is simply a loop that is completely contained inside another loop. The loop that’s inside is called the inner loop, and the loop that’s outside is called the outer loop.

A simple nested for loop

To demonstrate the basics of nesting, here’s a simple little program that uses a pair of nested for loops:

public class NestedLoop

{

public static void main(String[] args)

{

for(int x = 1; x < 10; x++)

{

for (int y = 1; y < 10; y++)

System.out.print(x + "-" + y + " ");

System.out.println();

}

}

}

This program consists of two for loops. The outer loop uses x as its counter variable, and the inner loop uses y. For each execution of the outer loop, the inner loop executes 10 times and prints a line that shows the value of x and y for each pass through the inner loop. When the inner loop finishes, a call to System.out.println with no parameters forces a line break, thus starting a new line. Then the outer loop cycles so that the next line is printed.

When you run this program, the console displays this text:

1-1 1-2 1-3 1-4 1-5 1-6 1-7 1-8 1-9

2-1 2-2 2-3 2-4 2-5 2-6 2-7 2-8 2-9

3-1 3-2 3-3 3-4 3-5 3-6 3-7 3-8 3-9

4-1 4-2 4-3 4-4 4-5 4-6 4-7 4-8 4-9

5-1 5-2 5-3 5-4 5-5 5-6 5-7 5-8 5-9

6-1 6-2 6-3 6-4 6-5 6-6 6-7 6-8 6-9

7-1 7-2 7-3 7-4 7-5 7-6 7-7 7-8 7-9

8-1 8-2 8-3 8-4 8-5 8-6 8-7 8-8 8-9

9-1 9-2 9-3 9-4 9-5 9-6 9-7 9-8 9-9

A guessing game

Listing 5-1 shows a more complicated but realistic example of nesting. This program implements a simple guessing game in which the computer picks a number between 1 and 10, and you have to guess the number. After you guess, the computer tells you whether you’re right or wrong and then asks whether you want to play again. If you enter Y or y, the game starts over.

The nesting comes into play because the entire game is written in a while loop that repeats as long as you say you want to play another game. Then — within that loop — each time the game asks for input from the user, it uses a do-while loop to validate the user’s entry. Thus, when the game asks the user to guess a number between 1 and 10, it keeps looping until the number entered by the user is in that range. And when the game asks the user whether he or she wants to play again, it loops until the user enters Y, y, N, or n.

Here’s a sample of the console output displayed by this program:

Let's play a guessing game!

I'm thinking of a number between 1 and 10.

What do you think it is? 5

You're wrong! The number was 8

Play again? (Y or N)y

I'm thinking of a number between 1 and 10.

What do you think it is? 32

I said, between 1 and 10. Try again: 5

You're wrong! The number was 6

Play again? (Y or N)maybe

Play again? (Y or N)ok

Play again? (Y or N)y

I'm thinking of a number between 1 and 10.

What do you think it is? 5

You're right!

Play again? (Y or N)n

Thank you for playing.

LISTING 5-1 The Guessing Game

import java.util.Scanner;

public class GuessingGame

{

static Scanner sc = new Scanner(System.in);

public static void main(String[] args)

{

boolean keepPlaying = true;→7

System.out.println("Let's play a guessing game!");

while (keepPlaying)→9

{

boolean validInput;→11

int number, guess;

String answer;

// Pick a random number

number = (int)(Math.random() * 10) + 1;→16

// Get the guess

System.out.println("\nI'm thinking of a number "

+ "between 1 and 10.");

System.out.print("What do you think it is? ");

do→22

{

guess = sc.nextInt();

validInput = true;

if ( (guess < 1) || (guess > 10) )

{

System.out.print

("I said, between 1 and 10. "

+ "Try again: ");

validInput = false;

}

} while (!validInput);→33

// Check the guess

if (guess == number)→36

System.out.println("You're right!");

else

System.out.println("You're wrong! " +

"The number was " + number);

// Play again?

do→43

{

System.out.print("\nPlay again? (Y or N)");

answer = sc.next();

validInput = true;

if (answer.equalsIgnoreCase("Y"));

else if (answer.equalsIgnoreCase("N"))

keepPlaying = false;

else

validInput = false;

} while (!validInput);→53

}→54

System.out.println("\nThank you for playing!");→55

}

}

The following paragraphs describe some of the key lines in this program:

  • →7 Defines a boolean variable named keepPlaying that’s initialized to true and changed to false when the user indicates that he or she has had enough of this silly game.
  • →9–54 Begins the main while loop for the game. The loop continues as long as keepPlaying is true. This loop ends on line 54.
  • →11 Defines a boolean variable named validInput that’s used to indicate whether the user’s input is valid. The same variable is used for both the entry of the user’s guess and the Y or N string at the end of each round.
  • →16 Picks a random number between 1 and 10. For more information on random numbers, refer to Book 2, Chapter 3.
  • →22–33 Begins the do-while loop that gets a valid guess from the user. This loop ends on line 33. The statements in this loop read the user’s guess from the console and then test to make sure it is between 1 and 10. If so, validInput is set to true. Otherwise, validInput is set to false, an error message is displayed, and the loop repeats so that the user is forced to guess again. The loop continues as long as validInput is false.
  • →36 The if statement compares the user’s guess with the computer’s number. A message is displayed to indicate whether the user guessed right or wrong.
  • →43–53 Begins the do-while loop that asks whether the user wants to play again. This loop ends on line 53. The statements in this loop read a string from the user. If the user enters Y or y, validInput is set to true. (keepPlaying is already true, so it is left alone.) If the user enters N or n, validInput is set to true, and keepPlaying is set to false. And if the user enters anything else, validInput is set to false. The loop continues as long as validInput is false.
  • →55 This statement is executed after the program’s main while loop finishes; it thanks the user for playing the game.