Aquarium Lab Series    

Mini-Lab: More Fish!

Using ArrayLists

Alyce Brady
Kalamazoo College


This set of Mini-Lab Exercises is the fourth 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, (usually) abridged versions of one or more Patterns that will be useful in solving the problem or completing the task, and an Exercise.

In the exercises that precede this one, students will have created three fish that move randomly back and forth in an aquarium, being careful not to hit the sides. Students should be familiar with basic for loops, simple selection statements, prompting for input, and the Random class.

Students should read over the patterns that appear in this document before the lab.



Becoming a Collector

Introduction

A more realistic simulation of an aquarium would have more than two or three fish. We could modify the simulation so that it supports four fish, five fish, or twelve fish in that many variables, but if we "hard-code" the number of fish into the program in this way, then we must modify and re-compile the program to change the number of fish in the aquarium. We must also repeat statements, such as the code to display and move fish, four, five, or twelve times.

A better alternative would be to ask the user how many fish to place in the aquarium and then store them in a collection object. We can use a Linear Indexed Data Structure to store the collection of fish.

Exercise

  • Replace the three fish you constructed earlier with an Expandable Linear Indexed Data Structure (which doesn't yet have any fish). What does this data structure represent? Choose a Intention Revealing Name for it. Don't forget to import the appropriate library class (java.util.ArrayList).

    It is always difficult to test modified code part-way through the change. At this point, you have constructed an expandable collection that can contain three fish in the future. You no longer have three fish, but the rest of your program still expects three named fish. In order to test that you have not introduced any syntax errors into your program, "comment out" the code that displays and moves the three fish (who no longer exist). Do this by placing the specified code in comments. For example,

      /*
              d.showFish (fish1);
              .
              .    more code to display and move fish
              .
              d.showFish (fish3);
      */
    Now compile your program just to make sure that you have created your expandable collection correctly. (Don't be surprised when your program no longer moves or displays fish!)



Let's Go Fishing

Introduction

Of course, we don't see any fish, because we haven't created any.  But we do have a container to hold them.  When we create fish, we can put them directly into the Linear Indexed Data Structure as Appended Items.

Exercise

  • Construct three new fish as Appended Items in your ArrayList. Don't forget to pass the aquarium to the AquaFish constructor.



Viewing the Catch

Introduction

Now that we have three fish in a collection, how do we do anything with them? How do we display one of them, or ask one for its color? We can use the Indexed Random Access pattern to refer to any individual object in a Linear Indexed Data Structure.

Exercise

  • Display each of the fish in your ArrayList using the Indexed Random Access pattern. You may leave the code for moving the fish commented out for now.

  • Test your program to make sure that your program is correctly constructing and displaying three fish.



Loopy Fish

Introduction

One of the reasons we switched to using a collection object was to avoid having to duplicate code for each fish, but we currently have three lines to display the three fish.  This will not scale up well if we want to put 25 fish in the aquarium!  We can access all of the fish sequentially using the Linear Indexed Traversal pattern.

Exercise

  • Replace your code from the last exercise (where you displayed each fish individually) with a Linear Indexed Traversal to display the fish.

  • Now that your code to display fish will handle however many fish are in the aquarium, it's time to let the user decide how many fish there should be. Prompt the user for the number of fish to put in the aquarium and then use the Counted Repetition pattern to construct that number of fish in your ArrayList. (Question: Where in the program should your prompt appear?) Even though you are adding new functionality to your program, it should be getting considerably shorter!

  • Test your program to make sure that it correctly constructs and displays the number of fish specified by the user. Remember that you may need to drag the display window to the side to see your prompt for the number of fish.



A School In Motion

Introduction

Now let's think about how to move and display all the fish for as many time steps as the user wants. 

It seems clear that we will want to loop through the steps in the simulation, as we are already doing. It also seems clear that we will want to loop through all the fish. The question is:

Processing all the fish and all the steps in the simulation are not independent of one another. That is, we can't process all the fish and then process all the simulation steps, or vice versa. Either processing all the fish is part of what we do in one step of the simulation, or running all the steps of the simulation is part of what we do for each fish. Thus, we will need to nest one of the loops inside the other.

To decide which loop gets nested inside of which, consider the following algorithmic structures in which we assume that we have 25 fish in the aquarium and we want to run the simulation 100 times.

For each fish in the collection:
        Move 100 times and display the aquarium.
For each step in the simulation:
        Move the 25 fish once and display the aquarium.

We do not want the first fish to move 100 times, followed by the second fish moving 100 times, followed by the third fish moving 100 times. Instead, we want all 25 fish to move once, then all 25 fish to move again. This corresponds to the second solution above.

Another question we have to consider is where the display of the aquarium should be relative to the fish movement. Do we want to display the fish and aquarium in the outer loop (as part of each simulation step), or in the inner loop (as part of processing each fish)? The following table illustrates these two options.

For each step in the simulation:
        For each fish in the collection:
                Move, possibly changing direction.
        Display aquarium & fish.
For each step in the simulation:
        For each fish in the collection:
                Move, possibly changing direction.
                Display aquarium & fish.

Which behavior do you wish to implement?

Exercise

  • Remove the remaining comments around the code that runs through the steps of the simulation, moving and displaying the fish in the aquarium.

  • Inside the simulation loop, replace the code that moves the three named fish with a loop that will move all the fish in your collection. (Each will still change direction when it has to or when it randomly chooses to.) Use a Linear Indexed Traversal through your Linear Indexed Data Structure of fish. You may wish to create a temporary variable in the loop to refer to the fish being processed in this iteration rather than repeatedly retrieve the same fish from the ArrayList.

  • Display all the fish in the aquarium with a single statement.  Research the AquaView specification to discover how to display an indexed collection of fish. Note that this method will also display the aquarium and pause, so you no longer need to do that separately. Where does this statement belong? Should it be part of the inner or outer loop?

  • Update the initial display of fish in the aquarium also to display all the fish at once.

  • Test your modifications.




Copyright Alyce Faulstich Brady, 2001.