Using arrays

5.6 Using arrays

Currently, our 12 keys are created, and placed at appropriate locations on the screen, but they all react to the “g” key, and they all play the same note. This is despite the fact that we have prepared our keys to accept different keyboard keys and sound files in the constructor. However, since all our keys are created by the same line of source code (executed in a loop), they are all created with “g” and “3a.wav” as parameters.

The solution is similar to the change we made in regards to the x-coordinate: We should use variables for the keyboard key and the sound file name, and assign different values to them each time the loop executes.

Concept:

This is more problematic than in the case with the x-coordinate, though. The correct keys and sound file names cannot be computed as easily. So where do we get the values from?

An array is an object that holds

Our answer is: We will store them in an array.

multiple variables. These can be

An array is an object that can hold many variables, and thus can store many values. We can show

accessed using an

this in a diagram. Assume we have a variable named “name” of type String . To this variable,

index.

we assign the String “Fred”:

String name; name = “Fred”;

Figure 5.2 illustrates this example. This case is very simple. The variable is a container that can hold a value. The value is stored in

the variable. In case of an array, we get a separate object—the array object—that holds many variables. We

can then store a reference to that array object in our own variable (Figure 5.3).

Figure 5.2 A simple String

String name

“Fred”

variable

5.6 Using arrays

Figure 5.3

String [] names

An array of Strings

String[ ]

0 1 2 3 4 5 6 7 8 9 10 11 "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"

The Java code to create this situation is as follows:

String[] names; names = { “a”,“b”,“c”,“d”,“e”,“f”,“g”,“h”,“i”,“j”,“k”,“l” };

In the variable declaration, the pair of square brackets ( [] ) indicates that the type of the variable is an array. The word before the brackets indicates the element type of the array, that is, the type that each entry in the array should have. Thus String[] denotes an array of Strings, while int[] denotes an array of integers.

The expression

{ “a”,“b”,“c”,“d”,“e”,“f”,“g”,“h”,“i”,“j”,“k”,“l” }

creates the array object and fills it with the Strings “a” to “l”. This array object is then assigned to our variable names . We can see from the diagram that, when an array object is assigned to a variable, the variable then contains a pointer to that object.

Once we have our array variable in place, we can access individual elements in the array by using an index—a position number in the array object. In Figure 5.3, the index of each individual String is shown above each array element. Note that counting again starts at 0, so the String “a” is at position 0, “b” is at position 1, and so on.

In Java, we access array elements by attaching the index in square brackets to the array name.

Concept:

For example,

Individual names[3] elements in an array are

accesses the element in the names array at index 3—the String “d”.

accessed using square brackets

For our piano project, we can now prepare two arrays: one with the names of the keyboard keys

([ ]) and an index

(in order) for our piano keys, and one with the names of the sound files for those piano keys.

to specify the

We can declare fields in the Piano class for those arrays and store the filled arrays. Code 5.6

array element.

illustrates this. Note that the values in the whiteKeys array are the keys on the middle row of my computer

keyboard. Keyboards are slightly different on different systems and in different countries, so you may have to change these to match your own keyboard. The other slightly odd thing here is the String “ \\ ”. The backslash character ( \ ) is called an escape character and has a special meaning in Java Strings. To create a String that contains the backslash as a normal character, you have to type it twice. So typing the String “ \\ ” in your Java source code actually creates the String “ \ ”.

74 Chapter 5 | ■ Making music: An on-screen piano

Code 5.6 Creating arrays for

public class Piano extends World keys and notes

private String[] whiteKeys =

{ “a” , “s” , “d” , “f” , “g” , “h” , “j” , “k” , “l” , “;” , “’” ,

“\\” }; private String[] whiteNotes =

{ “3c” , “3d” , “3e” , “3f” , “3g” , “3a” , “3b” , “4c” , “4d” , “4e” ,

“4f” , “4g” }; // constructor and methods omitted.

Now we have arrays available listing the keys and sound file names that we want to use for our piano keys. We can now adapt our loop in the makeKeys method to make use of the array elements to create appropriate keys. Code 5.7 shows the resulting source code.

Code 5.7 Creating piano keys

