Simulating a deck of cards

  • In the real world, a deck of cards looks like this:

  • In this lecture, we will represent a deck of cards using a object in Java

  • We will also study how to implement the following instance methods to:

      • Shuffle a deck of cards
      • Deal a card from a deck of cards

  Essence of representing things in the real world using programming objects  

  • Things in the real world as physical

    • Is is not possible to represent physical things literally with computer "objects"

    • The representation will only describe the behaviors of the physical things in the real world


  • Things in the real world are represented as follows:

    1. Things in the real world have certain properties (= state)

      • Example: a car has a maximum speed

    2. Things in the real world can "do stuff" (= action)

      • Example: a car can travel

Defining the Card class to represent a card

  • A card has the following properties:

     A suit (e.g.: Spades, Hearts, Diamond, Clubs)
     A rank (e.g.: Ace, 2, 3, ..., 9, 10, Jack, Queen, King)

  • A card has the following actions:

      • A card can be read by a player   (we will add a toString() action later)

  • Therefore, the skeleton code for Card class that represents a card is:

    public class Card
    {
        private String suit;
        private String rank;
    
        public Card(...) // Constructor to create a Card object
        {
            ...
        }
    
        // "Read" a playing card (to be discussed later)
    }

Defining the Card class to represent a card

  • Recall that:

    • Every class must have a constructor method (so users can initialize objects of this class)


  • We want the ability to initialize a Card with a certain suit and rank:

    public class Card
    {
        private String suit;
        private String rank;
    
        public Card(String cardSuit, String cardRank)
        {
           // Initialize the Card with:
           //     suit = cardSuit  and rank = cardRank
        }
    
    }

    Let's write the constructor...

Defining the Card class to represent a card

  • Recall that:

    • Every class must have a constructor method (so users can initialize objects of this class)


  • The constructor of the Card class initializes the instance variable using the parameters:

    public class Card
    {
        private String suit;
        private String rank;
    
        public Card(String cardSuit, String cardRank)
        {
            suit = cardSuit; // Initialize the suit
            rank = cardRank; // Initialize the rank
        }
    
    }

    Let's create some Card objects and print them out...

How to use the Card class to make card objects

  • Sample program that instantiates 2 Card objects and print them out:

    public class myProg
    {
        public static void main(String[] args)
        {
            Card c1 = new Card("Spades", "Ace");
            Card c2 = new Card("Hearts", "10");
            
            System.out.println( c1 );
            System.out.println( c2 );
        } 
    }


  • You will see output like this:

      Card@c72318e
    

  • Let's make the System.out.println( )'s output look nicer first...

DEMO: demo/10-classes/12-card/Demo.java + Card.java

The toString( ) method to return a String representation of objects

  • Background information:

    • The System.out.println(object) call will always print the output of object.toString()

  • How you can control how an object will be printed out:

    • Define a String toString( ) method that return a String representation with the object's information

  • Example:   print a Card object as "Ace of Spades":

     public class Card
     {
        private String suit;   // Stores the suit of this card
        private String rank;   // Stores the rank of this card
    
        // Define the toString() method to control print out of a Card
        public String toString() // Used to print an object
        {
            return rank + " of " + suit;
        }
     }

Witness the effect of the toString method

  • Run the same program using the new Card class:

    public class myProg
    {
        public static void main(String[] args)
        {
            Card c1 = new Card("Spades", "Ace");
            Card c2 = new Card("Hearts", "10");
            
            System.out.println( c1 );
            System.out.println( c2 );
        } 
    }

  • The output is now:

      Ace of Spades
      10 of Hearts
    

DEMO: demo/10-classes/13-card/Demo.java + Card.java

Representing a deck of card

  • A computer program cannot replace a real deck of cards:

                

  • However:   a computer program can imitate the things you can do with a deck of cards

  • We will imitate the following "things that you can do" with a deck of cards:

      • Shuffle a deck of cards

      • Deal a card from a deck of cards

We must first define a class that represents a deck of cards...

Defining the DeckOfCards class to represent a deck of cards

  • We will now use the Card class to construct the DeckOfCards class that represents a deck of playing cards

  • A deck of cards has the following properties:

      52 playing cards consisting of:
    
          Ace of Spades,   2 of Spades,   ...., King of Spades
          Ace of Hearts,   2 of Hearts,   ...., King of Hearts
          Ace of Diamonds, 2 of Diamonds, ...., King of Diamonds
          Ace of Clubs,    2 of Clubs,    ...., King of Clubs

    Notice:   since we have the Card class, representing these playing cards are now very easy

  • A deck of cards can perform the following actions:

      shuffle( ): re-arranges the cards randomly
                  After shuffle( ), all cards are available
    	      for dealing                              
                                       
      deal( ):    deals out the top card in the deck
                  A card that is dealt cannot be dealt again

