今回は最近流行りのポーカー
に関する確率のシミュレーションです
解説動画はこちら
ポーカーについて
ポーカーはトランプ5枚の手札の組み合わせで
役を作るゲームです。
役を計算するプログラム
シミュレーションを行うには
ポーカーの役の判定を行うプログラムが必要ですね
これを用いてシミュレーションを行なっていきます。
テキサスホールデムのシミュレーション
初期手札2枚と公開札5枚で、役を作り、勝率がどうなるか

やはり、最初にワンペアを持っているだけで勝率は高くなりますね
とはいえ、それだけでは勝てないのが
このテキサスホールデムルールの面白いところ
初期手札の読み合いやベットなどの駆け引き
この辺りが組み合わさることで
ゲーム性が高くかなり面白いものになっています。
とはいえ
日本ではまだまだ、カジノがないので
ポーカーを楽しむには
単純なゲームとしてのポーカーしか出来ません
オンラインで展開されているものは
ほぼ日本国内では違法ではあるので
手を出さないように気を付けないといけません!!!
カジノが出来たら
もっともっとシミュレーションしましょう。
今回はここまでです
それでは
に関する確率のシミュレーションです
解説動画はこちら
ポーカーについて
ポーカーはトランプ5枚の手札の組み合わせで
役を作るゲームです。
1.ハイカード(強いカードの所持 2 < A)
2.ワンペア(同じ数字の組み合わせが1つ)
3.ツーペア(同じ数字の組み合わせが2つ)
4.スリーカード(同じ数字3つ)
5.ストレート(2,3,4,5,6 などの数字の並び)
6.フラッシュ(同じスートの組み合わせ HDCS)
7.フルハウス(スリーカードに加えて、同じ数字の組み合わせが1つ)
8.フォーカード(同じ数字4つ)
9.ストレートフラッシュ(ストレート + フラッシュ)
10.ロイヤルフラッシュ(AKQJTのフラッシュ)
テキサスホールデムルール
ポーカーのルールの一つで
ここからはテキサスホールデムの
初期手札による勝率がどうなるのかを
検証するシミュレーションプログラムについてです。
ポーカーのルールの一つで
プレイヤーそれぞれに配られた2枚のカードと
プレイヤー全員が共有する公開された
コミュニティカード"枚の計7枚で役を作り
プレイヤー全員が共有する公開された
コミュニティカード"枚の計7枚で役を作り
チップをベットするなどの駆け引きを行うゲームルールです
(ベット周りの詳細なルールは割愛)
(ベット周りの詳細なルールは割愛)
ここからはテキサスホールデムの
初期手札による勝率がどうなるのかを
検証するシミュレーションプログラムについてです。
役を計算するプログラム
シミュレーションを行うには
ポーカーの役の判定を行うプログラムが必要ですね
import random
from collections import Counter
from itertools import combinations
# ポーカーの役
POKER_HANDS = {
0: "ハイカード",
1: "ワンペア",
2: "ツーペア",
3: "スリーカード",
4: "ストレート",
5: "フラッシュ",
6: "フルハウス",
7: "フォーカード",
8: "ストレートフラッシュ",
9: "ロイヤルストレートフラッシュ"
}
# カードのランクとスート(HA=ハートのエース, D2=ダイヤの2)
RANKS = "23456789TJQKA"
SUITS = "HDSC" # ハート, ダイヤ, スペード, クラブ
DECK = [s + r for r in RANKS for s in SUITS]
# 役の評価(スコアをタプルで返す)
def evaluate_hand(hand):
ranks = sorted([RANKS.index(c[1]) for c in hand], reverse=True)
suits = [c[0] for c in hand]
rank_counts = Counter(ranks)
flush = len(set(suits)) == 1
straight = len(rank_counts) == 5 and (max(ranks) - min(ranks) == 4 or set(ranks) == {12, 3, 2, 1, 0}) # A-2-3-4-5対応
# 役の判定(同率はRankで比較)
if straight and flush:
if set(ranks) == {12, 11, 10, 9, 8}: # A, K, Q, J, 10
return (9, max(ranks)) # ロイヤルストレートフラッシュ
return (8, max(ranks)) # ストレートフラッシュ
if 4 in rank_counts.values():
return (7, max(k for k, v in rank_counts.items() if v == 4)) # フォーカード
if 3 in rank_counts.values() and 2 in rank_counts.values():
return (6, max(k for k, v in rank_counts.items() if v == 3)) # フルハウス
if flush:
return (5, ranks) # フラッシュ
if straight:
return (4, max(ranks)) # ストレート
if 3 in rank_counts.values():
return (3, max(k for k, v in rank_counts.items() if v == 3)) # スリーカード
if list(rank_counts.values()).count(2) == 2:
return (2, sorted([k for k, v in rank_counts.items() if v == 2], reverse=True)) # ツーペア
if 2 in rank_counts.values():
return (1, max(k for k, v in rank_counts.items() if v == 2)) # ワンペア
return (0, ranks) # ハイカード
これを用いてシミュレーションを行なっていきます。
テキサスホールデムのシミュレーション
初期手札2枚と公開札5枚で、役を作り、勝率がどうなるか
4人で対戦をする際の勝率を出す
シミュレーションプログラムです。
user_num のところが対戦人数になるので
変更すれば、その人数での確率を求めることができます。
カードの組み合わせを変えれば
その都度計算が行えます。
これをヒートマップにしてみましょう。
勝率をヒートマップにする
シミュレーションプログラムです。
user_num のところが対戦人数になるので
変更すれば、その人数での確率を求めることができます。
# モンテカルロ法で勝率計算
def monte_carlo_win_rate(my_hand, num_simulations=10000):
wins = 0
user_num = 3
for _ in range(num_simulations):
deck = DECK.copy()
for card in my_hand:
deck.remove(card)
# 4人分の手札をランダムに配る
random.shuffle(deck)
opponent_hands = [deck[i * 2: (i + 1) * 2] for i in range(user_num)]
community_cards = deck[6:11]
# 各プレイヤーのベストハンドを評価
my_best = max(evaluate_hand(list(comb)) for comb in combinations(my_hand + community_cards, 5))
opponent_best = [max(evaluate_hand(list(comb)) for comb in combinations(hand + community_cards, 5)) for hand in opponent_hands]
# 自分が最も強い手を持っているか判定
if my_best > max(opponent_best):
wins += 1
return wins / num_simulations
# 例: 自分の手札をセットして勝率を計算
my_hand = ["HA", "HK"] # ハートのエース・キング
win_rate = monte_carlo_win_rate(my_hand, num_simulations=5000)
print(f"勝率: {win_rate:.2%}")
勝率: 33.02%カードの組み合わせを変えれば
その都度計算が行えます。
初期カードの組み合わせでの勝率
2種の13 * 13 枚の組み合わせにおける
勝率を計算してみましょう。
これで、13x13=169通りの結果が出せます。勝率を計算してみましょう。
RANKS = "23456789TJQKA"
H_DECK = [s + r for r in RANKS for s in "H"]
D_DECK = [s + r for r in RANKS for s in "D"]
combi = [[h, d] for h in H_DECK for d in D_DECK]
result = {":".join(c):0 for c in combi}
for my_hand in combi:
result[":".join(my_hand)] = monte_carlo_win_rate(my_hand, num_simulations=5000)
これをヒートマップにしてみましょう。
勝率をヒートマップにする
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# キーのソート用の関数
def get_rank_order(card):
return RANKS.index(card[1])
# キーを分離してデータフレームを作成
data_list = []
for key, value in result.items():
row_key, col_key = key.split(':')
data_list.append({'row': row_key, 'col': col_key, 'value': value})
df = pd.DataFrame(data_list)
unique_rows = sorted(df['row'].unique(), key=get_rank_order)
unique_cols = sorted(df['col'].unique(), key=get_rank_order)
# ピボットテーブルを作成
pivot_df = df.pivot(index='row', columns='col', values='value')
# インデックスと列を順序通りに並び替え
pivot_df = pivot_df.reindex(index=unique_rows, columns=unique_cols)
# ヒートマップの作成
plt.figure(figsize=(10, 8))
sns.heatmap(pivot_df,
cmap='RdYlGn',
vmin=0,
vmax=1,
annot=True,
fmt='.2f',
cbar_kws={'label': 'Value'})
plt.title('Win rate for first hand combination')
plt.tight_layout()
plt.show()

やはり、最初にワンペアを持っているだけで勝率は高くなりますね
とはいえ、それだけでは勝てないのが
このテキサスホールデムルールの面白いところ
初期手札の読み合いやベットなどの駆け引き
この辺りが組み合わさることで
ゲーム性が高くかなり面白いものになっています。
とはいえ
日本ではまだまだ、カジノがないので
ポーカーを楽しむには
単純なゲームとしてのポーカーしか出来ません
オンラインで展開されているものは
ほぼ日本国内では違法ではあるので
手を出さないように気を付けないといけません!!!
カジノが出来たら
もっともっとシミュレーションしましょう。
今回はここまでです
それでは






