ブラックジャックでの戦略をまたまた考えてみる

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

こんにちは。またブラックジャックでがんばってみます。

今度の作戦

前回の予告どおり期待値で攻めてみましょう。

ステイした場合の期待値は,プレイヤーの今の手とディーラーの手を比較して,プレイヤーの方が大きいかディーラーがバーストすれば+1ポイント,プレイヤーの方が小さければー1ポイントになります。

ヒットした場合の期待値は,プレイヤーのヒット後の手がディーラーの手を比べることになります。

きれいなプログラムにはしていませんが,次のようにしました。

コメントを入れていないので,ちょっと補足です。

変数probは今の手が4,5,・・・,21についてリストを要素としてもたせていて,その中に[16以下,17,18,19,20,21,バースト]の確率を入れています。

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
    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
    return s
upcard_prob = { 2 : [ 0.3533, 0.1386, 0.1325, 0.1321, 0.1236, 0.1199 ],
                3 : [ 0.3758, 0.1307, 0.1313, 0.1235, 0.1228, 0.1160 ],
                4 : [ 0.4023, 0.1308, 0.1140, 0.1218, 0.1165, 0.1147 ],
                5 : [ 0.4291, 0.1193, 0.1229, 0.1174, 0.1049, 0.1064 ],
                6 : [ 0.4205, 0.1668, 0.1062, 0.1073, 0.1010, 0.0982 ],
                7 : [ 0.2598, 0.3724, 0.1382, 0.0776, 0.0789, 0.0732 ],
                8 : [ 0.2390, 0.1313, 0.3625, 0.1294, 0.0678, 0.0700 ],
                9 : [ 0.2340, 0.1213, 0.1036, 0.3578, 0.1222, 0.0611 ],
               10 : [ 0.2141, 0.1143, 0.1131, 0.1146, 0.3293, 0.1148 ],
               11 : [ 0.1163, 0.1259, 0.1308, 0.1291, 0.1318, 0.3660 ]
               }
prob = [
        [ 1.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 ],
        [ 1.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 ],
        [ 0.924, 0.076, 0.000, 0.000, 0.000, 0.000, 0.000 ],
        [ 0.608, 0.311, 0.080, 0.000, 0.000, 0.000, 0.000 ],
        [ 0.519, 0.081, 0.321, 0.080, 0.000, 0.000, 0.000 ],
        [ 0.439, 0.083, 0.078, 0.331, 0.070, 0.000, 0.000 ],
        [ 0.368, 0.083, 0.077, 0.081, 0.316, 0.075, 0.000 ],
        [ 0.380, 0.080, 0.074, 0.072, 0.076, 0.317, 0.000 ],
        [ 0.322, 0.080, 0.076, 0.082, 0.075, 0.075, 0.290 ],
        [ 0.276, 0.078, 0.078, 0.079, 0.079, 0.080, 0.330 ],
        [ 0.222, 0.072, 0.072, 0.077, 0.077, 0.079, 0.402 ],
        [ 0.162, 0.080, 0.079, 0.078, 0.066, 0.073, 0.462 ],
        [ 0.103, 0.078, 0.079, 0.077, 0.081, 0.076, 0.507 ],
        [ 0.064, 0.051, 0.073, 0.078, 0.083, 0.082, 0.571 ],
        [ 0.073, 0.017, 0.056, 0.081, 0.080, 0.077, 0.616 ],
        [ 0.083, 0.012, 0.016, 0.066, 0.081, 0.074, 0.669 ],
        [ 0.046, 0.009, 0.011, 0.007, 0.041, 0.073, 0.812 ],
        [ 0.376, 0.076, 0.079, 0.080, 0.088, 0.301, 0.000 ]
    ]


