/*
   This program is a simple card game.  The user sees a card and
   tries to predict whether the next card will be higher or 
   lower.  Aces are the lowest-valued cards.  If the user makes
   three correct predictions, the user wins.  If not, the
   user loses.
   
   This program is almost the same as the applet, HighLowGUI2.java,
   modified to use a JFrame instead of a JApplet.  As a demonstration,
   a WindowListener has been added to ask whether the user really
   wants to quit, when the user closes the window.
      
*/

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class HighLowFrame extends JFrame 
{

   Image cardImages;   // This will be an image that contains pictures
                       // of all the playing cards.  It is provided
                       // as a parameter to the constructor of this
                       // class of this class and is used in the
                       // drawCard method in nested class HighLowCanvas.
                       // (The images are stored in a file named
                       // "smallcards.gif".)
                       
   boolean runStandAlone;  // This is set to true in the main routine,
                           // to indicate that the frame is being run
                           // as a stand-alone program (rather than being
                           // opened by an applet, for example).  If this
                           // variable is true when the user closes the
                           // window, then System.exit() will be called
                           // to end the program.
                       
   public static void main(String[] args) 
   {
           // Main program simply opens a frame belonging
           // to this class, and sets the variable "runStandAlone"
           // in that frame to true.  The image file for the
           // cards is loaded using a "Toolkit" and is provided
           // as a parameter to the constructor.
      Image cards = Toolkit.getDefaultToolkit().getImage("smallcards.gif");
      HighLowFrame game = new HighLowFrame(cards);
      game.runStandAlone = true;
   }

   public HighLowFrame(Image cards) 
   {
   
         // The constructor.  The parameter must be an image
         // containing the card images.  I've done things this
         // way because images have to be loaded in different 
         // ways in applets and in stand-alone programs.
         // A HighLowCanvas occupies the CENTER position of the layout.
         // On the bottom is a panel that holds three buttons.  The
         // HighLowCanvas object listens for ActionEvents from the
         // buttons and does all the real work of the program.
         
      super("High Low Card Game");  // Call constructor to give
                                    // a title to the window.
                                    
      cardImages = cards;
         
      setBackground( new Color(130,50,40) );
      
      HighLowCanvas board = new HighLowCanvas();
      getContentPane().add(board, BorderLayout.CENTER);
      
      JPanel buttonPanel = new JPanel();
      buttonPanel.setBackground( new Color(220,200,180) );
      getContentPane().add(buttonPanel, BorderLayout.SOUTH);
      
      JButton higher = new JButton( "Higher" );
      higher.addActionListener(board);
      buttonPanel.add(higher);
      
      JButton lower = new JButton( "Lower" );
      lower.addActionListener(board);
      buttonPanel.add(lower);
      
      JButton newGame = new JButton( "New Game" );
      newGame.addActionListener(board);
      buttonPanel.add(newGame);
      
      setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
          // Closing is taken care of by the following WindowListener,
          // so we don't want any default close operation.
      
      addWindowListener( new WindowAdapter() 
      {
               // This window listener responds when the user
               // clicks the window's close box by giving the
               // user a chance to change his mind.
            public void windowClosing(WindowEvent evt) 
            {
               int response = JOptionPane.showConfirmDialog(null,
                                  "Do you really want to quit?");
               if (response == JOptionPane.YES_OPTION) 
               {
                  dispose();
                  if (runStandAlone)
                     System.exit(0);
               }
            }
      } );
         
       pack();  // Make the frame just large enough to hold
                // the components that it contains.
                
       setResizable(false);  // Don't allow the user to change
                             // the size of the frame.
                
       setLocation(150,100); 
       
       show(); // Make the frame appear on the screen.
      
   }  // end constructor
   


   class HighLowCanvas extends JPanel implements ActionListener 
   {

         // A nested class that displays the cards and does all the work
         // of keeping track of the state and responding to user events.

      Deck deck;       // A deck of cards to be used in the game.
      Hand hand;       // The cards that have been dealt.
      String message;  // A message drawn on the canvas, which changes
                       //    to reflect the state of the game.

      boolean gameInProgress;  // Set to true when a game begins and to false
                               //   when the game ends.

      Font bigFont;      // Font that will be used to display the message.
      Font smallFont;    // Font that will be used to draw the cards.


      HighLowCanvas() 
      {
            // Constructor.  Creates fonts, sets the foreground and
            // background colors, and starts the first game.
            // ALSO SETS PREFERRED SIZE so that the size can be
            // used when the frame is packed.
         setPreferredSize(new Dimension(310,120));
         setBackground( new Color(0,120,0) );
         setForeground( Color.green );
         smallFont = new Font("SansSerif", Font.PLAIN, 12);
         bigFont = new Font("Serif", Font.BOLD, 14);
         doNewGame();
      } // end constructor


      public void actionPerformed(ActionEvent evt) 
      {
             // Respond when the user clicks on a button by calling
             // the appropriate procedure.  Note that the canvas is
             // registered as a listener in frame's constructor.
         String command = evt.getActionCommand();
         if (command.equals("Higher"))
            doHigher();
         else if (command.equals("Lower"))
            doLower();
         else if (command.equals("New Game"))
            doNewGame();
      } // end actionPerformed()


      void doHigher() 
      {
               // Called by actionPerformmed() when user clicks "Higher" button.
               // Check the user's prediction.  Game ends if user guessed
               // wrong or if the user has made three correct predictions.
         if (gameInProgress == false) 
         {
               // If the game has ended, it was an error to click "Higher",
               // So set up an error message and abort processing.
            message = "Click \"New Game\" first!";
            repaint();
            return;
         }
         hand.addCard( deck.dealCard() );     // Deal a card to the hand.
         int cardCt = hand.getCardCount();
         Card thisCard = hand.getCard( cardCt - 1 );  // Card just dealt.
         Card prevCard = hand.getCard( cardCt - 2 );  // The previous card.
         if ( thisCard.getValue() < prevCard.getValue() ) 
         {
            gameInProgress = false;
            message = "Too bad! You lose.";
         }
         else if ( thisCard.getValue() == prevCard.getValue() ) 
         {
            gameInProgress = false;
            message = "Too bad, you lose on ties!";
         }
         else if ( cardCt == 4) 
         {
            gameInProgress = false;
            message = "OK!  You win!";
         }
         else 
         {
            message = "Right!  Try for " + cardCt + ".";
         }
         repaint();
      } // end doHigher()


      void doLower() 
      {
               // Called by actionPerformmed() when user clicks "Lower" button.
               // Check the user's prediction.  Game ends if user guessed
               // wrong or if the user has made three correct predictions.
         if (gameInProgress == false) 
         {
               // If the game has ended, it was an error to click "Lower",
               // So set up an error message and abort processing.
            message = "Click \"New Game\" first!";
            repaint();
            return;
         }
         hand.addCard( deck.dealCard() );     // Deal a card to the hand.
         int cardCt = hand.getCardCount();
         Card thisCard = hand.getCard( cardCt - 1 );  // Card just dealt.
         Card prevCard = hand.getCard( cardCt - 2 );  // The previous card.
         if ( thisCard.getValue() > prevCard.getValue() ) 
         {
            gameInProgress = false;
            message = "Too bad! You lose.";
         }
         else if ( thisCard.getValue() == prevCard.getValue() ) 
         {
            gameInProgress = false;
            message = "Too bad, you lose on ties.";
         }
         else if ( cardCt == 4) 
         {
            gameInProgress = false;
            message = "Great!  You win!";
         }
         else 
         {
            message = "Right!  Try for " + cardCt + ".";
         }
         repaint();
      } // end doLower()


      void doNewGame() 
      {
             // Called by the constructor, and called by actionPerformed() if
             // the use clicks the "New Game" button.  Start a new game.
         if (gameInProgress) 
         {
                 // If the current game is not over, it is an error to try
                 // to start a new game.
            message = "Finish the game first!";
            repaint();
            return;
         }
         deck = new Deck();   // Create the deck and hand to use for this game.
         hand = new Hand();
         deck.shuffle();
         hand.addCard( deck.dealCard() );  // Deal the first card into the hand.
         message = "Is the next card higher or lower?";
         gameInProgress = true;
         repaint();
      } // end doNewGame()


      public void paintComponent(Graphics g) 
      {
            // This method draws the message at the bottom of the
            // canvas, and it draws all of the dealt cards spread out
            // across the canvas.  If the game is in progress, an
            // extra card is dealt representing the card to be dealt next.
         super.paintComponent(g);
         g.setFont(bigFont);
         g.drawString(message,10,getSize().height-10);
         g.setFont(smallFont);
         int cardCt = hand.getCardCount();
         for (int i = 0; i < cardCt; i++)
            drawCard(g, hand.getCard(i), 30 + i * 70, 15);
         if (gameInProgress)
            drawCard(g, null, 30 + cardCt * 70, 15);
      } // end paintComponent()


   void drawCard(Graphics g, Card card, int x, int y)
   {
           // Draws a card as a 40 by 60 rectangle with
           // upper left corner at (x,y).  The card is drawn
           // in the graphics context g.  If card is null, then
           // a face-down card is drawn. The cards are taken
           // from an image file, smallcards.gif.
      if (card == null) 
      {  
             // Draw a face-down card
         g.setColor(Color.blue);
         g.fillRect(x,y,40,60);
         g.setColor(Color.white);
         g.drawRect(x+3,y+3,33,53);
         g.drawRect(x+4,y+4,31,51);
      }
      else 
      {
         int row = 0;
         switch (card.getSuit()) 
         {
            case Card.CLUBS:    row = 0;  break;
            case Card.HEARTS:   row = 1;  break;
            case Card.SPADES:   row = 2;  break;
            case Card.DIAMONDS: row = 3;  break;
         }
         int sx, sy;  // coords of upper left corner in the source image.
         sx = 40*(card.getValue() - 1);
         sy = 60*row;
         g.drawImage(cardImages, x, y, x+40, y+60,
                                 sx, sy, sx+40, sy+60, this);
      }
   }


   } // end nested class HighLowCanvas


} // end class HighLowFrame

(Applet "HighLowLauncher" would be displayed here
if Java were available.)

Back to Lesson 33 Examples

Back to Java Main Page