Pythonでブラックジャックをシミュレーションしてみる
こんにちは。今回は,Pythonを使ってブラックジャックのシミュレーションをしてみます。
以前Excelでシミュレーションをしてみたものは,次のリンクにあります。
これと同じことをPythonで書いてみます。
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, 1000000 ):
ca = []
hand = [ draw() ]
hand.append( draw() )
pre, soft = calc( hand )
hand.append( draw() )
post, st = calc( hand )
if post > 21:
post = 'Burst'
if not ( pre, soft, post ) in cnt:
cnt[ (pre,soft,post) ] = 0
cnt[ (pre,soft,post) ] += 1
po = list( range( 6, 22 ) )
po.append('Burst')
print('ヒット前 ハンド ヒット後 回数')
for i in range( 4, 22 ):
for j in [ 'Hard', 'Soft' ]:
for k in po:
if ( i, j, k ) in cnt:
print('{:5} {} {:5} {:5}'.format( i, j, k, cnt[(i,j,k)] ) )
print('***************************')
print('ヒット前 ハンド 向上率 バースト率')
for i in range( 4, 22 ):
for j in [ 'Hard', 'Soft' ]:
to = 0
better = 0
bu = 0
for k in po:
if not ( i, j, k ) in cnt:
continue
to += cnt[(i,j,k)]
if k=='Burst':
bu = cnt[(i,j,k)]
if k!='Burst' and i < k:
better += cnt[(i,j,k)]
if to!=0:
print('{:5} {:4} {:6.2f}% {:6.2f}%'
.format( i, j, better*100/to, bu*100/to ) )
う~ん,ぐちゃぐちゃですね。
一応,説明らしいことをしてみます。
def draw():
x = random.randint(0,51)
while x in ca:
x = random.randint(0,51)
ca.append(x)
return x
2~7行目では,手札を引いています。
while文は,発生させた乱数が既に引いていたカードと同じならば引き直しをするようにループさせています。
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
8~19では手札の合計を計算させています。
変数 s には手札の合計,変数 flag にはエースが含まれるかどうか,変数 soft にはソフトハンド(エースを11として計算した)かハードハンドかといった情報を持たせています。
13行目で手札の値を加えています。
13で割った余り+1がカードの番号です。
余りが10・11・12はJ・Q・Kにあたるので,これらのときは10を加えています。
cnt = {}
for i in range( 0, 1000000 ):
ca = []
hand = [ draw() ]
hand.append( draw() )
pre, soft = calc( hand )
hand.append( draw() )
post, st = calc( hand )
if post > 21:
post = 'Burst'
if not ( pre, soft, post ) in cnt:
cnt[ (pre,soft,post) ] = 0
cnt[ (pre,soft,post) ] += 1
変数 cnt は,キーを(ヒット前,ハンド,ヒット後)として,バリューを頻度として記憶させています。
変数 ca はすでに引いたカードを記憶させています。
変数 hand は手札です。
28・29行目はバーストを判定しています。
とりあえず100万回シミュレーションさせています。
なお,手元の実行環境では約8秒程度で実行終了しました。
po = list( range( 6, 22 ) )
po.append('Burst')
print('ヒット前 ハンド ヒット後 回数')
for i in range( 4, 22 ):
for j in [ 'Hard', 'Soft' ]:
for k in po:
if ( i, j, k ) in cnt:
print('{:5} {} {:5} {:5}'.format( i, j, k, cnt[(i,j,k)] ) )
print('***************************')
print('ヒット前 ハンド 向上率 バースト率')
for i in range( 4, 22 ):
for j in [ 'Hard', 'Soft' ]:
to = 0
better = 0
bu = 0
for k in po:
if not ( i, j, k ) in cnt:
continue
to += cnt[(i,j,k)]
if k=='Burst':
bu = cnt[(i,j,k)]
if k!='Burst' and i < k:
better += cnt[(i,j,k)]
if to!=0:
print('{:5} {:4} {:6.2f}% {:6.2f}%'
.format( i, j, better*100/to, bu*100/to ) )
33行目以降は結果を表示させています。
汚いコードですね。ひたすらループを回して処理しています。
実行結果
それでは実行結果です。
ヒット前 ハンド ヒット後 回数
4 Hard 6 181
4 Hard 7 372
4 Hard 8 380
4 Hard 9 336
4 Hard 10 365
4 Hard 11 349
4 Hard 12 334
4 Hard 13 365
4 Hard 14 1466
4 Hard 15 319
5 Hard 7 748
5 Hard 8 737
5 Hard 9 970
5 Hard 10 937
5 Hard 11 974
5 Hard 12 967
5 Hard 13 957
5 Hard 14 896
5 Hard 15 3886
5 Hard 16 958
6 Hard 8 1011
6 Hard 9 1162
6 Hard 10 1066
6 Hard 11 1272
6 Hard 12 1316
6 Hard 13 1412
6 Hard 14 1299
6 Hard 15 1373
6 Hard 16 5210
6 Hard 17 1291
7 Hard 9 1650
7 Hard 10 1627
7 Hard 11 1713
7 Hard 12 1760
7 Hard 13 1914
7 Hard 14 2016
7 Hard 15 1912
7 Hard 16 2008
7 Hard 17 7722
7 Hard 18 1943
8 Hard 10 1954
8 Hard 11 2125
8 Hard 12 2100
8 Hard 13 2102
8 Hard 14 2014
8 Hard 15 2292
8 Hard 16 2348
8 Hard 17 2326
8 Hard 18 9147
8 Hard 19 2314
9 Hard 11 2657
9 Hard 12 2690
9 Hard 13 2551
9 Hard 14 2592
9 Hard 15 2727
9 Hard 16 2673
9 Hard 17 2851
9 Hard 18 2824
9 Hard 19 11505
9 Hard 20 2867
10 Hard 12 3043
10 Hard 13 3018
10 Hard 14 3217
10 Hard 15 3153
10 Hard 16 3050
10 Hard 17 3085
10 Hard 18 2971
10 Hard 19 3277
10 Hard 20 13041
10 Hard 21 3225
11 Hard 12 3826
11 Hard 13 3576
11 Hard 14 3656
11 Hard 15 3670
11 Hard 16 3648
11 Hard 17 3705
11 Hard 18 3654
11 Hard 19 3658
11 Hard 20 3643
11 Hard 21 15659
12 Hard 13 7044
12 Hard 14 6141
12 Hard 15 6746
12 Hard 16 6816
12 Hard 17 6846
12 Hard 18 6811
12 Hard 19 6877
12 Hard 20 6809
12 Hard 21 6803
12 Hard Burst 27568
12 Soft 12 1384
12 Soft 13 176
12 Soft 14 372
12 Soft 15 404
12 Soft 16 345
12 Soft 17 383
12 Soft 18 410
12 Soft 19 383
12 Soft 20 362
12 Soft 21 324
13 Hard 14 6671
13 Hard 15 6755
13 Hard 16 5715
13 Hard 17 6446
13 Hard 18 6423
13 Hard 19 6538
13 Hard 20 6617
13 Hard 21 6577
13 Hard Burst 32573
13 Soft 12 981
13 Soft 13 3891
13 Soft 14 763
13 Soft 15 741
13 Soft 16 1006
13 Soft 17 1008
13 Soft 18 909
13 Soft 19 1002
13 Soft 20 989
13 Soft 21 970
14 Hard 15 6071
14 Hard 16 6105
14 Hard 17 6188
14 Hard 18 5189
14 Hard 19 5946
14 Hard 20 5937
14 Hard 21 5948
14 Hard Burst 35298
14 Soft 12 927
14 Soft 13 1004
14 Soft 14 3868
14 Soft 15 758
14 Soft 16 903
14 Soft 17 680
14 Soft 18 988
14 Soft 19 1015
14 Soft 20 933
14 Soft 21 887
15 Hard 16 5892
15 Hard 17 5801
15 Hard 18 5655
15 Hard 19 5781
15 Hard 20 4807
15 Hard 21 5512
15 Hard Burst 38810
15 Soft 12 941
15 Soft 13 976
15 Soft 14 954
15 Soft 15 3797
15 Soft 16 726
15 Soft 17 1021
15 Soft 18 945
15 Soft 19 739
15 Soft 20 1014
15 Soft 21 979
16 Hard 17 5256
16 Hard 18 5170
16 Hard 19 5079
16 Hard 20 5164
16 Hard 21 5151
16 Hard Burst 38643
16 Soft 12 916
16 Soft 13 1005
16 Soft 14 965
16 Soft 15 981
16 Soft 16 3900
16 Soft 17 764
16 Soft 18 965
16 Soft 19 948
16 Soft 20 987
16 Soft 21 753
17 Hard 18 4927
17 Hard 19 4812
17 Hard 20 4870
17 Hard 21 4787
17 Hard Burst 41030
17 Soft 12 916
17 Soft 13 704
17 Soft 14 930
17 Soft 15 970
17 Soft 16 1001
17 Soft 17 3951
17 Soft 18 732
17 Soft 19 993
17 Soft 20 1000
17 Soft 21 934
18 Hard 19 4300
18 Hard 20 4226
18 Hard 21 4320
18 Hard Burst 39677
18 Soft 12 911
18 Soft 13 1016
18 Soft 14 950
18 Soft 15 729
18 Soft 16 963
18 Soft 17 967
18 Soft 18 3852
18 Soft 19 737
18 Soft 20 944
18 Soft 21 937
19 Hard 20 3920
19 Hard 21 4005
19 Hard Burst 40605
19 Soft 12 961
19 Soft 13 1021
19 Soft 14 958
19 Soft 15 1000
19 Soft 16 949
19 Soft 17 707
19 Soft 18 958
19 Soft 19 3999
19 Soft 20 717
19 Soft 21 944
20 Hard 21 7400
20 Hard Burst 83566
20 Soft 12 1000
20 Soft 13 953
20 Soft 14 957
20 Soft 15 965
20 Soft 16 906
20 Soft 17 951
20 Soft 18 972
20 Soft 19 728
20 Soft 20 3956
20 Soft 21 722
21 Soft 12 2837
21 Soft 13 3857
21 Soft 14 3776
21 Soft 15 3942
21 Soft 16 3743
21 Soft 17 3909
21 Soft 18 3742
21 Soft 19 4050
21 Soft 20 3913
21 Soft 21 14496
***************************
ヒット前 ハンド 向上率 バースト率
4 Hard 100.00% 0.00%
5 Hard 100.00% 0.00%
6 Hard 100.00% 0.00%
7 Hard 100.00% 0.00%
8 Hard 100.00% 0.00%
9 Hard 100.00% 0.00%
10 Hard 100.00% 0.00%
11 Hard 100.00% 0.00%
12 Hard 68.84% 31.16%
12 Soft 69.54% 0.00%
13 Hard 61.37% 38.63%
13 Soft 60.26% 0.00%
14 Hard 53.97% 46.03%
14 Soft 51.53% 0.00%
15 Hard 46.29% 53.71%
15 Soft 44.86% 0.00%
16 Hard 40.05% 59.95%
16 Soft 36.25% 0.00%
17 Hard 32.10% 67.90%
17 Soft 30.16% 0.00%
18 Hard 24.46% 75.54%
18 Soft 21.81% 0.00%
19 Hard 16.33% 83.67%
19 Soft 13.60% 0.00%
20 Hard 8.13% 91.87%
20 Soft 5.96% 0.00%
21 Soft 0.00% 0.00%
まあ当たり前といえば当たり前ですが,Excelのときと似たような値になっています。
今回はこれでおしまいにします。それではまた。
ディスカッション
コメント一覧
まだ、コメントがありません