/** Version 3 of the playing card class. * I've decided not to make "denomValue" an attribute, because this would * require me to change all 4 constructors! Instead, I'll just write a * new function that computes the denomValue (2-14) based on the denom. * This is useful when comparing/sorting cards. */ public class Card { private char denom; private char suit; /** default constructor -- just initialize to Q-d */ public Card() { denom = 'Q'; suit = 'd'; } /** Initial value constructor -- given 2 parameters that specify * what the denomination and suit should be, just initialize */ public Card(char d, char s) { denom = d; suit = s; } /** This constructor would be useful when we want to shuffle cards, * because a random number generator can give us a number 1-52. * We assume that our parameter i is in the range 1-52. * Because of the behavior of the % and / operators, * the denom number will be: 1=ace, 2=two, ..., 12=queen, 0=king * and the suit number will be 0=clubs up to 3=spades. * We need to say (i-1) for calculating the suit number because * we want the outcome to be in the range 0-3, and the king of spades, * being card # 52, would have been 52/13 = 4. The other kings would have * been wrong too: 13 (king of clubs) would have been called a diamond. */ public Card(int i) { int denomNum = i % 13; int suitNum = (i-1) / 13; switch(denomNum) { case 1 : denom = 'A'; break; case 0 : denom = 'K'; break; case 12 : denom = 'Q'; break; case 11 : denom = 'J'; break; case 10 : denom = 'T'; break; default : denom = (char) (denomNum + '0'); break; } switch(suitNum) { case 0 : suit = 'c'; break; case 1 : suit = 'd'; break; case 2 : suit = 'h'; break; case 3 : suit = 's'; break; } } /** This function will return a number in the range 2-14 which * represents a numerical value of the card. This number is * based on the denomination attribute, where A=14, K=13, etc. * Assume Ace is high. * Unfortunately, this means we won't * be able to detect the rare case of a 5,4,3,2,A straight * unless we treat that as a special case elsewhere. * @param none */ public int findDenomValue() { int denomValue = 0; switch (denom) { case 'A' : denomValue = 14; break; case 'K' : denomValue = 13; break; case 'Q' : denomValue = 12; break; case 'J' : denomValue = 11; break; case 'T' : denomValue = 10; break; default : denomValue = denom - '0'; break; } return denomValue; } /** We may find it convenient to have a copy constructor when it comes * time to deal cards. */ public Card(Card c) { denom = c.denom; suit = c.suit; } /** Here's a nice way to print cards, using a phrase such as "four of clubs" */ public String toString() { String denomName = new String(); String suitName = new String(); switch(denom) { case '2': denomName = "two"; break; case '3': denomName = "three"; break; case '4': denomName = "four"; break; case '5': denomName = "five"; break; case '6': denomName = "six"; break; case '7': denomName = "seven"; break; case '8': denomName = "eight"; break; case '9': denomName = "nine"; break; case 'T': denomName = "ten"; break; case 'J': denomName = "jack"; break; case 'Q': denomName = "queen"; break; case 'K': denomName = "king"; break; case 'A': denomName = "ace"; break; } switch (suit) { case 'c': suitName = "clubs"; break; case 'd': suitName = "diamonds"; break; case 'h': suitName = "hearts"; break; case 's': suitName = "spades"; break; } return denomName + " of " + suitName; } /** shortForm() -- Sometimes we just want to print a shortened form * of the name of this card like J-c instead of "jack of clubs". */ public String shortForm() { return denom + "-" + suit; } /** isSameSuit() will return true or false depending on whether * the two cards are in the same suit or not. */ public boolean isSameSuit(Card c) { return (this.suit == c.suit); } /** isSameValue() is analogous: we compare denominations */ public boolean isSameValue(Card c) { return (this.denom == c.denom); } /** isOneHigherThan(). This function will be useful when we want * to detect a straight. See if I am 1 higher than the 2nd card * (the parameter). For example we would return true if we had * this = 'Q' and parameter = 'J'. * For numbers, we can just add one. For example '4' == '3' + 1. * However, there is a special case to avoid: 'K' == 'J' + 1, * but king should not be one higher than jack. */ public boolean isOneHigherThan(Card c) { return this.denom == 'A' && c.denom == 'K' || this.denom == 'K' && c.denom == 'Q' || this.denom == 'Q' && c.denom == 'J' || this.denom == 'J' && c.denom == 'T' || this.denom == 'T' && c.denom == '9' || this.denom != 'K' && this.denom == 1 + c.denom || this.denom == '2' && c.denom == 'A'; } /** isFaceCard() and other similar functions are not really needed in * the poker program, but are included here so you can see some variety. */ public boolean isFaceCard() { return (this.denom == 'J' || this.denom == 'Q' || this.denom == 'K'); } /** isRed() -- The red cards are diamonds and hearts. */ public boolean isRed() { return (this.suit == 'd' || this.suit == 'h'); } /** We already have a way of determining if a card is red, so we simply * call isRed(), and return the opposite answer. */ public boolean isBlack() { return (! this.isRed()); } /** Having an isAce() function is useful when we want to tell if a * straight flush is ace high: then it's a royal flush. */ public boolean isAce() { return (this.denom == 'A'); } /** This function is similar to the compareTo you find in the String class. * @param c A card object. * @return A positive value if I'm greater than the card object, 0 if * we are equal, and negative value if I'm less than c. */ public int compareTo(Card c) { return this.findDenomValue() - c.findDenomValue(); } }