Conditional Statements and Loops

So far, we have looked at storing values in our programs, which isn't the most exciting thing in the world. We will now look at how to manipulate the data using conditional statements and loops, the key ingredients to adding functionality to your games and spicing them up a little. Conditional statements are used to test values and execute different sections of code based on the result of the test. Loops are used to repeatedly execute a section of code, meaning you can use the same piece of code to perform a task multiple times, an essential implementation for many circumstances.

Conditional Statements

The ability to choose the path that your program takes, based on any given data, is the key to all functionality in programming. In order to create conditional statements, we must first learn about the relational operators that we will use with these statements. The following table is a list of the relational operators in Java.

Operator

Returns true if…

<

Left operand is less than the right operand

<=

Left operand is less than or equal to the right operand

==

Operands are equal

>=

Left operand is greater than or equal to right operand

>

Left operand is greater than right operand

!=

Operands are not equal

The equality operator (==) is different from the other relational operators in that it can be used to test the value of any similar data types, such as two integer expressions, two Boolean expressions, or even two objects.

Note 

When testing the value of two objects, we are not actually testing the data within the objects, but rather we are testing to see if both references refer to the same object. For example, remember back when we created two Person objects referenced by glennMurphy and andrewMulholland. A test between these two references using the equality operator (==) would simply return true if they both referred to the same object, like they do in Figure 2-3 but do not in Figure 2-2. We will look at comparing objects in more detail later in the book.

Simple if Statements

An if statement is rather self explanatory; it contains a Boolean expression and is followed by a line or block of code that it will execute if the Boolean expression returns true. The following code shows an example of an if statement with one line that it will execute if the Boolean expression returns true.

boolean televisionOn = true; if(televisionOn == true)     System.out.println("The TV is on"); 

This if statement will execute the one line of code that is immediately after it, provided the Boolean expression returns true. If there was another statement after the screen printing code, it would execute regardless of the result of the if statement. You must specify a code block for the if statement if you wish to have more than one line of code executed when its test is true.

if(televisionOn) {     System.out.println("The TV is on");     System.out.println("Turn it off and get back to work"); }

Notice that the Boolean expression merely specifies the boolean data type televisionOn on its own. This is another way to test if the Boolean value is true just without the "== true" part, which is a neater way to do it, although it is also less readable and less like pseudocode. You may implement this test in whatever way you feel the most comfortable. Similarly, you can also write the test like this:

//    not false is the same as equal to true if(televisionOn != false)     System.out.println("I said turn it off!");

Using the other relational operators is the same as using the == and != operators, although you cannot use them with Boolean expressions, as you cannot say that one Boolean value is, for example, greater than or equal to another. The other relational operators must be used with values with a comparable scope that exceeds just equality testing, such as numeric values.

int numberOfLions = 5; int numberOfWildebeest = 2;     if(numberOfLions > numberOfWildebeest)     numberOfWildebeest--;

Those poor wildebeest; they have a heck of a time! You can also have if statements nested inside one another quite simply.

if(numberOfLions > numberOfWildebeest) {     numberOfWildebeest--;     if(numberOfWildebeest == 1)     {         System.out.println("Oh no, there is only one left");     } }

This code will first check to see if there are a greater number of lions than wildebeests. If this is false, none of the nested code will be executed at all. If it is true, the value of numberOfWildebeest is decremented by one and followed by another if statement, which tests to see if there is only one wildebeest left. If this is true, some text is printed to the console screen stating this unfortunate fact.

The if with else Statements

Suppose we wanted to execute some code for either of the two possible results of a Boolean expression, true or false. We can perform this task easily using an else statement along with an if statement, basically giving the option of performing one task if a test is satisfied or else perform another task.

int personsAge = 21;     if(personsAge == 0)     System.out.println("Get me one of those cool door swings"); else     System.out.println("Old enough to start programming :)");

This code simply says that if the value of the personsAge variable is equal to 0, then perform the first task; otherwise, if this is false, perform the else task. The problem with this code, and in many other situations, is that we may need to check more than just two possible outcomes. In this code, we do not check to see if the value of personsAge is less than zero, presuming that any value other than zero is a positive integer. To test more than two different outcomes, we can use an else if statement. An initial else if statement needs to appear after an if statement and can then be followed by more else if statements, each performed in the same way as if statements with a Boolean test.