point = 0
cnt = {}
wi = 0
lo = 0
dr = 0
tr = 1000000
for i in range( 0, tr ):
    ca = []
    c_hand = [ draw() ]
    d_hand = [ draw() ]
    upcard = calc( d_hand )
    c_hand.append( draw() )
    d_hand.append( draw() )
    cp = calc( c_hand )
    dp = calc( d_hand )
    if cp==21 and dp!=21:
        wi += 1
        point += 1.5
        continue
    elif cp!=21 and dp==21:
        lo += 1
        point -= 1.0
        continue
    calc_p = cp - 16 +1 if cp > 16 else 0
    st_exp = upcard_prob[upcard][0] \
            + sum( upcard_prob[upcard][1:calc_p] ) \
            - sum(upcard_prob[upcard][calc_p+1:])
    calc_p2 = cp - 4
    ht_exp = -prob[calc_p2][6] \
             +prob[calc_p2][0]*sum(upcard_prob[upcard][0:1]) \
             +prob[calc_p2][1]*sum(upcard_prob[upcard][0:1]) \
             +prob[calc_p2][2]*sum(upcard_prob[upcard][0:2]) \
             +prob[calc_p2][3]*sum(upcard_prob[upcard][0:3]) \
             +prob[calc_p2][4]*sum(upcard_prob[upcard][0:4]) \
             +prob[calc_p2][5]*sum(upcard_prob[upcard][0:5]) \
             -prob[calc_p2][0]*sum(upcard_prob[upcard][1:6]) \
             -prob[calc_p2][1]*sum(upcard_prob[upcard][2:6]) \
             -prob[calc_p2][2]*sum(upcard_prob[upcard][3:6]) \
             -prob[calc_p2][3]*sum(upcard_prob[upcard][4:6]) \
             -prob[calc_p2][4]*sum(upcard_prob[upcard][5:6])
    while cp < 21 and st_exp 16 else 0
        st_exp = upcard_prob[upcard][0] + sum( upcard_prob[upcard][1:calc_p] )-sum(upcard_prob[upcard][calc_p+1:])
        calc_p2 = cp - 4 if cp <= 21 else 0
        ht_exp = -prob[calc_p2][5] \
                 +prob[calc_p2][0]*sum(upcard_prob[upcard][0:1]) \
                 +prob[calc_p2][1]*sum(upcard_prob[upcard][0:1]) \
                 +prob[calc_p2][2]*sum(upcard_prob[upcard][0:2]) \
                 +prob[calc_p2][3]*sum(upcard_prob[upcard][0:3]) \
                 +prob[calc_p2][4]*sum(upcard_prob[upcard][0:4]) \
                 +prob[calc_p2][5]*sum(upcard_prob[upcard][0:5]) \
                 -prob[calc_p2][0]*sum(upcard_prob[upcard][1:6]) \
                 -prob[calc_p2][1]*sum(upcard_prob[upcard][2:6]) \
                 -prob[calc_p2][2]*sum(upcard_prob[upcard][3:6]) \
                 -prob[calc_p2][3]*sum(upcard_prob[upcard][4:6]) \
                 -prob[calc_p2][4]*sum(upcard_prob[upcard][5:6])
    if cp > 21:
        lo += 1
        point -= 1.0
        continue
    while dp < 17:
        d_hand.append( draw() )
        dp = calc( d_hand )
    if dp > 21:
        wi += 1
        point += 1.0
        continue
    if cp > dp:
        wi += 1
        point += 1.0
    elif cp < dp:
        lo += 1
        point -= 1.0
    else:
        dr += 1
print('プレーヤー: 勝ち{}回 引き分け{}回 負け{}回'.format( wi, dr, lo ))
print('プレーヤー: 勝ち{:0.2f}% 引き分け{:0.2f}% 負け{:0.2f}% 掛金{:0.1f}'
        .format( wi*100/tr, dr*100/tr, lo*100/tr , point ))

実行結果は

100万回ループを回して調べてみました。

実行結果です。

プレーヤー: 勝ち422988回 引き分け83847回 負け493165回
プレーヤー: 勝ち42.30% 引き分け8.38% 負け49.32% 掛金-46784.5

これまでより,マシだけれどあまりよくないな・・・

せめて立川マシマシくらいにしたいもんです・・・

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

Posted by 春日井 優