// Michael Tartagli
// 30 April 2002
// Two-way game program where user chooses either to guess the computer's number
//		or have the computer guess the user's number


import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class GuessMyNumber extends Applet
implements ActionListener {
   private int max = 1000,    // higest possible number
               tries,         // # of guesses
               num,           // inputted number
               jump,          // amount to jump
               compCurNum,    // current number
               compRandNum;   // random number to guess
   private String message = "",     // message to print
                  errorMesg = "";   // error messages
   private boolean winner = false;  // game-over check

   private TextField guess;   // input number box
   private Button enterKey,   // input number key
                  play,       // play game key
                  high,       // guess higher key
                  low,        // guess lower key
                  gotIt;      // correct guess key
   private Choice game;       // choose game menu


   public void init()
   {
      setBackground(Color.white);

      Panel chooseGame = new Panel();
      chooseGame.setLayout(new FlowLayout(FlowLayout.CENTER, 2, 2));
      chooseGame.setBackground(new Color(200,200,200));

			// GAME OPTIONS
         game = new Choice();
         game.addItem("Which guessing game shall we play?");
         game.addItem(" 1. You guess computer\'s #.");
         game.addItem(" 2. Computer guesses your #.");
         game.setEnabled(true);
         game.select(0);

			// "GO PLAY" BUTTON
         play = new Button("Play.");
         play.setEnabled(true);
         play.addActionListener(this);

      chooseGame.add(game);
      chooseGame.add(play);

      Panel guessBox = new Panel();
      guessBox.setLayout(new FlowLayout(FlowLayout.CENTER, 2, 2));
      guessBox.setBackground(new Color(200,200,255));

			// GUESS FIELD (FOR USER-GUESSES-COMPUTER'S NUMBER GAME)
         guess = new TextField(5);
         guess.setBackground(Color.white);
         guess.setEditable(false);
         guess.addActionListener(this);

			// ENTER BUTTON (FOR USER-GUESSES-COMPUTER'S NUMBER GAME)
         enterKey = new Button("Guess it.");
         enterKey.setEnabled(false);
         enterKey.addActionListener(this);

      guessBox.add(guess);
      guessBox.add(enterKey);

      Panel hiOrLow = new Panel();
      hiOrLow.setLayout(new FlowLayout(FlowLayout.CENTER, 2, 2));
      hiOrLow.setBackground(new Color(200,200,200));

			// HI, GOT IT, OR LO (FOR COMPUTER-GUESSES-USER'S NUMBER GAME)
         high = new Button("Higher");
         high.setEnabled(false);
         high.addActionListener(this);
         gotIt = new Button("Got it!");
         gotIt.setEnabled(false);
         gotIt.addActionListener(this);
         low = new Button("Lower");
         low.setEnabled(false);
         low.addActionListener(this);

      hiOrLow.add(high);
      hiOrLow.add(gotIt);
      hiOrLow.add(low);

      add(chooseGame);
      add(guessBox);
      add(hiOrLow);
   }


   public void actionPerformed(ActionEvent E)
   {
   /* INPUT: Action event
      OUTPUT: nothing
      FUNCTION: directs computer to action of which
                user hit the corresponding button */

      Object done = E.getSource();	// OBJECT ACTED UPON
      if (done == play) setUpGame(game.getSelectedIndex());
      else if (done == guess || done == enterKey)
         guessTheNumber();
      else if (done == high) tellComputer(1);
      else if (done == gotIt) tellComputer(0);
      else if (done == low) tellComputer(-1);
      repaint();
   }


   public void setUpGame(int whichGame)
   {
   /* INPUT: which game to play
      OUTPUT: nothing
      FUNCTION: sets board objects to whether or not they
                can be acted upon; resets variables */

      message = "";	// OUTPUT MESSAGE
      tries = 0;	// NUMBER OF GUESSES
      winner = false;	// WINNER
      switch (whichGame) {
         case 0:	// GAME-OVER CASE
            game.setEnabled(true);
            game.select(0);
            play.setEnabled(true);
            guess.setEditable(false);
            enterKey.setEnabled(false);
            high.setEnabled(false);
            gotIt.setEnabled(false);
            low.setEnabled(false);
            gotError("game option");
            break;
         case 1:	// YOU-GUESS CASE
            game.setEnabled(false);
            play.setEnabled(false);
            guess.setEditable(true);
            enterKey.setEnabled(true);
            compRandNum = (int)(Math.random()*max);
            gotError("guess into the text field");
            break;
         case 2:	// COMP-GUESS CASE
            game.setEnabled(false);
            play.setEnabled(false);
            high.setEnabled(true);
            gotIt.setEnabled(true);
            low.setEnabled(true);
            jump = max/4;
            compCurNum = max/2;
            tellComputer(5);
            break;
      }
   }


   public void guessTheNumber()
   throws IllegalArgumentException
   {
   /* INPUT & OUTPUT: nothing
      FUNCTION: checks user input and gives error
                message if applicable */

      try {
         num = Integer.parseInt(guess.getText());
         if (num < 0) throw new IllegalArgumentException();
      }
      catch (NumberFormatException nfe) {
         gotError("number");
      } catch (IllegalArgumentException iae) {
         gotError("positive integer");
      }

      if (errorMesg.length() == 0) {
         tries++;
         if (num < compRandNum)
            message = "Go higher than " + num + "!";
         else if (num > compRandNum)
            message = "Go lower than " + num + "!";
         else if (num == compRandNum) {
            message = "You won! ";
            if (tries <= 10) message += "You\'re just lucky.";
            else if (tries > 10)
               message += "Better guessing-luck next time!";
            winner = true;
         }
         guess.setText("");
      }
      repaint();
   }


   public void tellComputer(int action)
   {
   /* INPUT: whether computer's guess is high (1),
             low (-1) or on the money (0), or if
             it is the first guess(5)
      OUTPUT: nada
      FUNCTION: calculates the computer's guess */

      tries++;
      message = "My guess is " + compCurNum + ".";

      if (action == 0) {
         --tries;
         message = "I won! ";
         if (tries > 10)
            message += "...but I think you cheated!";
         else
            message += "Not bad for a computer, huh!?";
         winner = true;
      } else if (action != 5) {
         compCurNum += action == -1 ? (0-jump) : (jump);
         jump = (jump+1)/2;
         if (jump <= 1) jump = 1;
         message = "My guess is " + compCurNum + ".";
      }

      repaint();
   }


   public void paint(Graphics g)
   {
   /* INPUT: graphics package
      OUTPUT: nothing
      FUNCTION: repaints screen and applicable messages */

      String range = "We\'re guessing numbers between 0 and "+max+".";

      g.setFont(new Font("Arial",Font.BOLD,12));
      g.setColor(Color.black);
      g.drawString(range, 40, 85);

      g.setColor(Color.red);
      if (errorMesg.length() > 0)
         g.drawString(errorMesg, 40, 100);

      g.setFont(new Font("Arial",Font.ITALIC + Font.BOLD,12));
      g.setColor(Color.black);
      g.drawString(message, 40, 115);

      g.setFont(new Font("Arial",Font.BOLD,12));
      if (tries > 0)
         g.drawString(tries + " guesses have been made.", 40, 130);

      if (winner) {
         g.setColor(new Color(185,185,0));
         g.drawString("Game over! Choose another game!", 40, 145);
         setUpGame(0);
      }
      errorMesg = "";
   }


   public void gotError(String e)
   {
         errorMesg = "Please put in a " + e + "!";
   }
}