if(personsAge == 0)     System.out.println("Get me one of those cool door swings"); else if(personsAge > 0)     System.out.println("Old enough to start programming :)"); else    // must be negative     System.out.println("On the way, perhaps");

You can have as many else if branches after an initial if statement as you require but only one else statement at the end. Note the else statement is optional and not required after using else if statements.

Logical Operators

Logical operators are used to test Boolean expressions, similar to the bit-wise operators that we saw earlier. The following table shows the full list of logical operators:

Operator

Description

!

Logical NOT (also known as logical-negation)

&&

Logical AND

||

Logical OR

These operators can be used in conjunction with if statements to add more complex tests.

if(houseOnFire && haveNoWater)     System.out.println("Call the fire brigade"); 

These operators are not only used with conditional statements. They can be used wherever a Boolean expression is required, such as assigning a value to a Boolean variable or specifying a condition for terminating a loop, which we shall see later in this chapter.

The Conditional Operator

The conditional operator is used to return one of two possible values, based on a Boolean test, using the question mark (?) and colon (:) characters. As we mentioned earlier, this is a ternary operator involving three operand arguments. The following shows the conditional operator in action:

int number = 4; boolean isEven = (number % 2 == 0) ? true : false;

This statement will return the value of true to the variable isEven because the remainder of number, which is equal to 4, from 2 is 0. If the Boolean expression before the question mark is true, the first value after the question mark is returned; otherwise the value specified after the colon character is returned instead. You can return any value in this statement, not just Boolean values, and you can even return object references. We will look in detail at objects in the next two chapters.

The code that we have just seen would be performed similarly using if statements in the following way:

int number = 4; boolean isEven = false; if(number % 2 == 0)     isEven = true;

As you can see, the conditional statement can make your code neater, but an if statement makes it more obvious as to what the code does.

Switch Statements

If you have one value that you need to test for equality with a variety of different outcomes (known as cases), you can use a switch statement. A switch statement introduces us to four new keywords: switch, case, break, and default. A basic switch statement would look as follows:

int number = 1; switch(number) {     case 0:          System.out.println("Number is zero");         break;         case 1:          System.out.println("Number is one");         break;         default:         System.out.println("Number not found");         break; } 

The value that you are testing is enclosed in brackets after the switch keyword is entered. To specify a case statement, you must enter the case keyword followed by a constant value that it will be compared with, followed by a colon character (:). From here, any lines of code after the colon will be executed until a break statement is reached, which will then exit out of the whole switch statement block.

The default keyword is used to specify an area of code that can be executed if none of the case values match the switch statement test value. A default statement does not need to be included in a switch statement if it is not required, but it is useful for debugging.

Note 

You can only use values that are compatible with the data type int as the test and case values for switch statements; that is, the compiler will look for an int value. This means that you can test characters, as they are also numeric values. Finally, the case values must be constant values, as in hard-coded numbers (e.g., 17, 2288, etc.) or constant variable values.

The example DaysOfTheMonth.java uses a switch statement to assign the number of days to a variable based on the current month and year. Here is the code:

public class DaysOfTheMonth {     public static void main(String args[])     {              int month = 7;        int year = 2002;        int totalDays = 0;               switch(month)        {           case 1: case 3: case 5: case 7:               case 8: case 10: case 12:         //  31 days              totalDays = 31;              break;                                      case 4: case 6: case 9: case 11:  //  30 days              totalDays = 30;              break;                                      case 2:                           //  28 or 29 days                              if(year % 4 != 0)                 totalDays = 28;              else if(year % 400 == 0)                 totalDays = 29;              else if(year % 100 == 0)                 totalDays = 28;              else                 totalDays = 29;                        default:              System.out.println("Error, Invalid month index =                   " + month);              break;        }               if(totalDays != 0)        {           System.out.println("Month = " + month);           System.out.println("Year = " + year);           System.out.println("There are " + totalDays + "            days in this month");        }     } } 

When you run this program, you should get output similar to this console screen shot:

click to expand
Figure 2-8:

This example shows us a new feature of using case statements inside the switch statement, which is using many case statements that all lead to the same code segment. This example is ideal for showing this feature because there are multiple months that share the same amount of days. So, for example, the months of April, June, September, and November all contain 30 days and are represented in the DaysOfTheMonth.java example as month numbers 4, 6, 9, and 11, respectively. The case statements and values can therefore simply be written one after another, separated by a colon after each value. This is functionally the same as the following code.

if(month == 4 || month == 6 || month == 9 || month == 11)     totalDays = 30;

The case 2: statement represents the month of February. Here we need to test if it is a leap year or not in order to accurately assign the number of days for the month of February. The definition of a leap year can be worked out with four steps.

