Solution for
Programming Exercise 5.1


THIS PAGE DISCUSSES ONE POSSIBLE SOLUTION to the following exercise from this on-line Java textbook.

Exercise 5.1: In all versions of the PairOfDice class in Section 2, the instance variables die1 and die2 are declared to be public. They really should be private, so that they are protected from being changed from outside the class. Write another version of the PairOfDice class in which the instance variables die1 and die2 are private. Your class will need methods that can be used to find out the values of die1 and die2. (The idea is to protect their values from being changed from outside the class, but still to allow the values to be read.) Include other improvements in the class, if you can think of any. Test your class with a short program that counts how many times a pair of dice is rolled, before the total of the two dice is equal to two.


Discussion

The versions of the PairOfDice class in Section 2 differ in how the dice are initialized. I like the idea of initializing the dice to random values, so I will work with the following version:

        public class PairOfDice {
        
            public int die1;   // Number showing on the first die.
            public int die2;   // Number showing on the second die.
            
            public PairOfDice() {
                    // Constructor.  Rolls the dice, so that they initially
                    // show some random values.
                roll();  // Call the roll() method to roll the dice.
            }
            
            public void roll() {
                    // Roll the dice by setting each of the dice to be
                    // a random number between 1 and 6.
                die1 = (int)(Math.random()*6) + 1;
                die2 = (int)(Math.random()*6) + 1;
            }
            
        } // end class PairOfDice

After a PairOfDice object has just been created, the number on each die is definitely between 1 and 6, just like the number on a real die. Can we be sure that this will always be true? Not if the instance variables die1 and die2 are public, since they can be changed from outside the class. There is nothing to stop someone from changing them to 42 and -17 or anything else. It's not good enough to say that you're not supposed to do that with dice. I want an absolute guarantee that my dice objects can only have the values that real dice could have. By making die1 and die2 private, I can have that guarantee, because the code that I write in the PairOfDice class is the only code that will ever affect the values of the variables.

So, we will make die1 and die2 private, and add instance methods getDie1() and getDie2() to return the values of die1 and die2. As for other improvements, I can forsee that people who use my class will often be interested in the total on the dice, so they will tend to say things like "dice.getDie1() + dice.getDie2()" a lot. If this is going to be done over and over, why not provide a method in the class to do it? So, I will also add a method getTotal() that returns the total value showing on the two dice. The complete, modified PairOfDice class is shown below.

(Here is another improvement that I thought about. We could modify the roll() method so that in addition to rolling the dice, it would also return an int value giving the total on the dice. For example, this would allow us to replace "dice.roll(); val = dice.getTotal()" with "val = dice.roll()". Since it's legal to call a function with a subroutine call statement, we could still say "dice.roll()" if we just want to roll the dice without recording the total immediately. However, I decided that it was a little clearer to leave this feature out.)

The main program is easy, especially since we've done the same problem before without using objects (in Exercise 3.1). Note how the pair of dice object is used. To test whether or not the total on the dice is 2, I use the test "while (dice.getTotal() != 2)". To show the numbers on the two dice, I use

      System.out.println("The dice come up " + dice.getDie1() 
                                            + " and " + dice.getDie2());

Remember that a function call such as dice.getDie1() represents a value, so it can be used anyplace where a literal number or variable could be used. There is no requirement that you assign the value returned by the function to a variable. You can use it directly.

The complete main program is shown below.


The Solution


The Modified PairOfDice Class

     /*
         An object of class PairOfDice represents a pair of dice,
         where each die shows a number between 1 and 6.  The dice
         can be rolled, which randomizes the numbers showing on the
         dice.
     */
     
     public class PairOfDice {
     
        private int die1;   // Number showing on the first die.
        private int die2;   // Number showing on the second die.
        
        public PairOfDice() {
                // Constructor.  Rolls the dice, so that they initially
                // show some random values.
            roll();  // Call the roll() method to roll the dice.
        }
        
        public void roll() {
                // Roll the dice by setting each of the dice to be
                // a random number between 1 and 6.
            die1 = (int)(Math.random()*6) + 1;
            die2 = (int)(Math.random()*6) + 1;
        }
                 
        public int getDie1() {
              // Return the number showing on the first die.
           return die1;
        }
        
        public int getDie2() {
              // Return the number showing on the second die.
           return die2;
        }
        
        public int getTotal() {
              // Return the total showing on the two dice.
           return die1 + die2;
        }
        
     }  // end class PairOfDice

     
     
The Main Program

     /* 
        Rolls a pair of dice until the dice come up snake eyes
        (with a total value of 2).  Counts and reports the
        number of rolls.
     */
     
     public class Main {
     
        public static void main(String[] args) {
           
           PairOfDice dice;          // A variable that will refer to the dice.
           int rollCount;    // Number of times the dice have been rolled.
     
           dice = new PairOfDice();  // Create the PairOfDice object.
           rollCount = 0;
           
           /* Roll the dice until they come up snake eyes. */
           
           do {
               dice.roll();
               System.out.println("The dice come up " + dice.getDie1() 
                                                + " and " + dice.getDie2());
               rollCount++;
           } while (dice.getTotal() != 2);
           
           /* Report the number of rolls. */
           
           System.out.println("\nIt took " + rollCount + " rolls to get a 2.");
           
        }
        
     }  // end class RollFor2
     

[ Exercises | Chapter Index | Main Index ]