In a standard deck of 52 playing cards, each card is one of the following kinds
ID: 3777846 • Letter: I
Question
In a standard deck of 52 playing cards, each card is one of the following kinds: Ace (A), 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack (J), Queen (Q), and King (K). In the card game Poker, you can think of the Jack, Queen, and King as being like 11, 12, and 13, respectively. An Ace is special because it can be treated either as a 1 (called low) or as a 14 (called high), but not both.
Each card is also one of the following suits: Spades (S), Hearts (H), Clubs (C), or Diamonds (D). A deck contains exactly one card for each combination of kind and suit. For example, there are four Aces which can be written AS, AH, AC, and AD representing the Ace of Spades, Ace of Hearts, Ace of Clubs, and Ace of Diamonds respectively. There are also four twos (which can be written 2S, 2H, 2C, 2D), etc.
The card game Poker uses a standard deck of 52 playing cards. A player is dealt a hand consisting of five cards at random. The player’s hand is then scored into one of a number of categories. Please read the description of Poker hand categories at:
https://en.wikipedia.org/wiki/List_of_poker_hand_categories
Note that the category “Five of a kind” does not apply to a standard deck of 52 playing cards. Also, note that a hand in thecategory “High Card” can be more precisely described using one of the following sub-categories determined by the highest ranking card in the hand. In a “High Card” hand, any Ace is always treated as high, i.e., as a 14, and thus has the highest rank.
1. Seven high
2. Eight high
3. Nine high
4. Ten high
5. Jack high
6. Queen high
7. King high
8. Ace high
If more than one category applies to a hand, then only the highest ranking applicable category is used to describe the hand. For example, any “straight flush” is also a “straight” and a “flush,” but would simply be described as a straight flush since that category outranks the categories straight and flush. And it is not possible to have a “five high” or “six high” hand because it would also be a straight and the category straight outranks “high card.”
Note that when considering whether a hand is a straight or straight flush, an Ace can be treated as either as a 1 (called low, for example the hand AH, 2D, 3C, 4H, 5S is a straight) or as a 14 (called high, for example the hand 10H, JD, QC, KH, AS is a straight). An Ace cannot be treated as both low and high in the same hand. Note that the order in which the cards are listed in the hand does not matter, so that the hand 5S, 2D, 4H, AH, 3C (these are the same cards as in the first example of a straight but in a different order) is also a straight.
You program should represent a card by storing the card’s kindand suit as follows. A card’s kind should be the integer 1 if it is an Ace, the integer 2 if it is a two, the integer 3 if it is a three, etc., the integer 10 if is a ten, the integer 11 if it is a Jack, the integer 12 if it is Queen, and the integer 13 if it is a King. The card’s suitshould be the integer 0 if it is a Diamond, 1 if it is a Heart, 2 if it is a Club, and 3 if it is a Spade. So a card consists of two pieces of data, but we would like to be able to treat a card a single “thing” (for example, we would like to be able to return a “card” from a method). Thus, your program should use an array (one-dimensional) of integers with two elements to represent a card. The first element represents the card’s kind and the second element represents the card’s suit.
Write a method with the following header which generates a random card by randomly generating integers in the appropriate ranges for the card’s kind and suit. (Note that zero is valid for the suit but not for the kind.) The method should return a reference to an array of integers containing two elements – the first element represents the card’s kind and the second the card’s suit.
public static int[] drawCard()
To represent a 5-card hand, use a two-dimensional array with 5 rows and 2 columns. The 5 rows represent the 5 cards. You can think of each row as a one-dimensional array representing one card. That is, the first column represents each card’s kind. The second column represents each card’s suit.
Write a method with the following header which generates a random 5-card hand. It should make one or more calls to drawCard()to generate each card in the hand. Before adding a card to the hand, it must check whether a card with the same kind and suit already appears in the hand. If so, it must not add the card to the hand but instead continue calling drawCard()until a card is generated whose combination of kind and suit does not yet appear in the hand. Once a hand consisting of 5 distinctcards has been generated, the method should return a reference to the two dimensional array representing the hand.
public static int[][] drawHand()
To repeat, you must ensure that no card appears twice in the same hand. For example, the hand 2D, AC, 9S, 2D, 9H is not a legal hand because the two of diamonds appears twice. Of course it is fine that there are two 9’s in this hand because they are of different suits.
Next, write a method with the following header that classifies the hand into one of the following categories, which are listed in increasing order of rank. The method should return an integer from 1 to 17 indicating the highest of the 17 ranks below which the hand satisfies. You must remember that when considering whether a hand is a straight or straight flush, an Ace can count as either a 1 or a 14, but not both. A Royal Flush is a Straight Flush in which a 10 is the lowest ranking card in the hand, such as 10S, JS, QS, KS, AS. Again, order does not matter, so QH, 10H, AH, KH, JH is also a Royal Flush.
public static int classifyHand(int[][] hand)
1. Seven high
2. Eight high
3. Nine high
4. Ten high
5. Jack high
6. Queen high
7. King high
8. Ace high
9. One Pair
10. Two pair
11. 3 of a kind
12. Straight
13. Flush
14. Full house
15. 4 of a kind
16. Straight flush
17. Royal Flush
Your main method should generate 10,000,000 random hands by making calls to drawhand and classify each hand by calling classifyHand. It should keep counts of the number of hands that fall into each category above. For each of the first 50 hands (out of the 10,000,000 hands) generated, your program should display the hand number (1-50), the five cards in the hand including the kind and suit of each card using the same notation used here, and the name of the (highest) appropriate rank of thehand from the 17 categories above. After the first 50 hands, display the hand count, hand, and hand rank only if the count of the hands so far for that category is ten or less.
After 10,000,000 random hands have been generated, display the name of each hand category followed by the percentage of hands that fell into that category. After printing the percentages for categories 1-8 (which are sub-categories of the “High Card” category), print a blank line followed by a “High Card” category with the total percentage from the sub-categories 1-8. Then continue printing the percentages for categories 9-17. Please see the example output that appears at the end of this document, including the category percentages at the very end.
Write your own code for all computations. Do not call any methods that come with Java which operate on entire arrays. If your program is written correctly, the percentages for each hand category should be very close to those in the “Probability” column at:
In a standard deck of 52 playing cards, each card is one of the following kinds: Ace (A), 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack (J), Queen (Q), and King (K). In the card game Poker, you can think of the Jack, Queen, and King as being like 11, 12, and 13, respectively. An Ace is special because it can be treated either as a 1 (called low) or as a 14 (called high), but not both. Each card is also one of the following suits: Spades (S), Hearts (H), Clubs (C), or Diamonds (D). A deck contains exactly one card for each combination of kind and suit. For example, there are four Aces which can be written AS, AH, AC, and AD representing the Ace of Spades, Ace of Hearts, Ace of Clubs, and Ace of Diamonds respectively. There are also four twos (which can be written 2S, 2H, 2C, 2D), etc. The card game Poker uses a standard deck of 52 playing cards. A player is dealt a hand consisting of five cards at random. The player's hand is then scored into one of a number of categories. Please read the description of Poker hand categories at: https://en.wikipedia.org/wiki/List_of_poker_hand_categories Note that the category "Five of a kind" does not apply to a standard deck of 52 playing cards. Also, note that a hand in the category "High Card" can be more precisely described using one of the following sub-categories determined by the highest ranking card in the hand. In a "High Card" hand, any Ace is always treated as high, i.e., as a 14, and thus has the highest rank. Seven high Eight high Nine high Ten high Jack high Queen high King high Ace high If more than one category applies to a hand, then only the highest ranking applicable category is used to describe the hand. For example, any "straight flush" is also a "straight" and a "flush, " but would simply be described as a straight flush since that category outranks the categories straight and flush. And it is not possible to have a "five high" or "six high" hand because it would also be a straight and the category straight outranks "high card." Note that when considering whether a hand is a straight or straight flush, an Ace can be treated as either as a 1 (called low, for example the hand AH, 2D, 3C, 4H, 5S is a straight) or as a 14 (called high, for example the hand 10H, JD, QC, KH, AS is a straight). An Ace cannot be treated as both low and high in the same hand. Note that the order in which the cards are listed in the hand does not matter, so that the hand 5S, 2D, 4H, AH, 3C (these are the same cards as in the first example of a straight but in a different order) is also a straight. You program should represent a card by storing the card's kind and suit as follows. A card's kind should be the integer 1 if it is an Ace, the integer 2 if it is a two, the integer 3 if it is a three, etc., the integer 10 if is a ten, the integer 11 if it is a Jack, the integer 12 if it is Queen, and the integer 13 if it is a King. The card's suit should be the integer 0 if it is a Diamond, 1 if it is a Heart, 2 if it is a Club, and 3 if it is a Spade. So a card consists of two pieces of data, but we would like to be able to treat a card a single "thing" (for example, we would like to be able to return a "card" from a method). Thus, your program should use an array (one-dimensional) of integers with two elements to represent a card. The first element represents the card's kind and the second element represents the card's suit. Write a method with the following header which generates a random card by randomly generating integers in the appropriate ranges for the card's kind and suit. (Note that zero is valid for the suit but not for the kind.) The method should return a reference to an array of integers containing two elements - the first element represents the card's kind and the second the card's suit. public static int[] drawCard() To represent a 5-card hand, use a two-dimensional array with 5 rows and 2 columns. The 5 rows represent the 5 cards. You can think of each row as a one-dimensional array representing one card. That is, the first column represents each card's kind. The second column represents each card's suit. Write a method with the following header which generates a random 5-card hand. It should make one or more calls to drawCard()to generate each card in the hand. Before adding a card to the hand, it must check whether a card with the same kind and suit already appears in the hand. If so, it must not add the card to the hand but instead continue calling drawCard()until a card is generated whose combination of kind and suit does not yet appear in the and. Once a hand consisting of 5 distinctcards has been generated, the method should return a reference to the two dimensional array representing the hand. public static int[][] drawHand() To repeat, you must ensure that no card appears twice in the same hand. For example, the hand 2D, AC, 9S, 2D, 9H is not a legal hand because the two of diamonds appears twice. Of course it is fine that there are two 9's in this hand because they are of different suits. Next, write a method with the following header that classifies the hand into one of the following categories, which are listed in increasing order of rank. The method should return an integer from 1 to 17 indicating the highest of the 17 ranks below which the hand satisfies. You must remember that when considering whether a hand is a straight or straight flush, an Ace can count as either a 1 or a 14, but not both. A Royal Flush is a Straight Flush in which a 10 is the lowest ranking card in the hand, such as 10S, JS, QS, KS, AS. Again, order does not matter, so QH, 10H, AH, KH, JH is also a Royal Flush. public static int classifyHand(int[][] hand) Seven high Eight high Nine high Ten high Jack high Queen high King high Ace high One Pair Two pair 3 of a kind Straight Flush Full house 4 of a kind Straight flush Royal Flush Your main method should generate 10,000,000 random hands by making calls to drawhand and classify each hand by calling classifyHand. It should keep counts of the number of hands that fall into each category above. For each of the first 50 hands (out of the 10,000,000 hands) generated, your program should display the hand number (1-50), the five cards in the hand including the kind and suit of each card using the same notation used here, and the name of the (highest) appropriate rank of thehand from the 17 categories above. After the first 50 hands, display the hand count, hand, and hand rank only if the count of the hands so far for that category is ten or less. After 10,000,000 random hands have been generated, display the name of each hand category followed by the percentage of hands that fell into that category. After printing the percentages for categories 1-8 (which are sub-categories of the "High Card" category), print a blank line followed by a "High Card" category with the total percentage from the sub-categories 1-8. Then continue printing the percentages for categories 9-17. Please see the example output that appears at the end of this document, including the category percentages at the very end. Write your own code for all computations. Do not call any methods that come with Java which operate on entire arrays. If your program is written correctly, the percentages for each hand category should be very close to those in the "Probability" column at:Explanation / Answer
import random
class Card(object):
"""
Represents a single card
2,3,4, ... 10, 11 for Jack, 12 for Queen,
13 for King, 14 for Ace
"""
suitList = ["Clubs", "Diamonds", "Hearts", "Spades"]
rankList = [ "narf", "narf", "2", "3", "4", "5", "6", "7", "8",
"9", "10",
"Jack", "Queen", "King", "Ace"]
def __init__(self, suit=0, rank=0):
"""
Initialise a card
@type suit: int
@param suit: suit of the card (see suitList)
@type rank: int
@param rank: rank of the card (see rankList)
"""
self.suit = suit
self.rank = rank
def __str__(self):
"""
Pretty print a card
"""
return self.rankList[self.rank] + " of " +
self.suitList[self.suit]
def __cmp__(self, other):
"""
Compare 2 cards
@type other: card
@param other: the card to compare with
"""
# check the suits
if self.suit > other.suit: return 1
if self.suit < other.suit: return -1
# suits are the same... check ranks
if self.rank > other.rank: return 1
if self.rank < other.rank: return -1
# ranks are the same... it's a tie
return 0
class Deck(object):
"""
Represents a deck of cards. We can have different decks of cards
"""
DECK_NORMAL = 1 # 52 cards
def __init__(self,decktype=DECK_NORMAL):
"""
Makes a deck of cards
@type decktype: type of deck
@param decktype: what type of deck is it? (DECK_NORMAL,...)
"""
self.cards = []
for suit in range(4):
for rank in range(2, 15):
self.cards.append(Card(suit, rank))
def printdeck(self):
"""
Pretty print the deck
"""
for card in self.cards:
print card
def __str__(self):
"""
Pretty print the deck
"""
s = ""
for i in range(len(self.cards)):
s = s + " "*i + str(self.cards[i]) + " "
return s
def sort(self,rank=True,suit=False):
"""
Sort the deck
"""
def sortonrank(x,y):
if x.rank > y.rank: return 1
if x.rank < y.rank: return -1
return 0
def sortonsuit(x,y):
if x.suit > y.suit: return 1
if x.suit < y.suit: return -1
return 0
def sortonboth(x,y):
return cmp(x,y)
if ( rank == True and suit == False):
self.cards.sort(sortonrank)
elif ( suit == True and rank == False ):
self.cards.sort(sortonsuit)
else:
self.cards.sort(sortonboth) # roept sort van card op
def shuffle(self,nshuffle=1):
"""
Shuffle the deck of cards. This happens by swapping cards
@type nshuffle: int
@param nshuffle: how many times do we shuffle
"""
import random
nCards = len(self.cards)
# swap cards on place i and j
for shuffle in range(nshuffle):
print " shuffle %s " % shuffle
for i in range(nCards):
j = random.randrange(i, nCards)
[self.cards[i], self.cards[j]] = [self.cards[j],
self.cards[i]]
def removecard(self, card):
"""
Removes a card from the deck. Do not use this function if you want
to keep playing with the same deck afterwards!
@type card: card
@param card: card you want to remove
"""
if card in self.cards:
self.cards.remove(card)
return 1
else: return 0
def removecardindex(self,index):
"""
Remove a card at the given index. You get the card so you can
return it to the deck later
"""
if ( index >= 0 and index <= len(self) ):
return self.cards.pop(index)
def addcard(self,card):
"""
Add the card back to the bottom of the deck
@type card: card
@param card: card you want to add to the deck
"""
self.cards.append(card)
def popcard(self):
"""
Get the top card and deal it
"""
return self.cards.pop()
def isempty(self):
"""
Is the deck empty?
"""
return (len(self.cards) == 0)
def deal(self, hands, ncards=999):
"""
Deal a number of cards to the hands. ncards are dealt to each
hand.
@type hands: list
@param hands: list of hands to deal to
@type ncards: int
@param ncards: number of cards to deal to each hand
"""
nhands = len(hands)
for hand in hands:
for i in range(ncards):
if self.isempty(): break # break if out of cards
card = self.popcard() # take the top card
# hand = hands[i % nhands] # whose turn is next?
hand.addcard(card) # add the card to the hand
# print " deal card %s to %s " % (card,hand)
def __len__(self):
"""
How many cards are there in the deck?
"""
return len(self.cards)
class Hand(Deck):
"""
A hand is a kind of deck that contains cards
"""
def __init__(self, name=""):
"""
Make a hand of cards
@type name: string
@param name: hand belongs to person with this name
"""
self.cards = []
self.name = name
"""
def addcard(self,card) :
self.cards.append(card)
"""
def __str__(self):
"""
Pretty print the hand
"""
s = "Hand " + self.name
if self.isempty():
s = s + " is empty "
else:
s = s + " contains "
return s + Deck.__str__(self)
class CardGame(object):
"""
A card game
"""
def __init__(self):
"""
Start a card game by taking a deck of cards and shuffling it
"""
self.deck = Deck()
self.deck.shuffle()
class Rank(object):
def __init__(self,rnk,name):
self.rnk = rnk
self.name = name
def __str__(self):
return self.name
class HandComparator(object):
pass
class HandEvaluator(object):
RANK_NOTHING = Rank(1,"High card")
RANK_PAIR = Rank(2,"Pair")
RANK_DOUBLEPAIR = Rank(3,"Double Pair")
RANK_THREEOFAKIND = Rank(4,"Three of a Kind")
RANK_STRAIGHT = Rank(5,"Straight")
RANK_FLUSH = Rank(6,"Flush")
RANK_FULLHOUSE = Rank(7,"Full House")
RANK_FOUROFAKIND = Rank(8,"Four of a Kind")
RANK_STRAIGHTFLUSH = Rank(9,"Straight Flush")
RANK_FIVEOFAKIND = Rank(10,"Five of a Kind")
def __init__(self):
print "Ready to evaluate hands"
def is_straight(self,hand,numwildcards=0):
"""Checks for a five card straight
Inputs: list of non-wildcards plus wildcard count
2,3,4, ... 10, 11 for Jack, 12 for Queen,
13 for King, 14 for Ace
Hand can be any length (i.e. it works for seven card games).
Outputs: highest card in a five card straight
or 0 if not a straight.
Original list is not mutated.
Ace can also be a low card (i.e. A2345).
>>> is_straight([14,2,3,4,5])
5
>>> is_straight([14,2,3,4,6])
0
>>> is_straight([10,11,12,13,14])
14
>>> is_straight([2,3,5], 2)
6
>>> is_straight([], 5)
14
>>> is_straight([2,4,6,8,10], 3)
12
>>> is_straight([2,4,4,5,5], 2)
6
"""
hand = set(hand)
if 14 in hand:
hand.add(1)
for low in (10,9,8,7,6,5,4,3,2,1):
needed = set(range(low, low+5))
if len(needed & hand) + numwildcards >= 5:
lhand = [x for x in hand]
ind = lhand.index(low+4)
str = lhand[ind-4:ind+1]
return low+4
return -1
def is_group(self,hand,numwildcards=0):
"""Checks for pairs, threes-of-kind, fours-of-a-kind,
and fives-of-a-kind
Inputs: list of non-wildcards plus wildcard count
2,3,4, ... 10, 11 for Jack, 12 for Queen,
13 for King, 14 for Ace
Hand can be any length (i.e. it works for seven card games)
Output: tuple with counts for each value (high cards first)
for example (3, 14), (2, 11) full-house Aces over Jacks
for example (2, 9), (2, 7) two-pair Nines and Sevens
Maximum count is limited to five (there is no seven of a kind).
Original list is not mutated.
>>> groups([11,14,11,14,14])
[(3, 14), (2, 11)]
>>> groups([7, 9, 10, 9, 7])
[(2, 9), (2, 7)]
>>> groups([11,14,11,14], 1)
[(3, 14), (2, 11)]
>>> groups([9,9,9,9,8], 2)
[(5, 9), (2, 8)]
>>> groups([], 7)
[(5, 14), (2, 13)]
"""
result = []
counts = [(hand.count(v), v) for v in range(2,15)]
for count, value in sorted(counts, reverse=True):
newcount = min(5, count + numwildcards) # Add wildcards
upto five
numwildcards -= newcount - count # Wildcards remaining
if newcount > 1:
result.append((newcount, value))
return result
def is_flush(self,hand,numwildcards=0):
result = []
counts = [(hand.count(v), v) for v in range(0,4)]
for count, suit in sorted(counts, reverse=True):
newcount = min(5, count + numwildcards) # Add wildcards
upto five
numwildcards -= newcount - count # Wildcards remaining
if newcount >= 5:
# we have a flush, return the flush suit
# result.append((newcount, value))
return suit
return -1
def is_straightflush(self,hand,numwildcards=0):
return -1
def getrank(self,hand,numwildcards=0):
result_group = None
result_straight = None
result_flush = None
result_sf = None
nrofresult = 0
rank = None
cardranks = [card.rank for card in hand.cards]
cardsuits = [card.suit for card in hand.cards]
# check for groups
result_group = self.is_group(cardranks,numwildcards)
rank = self.__rankgroup(result_group)
# if rank is lower than a four of a kind, a straight flush is
# still better
"""
if (rank[0] < HandEvaluator.RANK_FIVEOFAKIND):
result_sf = is_straightflush(hand
"""
# if rank is lower than a fullhouse, a flush might be higher
if (rank[0] < HandEvaluator.RANK_FULLHOUSE):
result_flush = self.is_flush(cardsuits,numwildcards)
if ( result_flush > -1 ):
return self.__rankflush(result_flush)
# if rank is lower than a straight, it's useful to check for a
# straight
if (rank[0] < HandEvaluator.RANK_STRAIGHT):
result_straight = self.is_straight(cardranks,numwildcards)
if ( result_straight > -1 ):
return self.__rankstraight(result_straight)
# return the rank
return rank
def __namerank(self,rank):
return Card.rankList[rank]
def __namesuit(self,suit):
return Card.suitList[suit]
def __rankgroup(self,group):
pair = 0
trips = 0
ranks = []
if (len(group) == 0 ): return (HandEvaluator.RANK_NOTHING,ranks)
for count,rank in group:
ranks.append(self.__namerank(rank))
if ( count >= 5 ):
return (HandEvaluator.RANK_FIVEOFAKIND,ranks)
elif ( count == 4 ):
return (HandEvaluator.RANK_FOUROFAKIND,ranks)
elif ( count == 3 ):
trips += 1
elif ( count == 2 ): # can lead to a double pair
# check to see if we have a next pair
pair += 1
# Full house?
if ( trips >= 2 ): return (HandEvaluator.RANK_FULLHOUSE,ranks)
if ( trips == 1 and pair >= 1 ): return
(HandEvaluator.RANK_FULLHOUSE,ranks)
# Trips
if ( trips >= 1 ): return (HandEvaluator.RANK_THREEOFAKIND,ranks)
# Check for a pair or a double pair
if ( pair >= 2 ):
return (HandEvaluator.RANK_DOUBLEPAIR,ranks)
elif ( pair == 1 ):
return (HandEvaluator.RANK_PAIR,ranks)
def __rankflush(self,suit):
ranks = []
ranks.append(self.__namesuit(suit))
return (HandEvaluator.RANK_FLUSH,ranks)
def __rankstraight(self,highcard):
ranks = []
ranks.append(self.__namerank(highcard))
return (HandEvaluator.RANK_STRAIGHT,ranks)
def getprintablerank(self,handeval):
rank = handeval[0]
cards = handeval[1]
what = ""
if ( rank == HandEvaluator.RANK_PAIR or
rank == HandEvaluator.RANK_THREEOFAKIND or
rank == HandEvaluator.RANK_FOUROFAKIND or
rank == HandEvaluator.RANK_FIVEOFAKIND ):
what = "%s of %s's " % (rank, cards[0])
elif ( rank == HandEvaluator.RANK_FULLHOUSE ):
what = "%s, %s's over %s's" % (rank, cards[0], cards[1])
elif ( rank == HandEvaluator.RANK_DOUBLEPAIR ):
what = "%s, %s's and %s's" % (rank, cards[0], cards[1])
elif ( rank == HandEvaluator.RANK_NOTHING ):
what = "%s" % rank
elif ( rank == HandEvaluator.RANK_STRAIGHT ):
what = "%s, %s high" % (rank,cards[0])
elif ( rank == HandEvaluator.RANK_FLUSH ):
what = "%s of %s" % (rank,cards[0])
return what
if __name__ == "__main__":
# Deal to 5 players, first 3 cards, then 1 and another 3
todeal = []
for hnd in range(0,5):
todeal.append(Hand("Player %s" % (hnd + 1) ))
d = Deck()
d.shuffle(3)
print " Dealing 2 cards to all players "
d.deal(todeal,3)
print " Dealing 1 cards to all players "
d.deal(todeal,1)
print " Dealing 2 cards to all players "
d.deal(todeal,3)
print " What are the hands of the players "
ev = HandEvaluator()
for hand in todeal:
print "%s" % hand
rank = ev.getrank(hand)
print "%s" % ev.getprintablerank(rank)
print "*"*40
print " What's left in the deck?"
print "%s" % d
print " %s cards left in the deck " % len(d)