  1. If the year is not divisible by 4 (that is, the remainder of the year divided by 4 is not zero, e.g., 1997, 2002), then it is definitely not a leap year. Assign totalDays the value of 28. Otherwise go to step 2.

  2. If the year is divisible by 400 (that is, the remainder of the year divided by 400 is zero, e.g., 1600, 2000), then it is a leap year. Assign totalDays the value of 29. Otherwise go to step 3.

  3. If the year is divisible by 100 (that is, the remainder of the year divided by 100 is zero, e.g., 1900, 2100), then it is not a leap year. Assign totalDays the value of 28. Otherwise, go to step 4.

  4. It must be a leap year, so assign totalDays the value of 29.

The code for these four steps is simple; we can use the modulus operator (%) to find the remainder values and the if, else if, and else statements to test the values.

if(year % 4 != 0)     totalDays = 28;          // not leap year else if(year % 400 == 0)     totalDays = 29;          // leap year else if(year % 100 == 0)     totalDays = 28;          // not leap year else     totalDays = 29;          // leap year
Note 

It is a common mistake with switch statements to forget to add a break statement at the end of your case block. If this is omitted, the code will simply continue to execute the next line of code. For example, the following code will print all three words to the console window regardless of the fact that only the first case is true.

switch(1) {     case 1:         System.out.println("Forgot");     case 2:         System.out.println("the");     case 3:         System.out.println("breaks"); }

The first case statement will be executed because the switch test value is equal to 1 also, but then the other case statements will also be executed because there are no break statements to tell your program to exit from the switch block altogether. Sometimes, you may actually wish to execute the code from one case block and then continue to execute the code in the next case block also, although this can lead to unseen errors later on.

Loops

Loops are used to execute code repeatedly, meaning that you only need to enter code once and then execute it a specified number of times. In order for a loop to stop, at least one condition for termination should go with it; otherwise, the loop could be infinite, running forever (that is, until you find some way of crashing out of it, like pressing Ctrl+Alt+Del or buying a shotgun, but it won't come to that).

Let's say we want to write the value of all of the positive integers that are less than 10 to the console window, which is 0 to 9. A loop can be used to perform this task in just a few lines of code instead of manually coding ten System.out.println… statements, which would be too tedious a task for someone of your intelligence. The basic loops are the while loop, the do while loop, and the for loop.

Using the while Loop

A while loop is implemented in exactly the same way as an if statement. It must specify a Boolean expression test for itself and be followed by a line or block of code that it will execute if the Boolean expression test is true. The following example, WhileCounter.java, will perform the task of printing the numbers 0 to 9 to the console window using a while loop. Here is the code:

public class WhileCounter {     public static void main(String args[])     {        int counter = 0;        while(counter < 10)        {           System.out.println("Value = " + counter);           counter++;        }     } }

The screen output in a console window should be similar to the following:

click to expand
Figure 2-9:

Inside the code block of the while loop is a line of code to increment the value of the variable counter by 1, which eventually causes the loop to terminate. When the while loop begins, and every time the code block of the while loop completes its execution after that, there is a test to see if the condition counter < 10 is true. The while loop will continue to execute while the conditional statement test returns true and terminate when it returns false, which in this case is when the variable counter is equal to 10.

Using the do while Loop

A do while loop is very similar to a while loop. The difference is that a do while loop will execute its code block at least once and then test for termination, whereas the while loop tests for termination at the beginning before entering its code block.

int counter = 11; do {     System.out.println("Value = " + counter);     counter++; } while(counter < 10);

Here, the code block of the do while loop is entered, first of all, where the value of counter is printed to the console screen and then incremented by 1 to the value 12. The loop is then terminated, as 12 is not less than 10. This code will only print the value of 11 to the console, a wrongly written program if you wanted to print only numbers that are less than 10 to the console screen. So be aware of the fact that there is no condition for entering the do while loop for the first time. They are advantageous for situations where you want to execute code at least once and maybe more times.

Using the for Loop

The for loop is the most convenient of the loops. The standard implementation for a for loop is to specify a start value, a termination condition, and an action to be performed. A standard for loop looks like this:

for(int counter=0; counter<10; counter++)     System.out.println("Value = " + counter);

This will do the same as the previous WhileCounter.java example, only in a neater fashion. For the for loop an integer counter is declared and initialized to 0. This is done once at the start of the for loop. The next statement is the termination condition for the loop, which in this case is if the value of counter is less than 10. The last statement is an action that will be performed per loop, which is to increment counter by one.

The following MultiTable.java example shows a multiplication table of values from 1 to 5 using two for loops.

public class MultiTable {     public static void main(String args[])     {        final int TABLE_SIZE = 5;               for(int j=1; j<=TABLE_SIZE; j++)        {           for(int i=1; i<=TABLE_SIZE; i++)           {              int value = i * j;              if(value < 10)                 System.out.print(" ");                               System.out.print(value + " ");           }                     System.out.println();     // move to new line        }     } }

The output for this program should look like the following screen shot.

click to expand
Figure 2-10:

This example contains two for loops, one nested inside the other. After the first for loop is entered, the second for loop is executed straight away. The code block for the second for loop is where the important code is implemented; this block of code prints a value to the console window, which is the multiplication of the current values of the variables i and j. The first time that the code block for the second for loop is entered, j is equal to 1. From here, the value of i will run from 1 to 5, with j always equal to 1. This gives us the first output line of 1, 2, 3, 4, and 5. These are the calculations of (1*1), (1*2), (1*3), (1*4), and (1*5), where j is the first operand (always 1) and the second operand is i (incremented by one each time). After this, there is a call to the System.out.println() method to move the console carat position onto the next line. This procedure is then repeated with the value of j incremented each time until it is equal to 5.

Note 

The printing method that was used to print the multiplication values was System.out.print(). This method leaves the cursor position at the point where the last character was output, not moving it onto the next line, whereas System.out.println() will move the cursor to the start of the next line.

The purpose of the final int variable TABLE_SIZE is to define the limit of the for loop counter variables i and j and is a good technique for making reusable code. It means that changes made to the value of this variable at a later time will influence the outcome of the table sufficiently, so you only need to make the change once. If you change the value of TABLE_SIZE from 5 to the value 10, for example, you will get output similar to the following screen shot:

click to expand
Figure 2-11:

Here the dimension of the table is now 10, where the last calculated value is 10 multiplied by 10, giving the value 100 in the bottom-right corner of the table. You could specify the width and the height of the table as two separate variables, giving you a table of any dimension, such as 5 by 9 or 200 by 310 (although the latter dimension would not fit in the console window properly).

Note 

Notice that when declaring the constant variable TABLE_SIZE, it is only declared as final and not static and final. This is simply because the method main that it belongs to is already static, which means that variables declared inside it are static also.

An Advanced Look at the for Loop

The first statement in a for loop is most often used to declare a variable and assign it a value. It is also possible to declare more than one variable of the same specified data type in the same declaration. For example, the following code declares two variables, i and j:

for(int i=0, j; i<10; i++)     System.out.println("i = " + i);

We can also add more actions to the third statement of the for loop separated by commas, as follows.

for(int i = 0, j = 0; i<10; i++, j=i*i) {     System.out.println("i = " + i);     System.out.println("i squared = " + j); }

This code will add one to the variable i per loop cycle and assign to the variable j the value of i*i, printing the value each time.

The statements in a for loop do not need to be implemented if it is unnecessary to do so. Suppose you have a previously declared variable that you want to use as the counter in the for loop. This means that you do not need to implement a declaration statement for the for loop at all, as you want to use a previously declared variable instead.

int counter = 0;     // later on in code (within scope of variable counter)     for(; counter<10; counter++)     System.out.println("Value = " + counter);

Note that you must still add a semicolon (;) where the statement should be. You may still initialize an existing variable in a for loop.

int counter = 0;     // later on in code     // Counts down from 10 to 0 for(counter = 10; counter>=0; counter--)     System.out.println("Value = " + counter);

Similar to removing the first statement, you may remove the last statement and simply implement the code inside the code block for the for loop, as follows:

int counter = 0;     // later on in code     for(; counter<10;) {     counter++;     System.out.println("Value = " + counter); }

You can omit the second conditional statement also, which would leave you with the following code:

for(;;)     System.out.println("This loops infinitely");

The loop statement for(;;) performs the same way as while(true) as a loop declaration, looping continuously. You can exit out of an infinite loop (or a loop that already has a condition to terminate early) using break statements, which we will now discuss.

Using break and continue

We have already seen the break statement, using it to exit out of case statements inside a switch statement. Similarly, the break statement can also be used to exit from loops; this can replace or supplement existing termination conditions, which means that you can have multiple termination conditions for loops at different stages in the code block.

int number = 0; while(true) {     number++;     if(number > 9)         break; }

This slice of code again will count from 0 to 9, "breaking" out of the while loop when the value of the variable number is greater than 9. Notice that we have replaced the condition statement with the Boolean value of true; this will simply make the loop repeat forever, which means you must add code to jump out of the loop yourself using a break statement.

The continue statement is very useful with loops. It allows you to jump through the loop's code block, basically jumping from the current position and past the rest of the code block to start off the next loop stage. A good example of this is shown in OddNumbers.java. This example uses the continue statement to jump past the remaining code in the loop's code block when the value of the loop counter is found to be even. The result is that only odd numbers are printed to the console screen.

public class OddNumbers {     public static void main(String args[])     {        for(int counter=0; counter<10; counter++)        {             System.out.print("Value of counter =  " + counter);                     if(counter % 2 == 0)    //  counter is even           {              System.out.println(", counter is even so continue");              continue;          // jump to next loop step           }               System.out.println(", odd number found, hurray");        }     } }

When you run this code, the output should be similar to the following screen shot.

click to expand
Figure 2-12:

The previous example was structured merely to illustrate the use of the continue statement. In order to get a list of odd numbers, the following code is a simpler and more suitable implementation.

for(int counter=1; counter<10; counter+=2) {     System.out.println("Odd number = " + counter); }

Instead of testing to see if the value of counter is an even or odd number, we can simply ensure that all of the numbers are odd. To do this, the value of counter is initialized to 1 and is incremented by 2 every loop cycle. This means that by continually adding values of 2 per loop cycle, the value of counter is always the next odd number, as it started as an odd number.

Jumping to Labels

The ability to jump to labels can be a very useful tool when using nested loops. Let's consider the following section of code:

for(int i=0; i<5; i++)         // first loop {     for(int j=0; j<5; j++)     // second/nested loop     {         break;     } }

Here we have two loops, one nested inside another. If you are in the second/nested loop, there is no instant way that you can break out of both loops altogether. The break statement will only "break out" of the nested loop but continue performing the first loop until it terminates when the value of i is not less than 5.

We can give the first loop a label and then break out of both loops entirely by specifying the label with the break statement, as follows.

firstLoop: for(int i=0; i<5; i++)        // first loop {     for(int j=0; j<5; j++)   // second/nested loop     {         break firstLoop;     } } // breaking from firstLoopLabel will go to here

Here we specify the first loop with the label firstLoop, followed by a colon. It is almost like giving the first loop an identifier or variable name so that you can differentiate between it and the nested loop from within the nested loop. You can then specify which one of the loops that you want the break statement to affect by adding the label after the break keyword.

Now that we are able to choose the loop that we want the break statement to "break," we can look at using the continue statement in exactly the same way.

The following example code illustrates the use of the break and continue statements using labels with two loops, one nested inside the other. They are manipulated from within the second/nested loop.

firstLoop: for(int i=0; i<10; i++) {     for(int j=0; j<10; j++)     {                          if(i!=7)            continue firstLoop;  //  or just break this loop         else if(j!=7)             continue;           //  continue this loop                             //  if this is reached both i and j equal 7             System.out.println("i = " + i);         System.out.println("j = " + j);                        break firstLoop;        // this will exit both loops     } }

This code only prints to the console the values of the variables i and j when they are both equal to 7, using the label firstLoop to manipulate the first loop from inside the second/nested loop.



Java 1.4 Game Programming
Java 1.4 Game Programming (Wordware Game and Graphics Library)
ISBN: 1556229631
EAN: 2147483647
Year: 2003
Pages: 237

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net