Scheletal class of the DeckOfCard class

  • From the previous description, the DeckOfCards class must contain at least the following members:

    public class DeckOfCards
    {
        private Card[] deck;  // Array that holds 52 Card objects 
    
        DeckOfCards()  // Initialize a deck of 52 cards
        {
           ....
        }
    
        public void shuffle() // Shuffle this deck of cards
        {
           perform a shuffle on the deck of cards   
        }
        
        public Card deal() // Deal the next card from this deck
        {
           returns the next card in deck
        }
    }  

Defining the DeckOfCards class to represent a deck of cards

  • Representing the 52 cards in a deck:

      52 specific cards:
    
                   
     
      Represented by array of Card objects initialized to specific cards:
    
                   

Defining the DeckOfCards class to represent a deck of cards

  • Representing the card shuffle action of a deck of cards:

      shuffle( ):
    
                   
     
      Use: random shuffle algorithm:
    
                   

Defining the DeckOfCards class to represent a deck of cards

  • Representing the "deal a card" action of a deck of cards:

      deal( ): deal the next card from the deck
    
                   
     
      Use: variable dealPosition to mark the top position in the deck:
    
                   

  Refining the definition of the DeckOfCards class to represent a deck of cards  

Based on the properties and actions, we must add the variable dealPosition to the DeckOfCards class:

public class DeckOfCards
{
    private Card[] deck;  // Hold 52 cards (to be created)
    private int    dealPosition;  // Location of the top card in deck

    DeckOfCards()  // Constructor to make a deck of cards
    {
       ....
    }

    public void shuffle() // Shuffle this deck of cards
    {
       perform a shuffle on the deck of cards   
    }
    
    public Card deal() // Deal the next card from this deck
    {
       returns the dealt card
    }
}  

Next:   implement the constructor(s) and methods...

The constructor of the DeckOfCards class

Constructor:   making a deck of cards with 52 specific cards:   ( naive approach)

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition;

    DeckOfCards()  // Constructor to make a deck of cards
    {
        deck = new Card[52];    // Make a holder for 52 cards

        deck[0] = new Card( "Spades", "Ace");
        deck[1] = new Card( "Spades", "2");
        deck[2] = new Card( "Spades", "3");
        deck[3] = new Card( "Spades", "4");
        deck[4] = new Card( "Spades", "5");
        ...
        and so on
 
	Uses 52 assignment statements !!!  


        How can we code this easier ??

    }
}  

The naive approach is very tedious to code    --    we can simplify the coding work with loops

The constructor of the DeckOfCards class

Constructor:   making a deck of cards with 52 specific cards:

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition;

    DeckOfCards()  // Constructor to make a deck of cards
    {
        deck = new Card[52];    // Make a holder for 52 cards

        // Define 2 arrays with all the suits and ranks
        String[] suit = {"Spades", "Hearts", "Diamonds", "Clubs"};
        String[] rank = {"Ace", "2", "3", "4", "5", "6", "7", "8",
                         "9", "10", "Jack", "Queen", "King"};


 
       

        
         
        
       
    }
}  

The suit[] array contains all possible suits and The rank[] array contains all possible ranks of the cards

The constructor of the DeckOfCards class

Constructor:   making a deck of cards with 52 specific cards:

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition;

    DeckOfCards()  // Constructor to make a deck of cards
    {
        deck = new Card[52];    // Make a holder for 52 cards


        String[] suit = {"Spades", "Hearts", "Diamonds", "Clubs"};
        String[] rank = {"Ace", "2", "3", "4", "5", "6", "7", "8",
                         "9", "10", "Jack", "Queen", "King"};

        int k = 0;   // Index into deck[ ]
        // Use a nested loop to make all 52 cards and store it in deck[k]
        for ( int i = 0; i < suit.length; i++ )
            for (int j = 0; j < rank.length; j++ )
            {
                deck[k] = new Card( suit[i], rank[j] );
                k++;
            }
    }
}  

The index i go through all the suits and the index j go through all the ranks

Prelude to shuffle()    swap value in 2 variables

Before we write the shuffle() method, we review how to swap 2 variables:

 

 

Prelude to shuffle()    swap value in 2 variables

Before we write the shuffle() method, we review how to swap 2 variables:

public class MyProg
{
   public static void main(String[] args)
   {
       int a = 1, b = 2;

       

       // Code to swap values in a and b


       // End result: a = 2, b = 1
   }
}
  

Prelude to shuffle()    swap value in 2 variables

The algorithm used to exchange the values in the variables a and b:

public class MyProg
{
   public static void main(String[] args)
   {
       int a = 1, b = 2;

       int help;       

       // Code to swap values in a and b
       help = a;
       a = b;
       b = help;
   }
}
  

The shuffle() method of the DeckOfCards class

The shuffle() method will re-arrange the cards randomly and allow all cards to be dealt:

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition;

    DeckOfCards() ...  // Done 

    public void shuffle()  // Shuffle this deck of cards
    { 
        for (int i = 0; i < deck.length; i++) 
        { // Generate an index randomly
            int j = (int)(Math.random() * deck.length);

            Card temp = deck[i];   // Swap
            deck[i] = deck[j];
            deck[j] = temp;
        }
        
        dealPosition = 0;
    }
} 

