/*
 * @(#)MemoryGame.java     2.0 96/11/04 Kerry Imming
 *
 */

import java.awt.*;
import java.lang.Math;

public class MemoryGame extends java.applet.Applet implements Timed {

  Button b[] = new Button[16];
  int iChoice1 = -1;
  String label[] = { "1 + 5 =", "2 + 3 =", "1 + 3 =", "2 + 1 =",
                     "7 + 2 =", "6 + 1 =", "5 + 4 =", "3 + 5 =",
                     "6", "5", "4", "3",
                     "9", "7", "9", "8" };
  int labelPtr[] = { 1, 2, 3, 4, 5, 6, 5, 8,
                   -1, -2, -3, -4, -5, -6, -5, -8 };
  int bState[] = {1, 1, 1, 1, 1, 1, 1, 1,
                  1, 1, 1, 1, 1, 1, 1, 1 };

  public void init() {
    int i;

    setLayout( new BorderLayout() );
    Panel menuBar = new Panel();
    Panel grid = new Panel();
    add("North", menuBar);
    add("Center", grid);

    menuBar.add(new Button("New Game") );
    menuBar.add(new Button("Peek") );
    menuBar.add(new Button("Quit") );
    grid.setLayout( new GridLayout( 4, 4, 2, 2) );

    for (i = 0; i < b.length; i++) {
      b[i] = new Button("???");
      grid.add( b[i] );
      }
    shuffle();
    new Timer(this, 1500).start();
   }
 
  public Insets insets() {
    return new Insets(2,2,2,2);
  }

  public boolean action(Event evt, Object arg) {
    int i;
    if (evt.target instanceof Button) {
      if ("New Game".equals(arg) ) {
        clear();
        iChoice1 = -1;
        shuffle();
      }
      else if ("Peek".equals(arg) ) {
        peek();
      }
      else if ("Quit".equals(arg) ) {
        quit();
      }
      else {
        for (i=0; i<b.length; i++) {
          if (evt.target == b[i] && "???".equals(arg) ) {
            b[i].setLabel(label[i]);
            bState[i] = 2;  /* face up */
            if (iChoice1 < 0) {
              /* First pick */
              iChoice1 = i;
            }
            else {
              if (labelPtr[i] == -labelPtr[iChoice1]) {
                /* Second pick -- Match */
                bState[i] = -13;   /* disable pending */
                bState[iChoice1] = -13;
              }
              else {
                /* Second pick -- no match */
                bState[i] = -11;
                bState[iChoice1] = -11;
              }
              iChoice1 = -1;
            }
            break;
          }
        }
      }
    }
    return true;
  }

  public void tick(Timer t) {
    int i;
 
    for (i=0; i<b.length; i++) {
      switch (bState[i]) {
         case  1:  /* face down */
         case  2:  /* face up */
         case  3:  /* disabled */
                    break;
         case -2:  b[i].setLabel(label[i]);
                    b[i].enable();
                    bState[i] = 2;
                    break;
         case -1:  b[i].setLabel("???");
                    b[i].enable();
                    bState[i] = 1;
                    break;
         case -3:  b[i].setLabel(label[i]);
                    b[i].disable();
                    bState[i] = 3;
                    break;
         case -11: bState[i] = -1;
                    break;
         case -12: bState[i] = -2;
                    break;
         case -13: bState[i] = -3;
                     break;
       }
     }
    /* repaint();  */
  }

  private void clear() {
    int i;
    for (i = 0; i < b.length; i++) {
      b[i].setLabel("???");
      b[i].enable();
      bState[i] = 1;
      }
  }

  private void peek() {
    int i;
    for (i = 0; i<b.length; i++) {
      if (bState[i] == 1) {
        b[i].setLabel(label[i]);
        bState[i] = -11;
      }
    }
  }

  private void quit() {
    for (int i = 0; i<b.length; i++) {
      if (bState[i] == 1) {
        b[i].setLabel(label[i]);
        bState[i] = 2;
      }
    }
  }

  private void shuffle() {
    int i;
    int j1;
    int j2;
    int tempLabelPtr;
    String tempLabel;
    for (i=0; i<48; i++) {
      j1 = (int) (Math.random() * (b.length + 0));
      j2 = (int) (Math.random() * (b.length + 0));
      tempLabelPtr = labelPtr[j1];
      labelPtr[j1] = labelPtr[j2];
      labelPtr[j2] = tempLabelPtr;
      tempLabel = label[j1];
      label[j1] = label[j2];
      label[j2] = tempLabel;
    }
  }

}

interface Timed {
  public void tick(Timer t);
}

class Timer extends Thread {
  private Timed target;
  private int interval;

  public Timer(Timed t, int i) {
    target = t;
    interval = i;
    setDaemon(true);
  }

  public void run() {
    while (true) {
      try { Thread.sleep(interval); }
      catch (InterruptedException e) { }
      target.tick(this);
    }
  }
}
