今回は神経衰弱を一人で行う
シミュレーションプログラムを考えてみました
解説動画はこちら
神経衰弱
今回は神経衰弱です
トランプで行うゲームのひとつで
カードを伏せた状態で混ぜ
プレイヤーは好きな2枚を
その場で表に向けます
プレイヤーは好きな2枚を
その場で表に向けます
2枚が同じ数字であれば
それらを得ることができ
もう一度プレイできます
2枚が異なる数の場合
カードを元通りに伏せて
次のプレイヤーの順番に
カードを元通りに伏せて
次のプレイヤーの順番に
すべてのカードが取られるまで行い
取ったカードの枚数が多い
プレイヤーの勝ちになります
が
取ったカードの枚数が多い
プレイヤーの勝ちになります
が
今回は友達がいないので
一人で神経衰弱をしてみる事を考えてみます
何ターンあれば全部空けられるのか?
仮想のカードを作って
シミュレーションしてみましょう考え方
最初はデッキを用意して
52枚をシャッフルします
# 52枚のカードのデッキ deck = [i for i in range(1,14)] * 4 import numpy as np # シャッフルする np.random.shuffle(deck) print(deck)[1, 11, 7, 6, 11, ・・・]
こんな感じで52枚分のデータを用意します
ターン時の行動を考えてみましょう
こんな感じでしょうか?
こんな感じでしょうか?
カードを1枚開ける
知ってる数字があればそれを開ける
カードをもう1枚開ける
同じ数字なら取る 次の行動へ
違う数字ならターンプラス1
2枚ペアが判明していたらそれを開ける
ここら辺の行動を関数にまとめて
ゲームできる様にしてみました
ゲーム関数
import numpy as np
import collections
# under : カードを覚えておくための変数
# 2個以上分かったカードがあるかどうか
def check_2(under):
c = collections.Counter(under.values())
for i in range(1,14):
if c[i]>=2:
return i
return 0
# 2個のペアのインデックスを返す
def get_2pair(under , num):
pair = [k for k , v in under.items() if v == num]
return pair
# ペアカードを取る
def get_card(under , pair):
for i in pair:
under[i] = 99
return under
# 開けていないカードを1枚選択する
def open_1card(under):
# 候補 0:未開、1-13:開封済、99:取得済
cand = [k for k,v in under.items() if v==0]
return np.random.choice(cand)
# 数字が判明しているかをチェック
def under_check(under,num,select):
# 候補 0:未開、1-13:開封済、99:取得済
cand = [k for k,v in under.items() if v==num and k!=select]
if len(cand)>0:
return True
else:
return False
# 数字が判明しているものを選択する
def open_under_card(under,num,select):
# 候補 0:未開、1-13:開封済、99:取得済
cand = [k for k,v in under.items() if v==num and k!=select]
return np.random.choice(cand)
# ログのプリント
def logs(turn , gets , sheets , num):
text = 'ターン : {0:02} , 取得済み : {1:02} , {2}枚目 , 数字:{3:02}'.format(turn , gets , sheets , num)
print(text)
# 神経衰弱ゲームをシミュレーションする
def game():
# デッキを作ってシャッフルする
deck = [i for i in range(1,14)] * 4
np.random.shuffle(deck)
# 回数と開けたカードの記憶
turn , gets , under = 1, 0 , {i:0 for i in range(52)}
# ゲーム開始
for j in range(100):
# 上がりの判定
if all([i==99 for i in under.values()]):
print('上がり , turn : {0:02}'.format(turn))
break
#2枚開いたのがあればそれを消す
pair_num = check_2(under)
if pair_num > 0:
print('判明済み有り : {0:2}'.format(pair_num))
# ペアを開きに変える
pair = get_2pair(under , pair_num)
under = get_card(under , pair)
gets +=1
print('get card : {0:02},{1:02} , 数字 : {2:02}'.format(pair[0] , pair[1] , pair_num))
else:
#1枚めくる
select_one = open_1card(under)
# 開けたカードの数字
num_one = deck[select_one]
# 数字を覚えておく
under[select_one] = num_one
logs(turn , gets , 1 , num_one)
#数字が分かっているものがあればそれを取る
if under_check(under,num_one,select_one):
target = open_under_card(under , num_one , select_one)
under[select_one] , under[target] = 99 , 99
print('判明済み有り : {0:2}'.format(num_one))
logs(turn , gets , 2 , num_one)
gets +=1
print('get card : {0:02},{1:02} , 数字 : {2:02}'.format(select_one , target , num_one))
else:
#分かってない場合はもう一枚めくる
select_2nd = open_1card(under)
num_2nd = deck[select_2nd]
# 数字を覚えておく
under[select_2nd] = num_2nd
logs(turn , gets , 2 , num_2nd)
#同じ数字ならカードを取る
if num_one==num_2nd:
under[select_one] , under[select_2nd] = 99 , 99
gets +=1
print('get card : {0:02},{1:02} , 数字 : {2:02}'.format(select_one,select_2nd,num_one))
else:
#違う数字ならターンプラス1
turn +=1
print('ターン終了')
return turn
game()
ターン : 01 , 取得済み : 00 , 1枚目 , 数字:04
ターン : 01 , 取得済み : 00 , 2枚目 , 数字:02
ターン終了
ターン : 02 , 取得済み : 00 , 1枚目 , 数字:07
ターン : 02 , 取得済み : 00 , 2枚目 , 数字:05
ターン終了
ターン : 03 , 取得済み : 00 , 1枚目 , 数字:09
ターン : 03 , 取得済み : 00 , 2枚目 , 数字:02
ターン終了
判明済み有り : 2
get card : 08,51 , 数字 : 02
ターン : 04 , 取得済み : 01 , 1枚目 , 数字:10
ターン : 04 , 取得済み : 01 , 2枚目 , 数字:09
ターン終了
判明済み有り : 9
get card : 29,34 , 数字 : 09
ターン : 05 , 取得済み : 02 , 1枚目 , 数字:07
判明済み有り : 7
ターン : 05 , 取得済み : 02 , 2枚目 , 数字:07
get card : 06,22 , 数字 : 07
ターン : 05 , 取得済み : 03 , 1枚目 , 数字:13
ターン : 05 , 取得済み : 03 , 2枚目 , 数字:03
ターン終了
ターン : 06 , 取得済み : 03 , 1枚目 , 数字:08
ターン : 06 , 取得済み : 03 , 2枚目 , 数字:08
get card : 37,31 , 数字 : 08
ターン : 06 , 取得済み : 04 , 1枚目 , 数字:01
ターン : 06 , 取得済み : 04 , 2枚目 , 数字:08
ターン終了
ターン : 07 , 取得済み : 04 , 1枚目 , 数字:06
ターン : 07 , 取得済み : 04 , 2枚目 , 数字:07
ターン終了
ターン : 08 , 取得済み : 04 , 1枚目 , 数字:12
ターン : 08 , 取得済み : 04 , 2枚目 , 数字:05
ターン終了
判明済み有り : 5
get card : 09,48 , 数字 : 05
ターン : 09 , 取得済み : 05 , 1枚目 , 数字:12
判明済み有り : 12
ターン : 09 , 取得済み : 05 , 2枚目 , 数字:12
get card : 28,38 , 数字 : 12
ターン : 09 , 取得済み : 06 , 1枚目 , 数字:08
判明済み有り : 8
ターン : 09 , 取得済み : 06 , 2枚目 , 数字:08
get card : 19,46 , 数字 : 08
ターン : 09 , 取得済み : 07 , 1枚目 , 数字:03
判明済み有り : 3
ターン : 09 , 取得済み : 07 , 2枚目 , 数字:03
get card : 03,26 , 数字 : 03
ターン : 09 , 取得済み : 08 , 1枚目 , 数字:04
判明済み有り : 4
ターン : 09 , 取得済み : 08 , 2枚目 , 数字:04
get card : 30,21 , 数字 : 04
ターン : 09 , 取得済み : 09 , 1枚目 , 数字:13
判明済み有り : 13
ターン : 09 , 取得済み : 09 , 2枚目 , 数字:13
get card : 13,25 , 数字 : 13
ターン : 09 , 取得済み : 10 , 1枚目 , 数字:05
ターン : 09 , 取得済み : 10 , 2枚目 , 数字:05
get card : 17,18 , 数字 : 05
ターン : 09 , 取得済み : 11 , 1枚目 , 数字:01
判明済み有り : 1
ターン : 09 , 取得済み : 11 , 2枚目 , 数字:01
get card : 01,23 , 数字 : 01
ターン : 09 , 取得済み : 12 , 1枚目 , 数字:11
ターン : 09 , 取得済み : 12 , 2枚目 , 数字:04
ターン終了
ターン : 10 , 取得済み : 12 , 1枚目 , 数字:01
ターン : 10 , 取得済み : 12 , 2枚目 , 数字:13
ターン終了
ターン : 11 , 取得済み : 12 , 1枚目 , 数字:09
ターン : 11 , 取得済み : 12 , 2枚目 , 数字:11
ターン終了
判明済み有り : 11
get card : 11,15 , 数字 : 11
ターン : 12 , 取得済み : 13 , 1枚目 , 数字:03
ターン : 12 , 取得済み : 13 , 2枚目 , 数字:01
ターン終了
判明済み有り : 1
get card : 35,45 , 数字 : 01
ターン : 13 , 取得済み : 14 , 1枚目 , 数字:02
ターン : 13 , 取得済み : 14 , 2枚目 , 数字:10
ターン終了
判明済み有り : 10
get card : 20,24 , 数字 : 10
ターン : 14 , 取得済み : 15 , 1枚目 , 数字:06
判明済み有り : 6
ターン : 14 , 取得済み : 15 , 2枚目 , 数字:06
get card : 10,49 , 数字 : 06
ターン : 14 , 取得済み : 16 , 1枚目 , 数字:12
ターン : 14 , 取得済み : 16 , 2枚目 , 数字:11
ターン終了
ターン : 15 , 取得済み : 16 , 1枚目 , 数字:10
ターン : 15 , 取得済み : 16 , 2枚目 , 数字:03
ターン終了
判明済み有り : 3
get card : 12,32 , 数字 : 03
ターン : 16 , 取得済み : 17 , 1枚目 , 数字:04
判明済み有り : 4
ターン : 16 , 取得済み : 17 , 2枚目 , 数字:04
get card : 39,14 , 数字 : 04
ターン : 16 , 取得済み : 18 , 1枚目 , 数字:12
判明済み有り : 12
ターン : 16 , 取得済み : 18 , 2枚目 , 数字:12
get card : 40,50 , 数字 : 12
ターン : 16 , 取得済み : 19 , 1枚目 , 数字:11
判明済み有り : 11
ターン : 16 , 取得済み : 19 , 2枚目 , 数字:11
get card : 41,47 , 数字 : 11
ターン : 16 , 取得済み : 20 , 1枚目 , 数字:07
判明済み有り : 7
ターン : 16 , 取得済み : 20 , 2枚目 , 数字:07
get card : 43,05 , 数字 : 07
ターン : 16 , 取得済み : 21 , 1枚目 , 数字:06
ターン : 16 , 取得済み : 21 , 2枚目 , 数字:10
ターン終了
判明済み有り : 10
get card : 42,44 , 数字 : 10
ターン : 17 , 取得済み : 22 , 1枚目 , 数字:09
判明済み有り : 9
ターン : 17 , 取得済み : 22 , 2枚目 , 数字:09
get card : 27,16 , 数字 : 09
ターン : 17 , 取得済み : 23 , 1枚目 , 数字:13
判明済み有り : 13
ターン : 17 , 取得済み : 23 , 2枚目 , 数字:13
get card : 02,07 , 数字 : 13
ターン : 17 , 取得済み : 24 , 1枚目 , 数字:02
判明済み有り : 2
ターン : 17 , 取得済み : 24 , 2枚目 , 数字:02
get card : 00,33 , 数字 : 02
ターン : 17 , 取得済み : 25 , 1枚目 , 数字:06
判明済み有り : 6
ターン : 17 , 取得済み : 25 , 2枚目 , 数字:06
get card : 36,04 , 数字 : 06
上がり , turn : 17
こんな感じで26ペアを取れた時点で
ゲームは終了です
多分合ってるとは
思うんですけどねー
大したデバッグはしていないので
間違いがあったらごめんなさいね
1000回でシミュレーション
こんな感じで26ペアを取れた時点で
ゲームは終了です
多分合ってるとは
思うんですけどねー
大したデバッグはしていないので
間違いがあったらごめんなさいね
1000回でシミュレーション
最後にこれを1000回繰り返して
何手で上がれたかのシミュレーションです
ログを抜いたgame2関数を用意して
1000回実行した際の
結果をまとめてみました
calc = {}
for i in range(1000):
key = game2()
if key in calc:
calc[key]+=1
else:
calc[key] =1
for k,v in sorted(calc.items()):
print('ターン数 : {0:02} , {1:03}回'.format(k,v))ターン数 : 11 , 001回
ターン数 : 13 , 004回
ターン数 : 14 , 041回
ターン数 : 15 , 149回
ターン数 : 16 , 266回
ターン数 : 17 , 295回
ターン数 : 18 , 168回
ターン数 : 19 , 059回
ターン数 : 20 , 016回
ターン数 : 21 , 001回
これでみると
大体17回もあれば
上がれるみたいですねー
ほぼほぼ20回以内に
上がれているので
記憶力があれば
20ターンもかからないようです
今回は神経衰弱を
シミュレーションしてみました
それでは

コメントする