The shuffle() method of the DeckOfCards class

Go through every card i in the deck:

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition;

    DeckOfCards() ...  // Done 

    public void shuffle()  // Shuffle this deck of cards
    {
        for (int i = 0; i < deck.length; i++) 
        {  
           

           
            
            
        }
         
        dealPosition = 0;
    }
} 

The shuffle() method of the DeckOfCards class

Pick a random card j to swap with the card i:

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition;

    DeckOfCards() ...  // Done 

    public void shuffle()  // Shuffle this deck of cards
    {
        for (int i = 0; i < deck.length; i++) 
        {  // Generate an index j randomly
            int j = (int)(Math.random() * deck.length);

            
           
            
        }
         
        dealPosition = 0;
    }
} 

The shuffle() method of the DeckOfCards class

Swap card[i] and card[j]:

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition;

    DeckOfCards() ...  // Done 

    public void shuffle()  // Shuffle this deck of cards
    {
        for (int i = 0; i < deck.length; i++) 
        {  // Generate an index j randomly
            int j = (int)(Math.random() * deck.length);

            Card temp = deck[i];   // Swap card[i] and card[j]
            deck[i] = deck[j];
            deck[j] = temp;
        }
         
        dealPosition = 0;
    }
} 

The shuffle() method of the DeckOfCards class

Reset dealPosition to point to the top card in the deck:

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition; // Marks the position of next card

    DeckOfCards() ...  // Done 

    public void shuffle()  // Shuffle this deck of cards
    {
        for (int i = 0; i < deck.length; i++) 
        {  // Generate an index j randomly
            int j = (int)(Math.random() * deck.length);

            Card temp = deck[i];   // Swap card[i] and card[j]
            deck[i] = deck[j];
            deck[j] = temp;
        }
       
        dealPosition =  0 ; // Reset the next deal card position to the top
    }
} 

The deal() method of the DeckOfCards class

The deal() method will deal out (= returns) the next card in the deck of cards

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition; // Marks the position of next card

    DeckOfCards() ...  // Done 

    public void shuffle() ...  // Done 

    public Card deal()  // deals (= returns) the next card in this deck
    {
        Card nextCard;  // Variable to store the next card dealt

        
        
           
            
        
       
           

        
    }
} 

The deal() method of the DeckOfCards class

If the deck has some cards left, (1) save the next card in nextCard and (2) advance dealPosition:

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition; // Marks the position of next card

    DeckOfCards() ...  // Done 

    public void shuffle() ...  // Done 

    public Card deal()  // deals (= returns) the next card in this deck
    {
        Card nextCard;

        if ( dealPosition < deck.length )
        {
            nextCard = deck[dealPosition];   // (1) save the next card dealt
            dealPosition++;                  // (2) advance to next card in deck
        }
      
           

        
    }
} 

The deal() method of the DeckOfCards class

Otherwise (the deck has no cards left), return null to indicate an error:

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition; // Marks the position of next card

    DeckOfCards() ...  // Done 

    public void shuffle() ...  // Done 

    public Card deal()  // deals (= returns) the next card in this deck
    {
        Card nextCard;

        if ( dealPosition < deck.length )
        {
            nextCard = deck[dealPosition];   // (1) save the next card dealt
            dealPosition++;                  // (2) advance to next card in deck
        }
        else
            nextCard = null;    // null is a special value to indicate error in Java

      
    }
} 

The deal() method of the DeckOfCards class

Return the saved next card:

public class DeckOfCards
{
    private Card[] deck;
    private int    dealPosition; // Marks the position of next card

    DeckOfCards() ...  // Done 

    public void shuffle() ...  // Done 

    public Card deal()  // deals (= returns) the next card in this deck
    {
        Card nextCard;

        if ( dealPosition < deck.length )
        {
            nextCard = deck[dealPosition];
            dealPosition++;
        }
        else
            nextCard = null;    // null is a special value to indicate error in Java

        return nextCard;
    }
} 

How to use the DeckOfCards class

This Java program shows how to create one deck of cards and deal out some cards:

public class myProg
{
    public static void main(String[] args)
    {
        DeckOfCards d = new DeckOfCards();   // Create 1 deck of cards
        
        for ( int i = 0; i < 53; i++ )
            System.out.println( d.deal() );  // Deal out 53 cards
        System.out.println();
            
        d.shuffle();                         // Shuffle the deck d

        for ( int i = 0; i < 5; i++ )
            System.out.println( d.deal() );  // Deal out 5 cards after shuffle
    } 
} 

DEMO: demo/10-classes/14-card/Demo.java + DeckOfCards.java + Card.java

We can use the DeckOfCards class to create any number of decks of cards
The DeckOfCards class will help you write Java program that play card games !!!