/*
   This applet 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 version of the game uses images of the cards, stored
   in a file smallcards.gif.  Each card is 40 pixels wide and
   60 pixels high.  Other than that, the applet is the same as
   the original HighLowGUI.
   
   The programming of this applet assumes that the applet is
   set up to be about 316 pixels wide and about 150 pixels high.
   That width is just big enough to show 4 cards, with spacing and
   borders.  The height is probably a little bigger than necessary,
   to allow for variations in the size of buttons from one platform
   to another.
   
   This file defines two class files, the applet class HighLowGUI2.class
   and a nested class HighLowGUI2$HighLowCanvas.class.  Both files
   are necessary to use the applet.
*/

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

public class HighLowGUI2 extends JApplet 
{

   Image cardImages;   // This will be an image that contains pictures
                       // of all the playing cards.  It is loaded in the
                       // init method of the applet and is used in the
                       // drawCard method in nested class HighLowCanvas.
                       
   public void init()
   {
   
         // The init() method loads the card image and lays out the applet.
         // 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.
         
      cardImages = getImage( getCodeBase(), "smallcards.gif" );
         
      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);
      
   }  // end init()
   
   public Insets getInsets() 
   {
         // Specify how much space to leave between the edges of
         // the applet and the components it contains.  The background
         // color shows through in this border.
      return new Insets(3,3,3,3);
   }


   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.
         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 applet's init() method.
         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, 10);
         if (gameInProgress)
            drawCard(g, null, 30 + cardCt * 70, 10);
      } // 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 HighLowGUI



/*
    An object of type Hand represents a hand of cards.  The maximum number of
    cards in the hand can be specified in the constructor, but by default
    is 5.  A utility function is provided for computing the value of the
    hand in the game of Blackjack.
*/

import java.util.Vector;

public class Hand 
{

   private Vector hand;   // The cards in the hand.
   
   public Hand() 
   {
           // Create a Hand object that is initially empty.
      hand = new Vector();
   }
   
   public void clear() 
   {
         // Discard all the cards from the hand.
      hand.removeAllElements();
   }
   
   public void addCard(Card c) 
   {
         // Add the card c to the hand.  c should be non-null.  (If c is
         // null, nothing is added to the hand.)
      if (c != null)
         hand.addElement(c);
   }
   
   public void removeCard(Card c) 
   {
         // If the specified card is in the hand, it is removed.
      hand.removeElement(c);
   }
   
   public void removeCard(int position) 
   {
         // If the specified position is a valid position in the hand,
         // then the card in that position is removed.
      if (position >= 0 && position < hand.size())
         hand.removeElementAt(position);
   }
   
   public int getCardCount() 
   {
         // Return the number of cards in the hand.
      return hand.size();
   }
   
   public Card getCard(int position) 
   {
          // Get the card from the hand in given position, where positions
          // are numbered starting from 0.  If the specified position is
          // not the position number of a card in the hand, then null
          // is returned.
      if (position >= 0 && position < hand.size())
         return (Card)hand.elementAt(position);
      else
         return null;
   }
   
   public void sortBySuit() 
   {
         // Sorts the cards in the hand so that cards of the same suit are
         // grouped together, and within a suit the cards are sorted by value.
         // Note that aces are considered to have the lowest value, 1.
      Vector newHand = new Vector();
      while (hand.size() > 0) 
      {
         int pos = 0;  // Position of minimal card.
         Card c = (Card)hand.elementAt(0);  // Minumal card.
         for (int i = 1; i < hand.size(); i++) 
         {
            Card c1 = (Card)hand.elementAt(i);
            if ( c1.getSuit() < c.getSuit() ||
                    (c1.getSuit() == c.getSuit() && c1.getValue() < c.getValue()) ) 
            {
                pos = i;
                c = c1;
            }
         }
         hand.removeElementAt(pos);
         newHand.addElement(c);
      }
      hand = newHand;
   }
   
   public void sortByValue() 
   {
         // Sorts the cards in the hand so that cards of the same value are
         // grouped together.  Cards with the same value are sorted by suit.
         // Note that aces are considered to have the lowest value, 1.
      Vector newHand = new Vector();
      while (hand.size() > 0) 
      {
         int pos = 0;  // Position of minimal card.
         Card c = (Card)hand.elementAt(0);  // Minumal card.
         for (int i = 1; i < hand.size(); i++) 
         {
            Card c1 = (Card)hand.elementAt(i);
            if ( c1.getValue() < c.getValue() ||
                    (c1.getValue() == c.getValue() && c1.getSuit() < c.getSuit()) ) 
            {
                pos = i;
                c = c1;
            }
         }
         hand.removeElementAt(pos);
         newHand.addElement(c);
      }
      hand = newHand;
   }
   
}


