Lecture 24 - More Arrays

More arrays

Now that you've seen how to delete an element from the middle of an array, as an exercise, let's write code for adding something to the middle of an array. In addition to moving items in the right order, we'll need to be sure to update the count of the number of items in the array.

Getting an array's length

A detail about Java arrays: If you have created an array (i.e., you have actually executed something like myArray = new SomeType[someSize] you can ask the array for its length (where length is the capacity of the array, not the number of items it currently holds).

You can get the length by writing myArray.length. Notice there are no parentheses after length. You are actually accessing a public instance variable. This is one of the few times that the Java libraries allow the user to access a public instance variable. I personally find it very confusing to have this be an instance variable rather than a method, since other very similar classes (like Vector and String) provide a method rather than an instance variable which returns the size of the structure.

Passing an array as a parameter

You might ask why you might ever need this information. The main reason it might be necessary is if you get an array passed as a parameter.

Here is a method which takes as a parameter an array of double's and returns the largest element in the array.

    // pre: there is at least one element in elt array
    // post: returns largest value in elt array.

    public double largest(double[] elt)
    {
       double largest = elt[0];
       for (int index=1; index < elt.length; index++)
       {
           if (elt[index] > largest)
               largest = elt[index];
       }
       return largest;
    } 

Of course this code only works if all the slots in the array hold useful values. If only some of the array elements hold useful information, then we can ensure we only search those elements by passing the useful size as a parameter:

    // pre: size >= 1 and the array has length at least size.
    // post: returns largest value in first size elements of elt array.

    public double largest(double[] elt, int size)
    {
       double largest = elt[0];
       for (int index=1; index < size; index++)
       {
           if (elt[index] > largest)
               largest = elt[index];
       }
       return largest;
    } 

Summary

Arrays are used to hold collections of objects of the same type. We use [] when we declare an array:

    private DrawableInterface myArray[];

When we construct an array, we specify its size:

    myArray = new DrawableInterface[20];

We can access an array element by indexing into it, remembering that array indices start at 0.

    myArray[0] = new Text (...);

A for loop is very useful for walking through arrays and repeating operations on each element:

    for (int i = 0; i < numObjects; i++)
    {
        myArray[i].setColor(Color.red);
    }

Remember that array indices should stay between 0 and the declared size. If they don't, you will get an ArrayOutOfBoundsException. Also, remember that array elements must be initialized before you can use them. If they aren't, you will probably get a NullPointerException.

Simon Discussion

For next week's lab, you will be writing a version of the game Simon. For those of you who don't know this game, Simon is a game that tests the player's memory. The game has 4 brightly colored buttons. Each button has a different tone associated with it. Simon creates songs by randomly selecting tones. Initially the song only contains one note. The player then repeats the note by pushing the appropriate button. If the user is right, Simon adds a note to the song and plays the entire song. The player tries to repeat the entire song. This continues until, eventually, the player cannot remember the entire song. Simon then starts over with a song of length 1.

We will provide two classes to you. One is a NoisyButton class and the other is a ButtonPanel. These will provide the colored buttons and the noise making associated with the buttons. (Please bring headphones to lab if you have some!)

Not too surprisingly, you will be using an array in this assignment. The song will be represented as an array of NoisyButtons. You need to make the array bigger than you believe the user will be able to remember. However, the array will not normally be full. So, just as we did with the shapes, you will need to keep track of the number of NoisyButtons currently in the array as well as the capacity of the array. Also, each time the user clicks on a button, you will need to compare that button with the next note in the song. Therefore, you will also need an instance variable that will track which note you are currently comparing to the button the user clicked. In summary, you need to remember three things about the array: its capacity (a constant), the number of notes currently in the song (like numObjects above), and the current note the user is trying to match.

Playing a song is like the animations we have been doing, except it is audio instead of visual. Thus, we will want to play a tone, pause, play another tone, and so on. Playing a song therefore requires an ActiveObject called a SongPlayer. The Song class should provide a play method. In it, it should create a SongPlayer whose execute method will simply walk through the song playing each note and pausing between notes. It has a short life (like the ball in the boxball game) and should stop running when it reaches the end of the song.

One final thing to be aware of is that the code that you will write to handle each button click that the user makes is a bit more intricate than what you have done previously. Your main class, called SimonController, will implement NoisyButtonListener. As a NoisyButtonListener, it must define the noisyButtonClicked method. When the user clicks a button, you must first determine if the button matches the next note in the song. If it does not match, you will play a razzing sound and start over with a new song. If it does match, you again have two cases to consider. If they matched the last note of the song, then you should add a note to the song and play the entire song again. If they matched but it wasn't the last note, you just want to update your variable that keeps track of which note is expected next. Think carefully about how to structure this method to handle these three cases. Remember that each button click results in a new call to the noisyButtonClicked method.