The easiest way is just to simulate the game lots of times. The R code below simulates a single game.
nplayers = 4
#Create an empty data frame to keep track
#of card number, suit and if it's magic
empty.hand = data.frame(number = numeric(52),
suit = numeric(52),
magic = numeric(52))
#A list of players who are in the game
players =list()
for(i in 1:nplayers)
players[[i]] = empty.hand
#Simulate shuffling the deck
deck = empty.hand
deck$number = rep(1:13, 4)
deck$suit = as.character(rep(c("H", "C", "S", "D"), each=13))
deck$magic = rep(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0), each=4)
deck = deck[sample(1:52, 52),]
#Deal out five cards per person
for(i in 1:length(players)){
r = (5*i-4):(5*i)
players[[i]][r,] = deck[r,]
}
#Play the game
i = 5*length(players)+1
current = deck[i,]
while(i < 53){
for(j in 1:length(players)){
playersdeck = players[[j]]
#Need to test for magic and suit also - left as an exercise!
if(is.element(current$number, playersdeck$number)){
#Update current card
current = playersdeck[match(current$number,
playersdeck$number),]
#Remove card from players deck
playersdeck[match(current$number, playersdeck$number),] = c(0,
0, 0)
} else {
#Add card to players deck
playersdeck[i,] = deck[i,]
i = i + 1
}
players[[j]] = playersdeck
#Has someone won or have we run out of card
if(sum(playersdeck$number) == 0 | i > 52){
i = 53
break
}
}
}
#How many cards are left for each player
for(i in 1:length(players))
{
cat(sum(players[[i]]$number !=0), "\n")
}
Some comments
- You will need to add a couple of lines for magic cards and suits, but data structure is already there. I presume you didn't want a complete solution? ;)
- To estimate the average game length, just place the above code in a function and call lots of times.
- Rather than dynamically increasing a vector when a player gets a card, I find it easier just to create a sparse data frame that is more than sufficient. In this case, each player has a data frame with 52 rows, which they will never fill (unless it's a 1 player game).
- There is a small element of strategy with this game. What should you do if you can play more than one card. For example, if 7H comes up, and you have in your hand 7S, 8H and the JC. All three of these cards are "playable".
Here's a Python program that I believe is correct. It takes a little under 7 minutes on my machine to run through every pair of hands.
from itertools import combinations
from collections import Counter
JACK, QUEEN, KING, ACE = 11, 12, 13, 14
N_HANDS = 22100 # 52 choose 3
deck = frozenset((rank, suit)
for rank in range(2, ACE + 1)
for suit in range(4))
assert len(deck) == 52
evaluate_hand_cache = {}
def evaluate_hand(hand):
if hand not in evaluate_hand_cache:
evaluate_hand_cache[hand] = evaluate_hand_(hand)
return evaluate_hand_cache[hand]
def evaluate_hand_(hand):
ranks = tuple(sorted((rank for (rank, _) in hand), reverse = True))
suits = [suit for (_, suit) in hand]
if ranks[0] == ranks[1] == ranks[2]:
# Three of a kind
return (5, ranks[0])
straight = (ranks[0] == ranks[1] + 1 == ranks[2] + 2
or ranks == (ACE, 3, 2))
flush = suits[0] == suits[1] == suits[2]
if straight and flush:
return (6, ranks[0])
if straight:
return (4, ranks[0])
if flush:
return (3,) + ranks
if ranks[0] == ranks[1]:
# Pair
return (2, ranks[0], ranks[2])
if ranks[1] == ranks[2]:
# Also a pair
return (2, ranks[2], ranks[0])
return (1,) + ranks
results = Counter()
divisor = N_HANDS // 100
for i, dealer_hand in enumerate(combinations(deck, 3)):
if i % divisor == 0:
print "{}% complete".format(i // divisor)
dealer_hand = frozenset(dealer_hand)
dealer_e = evaluate_hand(dealer_hand)
for player_hand in combinations(deck - dealer_hand, 3):
player_e = evaluate_hand(player_hand)
outcome = (
'Dealer does not qualify'
if dealer_e < (2, QUEEN) else
'Player loses'
if player_e < dealer_e else
'Player wins'
if dealer_e < player_e else
'Tie')
results[(player_e[0], outcome)] += 1
print "Player hand class,Outcome,Count"
for (hand, outcome), n in sorted(results.items()):
print ','.join([str(hand), outcome, str(n)])
The output is:
Player hand class,Outcome,Count
1,Dealer does not qualify,264851952
1,Player loses,38038608
2,Dealer does not qualify,60280560
2,Player loses,8453520
2,Player wins,242784
2,Tie,2592
3,Dealer does not qualify,17630040
3,Player loses,1260596
3,Player wins,1298780
3,Tie,3288
4,Dealer does not qualify,11581584
4,Player loses,267804
4,Player wins,1392204
4,Tie,23688
5,Dealer does not qualify,836520
5,Player loses,3312
5,Player wins,118216
6,Dealer does not qualify,771024
6,Player loses,956
6,Player wins,112204
6,Tie,168
Best Answer
Based on @remy-jurriens answer, just corrected.
Player1 has a pair and Player2 has same pair,
p(pair_pair) = (3/51)(2/50)(1/49) = 6/(51*50*49)
Player1 has a non-pair and Player2 has same hand,
p(non_pairs) = (48/51)(6/50)(3/49) = 864/(51*50*49)
Chance to get same Texas Holdem hand Heads-Up:
p = p(pair_pair) + p(non_pairs) = (864+6)/(51*50*49) = 0.006962785114045618
or 0.7% - same result