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.

 

  1. Open BlueJ either by selecting it from the Dock or navigating to it in the Applications folder and double clicking it.

  2. 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.

  3. 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.

  4. Create a class called Domino and remove the default instance variable and method that BlueJ puts in the class.

  5. 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.)

 

  1. 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).

 

  1. 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?]

 

  1. 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?

 

  1. 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.*).

 

  1. 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));

 

  1. Compile and test your constructor by creating a domino set and inspecting each domino in the set.

 

  1. 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.

 

  1. 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.

 

  1. 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).

 

  1. 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?

 

  1. 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?