/** with keyboard keys

* Create the piano keys and place them in the world.

and notes from

arrays private void makeKeys() {

int

i = 0; while (i < whiteKeys.length) {

Key key = new Key(whiteKeys[i], whiteNotes[i] + “.wav” ); addObject(key, 54 + (i*63), 140);

i = i + 1; }

A number of things are worth noting:

We have moved the creation of the new key out of the addObject method call into a sepa- rate line, and assigned the key object initially to a local variable, called key . This was just done for clarity: The line got very long and busy, and it was quite hard to read. Splitting it into two steps makes it easier to read.

The parameters for the Key constructor access whiteKeys[i] and whiteNotes[i] . That is, we use our loop variable i as the array index to access all the different key strings and note file names in turn.

We use a plus symbol ( + ) with whiteKeys[i] and a String (“.wav”). The variable whiteKeys[i] is also a String, so the plus symbol is used with two String operands. When

5.6 Using arrays

Concept:

+ is used with Strings, it performs string concatenation. String concatenation is an operation that sticks two Strings together and turns them into a single String. In other words, here, we

The plus symbol (

append the String “.wav” to the whiteNotes[i] value. This is because the name stored in

+), when used with Strings,

the array is of the form “3c”, while the file name on disk is “3c.wav”. We could have stored

stands for String

the full file name in the array, but since the suffix is the same for all notes files, this seemed

concatenation.

unnecessary. Just adding it here saves us some typing.

It merges two Strings together

We have also replaced the 12 in the condition of the while loop with whiteKeys.length .

into one.

The .length attribute of an array will return the number of elements in this array. In our case, we do have 12 elements, so leaving the 12 in place would have worked. However, using the length attribute is safer. Should we one day decide to use more or fewer keys, our loop will still do the right thing, without the need to change the condition.

With these changes, our piano should now be playable with the middle row of keys on our key- board, and it should produce different notes for different keys.

Exercise 5.19 Make the changes discussed above in your own scenario. Make sure that all keys work. If your keyboard layout is different, adapt the whiteKeys array to match your keyboard.

Exercise 5.20 The sounds folder of the piano scenario contains more notes than the ones we are using here. Change the piano so that the keys are one octave lower than they are now. That is, use the sound “2c” instead of “3c” for the first key, and move up from there.

Exercise 5.21 If you like, you can make your keys produce entirely different sounds. You can record you own sounds using sound recording software, or you can find sound files on the Internet. Move the sound files into the sounds folder, and make your keys play them.

The version we have now is in the book scenarios as piano-4. The missing part now is quite obvious: We have to add the black keys. There is nothing really new in this. We essentially have to do very similar things again as we did

for the white keys. We will leave this as an exercise for you to do. However, doing it all in one chunk is quite a substantial job. In general, when approaching a larger task, it is a good idea to break it down into several smaller steps. Thus, we will break this task down into a sequence of exercises that approaches the solution one step at a time.

Exercise 5.22 Currently, our Key class can only produce white keys. This is because we have hard-coded the file names of the key images (“white-key.png” and “white- key-down.png”). Use abstraction to modify the Key class so that it can show either white or black keys. This is similar to what we did with the key name and sound file name: Introduce two fields and two parameters for the two image file names, and then use the variables instead of the hard-coded file names. Test by creating some black and some white keys.

76 | Chapter 5 ■ Making music: An on-screen piano

Exercise 5.23 Modify your Piano class so that it adds two black keys at an arbitrary location.

Exercise 5.24 Add two more arrays to the Piano class for the keyboard keys and notes of the black keys.

Exercise 5.25 Add another loop in the makeKeys method in the Piano class that creates and places the black keys. This is made quite tricky by the fact that black keys are not as evenly spaced as white keys—they have gaps (see Figure 5.1). Can you come up with a solution to this? Tip: Create a special entry in your array where the gaps are, and use that to recognize the gaps. (Read the note below these exercises first before you start. This is a hard task! You may want to look at the solution in piano-5 if you cannot figure it out.)

Exercise 5.26 The full implementation of this project, piano-5, also includes another short method to show a line of text on the screen. Study it, and make some changes: Change the wording of the text; change its color; and move the text so that it is horizontally centered.

Concept: Note: The String class

The type String is defined by a

The type String that we have used many times before is defined by a class. Find this class in

normal class. It the Java library documentation and have a look at its methods. There are many, and some of has many useful

them are often very useful. methods, which we can look up in

You will see methods to create substrings, to find out the length of a string, to convert the case, the Java library

and much more. documentation.

Especially interesting for Exercise 5.25 above may be the equals method that allows you to compare the string with another string. It will return true if the two strings are the same.

This is as far as we go with this project. The piano is more or less complete now. We can play simple tunes, and we can even play chords (multiple keys at the same time).

Feel free to extend this if you like. How about adding a second set of sounds, and then adding

a switch on screen that allows you to switch from the piano sounds to your alternate sounds?