Chapter 15

The Old Runaround

In This Chapter

arrow Creating repetitive actions

arrow Creating loops within loops

arrow Insisting on a valid response from the user

arrow Looping through enumerated values

I remember it distinctly — the sense of dread I would feel on the way to Aunt Edna’s house. She was a kind old woman, and her intentions were good. But visits to her house were always so agonizing.

First, we’d sit in the living room and talk about other relatives. That was okay, as long as I understood what people were talking about. Sometimes, the gossip would be about adult topics, and I’d become very bored.

After all the family chatter, my father would help Aunt Edna with her bills. That was fun to watch because Aunt Edna had a genetically inherited family ailment. Like me and many of my ancestors, Aunt Edna couldn’t keep track of paperwork to save her life. It was as if the paper had allergens that made Aunt Edna’s skin crawl. After ten minutes of useful bill paying, my father would find a mistake, an improper tally, or something else in the ledger that needed attention. He’d ask Aunt Edna about it, and she’d shrug her shoulders. He’d become agitated trying to track down the problem, while Aunt Edna rolled her eyes and smiled with ignorant satisfaction. It was great entertainment.

Then, when the bill paying was done, we’d sit down to eat dinner. That’s when I would remember why I dreaded these visits. Dinner was unbearable. Aunt Edna believed in Fletcherism — a health movement whose followers chewed each mouthful of food 100 times. The more devoted followers used a chart, with a different number for the mastication of each kind of food. The minimal number of chews for any food was 32 — one chomp for each tooth in your mouth. People who did this said they were “Fletcherizing.”

Mom and Dad thought the whole Fletcher business was silly, but they respected Aunt Edna and felt that people her age should be humored, not defied. As for me, I thought I’d explode from the monotony. Each meal lasted forever. Each mouthful was an ordeal. I can still remember my mantra — the words I’d say to myself without meaning to do so:

I’ve chewed 0 times so far.

Have I chewed 100 times yet? If not, then

    Chew!

    Add 1 to the number of times that I’ve chewed.

    Go back to “Have I chewed”

        to find out if I’m done yet.

Repeating Statements a Certain Number Times (Java for Statements)

Life is filled with examples of counting loops. And computer programming mirrors life (. . . or is it the other way around?). When you tell a computer what to do, you’re often telling the computer to print three lines, process ten accounts, dial a million phone numbers, or whatever. Because counting loops are so common in programming, the people who create programming languages have developed statements just for loops of this kind. In Java, the statement that repeats something a certain number of times is called a for statement. An example of a for statement is in Listing 15-1.

Listing 15-1: Horace Fletcher’s Revenge

import static java.lang.System.out;

class AuntEdnaSettlesForTen {

    public static void main(String args[]) {

        for (int count = 0; count < 10; count++) {

            out.print(“I’ve chewed “);

            out.print(count);

            out.println(“ time(s).”);

        }

        out.println(“10 times! Hooray!”);

        out.println(“I can swallow!”);

    }

}

Figure 15-1 shows you what you get when you run the program of Listing 15-1:

check.png The for statement in Listing 15-1 starts by setting the count variable equal to 0.

check.png Then the for statement tests to make sure that count is less than 10 (which it certainly is).

check.png Then the for statement dives ahead and executes the printing statements between the curly braces. At this early stage of the game, the computer prints I’ve chewed 0 time(s).

check.png Then the for statement executes count++ — that last thing inside the for statement’s parentheses. This last action adds 1 to the value of count.

Figure 15-1: Chewing ten times.

9780470371749-fg1501.tif

This ends the first iteration of the for statement in Listing 15-1. Of course, this loop has more to it than just one iteration:

check.png With count now equal to 1, the for statement checks again to make sure that count is less than 10. (Yes, 1 is smaller than 10.)

check.png Because the test turns out okay, the for statement marches back into the curly braced statements and prints I’ve chewed 1 time(s) on the screen.

check.png Then the for statement executes that last count++ inside its parentheses. The statement adds 1 to the value of count, increasing the value of count to 2.

