ブラックジャックでディーラーの手がどうなるかPythonでシミュレーションしてみた

モデル化とシミュレーション

こんにちは。またブラックジャックをPythonでシミュレーションしてみたシリーズです。

ディーラーのルール

ブラックジャックでは、ディーラーはカードをヒットするか否かは意志ではなく、ルールとして決まっているらしいです。

そのルールは、ディーラーは手の合計が「17」以上になるまで引き続けるというものです。

こんなに単純なら、シミュレーションして、頻度を数えることができますね!

Pythonのプログラム

それでは、前回のプログラムを改造してみることにします。

import random
def draw():
    x = random.randint(0,51)
    while x in ca:
        x = random.randint(0,51)
    ca.append(x)
    return x
def calc( hand ):
    s = 0
    flag = False
    soft = 'Hard'
    for h in hand:
        s += 10 if ( h % 13 ) > 9 else (( h % 13 ) + 1)
        if h % 13 ==0:
            flag = True
    if s < 12 and flag:
        s += 10
        soft = 'Soft'
    return s, soft
cnt = {}
for i in range( 0, 10000000 ):
    ca = []
    hand = [ draw() ]
    hand.append( draw() )
    p, soft = calc( hand )
    while p < 17:
        hand.append( draw() )
        p, soft = calc( hand )
    upcard,soft = calc(hand[0:1])
    if p > 21:
        p = 'Burst'
    if not ( upcard, p ) in cnt:
        cnt[( upcard, p )] = 0
    cnt[( upcard, p )] += 1
total = {}
for i in range( 2, 12 ):
    total[i] = 0
    for j in range( 17 , 22 ):
        if (i,j) in cnt:
            total[i] += cnt[(i,j)]
    if (i,'Burst') in cnt:
        total[i] += cnt[(i,'Burst')]
for i in range( 2, 12 ):
    print( 'アップカード   合計   回数     割合' )
    for j in range( 17 , 22 ):
        if (i,j) in cnt:
            print( '{:8d}  {:5d} {:7d}  {:6.2f}%'
                .format(i, j, cnt[(i,j)], cnt[(i,j)]*100/total[i]) )
    if (i,'Burst') in cnt:
        print( '{:8d}  {:5} {:7d}  {:6.2f}%'
            .format(i, 'Burst', cnt[(i,'Burst')], cnt[(i,'Burst')]*100/total[i] ))
    print( '-'*33 )

19行目までは、前回とまったく同じです。

22~29行目が、ディーラーのルールに従ってカードを引いているところです。

30~34行目はバーストの処理をして、回数を数えています。

cnt = {}
for i in range( 0, 10000000 ):
    ca = []
    hand = [ draw() ]
    hand.append( draw() )
    p, soft = calc( hand )
    while p < 17:
        hand.append( draw() )
        p, soft = calc( hand )
    upcard,soft = calc(hand[0:1])
    if p > 21:
        p = 'Burst'
    if not ( upcard, p ) in cnt:
        cnt[( upcard, p )] = 0
    cnt[( upcard, p )] += 1

35~42行目では、アップカードの合計を求めています。

43行目以降で、表示をしています。

total = {}
for i in range( 2, 12 ):
    total[i] = 0
    for j in range( 17 , 22 ):
        if (i,j) in cnt:
            total[i] += cnt[(i,j)]
    if (i,'Burst') in cnt:
        total[i] += cnt[(i,'Burst')]
for i in range( 2, 12 ):
    print( 'アップカード   合計   回数     割合' )
    for j in range( 17 , 22 ):
        if (i,j) in cnt:
            print( '{:8d}  {:5d} {:7d}  {:6.2f}%'
                .format(i, j, cnt[(i,j)], cnt[(i,j)]*100/total[i]) )
    if (i,'Burst') in cnt:
        print( '{:8d}  {:5} {:7d}  {:6.2f}%'
            .format(i, 'Burst', cnt[(i,'Burst')], cnt[(i,'Burst')]*100/total[i] ))
    print( '-'*33 )

実行結果

それでは実行結果です。

結構プログラムが速そうなので、1000万回実行してみました。およそ実行時間は2分半でした。

カップラーメンなら、ちょっと固めといった感じでしょうか。

アップカード(表になって見えているカード)ごとに、最終的なカードの合計と回数、割合を表示します。

割合は、それぞれのアップカードに対する割合になっています。

例えば、アップカードが「2」になったうち、13.86%がディーラーの手は「17」となり、35.33%がディーラーの手は「バースト」してしまうというようになっています。

アップカード   合計   回数     割合
       2     17  106423   13.86%
       2     18  101712   13.25%
       2     19  101396   13.21%
       2     20   94899   12.36%
       2     21   92063   11.99%
       2  Burst  271213   35.33%
---------------------------------
アップカード   合計   回数     割合
       3     17  100274   13.07%
       3     18  100731   13.13%
       3     19   94768   12.35%
       3     20   94218   12.28%
       3     21   88999   11.60%
       3  Burst  288337   37.58%
---------------------------------
アップカード   合計   回数     割合
       4     17  100606   13.08%
       4     18   87673   11.40%
       4     19   93632   12.18%
       4     20   89581   11.65%
       4     21   88191   11.47%
       4  Burst  309362   40.23%
---------------------------------
アップカード   合計   回数     割合
       5     17   91702   11.93%
       5     18   94491   12.29%
       5     19   90253   11.74%
       5     20   80659   10.49%
       5     21   81793   10.64%
       5  Burst  329863   42.91%
---------------------------------
アップカード   合計   回数     割合
       6     17  128610   16.68%
       6     18   81841   10.62%
       6     19   82750   10.73%
       6     20   77845   10.10%
       6     21   75702    9.82%
       6  Burst  324130   42.05%
---------------------------------
アップカード   合計   回数     割合
       7     17  286479   37.24%
       7     18  106281   13.82%
       7     19   59668    7.76%
       7     20   60666    7.89%
       7     21   56299    7.32%
       7  Burst  199841   25.98%
---------------------------------
アップカード   合計   回数     割合
       8     17  101021   13.13%
       8     18  278904   36.25%
       8     19   99518   12.94%
       8     20   52196    6.78%
       8     21   53851    7.00%
       8  Burst  183876   23.90%
---------------------------------
アップカード   合計   回数     割合
       9     17   93521   12.13%
       9     18   79884   10.36%
       9     19  275930   35.78%
       9     20   94250   12.22%
       9     21   47119    6.11%
       9  Burst  180417   23.40%
---------------------------------
アップカード   合計   回数     割合
      10     17  351637   11.43%
      10     18  347910   11.31%
      10     19  352570   11.46%
      10     20 1013278   32.93%
      10     21  353210   11.48%
      10  Burst  658776   21.41%
---------------------------------
アップカード   合計   回数     割合
      11     17   96855   12.59%
      11     18  100614   13.08%
      11     19   99328   12.91%
      11     20  101406   13.18%
      11     21  281512   36.60%
      11  Burst   89466   11.63%
---------------------------------

今回はこれでおしまいにします。それではまた。

Posted by 春日井 優