Il semble que la probabilité de Tenwa soit une fois sur 330000 fois, donc Je voulais l'essayer, alors je l'ai écrit en python, C'était plus ennuyeux que ce à quoi je m'attendais.
L'algorithme est ici. http://www.onionsoft.net/hsp/mahjong.txt
Le rôle ou l'attente est correct ... Si je vais bien ~~ Je l'écrirai la prochaine fois ~~.
Je l'ai écrit @ [2014/9/25] http://qiita.com/arc279/items/1a7853ad8e2dc35961d1
Opération confirmée avec python2.7.6.
Je l'ai écrit honnêtement. J'ai hérité de list de builtin parce que c'est gênant, mais je pense qu'il vaut mieux la déléguer.
Le lavage est jeté au hasard.
mj.py
#!/usr/bin/env python
# -*- coding: utf8 -*-
import itertools
import random
from collections import OrderedDict
class Yama(list):
u'''mur'''
WANPAI_NUM = 14
class TsumoDoesNotRemain(Exception):
u'''Seul le roi reste'''
pass
def __init__(self):
pais = [ Pai.from_index(i)
for i in range(Pai.TOTAL_KIND_NUM * Pai.NUM_OF_EACH_KIND) ]
#La lessive
random.shuffle(pais)
super(Yama, self).__init__(pais)
def tsumo(self):
u'''L'autonomie'''
if len(self) <= self.WANPAI_NUM:
raise self.TsumoDoesNotRemain
return self.pop(0)
def wanpai(self):
return self[-self.WANPAI_NUM:]
def haipai(self):
u'''Distribution'''
tehais = [ Tehai(), Tehai(), Tehai(), Tehai() ] #est(parent)Sud Ouest Nord
# 4*3 tours
for j in range(0, 3):
for tehai in tehais:
for i in range(0, 4):
pai = self.tsumo()
tehai.append(pai)
#Choncho
for tehai in tehais:
pai = self.tsumo()
tehai.append(pai)
pai = self.tsumo()
tehais[0].append(pai)
return tehais
class Pai(object):
u'''牌'''
TOTAL_KIND_NUM = 34 # M/P/S +Tous types de personnages
NUM_OF_EACH_KIND = 4 #4 feuilles par type
NUM_OF_EACH_NUMBER_PAIS = 9 # M/P/Le nombre de S est 1..Jusqu'à 9
class Suit:
M = 0 #Homme
P = 1 #Tube
S = 2 #Mesure
J = 3 #Personnage
NAMES = {
M: u"Homme",
P: u"Tube",
S: u"Mesure",
J: u" ",
}
class Num:
NAMES = {
1: u"un",
2: u"deux",
3: u"Trois",
4: u"quatre",
5: u"Cinq",
6: u"Six",
7: u"Sept",
8: u"Huit",
9: u"Neuf",
}
class Jihai:
E = 1
S = 2
W = 3
N = 4
HAK = 5
HAT = 6
CHU = 7
NAMES = {
E: u"est",
S: u"Sud",
W: u"Ouest",
N: u"Nord",
HAK: u"blanc",
HAT: u"Repoussant",
CHU: u"Pendant ~",
}
@classmethod
def yaochupai(cls):
u'''么 9 牌'''
return [
cls(cls.Suit.M, 1),
cls(cls.Suit.M, 9),
cls(cls.Suit.P, 1),
cls(cls.Suit.P, 9),
cls(cls.Suit.S, 1),
cls(cls.Suit.S, 9),
cls(cls.Suit.J, cls.Jihai.E),
cls(cls.Suit.J, cls.Jihai.S),
cls(cls.Suit.J, cls.Jihai.W),
cls(cls.Suit.J, cls.Jihai.N),
cls(cls.Suit.J, cls.Jihai.HAK),
cls(cls.Suit.J, cls.Jihai.HAT),
cls(cls.Suit.J, cls.Jihai.CHU),
]
def __init__(self, suit, num):
self.suit = suit
self.num = num
@property
def index(self):
return self.suit * self.NUM_OF_EACH_NUMBER_PAIS + self.num
def __repr__(self):
#return str((self.suit, self.num)) #Affichage Taple
if self.suit == Pai.Suit.J:
return Pai.Jihai.NAMES[self.num].encode('utf-8')
else:
return (Pai.Num.NAMES[self.num] + Pai.Suit.NAMES[self.suit]).encode('utf-8')
def __eq__(self, other):
return self.suit == other.suit and self.num == other.num
@classmethod
def from_index(cls, index):
kind = index % cls.TOTAL_KIND_NUM
if True:
suit = kind / cls.NUM_OF_EACH_NUMBER_PAIS
num = kind % cls.NUM_OF_EACH_NUMBER_PAIS + 1
else:
if 0 <= kind < 9:
suit = cls.Suit.M
num = kind - 0 + 1
elif 9 <= kind < 18:
suit = cls.Suit.P
num = kind - 9 + 1
elif 18 <= kind < 27:
suit = cls.Suit.S
num = kind - 18 + 1
elif 27 <= kind < 34:
suit = cls.Suit.J
num = kind - 27 + 1
assert(cls.Suit.M <= suit <= cls.Suit.J)
assert(1 <= num <= cls.NUM_OF_EACH_NUMBER_PAIS)
return cls(suit, num)
class Tehai(list):
u'''Artisanat'''
@staticmethod
def sorter(a, b):
u'''Comment faire'''
return a.suit - b.suit if a.suit != b.suit else a.num - b.num
def rihai(self):
u'''Rimu'''
self.sort(cmp=self.sorter)
return self
def aggregate(self):
u'''{牌 graine:Nombre de feuilles}Agrégat sous forme de'''
hash = { x[0]: len(list(x[1])) for x in itertools.groupby(self.rihai()) }
ret = OrderedDict()
#Les tuiles clés restent désormais triées
for x in sorted(hash.keys(), cmp=self.sorter):
ret[x] = hash[x]
return ret
def show(self):
u'''Affichage sous une forme facile à lire'''
line1 = u"|"
line2 = u"|"
for pai in self.rihai():
if pai.suit != Pai.Suit.J:
line1 += Pai.Num.NAMES[pai.num] + u"|"
line2 += Pai.Suit.NAMES[pai.suit] + u"|"
else:
line1 += Pai.Jihai.NAMES[pai.num] + u"|"
line2 += u" |"
print line1.encode("utf-8")
print line2.encode("utf-8")
Y a-t-il sept paires d'enfants et Kokushi Musou? Cette zone dépend de l'interprétation, donc c'est bien. Ici, j'ai écrit que les sept paires n'avaient pas de tête de moineau et que le Kokushi Musou avait deux têtes de moineau.
C'était difficile de couper la partie du jugement à la classe, alors j'ai utilisé une clôture.
mj.py
def check_hohra(tehai):
u'''Vérifiez la forme de l'extrémité'''
assert(len(tehai) == 14)
pais = tehai.aggregate()
keys = pais.keys()
length = len(keys)
#print pais, keys, length
def check_chitoitsu(pais):
u'''Vérification de sept paires'''
if all([ num == 2 for pai, num in pais.items()]):
return (), [ (pai, pai) for pai, num in pais.items() ]
return None
def check_kokushimusou(pais):
u'''Chèque Kokushi Musou'''
if length != 13:
return None
yaochupai = Pai.yaochupai()
mentsu = []
for pai, num in pais.items():
if pai not in yaochupai:
return None
# TODO:Est-il acceptable d'en avoir deux ici?
if num == 2:
atama = (pai, pai)
else:
assert(num == 1)
mentsu.append(pai)
return atama, mentsu
def search_syuntu(pais):
u'''Trouver Junko'''
for i in range(length):
if pais[keys[i]] >= 1:
first = keys[i]
try:
second = keys[i+1]
third = keys[i+2]
except IndexError as e:
#Il n'y a plus de 2 types
continue
if first.suit == Pai.Suit.J:
#Les personnages ne peuvent pas être Junko
continue
if not (first.suit == second.suit and first.suit == third.suit):
#Différents types
continue
if not ((second.num == first.num+1) and (third.num == first.num+2)):
#Pas un numéro de série
continue
if pais[second] >= 1 and pais[third] >= 1:
pais[first] -= 1
pais[second] -= 1
pais[third] -= 1
return (first, second, third)
return None
def search_kohtu(pais):
u'''Trouvez la gravure'''
for j in range(length):
if pais[keys[j]] >= 3:
pais[keys[j]] -= 3
return (keys[j], keys[j], keys[j])
return None
#Sept paires
tmp = pais.copy()
ret = check_chitoitsu(tmp)
if ret:
return [ ret ]
#Kokushi Musou
tmp = pais.copy()
ret = check_kokushimusou(tmp)
if ret:
return [ ret ]
#Forme basique
candidate = []
for i in range(length):
#Trouvez la tête
if not (pais[keys[i]] >= 2):
continue
tmp = pais.copy()
atama = (keys[i], keys[i])
tmp[keys[i]] -= 2
mentsu = []
while True:
#print tmp
ret = search_syuntu(tmp) or search_kohtu(tmp)
if ret is None:
ret = search_kohtu(tmp) or search_syuntu(tmp)
if ret is None:
#Je ne peux pas faire Junko ou Kiko
break
mentsu.append(ret)
#print atama, mentsu, tmp
if len(mentsu) == 4:
#4 faces 1 tête de moineau
candidate.append( (atama, mentsu) )
return candidate
Ce serait bien s'il avait la forme d'un agari par l'arrangement des parents, alors ce serait comme ça.
mj.py
def check_tenho():
for cnt in (x for x in itertools.count()):
yama = Yama()
oya, _, _, _ = yama.haipai()
ret = check_hohra(oya)
if ret:
print cnt
oya.show()
for atama, mentsu in ret:
print atama, mentsu
break
if __name__ == '__main__':
#Essayez environ 100 fois
for x in range(100):
check_tenho()
S'il ne sort pas même après avoir essayé 600 000 fois, il ne sort pas, et s'il sort, il sort environ 20 000 fois.
Eh bien, à mesure que le nombre de procès augmente, je pense qu'il va s'établir à 330 000 fois selon la loi des grands nombres. peut être. Cela prend du temps et c'est ennuyeux, donc je n'ai essayé qu'une dizaine de fois. J'étais satisfait quand je l'ai écrit.
Si vous voulez faire la distinction entre les rôles et l'attente, vous devez probablement le réécrire ...
Cela pour le débogage.
mj.py
class Debug:
u'''for debug'''
TEST_TEHAIS = [
[2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7],
[0, 0, 8, 8, 13, 13, 20, 20, 25, 25, 29, 29, 31, 31], #Quand
[0, 8, 9, 17, 18, 26, 27, 28, 29, 30, 31, 32, 33, 9], #Grinçant
[33, 33, 33, 32, 32, 32, 31, 31, 31, 0, 0, 0, 2, 2], #Daisangen
[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 1], #Churenpoto
[19, 19, 20, 20, 21, 21, 23, 23, 23, 25, 25, 32, 32, 32], #Ryu-so
[0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 0, 1, 2], #Chinitsu Ittsu Epaco
]
@classmethod
def tehai_from_indexes(cls, indexes):
assert(len(indexes) == 13 or len(indexes) == 14)
return Tehai([ Pai.from_index(x) for x in indexes ])
@classmethod
def test_tehai(cls, idx = None):
if not idx:
#14 fait maison
yama = Yama()
return Tehai([ yama.tsumo() for x in range(14) ])
else:
return cls.tehai_from_indexes(cls.TEST_TEHAIS[idx])
Vérifiez-le de vos propres mains!
Recommended Posts