DK-005 — Playing Cards & Probability with Python
🎯 Why This Note Exists
Playing cards are more than games — they are perfect tools for learning logic, probability, and programming.
By the end of this note, you will be able to:
- Identify all cards in a deck and their structure.
- Calculate probabilities of common card events.
- Write pure Python algorithms to simulate and solve card problems.
- Solve classic and tricky card puzzles.
- Understand card games logic like Poker, Dummy, and Pok Deng (Thai “ป๊อกเก้ง”).
This is everything you need, from basic cards to advanced probability, all in Python logic.
🃏 1 — The Deck: What Cards Are There?
A standard deck has 52 cards, divided into 4 suits:
| Suit | ชื่อไทย | Symbol | Example Cards |
|---|---|---|---|
| Spades | ไพ่โพดำ | ♠ | Ace, 2, 3, …, King |
| Hearts | ไพ่หัวใจ | ♥ | Ace, 2, 3, …, King |
| Diamonds | ไพ่ข้าวหลามตัด | ♦ | Ace, 2, 3, …, King |
| Clubs | ไพ่ดอกจิก | ♣ | Ace, 2, 3, …, King |
Each suit has 13 cards:
Ace (1), 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King
So the total deck = 4 suits × 13 cards = 52 cards.

Image credit: Cottage Life
🧑💻 Representing a Deck in Python
suits = ["Spades", "Hearts", "Diamonds", "Clubs"]
ranks = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"]
deck = [(rank, suit) for suit in suits for rank in ranks]
print(deck[:5]) # Show first 5 cards
print(len(deck)) # 52
🎲 2 — Basic Card Probabilities
Probability formula:
$$ P(\text{event}) = \frac{\text{favorable outcomes}}{\text{total outcomes}} $$
Examples:
- Probability of drawing a Heart:
13 hearts / 52 cards = 1/4
- Probability of drawing an Ace:
4 aces / 52 cards = 1/13
- Probability of drawing Ace of Spades:
1 / 52
When learning cards, probability is your most powerful tool.
It tells you how likely something is to happen, and it’s the foundation of all card games, poker, and combinatorics.
🔹 Probability Formula
The general formula is simple:
$$ P(\text{event}) = \frac{\text{favorable outcomes}}{\text{total outcomes}} $$
- Favorable outcomes → the ways your event can happen
- Total outcomes → all possible outcomes in the sample space
For a standard 52-card deck:
| Suit | ชื่อไทย | Symbol | Number of Cards |
|---|---|---|---|
| Spades | ไพ่โพดำ | ♠ | 13 |
| Hearts | ไพ่หัวใจ | ♥ | 13 |
| Diamonds | ไพ่ข้าวหลามตัด | ♦ | 13 |
| Clubs | ไพ่ดอกจิก | ♣ | 13 |
Total cards = 13 × 4 = 52
🔹 Examples of Basic Probabilities
- Probability of drawing a Heart (♥ / ไพ่หัวใจ)
- Favorable outcomes: 13 hearts
- Total outcomes: 52 cards
$$ P(\text{Heart}) = \frac{13}{52} = \frac{1}{4} = 0.25 $$
- Probability of drawing an Ace (ไพ่เอซ)
- There are 4 Aces in the deck (A♠, A♥, A♦, A♣)
$$ P(\text{Ace}) = \frac{4}{52} = \frac{1}{13} \approx 0.0769 $$
- Probability of drawing the Ace of Spades (A♠ / เอซโพดำ)
- Only 1 card matches
$$ P(\text{A♠}) = \frac{1}{52} \approx 0.0192 $$
- Probability of drawing a Red Card (Hearts ♥ or Diamonds ♦ / ไพ่แดง)
- Favorable outcomes: 13 hearts + 13 diamonds = 26
$$ P(\text{Red Card}) = \frac{26}{52} = \frac{1}{2} = 0.5 $$
- Probability of drawing a Face Card (J, Q, K / แจ็ค, ควีน, คิง)
- Each suit has 3 face cards → 3 × 4 = 12 cards
$$ P(\text{Face Card}) = \frac{12}{52} = \frac{3}{13} \approx 0.2308 $$
🔹 Key Intuition for Beginners
- Count first, divide later – always separate favorable outcomes and total outcomes.
- Check card uniqueness – is the event asking for one specific card, a suit, or a rank?
- Sum probabilities for combined events – e.g., Red or Face card: count all unique favorable cards.
Think: “If I shuffle and draw one card, what are the chances I get what I want?” That’s all probability is.
🔹 Python Check — Basic Probability
deck = [r+s for r in ['2','3','4','5','6','7','8','9','10','J','Q','K','A']
for s in ['♠','♥','♦','♣']]
# Probability of drawing a Heart
hearts = [c for c in deck if c.endswith('♥')]
p_heart = len(hearts)/len(deck)
print("P(Heart) =", p_heart)
# Probability of Ace
aces = [c for c in deck if c.startswith('A')]
p_ace = len(aces)/len(deck)
print("P(Ace) =", p_ace)
# Probability of Ace of Spades
p_aspade = 1/len(deck)
print("P(A♠) =", p_aspade)
✅ Output:
P(Heart) = 0.25
P(Ace) = 0.07692307692307693
P(A♠) = 0.019230769230769232
🔹 Takeaways
- Start simple: suit, rank, color
- Add layers: face cards, combinations, multiple draws
- Always check total vs favorable outcomes
Master these basic probabilities, and everything from poker strategy to advanced combinatorics will be much easier.
🧑💻 Python Simulation of Probability
import random
random.seed(1) # reproducible
def simulate_card_draw(deck, target, trials=100000):
count = 0
for _ in range(trials):
card = random.choice(deck)
if card == target:
count += 1
return count / trials
ace_of_spades = ("Ace", "Spades")
print(simulate_card_draw(deck, ace_of_spades))
This shows probability by simulation, but next we’ll calculate using logic only.
🃏 3 — Card Games Basics
Familiar games teach card handling and combinatorial logic:
| Game | Core Idea |
|---|---|
| Poker | Form hands (pair, straight, flush, etc.) |
| Dummy | Trick-taking, comparing card values |
| Pok Deng | Thai game: sum of 2-3 cards modulo 10 |
We don’t need full rules yet — understanding cards and values is enough.
🔹 4 — Trick Examples (Card Logic)
Problem: Pick 2 cards from a deck. Probability both are Hearts?
Logic:
- First card: 13 hearts / 52 total
- Second card: 12 hearts / 51 remaining
$$ P = \frac{13}{52} \times \frac{12}{51} = \frac{156}{2652} = \frac{1}{17} \approx 0.0588 $$
🧑💻 Python Code for Logic Calculation
def probability_two_hearts():
first = 13 / 52
second = 12 / 51
return first * second
print(probability_two_hearts()) # 0.058823529411764705
🔹 5 — Python Algorithm to Count Specific Hands
Example: Count all pairs (2 cards same rank) in the deck.
from itertools import combinations
def count_pairs(deck):
pairs = 0
for c1, c2 in combinations(deck, 2):
if c1[0] == c2[0]:
pairs += 1
return pairs
total_pairs = count_pairs(deck)
total_combinations = 52 * 51 // 2
print("Pairs:", total_pairs)
print("Probability:", total_pairs / total_combinations)
🔹 6 — Thinking About Probability
Ask:
- How many favorable outcomes?
- How many total outcomes?
- Are draws with replacement or without replacement?
🧩 7 — 20 Q&A — Common Card Problems (Pure Python Logic)
🔴 Problem 1 — Probability of drawing a red card
✅ Solution
# Red cards = Hearts + Diamonds
red_cards = [c for c in deck if c[1] in ["Hearts","Diamonds"]]
prob = len(red_cards)/len(deck)
print(prob) # 0.5
🔴 Problem 2 — Probability of drawing a face card (J,Q,K)
✅ Solution
face_cards = [c for c in deck if c[0] in ["Jack","Queen","King"]]
prob = len(face_cards)/len(deck)
print(prob) # 12/52 = 0.2307
🔴 Problem 3 — Probability of 2 cards being same suit
✅ Solution
from itertools import combinations
same_suit = 0
for c1, c2 in combinations(deck,2):
if c1[1]==c2[1]:
same_suit += 1
total = 52*51//2
print(same_suit/total) # 0.235
🔴 Problem 4 — Probability first card Ace, second card King
✅ Solution
prob = (4/52)*(4/51)
print(prob) # 0.00603
🔴 Problem 5 — Count all 3-card combinations summing to 21 (Ace=1, J/Q/K=10)
✅ Solution
def card_value(rank):
if rank in ["Jack","Queen","King"]:
return 10
elif rank=="Ace":
return 1
else:
return int(rank)
from itertools import combinations
count = 0
for c1,c2,c3 in combinations(deck,3):
if card_value(c1[0])+card_value(c2[0])+card_value(c3[0])==21:
count += 1
print(count)
🔴 Problem 6 — Simulate drawing 5-card poker hand
✅ Solution
import random
hand = random.sample(deck, 5)
print(hand)
🔴 Problem 7 — Probability 5-card hand contains at least 1 Ace
✅ Solution
from itertools import combinations
hands = list(combinations(deck,5))
count = sum(1 for h in hands if any(c[0]=="Ace" for c in h))
prob = count/len(hands)
print(prob)
🔴 Problem 8 — Probability 2 hearts and 1 spade in 3 cards
✅ Solution
from itertools import combinations
count = 0
for h in combinations(deck,3):
suits = [c[1] for c in h]
if suits.count("Hearts")==2 and suits.count("Spades")==1:
count += 1
prob = count / (52*51*50/6)
print(prob)
🔴 Problem 9 — Count all flush hands in poker
✅ Solution
from itertools import combinations
flush_count = 0
for hand in combinations(deck,5):
suits = [c[1] for c in hand]
if len(set(suits))==1:
flush_count += 1
print(flush_count)
🔴 Problem 10 — Probability 2 cards sum 10 (Ace=1, number cards as value, J/Q/K=10)
✅ Solution
def value(r): return 10 if r in ["Jack","Queen","King"] else 1 if r=="Ace" else int(r)
from itertools import combinations
count = 0
for c1,c2 in combinations(deck,2):
if value(c1[0])+value(c2[0])==10:
count += 1
prob = count / (52*51/2)
print(prob)
🔴 Problem 11 — Probability of 4 of a kind in 5 cards
✅ Solution
from itertools import combinations
count = 0
for hand in combinations(deck,5):
ranks = [c[0] for c in hand]
if any(ranks.count(r)==4 for r in ranks):
count +=1
prob = count/len(list(combinations(deck,5)))
print(prob)
🔴 Problem 12 — Probability first two cards are same rank
✅ Solution
from itertools import combinations
count = 0
for c1,c2 in combinations(deck,2):
if c1[0]==c2[0]:
count+=1
prob = count / (52*51/2)
print(prob)
🔴 Problem 13 — Count all straight hands (Ace=1,2,…,10, J=11, Q=12, K=13)
✅ Solution
def rank_value(r):
if r=="Ace": return 1
if r=="Jack": return 11
if r=="Queen": return 12
if r=="King": return 13
return int(r)
from itertools import combinations
count = 0
for hand in combinations(deck,5):
vals = sorted([rank_value(c[0]) for c in hand])
if all(vals[i]+1==vals[i+1] for i in range(4)):
count+=1
print(count)
🔴 Problem 14 — Probability 3 cards of same suit
✅ Solution
from itertools import combinations
count = 0
for h in combinations(deck,3):
suits = [c[1] for c in h]
if len(set(suits))==1:
count+=1
prob = count / (52*51*50/6)
print(prob)
🔴 Problem 15 — Probability of drawing Joker (if deck has 2 Jokers)
✅ Solution
deck_with_joker = deck + [("Joker1","Joker"),("Joker2","Joker")]
prob = 2/len(deck_with_joker)
print(prob)
🔴 Problem 16 — Probability first card red, second card black
✅ Solution
prob = (26/52)*(26/51)
print(prob)
🔴 Problem 17 — Count all full house hands
✅ Solution
from itertools import combinations
def is_full_house(hand):
ranks = [c[0] for c in hand]
return sorted([ranks.count(r) for r in set(ranks)])==[2,3]
count=0
for hand in combinations(deck,5):
if is_full_house(hand):
count+=1
print(count)
🔴 Problem 18 — Probability at least one King in 5 cards
✅ Solution
from itertools import combinations
hands = list(combinations(deck,5))
count = sum(1 for h in hands if any(c[0]=="King" for c in h))
prob = count/len(hands)
print(prob)
🔴 Problem 19 — Probability all number cards in 5-card hand
✅ Solution
number_ranks = [str(i) for i in range(2,11)]
count = 0
for h in combinations(deck,5):
if all(c[0] in number_ranks for c in h):
count +=1
prob = count/len(list(combinations(deck,5)))
print(prob)
🔴 Problem 20 — Probability 3 consecutive cards in suit
✅ Solution
def rank_value(r):
if r=="Ace": return 1
if r=="Jack": return 11
if r=="Queen": return 12
if r=="King": return 13
return int(r)
count=0
for h in combinations(deck,3):
suits = [c[1] for c in h]
vals = sorted([rank_value(c[0]) for c in h])
if len(set(suits))==1 and vals[1]==vals[0]+1 and vals[2]==vals[1]+1:
count+=1
total=52*51*50/6
print(count/total)
🧠 Summary — How to THINK About Cards
- Deck structure first — suits, ranks, counts.
- Identify favorable outcomes.
- Use combinations logic — “without replacement” vs “with replacement”.
- Convert cards to numbers if needed — Ace=1, face=10, etc.
- Write pure Python — no shortcuts, no libraries.
- Start simple, scale complexity — 1 card → 2 cards → 3 cards → poker hands.
With this logic, any card problem can be solved programmatically.
🎯 Why This Advanced Note Exists
Once you understand deck structure and basic probabilities, the next step is to simulate real card games and analyze strategies.
This section shows:
- How to simulate popular card games in Python.
- How to calculate odds and hand strength.
- Tricks and tips for decision-making in games.
- Algorithms to automate and analyze hands, without libraries.
🃏 1 — Poker Simulation & Probability
Poker uses 5-card hands (Texas Hold’em simplified). Common hand rankings:
| Rank | Description |
|---|---|
| 1 | Royal Flush |
| 2 | Straight Flush |
| 3 | Four of a Kind |
| 4 | Full House |
| 5 | Flush |
| 6 | Straight |
| 7 | Three of a Kind |
| 8 | Two Pair |
| 9 | One Pair |
| 10 | High Card |
🔹 Python — Evaluate Poker Hand
from collections import Counter
def rank_value(r):
if r=="Ace": return 14
if r=="King": return 13
if r=="Queen": return 12
if r=="Jack": return 11
return int(r)
def hand_rank(hand):
"""Returns the rank of a 5-card poker hand."""
ranks = sorted([rank_value(c[0]) for c in hand], reverse=True)
suits = [c[1] for c in hand]
rank_counts = Counter(ranks)
counts = sorted(rank_counts.values(), reverse=True)
# Check flush
flush = len(set(suits))==1
# Check straight
straight = all(ranks[i]-1==ranks[i+1] for i in range(4))
# Royal flush
if flush and straight and ranks[0]==14:
return "Royal Flush"
if flush and straight:
return "Straight Flush"
if counts==[4,1]:
return "Four of a Kind"
if counts==[3,2]:
return "Full House"
if flush:
return "Flush"
if straight:
return "Straight"
if counts==[3,1,1]:
return "Three of a Kind"
if counts==[2,2,1]:
return "Two Pair"
if counts==[2,1,1,1]:
return "One Pair"
return "High Card"
# Example:
hand = [("Ace","Hearts"),("King","Hearts"),("Queen","Hearts"),("Jack","Hearts"),("10","Hearts")]
print(hand_rank(hand)) # Royal Flush
Explanation:
- Convert ranks to numeric values for comparison.
- Count repeated ranks with
Counter. - Detect flush and straight.
- Map combinations to hand rank.
🔹 Simulate 100,000 Poker Hands
import random
random.seed(42)
hands_count = {"Royal Flush":0,"Straight Flush":0,"Four of a Kind":0,"Full House":0,
"Flush":0,"Straight":0,"Three of a Kind":0,"Two Pair":0,"One Pair":0,"High Card":0}
for _ in range(100000):
hand = random.sample(deck,5)
rank = hand_rank(hand)
hands_count[rank] += 1
for k,v in hands_count.items():
print(f"{k}: {v/100000:.6f}")
You can now estimate probabilities of each hand using simulation.
🃏 2 — Dummy / Trick-Taking Simulation
Dummy (like Bridge) is about playing tricks:
- Each player plays 1 card per trick.
- Highest card of the suit led wins the trick.
- Goal: maximize tricks won.
🔹 Python — Simulate 1 Trick
def trick_winner(cards_played, lead_suit):
"""cards_played: list of tuples (rank,suit)"""
lead_cards = [c for c in cards_played if c[1]==lead_suit]
values = [rank_value(c[0]) for c in lead_cards]
winner_index = values.index(max(values))
return winner_index # player index
# Example:
cards = [("10","Hearts"),("Ace","Hearts"),("King","Spades"),("3","Hearts")]
lead_suit = "Hearts"
winner = trick_winner(cards, lead_suit)
print(f"Player {winner+1} wins the trick")
Logic:
- Only consider cards matching lead suit.
- Highest rank wins.
- Index shows who wins.
🃏 3 — Pok Deng (ป๊อกเก้ง) Simulation
Pok Deng is a 2-3 card game:
- Sum cards modulo 10 → “points”.
- Special hands: Pair, Three-of-a-Kind, Straight Flush.
- Dealer vs Player comparison.
🔹 Python — Evaluate Pok Deng Hand
def pok_points(hand):
"""hand: list of tuples (rank,suit)"""
values = [min(int(c[0]) if c[0].isdigit() else 10,10) for c in hand] # face=10
total = sum(values) % 10
return total
# Compare hands
def compare_pok(player, dealer):
p = pok_points(player)
d = pok_points(dealer)
if p>d: return "Player wins"
if p<d: return "Dealer wins"
return "Tie"
# Example:
player_hand = [("10","Hearts"),("7","Clubs")]
dealer_hand = [("9","Spades"),("8","Diamonds")]
print(compare_pok(player_hand,dealer_hand))
Adds modulo logic, simple but elegant.
🔹 Simulate 10,000 Pok Deng Games
wins = {"Player":0,"Dealer":0,"Tie":0}
for _ in range(10000):
shuffled = random.sample(deck,52)
player = shuffled[:2]
dealer = shuffled[2:4]
result = compare_pok(player,dealer)
if result=="Player wins": wins["Player"]+=1
elif result=="Dealer wins": wins["Dealer"]+=1
else: wins["Tie"]+=1
for k,v in wins.items():
print(k,v/10000)
This gives empirical win rates.
🧩 4 — Advanced Probability Tricks
-
Conditional Probability: If first card is Ace, probability second card is also Ace?
prob = (4/52)*(3/51) print(prob) -
Combinatorics for hands:
Number of ways to choose 2 pairs in 5-card hand:
from math import comb total = comb(52,5) two_pair = comb(13,2)*comb(4,2)**2*comb(44,1) print(two_pair/total) -
Simulate edge cases: Probability all hearts in 3-card hand:
count = 0 for h in combinations(deck,3): if all(c[1]=="Hearts" for c in h): count+=1 print(count/(52*51*50/6))
🧠 Key Takeaways
- Simulation + logic = best way to understand card games.
- Always break problem into suits, ranks, counts.
- Use Python combinations or
random.samplefor experimentation. - Advanced games like Poker/Dummy/Pok Deng teach conditional probability and strategy.
- This knowledge is applicable to AI card bots, probabilistic reasoning, and algorithmic game design.
🧠 Part 1 — Bayes’ Theorem (Mathematical Form)
The Formula (Must Memorize)
$$ P(A \mid B) = \frac{P(B \mid A),P(A)}{P(B)} $$
Meaning of Each Term
| Symbol | Meaning |
|---|---|
| (A) | Hypothesis (what might be true) |
| (B) | Evidence (what you observe) |
| (P(A)) | Prior belief |
| (P(B \mid A)) | Likelihood |
| (P(A \mid B)) | Posterior belief |
Human Translation
New belief
= Old belief × How well the evidence fits
Bayes is not a formula.
Bayes is a belief update rule.
🃏 Part 2 — Bayes with Cards (Concrete Example)
Problem
A card is drawn from a standard deck.
You are told:
- The card is red
Question:
What is the probability the card is an Ace?
Step 1 — Define Events
- (A): card is an Ace
- (B): card is red
Step 2 — Compute Components
- (P(A) = \frac{4}{52})
- (P(B \mid A) = \frac{2}{4})
- (P(B) = \frac{26}{52})
Step 3 — Apply Bayes
$$ P(A \mid B) = \frac{P(B \mid A)P(A)}{P(B)} = \frac{\frac{2}{4} \cdot \frac{4}{52}}{\frac{26}{52}} = \frac{2}{26} = \frac{1}{13} $$
🧠 Insight
The probability did not change.
But the reasoning path did.
That shift in thinking is AI-level reasoning.
🤖 Part 3 — Bayes as an AI Belief Update
AI does not ask:
“Is this true?”
AI asks:
“How plausible is this given what I see?”
Bayes formalizes that question.
Example — Hidden Card Suit
You draw a card but do not see it.
Evidence:
- The card is red
- The card is a face card
Which suit is more likely?
Hypotheses
- (H_1): Hearts
- (H_2): Diamonds
Likelihood Reasoning
- Both are red
- Both have 3 face cards out of 13
Bayes tells us:
$$ P(H \mid E) \propto P(H),P(E \mid H) $$
We compare relative scores, not exact values.
🧠 Part 4 — Naive Bayes (Key AI Simplification)
The Assumption
Evidence features are conditionally independent.
This is often false —
but extremely effective.
Naive Bayes Formula
For evidence (E_1, E_2, \dots, E_n):
$$ P(H \mid E_1,\dots,E_n) \propto P(H)\prod_{i=1}^{n} P(E_i \mid H) $$
Card Example
Evidence:
- Card is red
- Card is face card
Hypothesis:
- Suit = Hearts
🧑💻 Pure Python — Naive Bayes Scoring
def naive_score(suit):
prior = 1/4
red_given_suit = 1 if suit in ["Hearts","Diamonds"] else 0
face_given_suit = 3/13
return prior * red_given_suit * face_given_suit
for s in ["Hearts","Diamonds","Clubs","Spades"]:
print(s, naive_score(s))
We do ranking, not prediction.
That is how ML classifiers work.
♠️ Part 5 — Poker as Bayesian Pattern Recognition
Poker is not luck. Poker is inference under uncertainty.
Example — Opponent Holds 5 Cards
Observed:
- No pairs on table
- Many high cards missing
We update belief over:
- pair
- two pair
- straight
- flush
This is Bayesian reasoning, even if players don’t know the math.
🧠 Core Poker Principle
Poker hands are hypotheses Visible cards are evidence
🧮 Part 6 — Expected Value (Decision Theory)
Definition
Expected value measures long-run belief-weighted payoff.
$$ E[X] = \sum_i x_i \cdot P(x_i) $$
Card Example — Ace Value
Let:
- Ace payoff = 1
- Otherwise = 0
$$ E = 1 \cdot \frac{4}{52} + 0 \cdot \frac{48}{52} = \frac{1}{13} $$
Expectation is how AI decides what to do next.
🏆 Part 7 — Olympiad-Level Bayes Trick
Problem
Two decks:
- Deck A: 4 red, 6 black
- Deck B: 7 red, 3 black
One deck chosen uniformly. A red card is drawn.
What is the probability it was Deck B?
Solution
Let:
- (A): Deck A
- (B): Deck B
- (R): Red card
$$ P(B \mid R) = \frac{P(R \mid B)P(B)}{P(R)} $$
$$ P(R) = \frac{1}{2}\cdot\frac{4}{10} + \frac{1}{2}\cdot\frac{7}{10} $$
Final result:
$$ P(B \mid R) = \frac{\frac{7}{10}\cdot\frac{1}{2}} {\frac{4}{20} + \frac{7}{20}} = \frac{7}{11} $$
🧠 Final Mental Model (This Is Gold)
Cards teach:
- Probability → counting
- Bayes → belief update
- Naive Bayes → fast inference
- Poker → pattern ranking
- AI → decision under uncertainty
🎯 Why This Masterclass Exists
Once you know cards, probability, and simulation, the next frontier is AI-level reasoning for card games.
This masterclass shows how to:
- Build a Python AI that plays Poker or Pok Deng.
- Use probability, simulation, and logic to make decisions.
- Estimate hand strength and expected outcomes.
- Incorporate strategy for real-world play.
🃏 1 — AI for Poker (Simplified Texas Hold’em)
🔹 Step 1: Evaluate Hand Strength
In Poker, AI must know how strong its hand is before betting.
from itertools import combinations
import random
# Hand ranking function from previous section
def hand_strength(hand):
rank_order = ["High Card","One Pair","Two Pair","Three of a Kind","Straight","Flush",
"Full House","Four of a Kind","Straight Flush","Royal Flush"]
return rank_order.index(hand_rank(hand)) # 0=weakest, 9=strongest
Higher index = stronger hand. AI can use this to decide whether to fold, call, or raise.
🔹 Step 2: Simulate Opponent Hands
AI estimates probability of winning:
def win_probability(player_hand, community_cards, simulations=1000):
deck_remaining = [c for c in deck if c not in player_hand + community_cards]
wins = 0
for _ in range(simulations):
random.shuffle(deck_remaining)
opponent_hand = deck_remaining[:2]
community = community_cards + deck_remaining[2:5] # fill 5 cards
player_rank = hand_strength(player_hand + community)
opponent_rank = hand_strength(opponent_hand + community)
if player_rank > opponent_rank:
wins += 1
elif player_rank == opponent_rank:
wins += 0.5 # tie
return wins / simulations
# Example
player = [("Ace","Hearts"),("King","Hearts")]
community = [("10","Hearts"),("Queen","Hearts"),("Jack","Hearts")]
print(win_probability(player, community))
Logic:
- Remove known cards from deck.
- Simulate random opponent hands and remaining community cards.
- Count wins/ties to get probability.
🔹 Step 3: Decision Logic
AI can make decisions based on win probability:
def poker_decision(win_prob, threshold_fold=0.3, threshold_raise=0.7):
if win_prob < threshold_fold:
return "Fold"
elif win_prob > threshold_raise:
return "Raise"
else:
return "Call"
prob = win_probability(player, community)
print(poker_decision(prob))
Simple but powerful AI: it folds when weak, raises when strong, calls in-between.
🃏 2 — AI for Pok Deng (ป๊อกเก้ง)
Pok Deng AI is simpler but still requires probabilistic reasoning.
🔹 Step 1: Calculate Expected Value of Drawing Third Card
def expected_points(player_hand, deck_remaining):
current_points = pok_points(player_hand)
ev = current_points
if len(player_hand) == 2:
total = 0
for card in deck_remaining:
new_hand = player_hand + [card]
total += pok_points(new_hand)
ev = total / len(deck_remaining)
return ev
# Example:
player_hand = [("7","Hearts"),("8","Clubs")]
deck_remaining = [c for c in deck if c not in player_hand]
print(expected_points(player_hand, deck_remaining))
Logic:
- AI calculates average points if it draws a third card.
- Compare with dealer’s expected points to decide whether to draw.
🔹 Step 2: Decision Rule
def pok_decision(player_hand, deck_remaining, dealer_estimate=5):
ev = expected_points(player_hand, deck_remaining)
if ev > dealer_estimate:
return "Draw"
else:
return "Stay"
print(pok_decision(player_hand, deck_remaining))
AI decides draw or stay based on expected outcome vs dealer.
🧠 3 — Strategy Insights
-
Poker AI:
- Use hand strength + simulation for decisions.
- Add risk tolerance by adjusting fold/raise thresholds.
- Can simulate multiple opponents by repeating simulations.
-
Pok Deng AI:
- Use expected value for each action.
- Can incorporate probabilities of dealer hands.
- Extend to 3-card strategies and special hands.
-
General Tips:
- Always remove known cards from deck.
- Use combinatorics for exact probability calculation when feasible.
- Use simulation for complex scenarios.
🃏 4 — Advanced Simulation: Multi-Player Poker AI
def multi_player_simulation(player_hand, community_cards, n_opponents=3, simulations=1000):
deck_remaining = [c for c in deck if c not in player_hand + community_cards]
wins = 0
for _ in range(simulations):
random.shuffle(deck_remaining)
opponents = [deck_remaining[i*2:(i+1)*2] for i in range(n_opponents)]
community = community_cards + deck_remaining[2*n_opponents:5]
player_rank = hand_strength(player_hand + community)
opponent_ranks = [hand_strength(h + community) for h in opponents]
if all(player_rank > r for r in opponent_ranks):
wins += 1
elif all(player_rank >= r for r in opponent_ranks):
wins += 0.5 # tie
return wins / simulations
print(multi_player_simulation(player, community))
This allows AI to consider multiple opponents, a crucial real-game factor.
🔧 5 — Extending AI Further
- Monte Carlo simulation: simulate hundreds of thousands of scenarios.
- Learning thresholds: adjust decision thresholds based on win rate.
- Bluff simulation: add probabilistic “bluffing” moves.
- Advanced ranking: include kicker cards, suits for tie-breaking.
🧩 6 — Takeaways for AI-Level Card Strategy
- Combine logic, probability, and simulation.
- Always consider all unknowns: opponent hands, remaining deck.
- Use expected value and probabilities to make rational decisions.
- Start simple → fold/call/raise → extend to multi-player and bluffing.
- This framework works for any card game, from Poker to Pok Deng to Bridge.
With this knowledge, you can build a fully autonomous card AI that learns and adapts using pure Python logic.
🎯 Why This Appendix Exists
This is a complete set of advanced card problems for:
- Python programmers
- Competitive programming enthusiasts
- Game AI developers
Every problem comes with full logic explanation and pure Python solutions. By the end, you can tackle real card game probability and simulation problems like a pro.
🔴 Problem 1 — Probability of Drawing a Pair from 5 Cards
Question:
From a standard 52-card deck, what’s the probability that a 5-card hand contains exactly one pair?
✅ Logic
- Choose rank for the pair: 13 options.
- Choose 2 suits for the pair: C(4,2) = 6 ways.
- Choose 3 remaining ranks for other cards: C(12,3).
- Choose suits for remaining cards: 4^3.
- Divide by total 5-card hands: C(52,5).
✅ Python Solution
from math import comb
total_hands = comb(52,5)
pair_hands = comb(13,1)*comb(4,2)*comb(12,3)*(4**3)
probability = pair_hands/total_hands
print(probability) # ≈ 0.4226
🔴 Problem 2 — Count Number of Flush Hands
Question: How many 5-card hands are all the same suit?
✅ Logic
- Choose suit: 4 options.
- Choose 5 cards from 13 in that suit: C(13,5).
✅ Python Solution
flush_hands = 4 * comb(13,5)
print(flush_hands) # 5148 hands
🔴 Problem 3 — Probability of Getting at Least One Ace in 5 Cards
✅ Logic
- Probability of no Ace: C(48,5)/C(52,5)
- Probability of at least one Ace = 1 - P(no Ace)
✅ Python Solution
prob_no_ace = comb(48,5)/comb(52,5)
prob_at_least_one_ace = 1 - prob_no_ace
print(prob_at_least_one_ace) # ≈ 0.341
🔴 Problem 4 — Simulate 1000 Poker Hands for Royal Flush
✅ Logic
- Randomly pick 5 cards 1000 times
- Count how many are Royal Flush
✅ Python Solution
import random
suits = ["Hearts","Diamonds","Clubs","Spades"]
ranks = ["10","Jack","Queen","King","Ace","2","3","4","5","6","7","8","9"]
deck = [(r,s) for r in ranks for s in suits]
def hand_rank(hand):
ranks_order = {"10":10,"Jack":11,"Queen":12,"King":13,"Ace":14,
"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9}
values = sorted([ranks_order[c[0]] for c in hand])
suits_set = {c[1] for c in hand}
if values==[10,11,12,13,14] and len(suits_set)==1:
return "Royal Flush"
return "Other"
count = 0
for _ in range(1000):
hand = random.sample(deck,5)
if hand_rank(hand)=="Royal Flush":
count += 1
print(count/1000) # Very small probability
🔴 Problem 5 — Determine Winner in a Trick-Taking Game
✅ Logic
- Each player plays a card
- Highest card of the lead suit wins
✅ Python Solution
def trick_winner(cards_played, lead_suit):
lead_cards = [c for c in cards_played if c[1]==lead_suit]
values = {"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9,
"10":10,"Jack":11,"Queen":12,"King":13,"Ace":14}
winner_index = max(range(len(lead_cards)), key=lambda i: values[lead_cards[i][0]])
return winner_index
cards = [("10","Hearts"),("Ace","Hearts"),("King","Spades"),("3","Hearts")]
lead = "Hearts"
winner = trick_winner(cards,lead)
print(winner) # 1 → 2nd player
🔴 Problem 6 — Probability Dealer Gets Pok 9 in 2-Card Pok Deng
✅ Logic
- Pok points = sum modulo 10
- Need to count 2-card combinations summing to 9
✅ Python Solution
def pok_value(card):
if card[0] in ["Jack","Queen","King","10"]: return 10
return int(card[0])
count = 0
for i in range(len(deck)):
for j in range(i+1,len(deck)):
if (pok_value(deck[i])+pok_value(deck[j]))%10==9:
count+=1
prob = count/comb(52,2)
print(prob)
🔴 Problem 7 — Simulate Multiple Poker Opponents
✅ Logic
- Compare AI hand against N opponents using random simulation
✅ Python Solution
def multi_player_sim(player_hand, community_cards, n_opponents=3, simulations=1000):
wins = 0
for _ in range(simulations):
deck_remain = [c for c in deck if c not in player_hand+community_cards]
random.shuffle(deck_remain)
opponents = [deck_remain[i*2:(i+1)*2] for i in range(n_opponents)]
comm = community_cards + deck_remain[2*n_opponents:5]
player_rank = hand_strength(player_hand + comm)
if all(player_rank>hand_strength(h+comm) for h in opponents):
wins += 1
return wins/simulations
🔴 Problem 8 — Count Number of Full House Hands
✅ Logic
- Choose rank for triple: 13
- Choose suits for triple: C(4,3)=4
- Choose rank for pair: 12
- Choose suits for pair: C(4,2)=6
- Multiply
✅ Python Solution
full_house = 13*comb(4,3)*12*comb(4,2)
print(full_house) # 3744 hands
🔴 Problem 9 — Probability of Drawing Sequential Straight in 5 Cards
✅ Logic
- 10 possible starting ranks for 5-card straight
- 4^5 combinations of suits
- Subtract flushes (already counted separately)
✅ Python Solution
straight_hands = 10*(4**5) - 40 # subtract flush overlaps (approx)
prob = straight_hands/comb(52,5)
print(prob)
🔴 Problem 10 — Calculate Expected Points in 3-Card Pok Deng Draw
✅ Logic
- Average points after drawing 3rd card from remaining deck
✅ Python Solution
player_hand = [("7","Hearts"),("6","Clubs")]
deck_remain = [c for c in deck if c not in player_hand]
total = 0
for card in deck_remain:
new_hand = player_hand + [card]
total += pok_points(new_hand)
expected = total/len(deck_remain)
print(expected)
✅ Takeaways
- These problems combine combinatorics, probability, simulation, and AI logic.
- Each solution is pure Python, no external libraries for probability or hand evaluation.
- Completing all 20 prepares you for interviews, competitions, or AI card projects.