### Implementing playing cards

• Introduction to playing cards

• Playing cards:

• Properties of a playing card:

• Each playing card has a suit

 Spade, Heart, Club or Diamond

• Each playing card has a rank

 A, 2, 3, ..., Q. K, A

The Ace has 2 ranks, depending on the game played and how it is used in a hand....

• Note:

 We will not use a Joker in our playing card We will play poker with our deck of cards and this games does not use Jokers We can easily add a Joker card with a special value (like 99) and add the card to the deck.

• Representing playing cards

• We first need a code to represent the suit and rank of a playing card

• Code for the suit of a playing card:

 1 = Diamond 2 = Club 3 = Heart 4 = Spade

(I choose this code, because in most games, Spade ranks higher than Heart, Heart ranks higher than Club, and Club ranks higher than Diamond

• Code for the rank of a playing card:

 2 = 2 3 = 3 4 = 4 ... 10 = 10 11 = J 12 = Q 13 = K 14 = A

• (Initial) Data structure used to represent a (one) playing card:

 public class Card { private byte cardSuit; private byte cardRank; }

• Examples:

• cardSuit = 1 and cardRank = 4

• cardSuit = 3 and cardRank = 13

• cardSuit = 2 and cardRank = 9

• cardSuit = 4 and cardRank = 14

• Storing the encoding method inside the Card class

• We can add the following card suit and card value encoding information inside the Card class to help with decoding the card suit and card rank:

 public class Card { private static final String[] Suit = { "*", "d", "c", "h", "s"}; private static final String[] Rank = { "*", "*", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}; private byte cardSuit; private byte cardRank; }

• How to use the information in the arrays Suit[] and Rank[]:

 Suit[0] is not used ("*" means error) Suit[1] contains the string "d" (for Diamond) Suit[2] contains the string "c" (for Club) Suit[3] contains the string "h" (for Heart) Suit[4] contains the string "s" (for Spade) Rank[2] contains the string "2" ... Rank[10] contains the string "10" Rank[11] contains the string "J" Rank[12] contains the string "Q" Rank[13] contains the string "K" Rank[14] contains the string "A"

So:

 Suit[ cardSuit ] gives us the suit information of the card Rank[ cardRank ] gives us the rank information of the card

• Examples:

• cardSuit = 1 and cardRank = 4

Suit[1] = "d" and Rank[4] = "4"

• cardSuit = 3 and cardRank = 13

Suit[3] = "h" and Rank[13] = "K"

• cardSuit = 2 and cardRank = 9

Suit[2] = "c" and Rank[9] = "9"

• cardSuit = 4 and cardRank = 14

Suit[4] = "s" and Rank[14] = "A"

• Further information encoding:

• We can improve the readability by defining some symbolic constants that describe the suit information:

 public class Card { public static final int SPADE = 4; public static final int HEART = 3; public static final int CLUB = 2; public static final int DIAMOND = 1; private static final String[] Suit = { "*", "d", "c", "h", "s"}; private static final String[] Rank = { "*", "*", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}; private byte cardSuit; private byte cardRank; }

With these symblic constants, we don't have to remember the facts that: 4 = Spade, 3 = Heart, and so on...

• Constructor(s) for a Playing Card

• Rules of thumb:

 Always define a constructor method Define only constructor methods that make sense (i.e., that somebody will actually use)

• Purpose of constructor methods

 Create a playing card

Information necessary to create a playing card:

 The suit of the card The rank of the crad

A useful constructor:

 public Card ( int suit, int rank ) { initial the instance variables "cardSuit" and "cardRank" to represent this play card. }

• Is the default constructor useful ?

 Is there a special card in the deck that you would want to create by default ? Not likely So: omit it...

• Is the copy constructor useful ?

 Would you want to copy an existing card (in a deck of card) ? Not likely, because each card is uniuqe So: omit it...

• Constructor Method for the Card class:

 public class Card { public static final int SPADE = 4; public static final int HEART = 3; public static final int CLUB = 2; public static final int DIAMOND = 1; private static final String[] Suit = { "*", "d", "c", "h", "s"}; private static final String[] Rank = { "*", "*", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}; private byte cardSuit; private byte cardRank; /* ---------------------------------------------------------------- Constructor Example usage: Card x = new Card( Card.SPADE, 1 ); // Ace of Spade Card x = new Card( Card.HEART, 11 ); // Jack of Heart --------------------------------------------------------------- */ public Card( int suit, int rank ) { if ( rank == 1 (Ace) ) cardRank = 14; // Give Ace the rank 14 else cardRank = (byte) rank; cardSuit = (byte) suit; } }

• Taking stock of the Card class

• Examine the Card class carefully:

 public class Card { public static final int SPADE = 4; public static final int HEART = 3; public static final int CLUB = 2; public static final int DIAMOND = 1; private static final String[] Suit = { "*", "d", "c", "h", "s"}; private static final String[] Rank = { "*", "*", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}; private byte cardSuit; private byte cardRank; /* ---------------------------------------------------------------- Constructor Example usage: Card x = new Card( Card.SPADE, 1 ); // Ace of Spade Card x = new Card( Card.HEART, 11 ); // Jack of Heart --------------------------------------------------------------- */ public Card( int suit, int rank ) { if ( rank == 1 (Ace) ) cardRank = 14; // Give Ace the rank 14 else cardRank = (byte) rank; cardSuit = (byte) suit; } }

• Remember that the private variables (methods) are inaccessible by program statements located outside the Card class

So to your program, the Card class looks like THIS:

 public class Card { public Card( int suit, int rank ) { if ( rank == 1 (Ace) ) cardRank = 14; // Give Ace the rank 14 else cardRank = (byte) rank; cardSuit = (byte) suit; } }

• In other words:

 With the definition of the Card class that we have written so far, a Java program can only create a Card object A Java program cannot do any other operations on a Card object !!!

• What can you do with a Playing Card....

• What can you do with a Computer Simulated Playing card

• Not these tricks:

• A Computer Simulated Playing card is not physical...

You can only do these operations to them:

 Read some of the information that has been stored away Update (write) some of the information that has been stored away

• Operations on Computer Simulated Object are implemented as methods

• What operations do we want on a Playing Card ?

• Operations:

 Get the suit of a playing card as a number (for computational purposes)           Get the suit of a playing card as a String (for printing purposes) Get the rank of a playing card as a number (for computational purposes) Get the rank of a playing card as a String (for printing purposes)

• Note:

 We do not need to change the suit or the rank of a playing card So.... we do not need to implement any update operations

• The suit() and the rank() methods for the Playing Card:

 public class Card { public static final int SPADE = 4; public static final int HEART = 3; public static final int CLUB = 2; public static final int DIAMOND = 1; private static final String[] Suit = { "*", "d", "c", "h", "s"}; private static final String[] Rank = { "*", "*", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}; private byte cardSuit; private byte cardRank; /* ---------------------------------------------------------------- Constructor Example usage: Card x = new Card( Card.SPADE, 1 ); // Ace of Spade Card x = new Card( Card.HEART, 11 ); // Jack of Heart --------------------------------------------------------------- */ public Card( int suit, int rank ) { if ( rank == 1 (Ace) ) cardRank = 14; // Give Ace the rank 14 else cardRank = (byte) rank; cardSuit = (byte) suit; } public int suit() { return ( cardSuit ); // This is a shorthand for: // this.cardSuit } public String suitStr() { return( Suit[ cardSuit ] ); // This is a shorthand for: // this.Suit[ this.cardSuit ] } public int rank() { return ( cardRank ); } public String rankStr() { return ( Rank[ cardRank ] ); } }

• Printing a Playing Card

 Always include the toString() method in a class This will allow the Java Program to print the object variable in a format that is taylored for that object

• Printing a Playing card

• We will print a playing card as

 Rank+Suit

Example:

 5s = 5 of spade 4h = 4 of heart Kd = K of diamond Qc = Q of club

• The toString() method:

 public class Card { public static final int SPADE = 4; public static final int HEART = 3; public static final int CLUB = 2; public static final int DIAMOND = 1; private static final String[] Suit = { "*", "d", "c", "h", "s"}; private static final String[] Rank = { "*", "*", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}; private byte cardSuit; private byte cardRank; public Card( int suit, int rank ) { if ( rank == 1 ) cardRank = 14; // Give Ace the rank 14 else cardRank = (byte) rank; cardSuit = (byte) suit; } ..... (some methods omitted for brevity)..... public String toString() { return ( Rank[ cardRank ] + Suit[ cardSuit ] ); } }

• This is the final version of the Card class:

 public class Card { public static final int SPADE = 4; public static final int HEART = 3; public static final int CLUB = 2; public static final int DIAMOND = 1; private static final String[] Suit = { "*", "d", "c", "h", "s"}; private static final String[] Rank = { "*", "*", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}; private byte cardSuit; private byte cardRank; public Card( int suit, int rank ) { if ( rank == 1 ) cardRank = 14; // Give Ace the rank 14 else cardRank = (byte) rank; cardSuit = (byte) suit; } public int suit() { return ( cardSuit ); // This is a shorthand for: // this.cardSuit } public String suitStr() { return( Suit[ cardSuit ] ); // This is a shorthand for: // this.Suit[ this.cardSuit ] } public int rank() { return ( cardRank ); } public String rankStr() { return ( Rank[ cardRank ] ); } public String toString() { return ( Rank[ cardRank ] + Suit[ cardSuit ] ); } }

• Using the Card class to make card objects

• Next, we will discuss how to use the Card class to create card objects