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:

  1. Probability of drawing a Heart:

13 hearts / 52 cards = 1/4

  1. Probability of drawing an Ace:

4 aces / 52 cards = 1/13

  1. 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

  1. Probability of drawing a Heart (♥ / ไพ่หัวใจ)
  • Favorable outcomes: 13 hearts
  • Total outcomes: 52 cards

$$ P(\text{Heart}) = \frac{13}{52} = \frac{1}{4} = 0.25 $$

  1. 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 $$

  1. Probability of drawing the Ace of Spades (A♠ / เอซโพดำ)
  • Only 1 card matches

$$ P(\text{A♠}) = \frac{1}{52} \approx 0.0192 $$

  1. 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 $$

  1. 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

  1. Count first, divide later – always separate favorable outcomes and total outcomes.
  2. Check card uniqueness – is the event asking for one specific card, a suit, or a rank?
  3. 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:

  1. First card: 13 hearts / 52 total
  2. 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

  1. Deck structure first — suits, ranks, counts.
  2. Identify favorable outcomes.
  3. Use combinations logic — “without replacement” vs “with replacement”.
  4. Convert cards to numbers if needed — Ace=1, face=10, etc.
  5. Write pure Python — no shortcuts, no libraries.
  6. 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:

  1. Convert ranks to numeric values for comparison.
  2. Count repeated ranks with Counter.
  3. Detect flush and straight.
  4. 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:

  1. Only consider cards matching lead suit.
  2. Highest rank wins.
  3. 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

  1. Conditional Probability: If first card is Ace, probability second card is also Ace?

    prob = (4/52)*(3/51)
    print(prob)
    
  2. 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)
    
  3. 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.sample for 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:

  1. Remove known cards from deck.
  2. Simulate random opponent hands and remaining community cards.
  3. 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

  1. Poker AI:

    • Use hand strength + simulation for decisions.
    • Add risk tolerance by adjusting fold/raise thresholds.
    • Can simulate multiple opponents by repeating simulations.
  2. Pok Deng AI:

    • Use expected value for each action.
    • Can incorporate probabilities of dealer hands.
    • Extend to 3-card strategies and special hands.
  3. 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

  1. Combine logic, probability, and simulation.
  2. Always consider all unknowns: opponent hands, remaining deck.
  3. Use expected value and probabilities to make rational decisions.
  4. Start simple → fold/call/raise → extend to multi-player and bluffing.
  5. 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
  1. Choose rank for the pair: 13 options.
  2. Choose 2 suits for the pair: C(4,2) = 6 ways.
  3. Choose 3 remaining ranks for other cards: C(12,3).
  4. Choose suits for remaining cards: 4^3.
  5. 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
  1. Choose suit: 4 options.
  2. 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
  1. Probability of no Ace: C(48,5)/C(52,5)
  2. 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.

Previous
Next