And so on. This whole thing keeps being repeated over and over again until, after ten iterations, the value of count finally reaches 10. When this happens, the check for count being less than 10 fails, and the loop’s execution ends. The computer jumps to whatever statement comes immediately after the for statement. In Listing 15-1, the computer prints 10 times! Hooray! I can swallow! The whole process is illustrated in Figure 15-2.

Figure 15-2: The action of the for loop in Listing 15-1.

9780470371749-fg1502.tif

The anatomy of a for statement

A typical for statement looks like this:

for (Initialization; Condition; Update) {

    Statements

}

After the word for, you put three things in parentheses: an Initialization, a Condition, and an Update.

Each of the three items in parentheses plays its own distinct role:

check.png Initialization: The initialization is executed once, when the run of your program first reaches the for statement.

check.png Condition: The condition is tested several times (at the start of each iteration).

check.png Update: The update is also evaluated several times (at the end of each iteration).

If it helps, think of the loop as if its text is shifted all around:

//This is NOT real code

int count = 0

for count < 0 {

    out.print(“I’ve chewed “);

    out.print(count);

    out.println(“ time(s).”);

    count++;

}

You can’t write a real for statement this way. (The compiler would throw code like this right into the garbage can.) Even so, this is the order in which the parts of the for statement are executed.

warning_bomb.eps The first line of a for statement (the word for followed by stuff in parentheses) isn’t a complete statement. So you almost never put a semicolon after the stuff in parentheses. If you make a mistake and type a semicolon,

// DON’T DO THIS:

