Mini-Lab: A Whirl of Color

Using Conditional Statements


This set of Mini-Lab Exercises is the second in a series in which students build a small program with several fish moving around in an aquarium. The set includes the following exercises:

Each section contains an Introduction to a problem or task, descriptions or examples of one or more Concepts to apply in solving the problem or completing the task, and an Exercise.

In the exercises that precede this one, students created three fish, moved them forward one step, and displayed them graphically. Therefore, students should be familiar with constructing objects, using variables, and invoking methods. Some familiarity with logical expressions is also required for this set of exercises.



About Face!

Introduction

In our current program, fish move to the right and then get stuck at the right wall. This does not make sense. We can use a Simple Conditional statement to determine when a fish should turn around and start swimming the other direction.

Stop and Think

  • Which statements in Example 1 will be executed when there are no lemon squares? In what order will they be executed? Which statements will be executed, and in what order, when there are lemon squares?
     

Exercise

  • In your previous testing of the program you may or may not have noticed that fish swim only to the right and get stuck at the right wall. To verify the problem, make a copy of the statement that sets the dimensions of the aquarium. (Stop and Think: where is the statement that sets the dimensions of the aquarium? In what class, and what method?) "Comment out" the original, and change the dimensions in the copy to be 100 x 200. Copy the code that moves and redisplays the fish to let them move a second time. Now run the program several times and make sure you see the problem.
  • Research the AquaFish specification to find out how to determine whether a fish is at a wall and how to make it reverse direction. Modify the AquariumController class to have each fish check whether to change direction whenever it moves forward. (Stop and Think: You could check whether to reverse direction or not and then move forward, or you could move forward first and then check whether to reverse direction. Does the order matter? Consider three cases: a) for a fish that was constructed along the left wall, b) for a fish that was constructed in the middle of the aquarium, and c) for a fish that was constructed along the right wall.) Test your program in the narrower aquarium you created above. When you are satisfied that your program is behaving correctly, restore the aquarium to its original size.



Mixing It Up

Introduction

The runProgram method in the AquariumController class is starting to get long and tedious. Furthermore, as the program evolves, it is not clear that the right classes are taking responsibility for the right actions. The AquariumController object wants to tell all of the fish to move, but why is it concerned with the details of how a fish moves, such as when it should reverse direction?

Exercise

  • Look through the AquaFish class. Just before the moveForward and changeDir methods, there is a commented-out move method. Uncomment the move method and then modify it so that the fish checks whether to change direction whenever it moves forward. This is similar to the check that you just added to the AquariumController class, but not exactly the same. (Stop and Think: In the AquariumController class, what is the object associated with the calls to the moveForward, atWall, and changeDir methods? Will the same object be responsible for those tasks when the calls move to the newly uncommented move method? How would that be represented in the AquaFish class?)
  • Modify the AquariumController class to use the new move method rather than separate calls to moveForward, atWall, and changeDir. Test your changes by running the program several times and making sure that the program behavior is consistent with what it was before the refactoring.
  • Now that moveForward, atWall, and changeDir are only used internally in the AquaFish class, change the two modifying methods (moveForward and changeDir) to be protected rather than public. (There are commented-out lines that do this already there. You could uncomment them and delete the other lines that were being used instead, or you could change the public keyword to protected in the current lines, using the commented-out lines as a template. (The exact meanings of the public and protected keywords will be the focus of a future lab.)



One Fish, Two Fish, Red Fish, Blue Fish

Introduction

Our aquarium is a little boring, since the fish are all the same color. We could specify the color of each fish as we construct it, giving each fish a different color.

Exercise

  • Look through the AquaFish class. Where is the fish color set? Modify the class so that the fish color is set to Color.RED for the first fish (the fish whose ID is 1), and to Color.BLUE for all other fish. (Color.RED and Color.BLUE are constant Color values defined in the Java Color class.) Make sure to use a positive conditional expression.
  • If your program does not already construct at least three fish, modify it so that it does. (Where would this modification be made?)
  • Identify in advance what behavior you expect from your program when you test it. Do you know which fish will be which color? Do you know how many fish you should get of each color? Test your program to make sure that your results are what you expect.
  • Just for fun (and only if you have time): Modify your program so that all fish with odd ID numbers are red, and all fish with even ID numbers are blue. The % operator, which calculates the remainder when doing integer division, is useful for this exercise. Construct several additional fish to test this modification.



Rainbow Fish

Introduction

Why should there only be two colors of fish in our aquarium? We can use Multiple Alternatives to add diversity of color when constructing and displaying fish. Or, to make things more interesting, we could decide on the color of each fish based on a random number. We can use the standard Java Random class to do this.

Exercise

  • Modify your program to create fish with the colors of the rainbow. Use the fish's ID number to decide which color to use.
    ID Number Color
    1 Color.RED
    2 Color.ORANGE
    3 Color.YELLOW
    4 Color.GREEN
    5 Color.BLUE
    6 Color.MAGENTA
    (This table uses Color.MAGENTA because there are no Color constants for indigo and violet.)
  • Test your program to make sure that your results are what you expect. (What results were you expecting? What tests are necessary to make sure the results are what you expect?)
  • Make sure that you have updated the program documentation at the top of the file to reflect your modifications.
  • Just for fun (and only if you have time): Modify your program so that all fish whose ID numbers when divided by 6 have a remainder of 0 are constructed red, if they have a remainder of 1 they are constructed orange, etc. Construct additional fish to test this modification.



Leaving the Color to Chance

Introduction

We could get a wider array of fish colors by choosing a random color for each fish, rather than setting each fish to one of six pre-defined colors.

Exercise

  • In the AquaFish constructor, create three variables to represent a random amount of red, green, and blue, and randomly set each to a value between 0 and 255. (Stop and Think: how many numbers are there between 0 and 255?) (Note: Notice that the AquaFish class has an import java.util.Random; statement above the class definition; this allows you to use the Random class without specifying the package it comes from every time.)
  • Set the fish color to a random color constructed from the three random values for red, green, and blue.
  • Test your modifications.


Stop and Think

  • In Example 2, for what values of randNum would the student take a lemon square? An apple? A slice of apple pie? What does this code do when randNum has the value 9?
  • Overall, what behavior does Example 2 in the table above simulate? Express your answer in terms of percentages.
  • How would the behavior of the code in Example 1 be different if the first two else keywords were left out; in other words, if it were a sequence of separate, independent conditional statements? Could you write code that would have the same behavior as Example 1 without any else keywords?
  • How would the behavior of the code in Example 2 be different if both else keywords were left out; in other words, if it were a sequence of separate, independent conditional statements? Could you write code that would have the same behavior as Example 2 without any else keywords?
  • How would the behavior of the code in Example 1 be different if it repeatedly called the nextInt method and checked its return value against different values instead of calling nextInt once, saving the random number in a variable, and checking the variable against different values? In other words, if there were no randNum variable, and each conditional expression called the nextInt method instead?