// Purpose.  MasterMind demo.  AWT application - and - applet

import java.awt.*;   import java.awt.event.*;   import java.applet.Applet;

public class MasterMindGUI extends Applet {
   private MMBoard board;

   class MMBL implements ActionListener {
      public void actionPerformed( ActionEvent e ) {
         if (e.getActionCommand().equals("Submit guess")) {
            if (board.guess()) ((Button)e.getSource()).setLabel( "Go again?" );
         } else {
            ((Button)e.getSource()).setLabel( "Submit guess" );
            board.reset();
            board.repaint();
   }  }  }

   class MMBoard extends Canvas {
      public  boolean giveAnswer    = false;
      private Color   guesses[][]   = new Color[10][4];
      private Color   responses[][] = new Color[10][4], curCol;
      private Color   colors[]      = { Color.red, Color.green, Color.blue,
         Color.cyan, Color.magenta, Color.yellow };
      private int answer[] = new int[4], ansNums[] = new int[6], curRow, dw, dh;

      class MMML extends MouseAdapter {
         public void mousePressed( MouseEvent e ) {
            int x = e.getX(), y = e.getY();
            if (y < dh) {                              // click above the board
               board.giveAnswer = ! board.giveAnswer;  // to toggle the answer
               board.repaint();
            } else if (y < dh*11+dh/2) {               // click in a column to
               x = (x - dw) / dw;                      // place a color
               guesses[curRow][x] = curCol;
               repaint(); 
            } else {                                   // click below the board
               x = (x - dw/2) / dw;                    // to select a color
               curCol = colors[x];
      }  }  }

      public MMBoard() {
         setBackground( Color.white );
         addMouseListener( new MMML() );
         reset();
      }
      public void reset() {
         for (int i=0; i < 10; i++)
            for (int j=0; j < 4; j++) {
               guesses[i][j] = Color.white;
               responses[i][j] = Color.lightGray;
            }
         curRow = 0;
         curCol = Color.red;
         giveAnswer = false;
         for (int i=0; i < 4; i++) answer[i] = (int)(Math.random()*1000) % 6;
         for (int i=0; i < 6; i++) ansNums[i] = 0;
         for (int i=0; i < 4; i++) ansNums[ answer[i] ]++;
      }
      public void paint( Graphics g ) {       // paint() is defined on Canvas,
         dw = (int) getSize().width / 7;      //   not on Applet
         dh = (int) getSize().height / 13;
         fillBoard( g );  drawBoard( g );
      }
      private void fillBoard( Graphics g ) {
         if (giveAnswer)
            for (int j=0; j < 4; j++) {
               g.setColor( colors[answer[j]] );
               g.fillRect( dw*j+dw, 0, dw, dh ); }
         for (int i=0; i <= curRow; i++)
            for (int j=0; j < 4; j++) {
               g.setColor( guesses[i][j] );
               g.fillRect( dw*(j+1), dh*(i+1), dw, dh ); }
         for (int i=0; i < curRow; i++)
            for (int j=0; j < 4; j++) {
               g.setColor( responses[i][j] );
               g.fillRect( 5*dw+j%2*dw/2, dh*(i+1)+j/2*dh/2, dw/2, dh/2 );
      }     }
      private void drawBoard( Graphics g ) {
         g.setColor( Color.black );
         for (int i=0; i < 11; i++) g.drawLine( dw, dh*(i+1), 6*dw, dh*(i+1) );
         for (int i=0; i <  6; i++) g.drawLine( dw*(i+1), dh, dw*(i+1), 11*dh );
         for (int i=0; i < 10; i++)
            g.drawLine( dw*5, (i+1)*dh+dh/2, dw*6, (i+1)*dh+dh/2 );  
         g.drawLine( dw*5+dw/2, dh, dw*5+dw/2, dh*11 );  
         for (int i=0; i < 6; i++) {
            g.setColor( colors[i] );
            g.fillRect( i*dw+dw/2, dh*11+dh/2, dw, dh );  
      }  }
      public boolean guess() {
         int input[] = new int[4], inNums[] = new int[6], black=0, white=0, i;
         for (i=0; i < 4; i++) {
            for (int j=0; j < 6; j++)
               if (guesses[curRow][i] == colors[j]) { input[i] = j;  break; }
            inNums[ input[i] ]++;
         }
         for (i=0; i < 4; i++) if (input[i] == answer[i]) black++;
         for (i=0; i < 6; i++)
            white += (inNums[i] < ansNums[i] ? inNums[i] : ansNums[i]);
         white = white - black;
         for (i=0;     i < black;       i++) responses[curRow][i] = Color.black;
         for (i=black; i < black+white; i++) responses[curRow][i] = Color.white;
         curRow++;
         repaint(); 
         if ((black == 4) || (curRow == 10)) return true;
         return false;
   }  }

   public void init() {
      board  = new MMBoard();
      Button submit = new Button( "Submit guess" );
      submit.addActionListener( new MMBL() );
      setLayout( new BorderLayout() );
      add( "Center", board  );
      add( "South",  submit );
   }
   public static void main( String[] args ) {
      Frame f = new Frame( "MasterMind" );
      f.addWindowListener( new WindowAdapter() {
         public void windowClosing( WindowEvent e ) { System.exit( 0 ); } } );
      MasterMindGUI mm = new MasterMindGUI();
      f.add( mm );
      f.setSize( new Dimension( 220, 450 ) );
      // If init() does not go before setVisible(), then the board is not drawn.
      // If init() goes before setSize(), then the first paint() may be strange.
      mm.init();
      f.setVisible( true );
}  }