/* 
    An object of type Deck represents an ordinary deck of 52 playing cards.
    The deck can be shuffled, and cards can be dealt from the deck.
*/

public class Deck 
{

    private Card[] deck;   // An array of 52 Cards, representing the deck.
    private int cardsUsed; // How many cards have been dealt from the deck.
    
    public Deck()
    {
           // Create an unshuffled deck of cards.
       deck = new Card[52];
       int cardCt = 0; // How many cards have been created so far.
       for ( int suit = 0; suit <= 3; suit++ ) 
       {
          for ( int value = 1; value <= 13; value++ ) 
          {
             deck[cardCt] = new Card(value,suit);
             cardCt++;
          }
       }
       cardsUsed = 0;
    }
    
    public void shuffle() 
    {
          // Put all the used cards back into the deck, and shuffle it into
          // a random order.
        for ( int i = 51; i > 0; i-- ) 
        {
            int rand = (int)(Math.random()*(i+1));
            Card temp = deck[i];
            deck[i] = deck[rand];
            deck[rand] = temp;
        }
        cardsUsed = 0;
    }
    
    public int cardsLeft() 
    {
          // As cards are dealt from the deck, the number of cards left
          // decreases.  This function returns the number of cards that
          // are still left in the deck.
        return 52 - cardsUsed;
    }
    
    public Card dealCard() 
    {
          // Deals one card from the deck and returns it.
        if (cardsUsed == 52)
           shuffle();
        cardsUsed++;
        return deck[cardsUsed - 1];
    }

} // end class Deck


/*
      An object of class card represents one of the 52 cards in a
      standard deck of playing cards.  Each card has a suit and
      a value.
   */

   public class Card 
   {
   
       public final static int SPADES = 0,     // Codes for the 4 suits.
                               HEARTS = 1,
                               DIAMONDS = 2,
                               CLUBS = 3;
                               
       public final static int ACE = 1,      // Codes for non-numeric cards.
                               JACK = 11,    //   Cards 2 through 10 have
                               QUEEN = 12,   //   their  numerical values
                               KING = 13;    //   for their codes.
                               
       private final int suit;   // The suit of this card, one of the
                                 //    four constants:  SPADES, HEARTS, 
                                 //    DIAMONDS, CLUBS.
                                 
       private final int value;  // The value of this card, from 1 to 13.
                                
       public Card(int theValue, int theSuit) 
       {
               // Construct a card with the specified value and suit.
               // Value must be between 1 and 13.  Suit must be between
               // 0 and 3.  If the parameters are outside these ranges,
               // the constructed card object will be invalid.
           value = theValue;
           suit = theSuit;
       }
           
       public int getSuit() 
       {
               // Return the int that codes for this card's suit.
           return suit;
       }
       
       public int getValue() 
       {
               // Return the int that codes for this card's value.
           return value;
       }
       
       public String getSuitAsString() 
       {
               // Return a String representing the card's suit.
               // (If the card's suit is invalid, "??" is returned.)
           switch ( suit ) 
           {
              case SPADES:   return "Spades";
              case HEARTS:   return "Hearts";
              case DIAMONDS: return "Diamonds";
              case CLUBS:    return "Clubs";
              default:       return "??";
           }
       }
       
       public String getValueAsString() 
       {
               // Return a String representing the card's value.
               // If the card's value is invalid, "??" is returned.
           switch ( value ) 
           {
              case 1:   return "Ace";
              case 2:   return "2";
              case 3:   return "3";
              case 4:   return "4";
              case 5:   return "5";
              case 6:   return "6";
              case 7:   return "7";
              case 8:   return "8";
              case 9:   return "9";
              case 10:  return "10";
              case 11:  return "Jack";
              case 12:  return "Queen";
              case 13:  return "King";
              default:  return "??";
           }
       }
       
       public String toString() 
       {
              // Return a String representation of this card, such as
              // "10 of Hearts" or "Queen of Spades".
           return getValueAsString() + " of " + getSuitAsString();
       }
   
   
   } // end class Card

Back to Lesson 28 Examples

Back to Java Main Page