CS 151 Fall 2007 Lab 8
Arrays
and ArrayLists
The main goal for this lab is to practice working with
objects of the Array and ArrayList types.
We will implement the Domino class from the midterm exam using
arrays. Then, we will implement a
class for a set of Dominoes using ArrayLists.
- Open
BlueJ either by selecting it from the Dock or navigating to it in the
Applications folder and double clicking it.
- Mount your network directory/folder
so that you can access the lab after you leave Olin 323. Go to the Finder and from the
Go menu select Connect to Server.... Type afp://fileserver1 or choose it from the
list of selections and select the Personal volume
when prompted.
- From
the Project menu select New Project. Select your computer from the drop
down menu. Then scroll down
and open the Volumes folder and then the Personal folder inside it. Scroll down the long list of
folders until your find yours.
Create a project called "Lab8" in your personal network
folder.
- Create a class called Domino
and remove the default instance variable and method that BlueJ puts in the
class.
- Define a private
integer instance variable called value. Add a second public instance variable that we will use
to store the number of spots on each end using the following syntax:
private int[] numberOfSpots = new int[2];
The
square brackets [] denote that we want an array of integers. On the right we are telling the
compiler that our array will hold 2 integer values. They are indexed starting from 0 like the characters in a
String. Finally, add an integer
constant to your class called INVALID_SPOT_NUM_FLAG and set its value to -1.
(NOTE: We are only making
numberOfSpots public to make working with it easier in lab, in general it
should be private and accessed with a get method. See the end of the lab to do this.)
- Write a constructor
that takes two integer parameters specifying the number of spots for each
end of the domino. If the
value of both parameters is greater than or equal to 0, set the first and
second entry of numberOfSpots to the parameter values. Otherwise, set both entries of
numberOfSpots to the constant INVALID_SPOT_NUM_FLAG. The statement
numberOfSpots[0] = 5;
sets
the first entry of numberOfSpots to the integer (int) 5. Set the value instance variable to the
sum of numberOfSpots two entries, i.e. to numberOfSpots[0] + numberOfSpots[1]. Compile your class and fix any syntax errors. Test your constructor by creating
several different dominoes in the workbench in BlueJ. Try two negative numbers, a negative and non-negative
number, and two non-negative numbers.
After you create each domino, double click the red box representation of
it. Double click on the
numberOfSpots field or select that field then click the Inspect button. You should see the two entries of your
array and a field for the length of the array (always 2 in this case).
- Write a method called
isMatch() in your class that takes a single object of type Domino as a
parameter. The method should
return a boolean value: true if either end of the two dominoes have the
same number of spots and false otherwise. For example if one domino has 4
and 5 spots and another has 1 and 4 spots, they match, but dominoes with
spots 4 and 5 spots and 0 and 2 spots, respectively, do not match. Again, you can access the number
of spots for each end of the domino from which the method is called ("this"
domino) with
numberOfSpots[0]
and
numberOfSpots[1]. Feel free to preface them with the
keyword this for readability.
if your parameter variable is called dom, then you can access its
spot counts with dom.numberOfSpots[0]
and
dom.numberOfSpots[1]. [We can access
numberOfSpots for dom directly like this, because we made numberOfSpots
public. If it was private
what would you do?]
- Create several dominoes
in the workbench to test your isMatch() method. Try calling the isMatch() method from one domino and
typing in the name of that domino as the parameter to isMatch. Every domino should match
itself! Then try to enter the
name of different dominos that do and don't match. A good test would check to see
that the match works in any of the four possible combinations. You did test for 4 cases didn't
you?
- Create a new class
called DominoSet. As usual,
delete the helpful templates that BlueJ inserts in it for you. Add an instance variable called
dominoes that will store all the tiles in that set using the following
syntax:
private
ArrayList<Domino> dominoes;
We
are using an ArrayList since we want to be able to increase and decrease the
number of dominoes in the set as we play a game. Regular arrays have a fixed size and you can't add to or
remove from them any of their elements.
Note that the ArrayList type itself is "parameterized" in a
sense by our Domino type. That's
what the angle brackets denote. You will need to add an import statement as the very first
line of your class since ArrayList is part of the java.util package (import
either java.util.ArrayList or java.util.*).
- Add a constructor to
the DominoSet class that takes a single integer parameter that specifies
the maximum number of spots on an end in that set. Use a pair of nested for loops (one
for each of the two spot counts) to create new dominoes for all combinations
of spots between 0 and the specified parameter (include both 0 and the
maximum value). You can initialize
an array list to either a specified capacity or a default capacity (see
the Java Class Libraries documentation for details). Initialize the ArrayList to the
number of dominoes in the set.
How many will there be?
For example if your set were going to have 9 dominoes you would
say:
dominoes = new
ArrayList<Domino>(9);
Don't forget to add the type Domino in angle brackets. If you do you will get a compiler
warning. To add a domino with
2 and 4 spots to the dominoes ArrayList instance variable, use the
statement
dominoes.add(new Domino(2, 4));
- Compile and test your
constructor by creating a domino set and inspecting each domino in the
set.
- Add an instance
variable of type Random called randGen or something meaningful to your
DominoSet class to store a random number generator. Don't forget to import the Random
class which is in the java.util package. Modify your constructor to set that instance variable
to a new object of type random.
- Add a public method
called randomDraw() that takes no parameters and returns a Domino. The method should select a random
number between 0 and the number of dominoes in the set (inclusive), return
the domino in that position in the ArrayList dominoes, and remove it from
the list of dominoes in the set.
The ArrayList method
size() returns the number of
elements in an Array list.
The method remove(index) returns the element
from position index in the ArrayList, removes it from the list, and
subtracts one from the index of all elements after it in the list. The method get(index) returns the element
from that position without removing it from the list. Recall that the Random class
method nextInt(maxValue) returns a random
number between 0 and maxValue (exclusive). You may want to add a check for two potentially
troublesome conditions. What
are they? If either condition
occurs return null, otherwise return the domino you selected.
- Create a class called
DominoSetTester that has only a main method (public static void
main(String[] args) ...).
Note that the main method takes a single parameter that is an array
of Strings. The main method
should create a set of dominos, draw a random domino from the set and
store it in variable, continue to randomly draw dominoes from the set
until a matching domino is found.
Add a line that prints out spot counts for the first and all
subsequent dominoes drawn.
Also count and display the number of dominoes that were drawn
before a match was found (excluding the very first domino drawn).
- If you have time, fix the
DominoSet set constructor so that it only creates one Domino of each
number combination. The way
it is currently defined, if the number of spots are different, it creates
two dominoes with those spots, e.g. two dominoes with 3 and 5 spots are
created: (3,5) and (5,3).
Hint: make the inner for loop depend on the outer for loop. Also add to the same class a
constructor that takes no parameters and creates a default set of dominoes
with at most 6 spots. It should
contain a single statement (this( );) that calls your other constructor with
the appropriate parameter. A
set with maximum of 6 spots per end has 28 tiles. How many should a set with
maxSpots spots per end have?
- If you
still have time, try adding another constructor to the Domino class that
takes an array of integers as a parameter. Check that the array isn't null and has only two
entries. arrayName.length
(it's a public instance variable not a method so no parenthesis are
needed) gives you the number of entries in the array. Set the domino's spots to the
given values. Rather than
duplicating the same code in both constructors, can you think of a way to
have one constructor call the other?
Remember, you can do this by using the keyword this() like a
method, but it has to be the FIRST statement in the constructor. You do things after you call the
other constructor if needed.
Also add a method called getSpotCounts that takes no parameters and
returns an array of integers (it's an error to specify the size of the
array here). Modify your
methods to use this get method and make the access specifier for
numberOfSpots private instead of public. Can you figure out how to access the array entries
directly after calling this new method without storing the result in a
variable?