※この記事は2020年に作成しました
#概要
手牌を入力し、その手牌のシャン点数を求めるプログラムを作成した。
七対子、国士無双のシャンテン数は下記サイトの計算方法を参考にした。
一般手のシャンテン数の計算方法は下記のシャンテン数理論の【メンツ手のシャンテン数の簡単な求め方】を参考にした。
実際にこれで全ての手牌のシャンテン数を正確に数えられるとは限らないと思う。また、面子の取り方、ターツの取り方で色々工夫しなければならない。
今回は面子の取り方を16パターンに分けて取り出して、その後にターツを取り出してからシャンテン数を計算している。
16パターンの面子の取り方は以下になっている。
sが順子を手牌の最初からみて1回だけ取り出していて、kが刻子を手牌の最初から見て1回だけ取り出していることを表す。
また、Sは手牌を最初からみて順子を全て取り出していて、Kは手牌を最初からみて刻子をを全て取り出していることを表す。
パターン |
---|
S→K |
K→S |
s→k→s→k |
k→s→k→s |
s→k→k→s |
k→s→s→k |
s→s→s→k |
s→s→k→s |
s→k→s→s |
k→s→s→s |
k→k→k→s |
k→k→s→k |
k→s→k→k |
s→k→k→k |
s→s→k→k |
k→k→s→s |
#作成したプログラム
# coding: UTF-8
#手牌のシャンテン数を調べる(鳴きは無視)
import numpy as np
import copy
def OneCntKotsu(tmp):#刻子があれば1を返しその刻子を抜く,そうでなければ0を返す
for i in range(34):
if tmp[0,i] >=3:
tmp[0,i] -=3
return 1
return 0
def OneCntShunt(tmp):#順子があれば1を返しその刻子を抜く,そうでなければ0を返す
for i in range(25):
if i==7 or i==8 or i==16 or i==17:continue
if tmp[0,i]>0 and tmp[0,i+1]>0 and tmp[0,i+2]>0:
tmp[0,i]-=1
tmp[0,i+1]-=1
tmp[0,i+2]-=1
return 1
return 0
def CntShunt(tmp):#順子をカウント
CntS = 0
for i in range(25):
if i==7 or i==8 or i==16 or i==17:continue
while(tmp[0,i]>0 and tmp[0,i+1]>0 and tmp[0,i+2]>0):
tmp[0,i]-=1
tmp[0,i+1]-=1
tmp[0,i+2]-=1
CntS += 1
return CntS
def CntKotsu(tmp):#刻子をカウント
CntK = 0
for i in range(34):
if tmp[0,i] >=3:
tmp[0,i] -=3
CntK += 1
return CntK
def Tartsu(tmp):#ターツの数を返す
CntT = 0
for i in range(8):
if tmp[0,i]==1 and tmp[0,i+1]==1:
CntT +=1
tmp[0,i] -= 1#マンズのリャンメンorペンチャン待ち
if tmp[0,i+9]==1 and tmp[0,i+10]==1:
CntT += 1
tmp[0,i]-=1#ピンズのリャンメンorペンチャン待ち
if tmp[0,i+18]==1 and tmp[0,i+19]==1:
CntT += 1
tmp[0,i]-=1#ピンズのリャンメンorペンチャン待ち
for i in range(7):
if tmp[0,i]==1 and tmp[0,i+2]==1:
CntT += 1
tmp[0,i]-=1#マンズのカンチャン待ち
if tmp[0,i+9]==1 and tmp[0,i+11]==1:
CntT += 1
tmp[0,i]-=1#ピンズのカンチャン待ち
if tmp[0,i+18]==1 and tmp[0,i+20]==1:
CntT += 1
tmp[0,i]-=1#ソーズのカンチャン待ち
return CntT
def kari_shanten(CntS,CntK,CntT,tmp):#順子数と刻子数とターツ数から仮シャンテン数を返す
kari_shanten = 0
cntAtama = 0
for i in range(34):#雀頭を調べている
if tmp[0,i] == 2:
cntAtama += 1
tmp[0,i] -= 2
CntT += 1
Ments = CntS + CntK
MentsTarts = Ments + CntT
if MentsTarts >= 5:
MentsTarts = 5
if cntAtama == 0:MentsTarts = 4
kari_shanten = 8 - (MentsTarts + Ments)
return kari_shanten
def Shanten(tehai):#シャンテン数を返す
tmp = np.ndarray((4,34))
tmp = copy.deepcopy(tehai)
Shanten_value = 8
kari = 0
CntK=CntS=CntT = 0
CntS = CntShunt(tmp)#順子→刻子の順で面子を調べる
CntK = CntKotsu(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#刻子→順子の順で面子を調べる
CntK=CntS=CntT = 0
CntK = CntKotsu(tmp)
CntS = CntShunt(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#ksksの場合
CntK=CntS=CntT = 0
for i in range(2):
CntK += OneCntKotsu(tmp)
CntS += OneCntShunt(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#skskの場合
CntK=CntS=CntT = 0
for i in range(2):
CntS += OneCntShunt(tmp)
CntK += OneCntKotsu(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#skksの場合
CntK=CntS=CntT = 0
CntS += OneCntShunt(tmp)
CntK += OneCntKotsu(tmp)
CntK += OneCntKotsu(tmp)
CntS += OneCntShunt(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#ksskの場合
CntK=CntS=CntT = 0
CntK += OneCntKotsu(tmp)
CntS += OneCntShunt(tmp)
CntS += OneCntShunt(tmp)
CntK += OneCntKotsu(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#ssskの場合
CntK=CntS=CntT = 0
for i in range(3):CntS += OneCntShunt(tmp)
CntK += OneCntKotsu(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#ssksの場合
CntK=CntS=CntT = 0
CntS += OneCntShunt(tmp)
CntS += OneCntShunt(tmp)
CntK += OneCntKotsu(tmp)
CntS += OneCntShunt(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#skssの場合
CntK=CntS=CntT = 0
CntS += OneCntShunt(tmp)
CntK += OneCntKotsu(tmp)
CntS += OneCntShunt(tmp)
CntS += OneCntShunt(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#ksssの場合
CntK=CntS=CntT = 0
CntK += OneCntKotsu(tmp)
CntS += OneCntShunt(tmp)
CntS += OneCntShunt(tmp)
CntS += OneCntShunt(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#kkksの場合
CntK=CntS=CntT = 0
CntK += OneCntKotsu(tmp)
CntK += OneCntKotsu(tmp)
CntK += OneCntKotsu(tmp)
CntS += OneCntShunt(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#kkskの場合
CntK=CntS=CntT = 0
CntK += OneCntKotsu(tmp)
CntK += OneCntKotsu(tmp)
CntS += OneCntShunt(tmp)
CntK += OneCntKotsu(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#kskkの場合
CntK=CntS=CntT = 0
CntK += OneCntKotsu(tmp)
CntS += OneCntShunt(tmp)
CntK += OneCntKotsu(tmp)
CntK += OneCntKotsu(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#skkkの場合
CntK=CntS=CntT = 0
CntS += OneCntShunt(tmp)
CntK += OneCntKotsu(tmp)
CntK += OneCntKotsu(tmp)
CntK += OneCntKotsu(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#sskkの場合
CntK=CntS=CntT = 0
CntS += OneCntShunt(tmp)
CntS += OneCntShunt(tmp)
CntK += OneCntKotsu(tmp)
CntK += OneCntKotsu(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#kkssの場合
CntK=CntS=CntT = 0
CntK += OneCntKotsu(tmp)
CntK += OneCntKotsu(tmp)
CntS += OneCntShunt(tmp)
CntS += OneCntShunt(tmp)
CntT = Tartsu(tmp)
kari = kari_shanten(CntS,CntK,CntT,tmp)
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#国士無双のシャンテン数
kokushi = 0
for i in range(34):
if i==0 or i==8 or i==9 or i==17 or i==18 or i==26 or 27<=i:
if tmp[0,i] >=1:
tmp[0,i] -= 1
kokushi += 1
for i in range(34):#対子がある場合はkokushiに1を足してbreakする
if i==0 or i==8 or i==9 or i==17 or i==18 or i==26 or 27<=i:
if tmp[0,i] >=1:
tmp[0,i] -= 1
kokushi += 1
break
kari = 13 - kokushi
if Shanten_value > kari: Shanten_value = kari
tmp = copy.deepcopy(tehai)#七対子のシャンテン数計算
toits = 0
hai = 0
for i in range(34):
if tmp[0,i] >= 2:
toits += 1
if tmp[0,i] >= 1:
hai += 1
kari = 6 - toits
if toits >= hai:
kari = 6 - toits + (7-hai)
if Shanten_value > kari: Shanten_value = kari
return Shanten_value
tehai = np.ndarray((4,34))
tehai[0,]=[2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,]
#[0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,]
#[0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 2, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,]
#[0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,]
#[0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,]
#[3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 0, 0, 0,]
#雀頭なし国士無双[1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
print(Shanten(tehai))