for (int count = 0; count < 10; count++); {

you usually put the computer into an endless, do-nothing loop. The computer’s cursor just sits there and blinks until you forcibly stop the program’s run.

Initializing a for loop

Look at the first line of the for loop in Listing 15-1 and notice the declaration int count = 0. That’s something new. When you create a for loop, you can declare a variable (like count) as part of the loop initialization.

If you declare a variable in the initialization of a for loop, you can’t use that variable outside the loop. For example, in Listing 15-1, try putting out.println(count) after the end of the loop:

//This code does not compile.

for (int count = 0; count < 10; count++) {

    out.print(“I’ve chewed “);

    out.print(count);

    out.println(“ time(s).”);

}

out.print(count);   //The count variable doesn’t

                    //  exist here.

With this extra reference to the count variable, the compiler gives you an error message. You can see the message in Figure 15-3. If you’re not experienced with for statements, the message may surprise you. “Whadaya mean ‘count cannot be resolved to a variable’? There’s a count variable declaration just four lines above that statement.” Ah, yes. But the count variable is declared in the for loop’s initialization. Outside the for loop, that count variable doesn’t exist.

Figure 15-3: What count variable? I don’t see a count variable.

9780470371749-fg1503.tif

To use a variable outside of a for statement, you have to declare that variable outside the for statement. You can even do this with the for statement’s counting variable. Listing 15-2 has an example.

Listing 15-2: Using a Variable Declared Outside of a for Loop

import static java.lang.System.out;

class AuntEdnaDoesItAgain {

    public static void main(String args[]) {

        int count;

        for (count = 0; count < 10; count++) {

            out.print(“I’ve chewed “);

            out.print(count);

            out.println(“ time(s).”);

        }

        out.print(count);

        out.println(“ times! Hooray!”);

        out.println(“I can swallow!”);

    }

}

A run of the code in Listing 15-2 looks exactly like the run for Listing 15-1. The run is pictured in Figure 15-1. Unlike its predecessor, Listing 15-2 enjoys the luxury of using the count variable to display the number 10. It can do this because in Listing 15-2, the count variable belongs to the entire main method, and not to the for loop alone.

Notice the words for (count = 0 in Listing 15-2. Because count is declared before the for statement, you don’t declare count again in the for statement’s initialization. I tried declaring count twice, as in the following code:

//This does NOT work:

int count;

for (int count = 0; count < 10; count++) {

    ...etc.

and Eclipse told me to clean up my act:

Duplicate local variable count                 ^

Using Nested for Loops

Because you’re reading Beginning Programming with Java For Dummies, 3rd Edition, I assume that you manage a big hotel. The next chapter tells you everything you need to know about hotel management. But before you begin reading that chapter, you can get a little preview in this section.

I happen to know that your hotel has 9 floors, and each floor of your hotel has 20 rooms. On this sunny afternoon, someone hands you a flash drive containing a file full of numbers. You copy this hotelData file to your hard drive and then display the file in Eclipse’s editor. You see the stuff shown in Figure 15-4.

Figure 15-4: A file containing hotel occupancy data.

9780470371749-fg1504.tif

This file gives the number of guests in each room. For example, at the start of the file, you see 2 1 2. This means that, on the first floor, Room 1 has 2 guests, Room 2 has 1 guest, and Room 3 has 2 guests. After reading 20 of these numbers, you see 0 2 2. So, on the second floor, Room 1 has 0 guests, Room 2 has 2 guests, and Room 3 has 2 guests. The story continues until the last number in the file. According to that number, Room 20 on the ninth floor has 4 guests.

You’d like a more orderly display of these numbers — a display of the kind in Figure 15-5. So you whip out your keyboard to write a quick Java program.

Figure 15-5: A readable display of the data in Figure 15-4.

9780470371749-fg1505.tif

As in some other examples, you decide which statements go where by asking yourself how many times each statement should be executed. For starters, the display in Figure 15-5 has 9 lines, and each line has 20 numbers:

for (each of 9 floors)

    for (each of 20 rooms on a floor)

        get a number from the file and

        display the number on the screen.

So your program has a for loop within a for loop — a pair of nested for loops.

Next, you notice how each line begins in Figure 15-5. Each line contains the word Floor, followed by the floor number. Because this Floor display occurs only 9 times in Figure 15-5, the statements to print this display belong in the for each of 9 floors loop (and not in the for each of 20 rooms loop). The statements should be before the for each of 20 rooms loop because this Floor display comes once before each line’s 20-number display:

for (each of 9 floors)

    display “Floor” and the floor number,

    for (each of 20 rooms on a floor)

        get a number from the file and

        display the number on the screen.

You’re almost ready to write the code. But there’s one detail that’s easy to forget. (Well, it’s a detail that I always forget.) After displaying 20 numbers, the program advances to a new line. This new-line action happens only 9 times during the run of the program, and it always happens after the program displays 20 numbers:

for (each of 9 floors)

    display “Floor” and the floor number,

    for (each of 20 rooms on a floor)

        get a number from the file and

        display the number on the screen,

    Go to the next line.

That does it. That’s all you need. The code to create the display of Figure 15-5 is in Listing 15-3.

Listing 15-3: Hey! Is This a For-by-For?

import java.util.Scanner;

import java.io.File;

import java.io.FileNotFoundException;

import static java.lang.System.out;

class DisplayHotelData {

   public static void main(String args[])

      throws FileNotFoundException {

      Scanner diskScanner =

          new Scanner(new File(“hotelData”));

      for (int floor = 1; floor <= 9; floor++) {

         out.print(“Floor “);

         out.print(floor);

         out.print(“:  “);

         for (int roomNum = 1; roomNum <= 20; roomNum++) {

            out.print(diskScanner.nextInt());

            out.print(‘ ‘);

         }

         out.println();

      }

   }

}

The code in Listing 15-3 has the variable floor going from 1 to 9 and has the variable roomNum going from 1 to 20. Because the roomNum loop is inside the floor loop, the writing of 20 numbers happens 9 times. That’s good. It’s exactly what I want.

Repeating Until You Get What You Need (Java do Statements)

I introduce Java’s while loop in Chapter 12. When you create a while loop, you write the loop’s condition first. After the condition, you write the code that gets repeatedly executed.

while (Condition) {

    Code that gets repeatedly executed

}

This way of writing a while statement is no accident. The look of the statement emphasizes an important point — that the computer always checks the condition before executing any of the repeated code.

If the loop’s condition is never true, then the stuff inside the loop is never executed — not even once. In fact, you can easily cook up a while loop whose statements are never executed (although I can’t think of a reason why you would ever want to do it):

//This code doesn’t print anything:

int twoPlusTwo = 2 + 2;

while (twoPlusTwo == 5) {

    System.out.println(“Are you kidding?”);

    System.out.println(“2+2 doesn’t equal 5.”);

    System.out.print  (“Everyone knows that”);

    System.out.println(“ 2+2 equals 3.”);

}

In spite of this silly twoPlusTwo example, the while statement turns out to be the most useful of Java’s looping constructs. In particular, the while loop is good for situations in which you must look before you leap. For example: “While money is in my account, write a mortgage check every month.” When you first encounter this statement, if your account has a zero balance, you don’t want to write a mortgage check — not even one check.

But at times (not many), you want to leap before you look. In a situation when you’re asking the user for a response, maybe the user’s response makes sense, but maybe it doesn’t. Maybe the user’s finger slipped, or perhaps the user didn’t understand the question. In many situations, it’s important to correctly interpret the user’s response. If the user’s response doesn’t make sense, you must ask again.

Getting a trustworthy response

Consider a program that deletes several files. Before deleting anything, the program asks for confirmation from the user. If the user types Y, then delete; if the user types N, then don’t delete. Of course, deleting files is serious stuff. Mistaking a bad keystroke for a “yes” answer can delete the company’s records. (And mistaking a bad keystroke for a “no” answer can preserve the company’s incriminating evidence.) So if there’s any doubt about the user’s response, the program should ask the user to respond again.

Pause a moment to think about the flow of actions — what should and shouldn’t happen when the computer executes the loop. A loop of this kind doesn’t need to check anything before getting the user’s first response. Indeed, before the user gives the first response, the loop has nothing to check. The loop shouldn’t start with “as long as the user’s response is invalid, get another response from the user.” Instead, the loop should just leap ahead, get a response from the user and then check the response to see whether it made sense. The code to do all this is in Listing 15-4.

Listing 15-4: Repeat Before You Delete

/*

* DISCLAIMER: Neither the author nor Wiley Publishing,

* Inc., nor anyone else even remotely connected with the

* creation of this book, assumes any responsibility

* for any damage of any kind due to the use of this code,

* or the use of any work derived from this code,

* including any work created partially or in full by

* the reader.

*

* Sign here:_______________________________

*/

import java.util.Scanner;

import java.io.IOException;

class IHopeYouKnowWhatYoureDoing {

  public static void main(String args[])

      throws IOException {

    Scanner myScanner = new Scanner(System.in);

    char reply;

    do {

      System.out.print(“Reply with Y or N...”);

      System.out.print(“  Delete all .keep files? “);

      reply =

        myScanner.findWithinHorizon(“.”, 0).charAt(0);

    } while (reply != ‘Y’ && reply != ‘N’);

    if (reply == ‘Y’) {

      String opSystem = System.getProperty(“os.name”);

      

      if (opSystem.contains(“Windows”)) {

        

        Runtime.getRuntime().exec(“cmd /c del *.keep”);

        

      } else if (opSystem.contains(“Mac”)) {

        

        Runtime.getRuntime().exec(

            new String[] { “/bin/sh”, “-c”,

                “rm -f *.keep” });

      }

    }

  }

}

The exec.(“cmd ... ) code in Listing 15-4 works on all the industrial-strength versions of Microsoft Windows, including Windows 7 and Windows XP. To get the same effect in Windows 95, 98, or Me, you have to change the last line of code as follows:

Runtime.getRuntime().exec(“start command /c del *.keep”);

One way or another, the call to Runtime.getRuntime...yada-yada deletes all files whose names end with .keep.

technicalstuff.eps Java has no easy way to refer to all the files whose names end in .keep. So in Listing 15-4, I call Runtime.getRuntime().exec to execute an operating system command. This Runtime business can be tricky to use, so don’t fret over the details. Just take my word for it — the calls to Runtime.getRuntime().exec in Listing 15-4 delete files.

tip.eps To delete only one file, use the Java API’s delete method. For example, to delete your myData.txt file, execute new File(“myData.txt”).delete(). And don’t let the new File part fool you. The code new File(“myData.txt”).delete() gets rid of a file that’s already on your computer’s hard drive.

The Runtime.getRuntime().exec method is one of those “you need a throws clause” methods that I introduce in Chapter 13. Unlike the methods in Chapter 13, the exec method forces you to throw an IOException. And with a throws IOException clause comes an import java.io.IOException declaration.

At this point, you may be wondering how I know that the exec method needs a throws IOException clause. How many other Java API methods require throws clauses, and how do you find out about all these things? The answer is, you can find this information in Java’s API documentation. For details, see this book’s website (allmycode.com/BeginProg3).

Deleting files

A run of the Listing 15-4 program is shown in Figure 15-6. Before deleting a bunch of files, the program asks the user if it’s okay to do the deletion. If the user gives one of the two expected answers (Y or N), then the program proceeds according to the user’s wishes. But if the user enters any other letter (or any digit, punctuation symbol, or whatever), then the program asks the user for another response.

Figure 15-6: No! Don’t do it!

9780470371749-fg1506.tif

In Figure 15-6, the user hems and haws for a while, first with the letter U, then the digit 8, and then with lowercase letters. Finally, the user enters Y, and the program deletes the .keep files. If you compare the files on your hard drive (before and after the run of the program), you’ll see that the program trashes files with names ending in .keep.

If you use Eclipse, here’s how you can tell that files are being deleted:

1. Create a Java project containing the code in Listing 15-4.

If you followed the steps in Chapter 2 for importing this book’s examples, you can skip this create-a-project step and use the existing 15-04 project.

2. In the Package Explorer, select the project.

remember.eps Don’t select any of the project’s subfolders. (For example, don’t select the project’s src folder.) Instead, select the project’s root. For more info about a project’s root, see Chapter 13.

3. In Eclipse’s main menu, choose FileNewFile.

Eclipse’s New File dialog box appears.

tip.eps In the New File dialog box, make sure that the name of your project’s root folder is in the box’s Enter Or Select The Parent Folder field. For example, if you followed the steps in Chapter 2 for importing this book’s examples, make sure that 15-04 (and no other text) appears in the Enter Or Select The Parent Folder field.

4. In the dialog box’s File Name field, type the name of your new data file.

Type irreplaceableInfo.keep or something like that.

5. Click Finish.

The file’s name appears in Eclipse’s Package Explorer. For this experiment, you don’t have to add any text to the file. The file exists only to be deleted.

6. Repeat Steps 2 through 5 a few more times.

Create files named somethingOrOther.keep and files that don’t have .keep in their names.

7. Run the program.

When the program runs, type Y to delete the .keep files. (The program deletes .keep files only in this project’s root directory. The program’s run has no effect on any files outside of the root directory.)

After running the program, you want to check to make sure that the program deleted the .keep files.

8. In the Package Explorer, select the project’s root (again, for good measure).

9. In Eclipse’s main menu, choose FileRefresh.

Eclipse takes another look at the project directory and lists the directory’s files in the Package Explorer’s tree. Assuming that the program did its job correctly, files with names ending in .keep no longer appear in the tree.

Using Java’s do statement

To write the program in Listing 15-4, you need a loop — a loop that repeatedly asks the user whether the .keep files should be deleted. The loop continues to ask until the user gives a meaningful response. The loop tests its condition at the end of each iteration, after each of the user’s responses.

That’s why the program in Listing 15-4 has a do loop (also known as a do . . . while loop). With a do loop, the program jumps right in, executes some statements, and then checks a condition. If the condition is true, then the program goes back to the top of the loop for another go-around. If the condition is false, then the computer leaves the loop (and jumps to whatever code comes immediately after the loop). The action of the loop in Listing 15-4 is illustrated in Figure 15-7.

A closer look at the do statement

The format of a do loop is

do {

   Statements

} while (Condition)

Figure 15-7: Here we go loop, do loop.

9780470371749-fg1507.tif

Writing the Condition at the end of the loop reminds me that the computer executes the Statement inside the loop first. After the computer executes the Statement, the computer goes on to check the Condition. If the Condition is true, the computer goes back for another iteration of the Statement.

With a do loop, the computer always executes the statements inside the loop at least once:

//This code prints something:

int twoPlusTwo = 2 + 2;

do {

    System.out.println(“Are you kidding?”);

    System.out.println(“2+2 doesn’t equal 5.”);

    System.out.print  (“Everyone knows that”);

    System.out.println(“ 2+2 equals 3.”);

} while (twoPlusTwo == 5);

This code displays Are you kidding? 2+2 doesn’t equal 5 . . . and so on and then tests the condition twoPlusTwo == 5. Because twoPlusTwo == 5 is false, the computer doesn’t go back for another iteration. Instead, the computer jumps to whatever code comes immediately after the loop.

Repeating with Predetermined Values (Java’s Enhanced for Statement)

Most people say that they “never win anything.” Other people win raffles, drawings, and contests, but they don’t win things. Well, I have news for these people — other people don’t win things, either. Nobody wins things. That’s how the laws of probability work. Your chance of winning one of the popular U.S. lottery jackpots is roughly 1 in 135,000,000. If you sell your quarter-million dollar house and use all the money to buy lottery tickets, your chance of winning is still only 1 in 540. If you play every day of the month (selling a house each day), your chance of winning the jackpot is still less than 1 in 15.

Of course, nothing in the previous paragraph applies to me. I don’t buy lottery tickets, but I often win things. My winning streak started a few years ago. I won some expensive Java software at the end of an online seminar. Later that month, I won a microchip–enabled pinky ring (a memento from a 1998 Java conference). The following year I won a wireless PDA. Just last week, I won a fancy business-class printer.

I never spend money to enter any contests. All these winnings are freebies. When the national computer science educators’ conference met in Reno, Nevada, my colleagues convinced me to try the slot machines. I lost $23, and then I won back $18. At that point, I stopped playing. I wanted to quit while I was only $5 behind.

That’s why my writing a Java program about slot machines is such a strange occurrence. A typical slot machine has three reels, with each reel having about 20 symbols. But to illustrate this section’s ideas, I don’t need 20 symbols. Instead I use four symbols — a cherry, a lemon, a kumquat, and a rutabaga.

Creating an enhanced for loop

When you play my simplified slot machine, you can spin any one of over 60 combinations — cherry+cherry+kumquat, rutabaga+rutabaga+rutabaga, or whatever. This chapter’s goal is to list all possible combinations. But first, I show you another kind of loop. Listing 15-5 defines an enum type for a slot machine’s symbols and displays a list of the symbols. (For an introduction to enum types, see Chapter 10.)

Listing 15-5: Slot Machine Symbols

import static java.lang.System.out;

class ListSymbols {

  

  enum Symbol {

    cherry, lemon, kumquat, rutabaga

  }

  public static void main(String args[]) {

    for (Symbol leftReel : Symbol.values()) {

      out.println(leftReel);

    }

  }

}

Listing 15-5 uses Java’s enhanced for loop. The word “enhanced” means “enhanced compared with the loops in earlier versions of Java.” The enhanced for loop was introduced in Java version 5.0. If you run Java version 1.4.2 (or something like that), then you can’t use an enhanced for loop.

Here’s the format of the enhanced for loop:

for (TypeName variableName : RangeOfValues) {

    Statements

}

Here’s how the loop in Listing 15-5 follows the format:

check.png In Listing 15-5, the word Symbol is the name of a type.

The int type describes values like -1, 0, 1, and 2. The boolean type describes the values true and false. And (because of the code in Listing 15-5) the Symbol type describes the values cherry, lemon, kumquat, and rutabaga. For more information on enum types like Symbol, see Chapter 10.

check.png In Listing 15-5, the word leftReel is the name of a variable.

The loop in Listing 15-1 defines count to be an int variable. Similarly, the loop in Listing 15-5 defines leftReel to be a Symbol variable. So in theory, the variable leftReel can take on any of the four Symbol values.

By the way, I call this variable leftReel because the code lists all the symbols that can appear on the leftmost of the slot machine’s three reels. Because all three of the slot machine’s reels have the same symbols, I may also have named this variable middleReel or rightReel. But on second thought, I’ll save the names middleReel and rightReel for a later example.

check.png In Listing 15-5, the expression Symbol.values() stands for the four values in Listing 15-5.

To quote myself in the previous Bullet1, “in theory, the variable leftReel can take on any of the four Symbol values.” Well, the RangeOfValues part of the for statement turns theory into practice. This third item inside the parentheses says, “Have as many loop iterations as there are Symbol values and have the leftReel variable take on a different Symbol value during each of the loop’s iterations.”

So the loop in Listing 15-5 undergoes four iterations — an iteration in which leftReel has value cherry, another iteration in which leftReel has value lemon, a third iteration in which leftReel has value kumquat, and a fourth iteration in which leftReel has value rutabaga. During each iteration, the program prints the leftReel variable’s value. The result is in Figure 15-8.

Figure 15-8: The output of the code in Listing 15-5.

9780470371749-fg1508.tif

In general, a someEnumTypeName.values() expression stands for the set of values that a particular enum type’s variable can have. For example, in Listing 10-7 you may use the expression WhoWins.values() to refer to the home, visitor, and neither values.

tip.eps The difference between a type’s name (like Symbol) and the type’s values (as in Symbol.values()) is really subtle. Fortunately, you don’t have to worry about the difference. As a beginning programmer, you can just use the .values() suffix in an enhanced loop’s RangeOfValues part.

Nesting the enhanced for loops

Listing 15-5 solves a simple problem in a very elegant way. So after reading about Listing 15-5, you ask about more complicated problems. “Can I list all possible three-reel combinations of the slot machine’s four symbols?” Yes, you can. Listing 15-6 shows you how to do it.

Listing 15-6: Listing the Combinations

import static java.lang.System.out;

class ListCombinations {

    enum Symbol {

        cherry, lemon, kumquat, rutabaga

    }

    public static void main(String args[]) {

        

        for (Symbol leftReel : Symbol.values()) {

            for (Symbol middleReel : Symbol.values()) {

                for (Symbol rightReel : Symbol.values()) {

                    out.print(leftReel);

                    out.print(“ “);

                    out.print(middleReel);

                    out.print(“ “);

                    out.println(rightReel);

                }

            }

        }

    }

}

When you run the program in Listing 15-6, you get 64 lines of output. Some of those lines are shown in Figure 15-9.

Figure 15-9: The first several lines of output from the code in Listing 15-6.

9780470371749-fg1509.tif

Like the code in Listing 15-3, the program in Listing 15-6 contains a loop within a loop. In fact, Listing 15-6 has a loop within a loop within a loop. Here’s the strategy in Listing 15-6:

for (each of the 4 symbols that

     can appear on the left reel),

    

    for (each of the 4 symbols that

         can appear on the middle reel),

        for (each of the 4 symbols that

             can appear on the right reel),

            display the three reels’ symbols.

So you start the outer loop with the cherry symbol. Then you march on to the middle loop and begin that loop with the cherry symbol. Then you proceed to the inner loop and pick the cherry (pun intended). At last, with each loop tuned to the cherry setting, you display the cherry cherry cherry combination (see Figure 15-10).

Figure 15-10: Entering loops for the first time in the program of Listing 15-6.

9780470371749-fg1510.tif

After displaying cherry cherry cherry, you continue with other values of the innermost loop. That is, you change the right reel’s value from cherry to lemon (see Figure 15-11). Now the three reels’ values are cherry cherry lemon, so you display these values on the screen. (See the second line in Figure 15-9.)

After exhausting the four values of the innermost (right reel) loop, you jump out of that innermost loop. But the jump puts you back to the top of the middle loop, where you change the value of middleReel from cherry to lemon. Now the values of leftReel and middleReel are cherry and lemon, respectively (see Figure 15-12).

Having changed to lemon on the middle loop, you go barreling again into the innermost loop. As if you’d never seen this inner loop before, you set the loop’s variable to cherry (see Figure 15-13).

After displaying the tasty cherry lemon cherry combination, you start changing the values of the innermost loop (see Figure 15-14).

Figure 15-11: Changing from cherry to lemon in the innermost loop.

9780470371749-fg1511.tif

Figure 15-12: Changing from cherry to lemon in the middle loop.

9780470371749-fg1512.tif

Figure 15-13: Restarting the inner loop.

9780470371749-fg1513.tif

Figure 15-14: Traveling a second time through the innermost loop.

9780470371749-fg1514.tif

The loop keeps going until it displays all 64 combinations. Whew!