paloma blog

NWエンジニアやってます。主に自宅環境のお遊びを書きます。Pythonもちょっと。タイトルは好きなカクテルから。

スリーカードポーカーの手札の確率を計算してみる

スリーカードポーカーゲーム作成PJですが、あとはunittestを書けばひと段落です。
でもその前にシミュレータを改良しました。

改良点

  • 引き分けの処理を追加した
    • カジノだとベット額そのままで次のゲームに行くようなのですが、一勝負ごとに払い戻しの処理にしているのでベット額がそのまま返ってくるようにしました
  • プレイヤーが勝った手札の比率も集計した
    • 勝ったうちの手札の比率も知りたかったので出してみました。

実行

前回と同じ50万回試行します。

$ python3 simulater.py 
Three card poker simulator start.
The simulator trials 500,000 times.

=== Probabliry of winning or losing ===

Player 250265 wins.
Dealer 249735 wins.
Draw 0 times.

=== Percentage of Players all hands ===

High card!          74.592%
One Pair!           17.021%
Flash!                4.98%
Straight!            2.966%
Three of a kind!     0.239%
Straight Flash!      0.202%

=== Percentage of Players win(250,265 times) hands ===

High card!          74.515%
One Pair!           17.023%
Flash!               4.982%
Straight!             3.04%
Three of a kind!     0.235%
Straight Flash!      0.206%

なんと勝った時の比率も全体の結果と変わりませんでした!
上手くできてるもんですねぇ。

しかし引き分けが出ませんね。
どこか間違えたかな?
ディーラー勝負時かつ同役かつ同数字の場合だから出ないか…。

確率を計算してみる

組み合わせ

シミュレータ作る前に研究すべきことだと思いますが、比率は本当なのか確率を計算してみましょう。
高校ぶりに数学をやりますw

  • スリーカードポーカーの手札の組み合わせ

ジョーカーなしの52枚から3枚引くので{}_{52}  C _3 \通りですね。
せっかくなのでpythonで計算しましょう。

itertoolsのcombinationsを使います。

>>> val = set(itertools.combinations(range(52),3))
>>> len(val)
22100

22100通りです。
3枚だけでも結構組み合わせがありますね。

確率

役の組み合わせから22100を割れば出せますね。
確率の低いものから出してみます。

  • ストレートフラッシュ

1種類のスートでA,2,3 ~ 12,13,A までの組み合わせです。12通りあります。
スートが4種類なので48通り。

>>> 48 / 22100
0.0021719457013574662

で0.21%です。

  • スリーカード

同じ数字3枚です。
4種類のスートから3枚引く組み合わせは{}_4 C _2 \

>>> len(set(itertools.combinations(range(4),3)))
4

数字が13まであるので4×13で52通りです。

>>> 52 / 22100
0.002352941176470588

で0.23%です。

  • ストレート

3枚連続した数字です。
4種のスートを問わず3枚引くので43で64通り。
ストレートのパターンは12通りなので64×12で768通り。
ストレートフラッシュのパターンが重複してるので768 - 48で720通りです。

>>> 720 / 22100
0.03257918552036199

で3.25%です。

  • フラッシュ

1種類のスートから3枚引くので{}_{13} C _3 \通り。

>>> len(set(itertools.combinations(range(13),3)))
286

スートは4種類あるから286×4で1144通り。
これもストレートフラッシュの重複を抜いて1144 - 48で1096通りです。

>>> 1096 / 22100
0.049592760180995475

で4.95%です。

  • ワンぺア

同じ数2枚の役ですね。

同じ数は4枚あるのでペアの組み合わせは{}_4 C _2 \通り。

>>> len(set(itertools.combinations(range(4),2)))
6

3枚目の手札は何でもいいので上の4枚を除いて48通り

>>> 6 * 48
288

数字は1~13まであるので

>>> 288 * 13
3744
>>> 3744 / 22100
0.16941176470588235

で16.9%ですね。
3枚だと意外と出ないもんですね。

残りはいわゆる役無しなので今までの組み合わせを引いた数を割れば出ます。

イカード以外の役は

>>> 48 + 52 + 720 + 1096 + 3744
5660

で全体から引いて

>>> 22100 - 5660
16440

を全体で割って

>>> 16440 / 22100
0.7438914027149321

で74.3%ですね。

比較する

確率が出たところでシミュレータの結果と比較してみましょう。

計算した確率 シミュレータ(50万回)の確率
ストレートフラッシュ 0.21% 0.202%
スリーカード 0.23% 0.239%
ストレート 3.25% 2.966%
フラッシュ 4.95% 4.98%
ワンペア 16.9% 17.021%
イカード 74.3% 74.592%

ストレートが少しずれてますが、だいたい近似値になってますよね!
ということは私の判定処理、シミュレータの作りは間違ってなかった!

これは嬉しいです。

ちなみに100回だけ試行するとどうなるのか

回数が多いと大数の法則で真の値に近づいていくのですが、100回だとどうなるんでしょうか。

$ python3 simulater.py 
Three card poker simulator start.
The simulator trials 100 times.

=== Probabliry of winning or losing ===

Player 52 wins.
Dealer 48 wins.
Draw 0 times.

=== Percentage of Players all hands ===

High card!            68.0%
One Pair!             20.0%
Flash!                 7.0%
Straight!              3.0%
Three of a kind!       2.0%

=== Percentage of Players win(52 times) hands ===

High card!          71.154%
One Pair!           19.231%
Flash!               7.692%
Three of a kind!     1.923%

やはり回数が少ないと比率はばらけますね。
100回ではストレートフラッシュは出ませんでした。
ストレート3回も出したのに全部負けてますw

むすび

自分で作ったツールと数学の計算結果が合いました。
処理が正しい構造になってたんだと分かって自身が付きますね。

確率計算なんて高校ぶりで、数学は苦手でしたが今回は計算を自動でやってくれるので
取っつきにくさが無かったです。
苦手と思っていたのは計算が面倒なだけだったのかもしれません。

…と言ったものの、確率の答え合わせしたら一部間違えていたのでやはり苦手ですねw

参考サイト

  • ポーカーの確率
  • この他、答え合わせでスリーカードポーカーのサイトも見ました(カジノ系なので伏せます)

参考本

www.amazon.co.jp

リポジトリ

github.com