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のときと似たような値になっています。

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

Posted by 春日井 優