
/**
 *  A Dice object shows a pair of dice.  Methods are provided for
 *  rolling the dice, for setting them to specified values, and
 *  getting the values.  The size of this component should be
 *  about 100-by-100 pixels.  It should only be used in contexts
 *  where this size limit can be guaranteed.  Initially, the dice 
 *  show 4 and 3.
 */


import java.awt.*;


public class Dice extends Canvas {

   private int die1 = 4;  // The values shown on the dice.
   private int die2 = 3;


   public Dice() {
          // Constructor.  To initialize the canvas, set a 
          // light blue background color. 
       setBackground( new Color(200,200,250) );
   }
   


   // NOTE:  The following four methods are synchronized so that
   //        it will not be possible to get or set the values of
   //        the dice while the dice are being rolled.
   
   
   synchronized public void setDice(int d1, int d2) {
          // Set the dice to the specified values.  If the values
          // are not in the range 1 to 6, an exception is thrown.
      if (die1 < 1 || die1 > 6 || die2 < 1 || die2 > 6)
         throw new IllegalArgumentException("Out-of-range values for dice.");
      die1 = d1;
      die2 = d2;
      repaint();
   }
   

   synchronized public int getDie1() {
         // Return the value of the first of the two dice.
      return die1;
   }
   

   synchronized public int getDie2() {
         // Return the value of the second of the two dice.
      return die2;
   }
   

   synchronized public int getTotal() {
         // Return the total of the two dice.
      return die1 + die2;
   }
   
   
   synchronized public int roll() {
         // Roll the dice.  This will take up a small amount of time
         // (one second or less) during which the user interface will
         // stop responding.  The dice are shown with several random 
         // values befor they stop "rolling".  The final total on the
         // dice is returned as the value of the function.
      int times = (int)(3*Math.random()) + 3;
      for (int i = 0; i < times; i++) {
         die1 = die2 = 0;
         directPaint();
         delay(100);
         die1 = (int)(6*Math.random()) + 1;
         die2 = (int)(6*Math.random()) + 1;
         directPaint();
         if (i < times-1)
            delay(100);
      }
      return die1 + die2;
   }
   

   private void delay(int milliseconds) {
         // A method that just waits for the specified number of seconds.
      try {
         Thread.sleep(milliseconds);
      }
      catch (InterruptedException e) {
      }
   }


   public void paint(Graphics g) {
          // The paint method draws the two dice.
      drawDie(g, die1, 10, 10);
      drawDie(g, die2, 55, 55);
      g.setColor(Color.blue);
      g.drawRect(0,0,getSize().width-1,getSize().height-1);
   }
   
   
   private void directPaint() {
      Graphics g = getGraphics();
      g.setColor(getBackground());
      g.fillRect(0,0,getSize().width,getSize().height);
      paint(g);
      g.dispose();
   }


   private void drawDie(Graphics g, int val, int x, int y) {
         // Draw a die with upper left corner at (x,y).  The die is
         // 3 5 by 35 pixels in size.  The val parameter gives the
         // value showing on the die (that is, the number of dots).
         // Note that if val is zero, no dots will be drawn on the
         // dice.  The 
      g.setColor(Color.white);
      g.fillRect(x, y, 35, 35);
      g.setColor(Color.black);
      g.drawRect(x, y, 34, 34);
      if (val > 1)  // upper left dot
         g.fillOval(x+3, y+3, 9, 9);
      if (val > 3)  // upper right dot
         g.fillOval(x+23, y+3, 9, 9);
      if (val == 6) // middle left dot
         g.fillOval(x+3, y+13, 9, 9);
      if (val % 2 == 1) // middle dot (for odd-numbered val's)
         g.fillOval(x+13, y+13, 9, 9);
      if (val == 6) // middle right dot
         g.fillOval(x+23, y+13, 9, 9);
      if (val > 3)  // bottom left dot
         g.fillOval(x+3, y+23, 9, 9);
      if (val > 1)  // bottom right dot
         g.fillOval(x+23, y+23, 9,9);
   }


   public Dimension getPreferredSize() {
        // The size of this canvas MUST be about 100 pixels.
      return new Dimension(100,100);
   }

} // end class Dice
