http://qiita.com/arc279/items/7894d582a882906b94c7 Fortsetzung davon.
Es war viel nerviger als ich erwartet hatte.
Nach einigem Ausprobieren wurde es eine miserable Sache. Das ist interessant, also werde ich es veröffentlichen, während ich den Testprozess verlasse.
Ich schreibe ziemlich grob, also würde ich mich freuen, wenn Sie mir sagen könnten, ob es seltsam ist.
Hier ist die Referenz. Da es sich nur um ein klares Farburteil handelt, habe ich von hier aus angefangen und es mit meiner Superinterpretation einiges umgeschrieben. http://d.hatena.ne.jp/staebchen/20100403/1270256158
Ich habe den Verschluss und den Generator aufgebraucht Wenn Sie versuchen, es mit etwas anderem als Python umzuschreiben, kann es schwierig sein, aber das ist in Ordnung.
Es ist das gleiche wie vor den Grundlagen, aber ich habe es so wie es ist überarbeitet, also werde ich alles noch einmal sagen.
Ich persönlich mag es nicht, Code wie # gist nach draußen zu stellen.
mj2.py
#!/usr/bin/env python
# -*- coding: utf8 -*-
import itertools
import random
class Yama(list):
u'''Wand'''
WANPAI_NUM = 14
class TsumoDoesNotRemain(Exception):
u'''Nur der König ist noch übrig'''
pass
def __init__(self):
pais = [ Pai.from_index(i)
for i in range(Pai.TOTAL_KIND_NUM * Pai.NUM_OF_EACH_KIND) ]
#Waschen
random.shuffle(pais)
super(Yama, self).__init__(pais)
def tsumo(self):
u'''Eigenständigkeit'''
if len(self) <= self.WANPAI_NUM:
raise self.TsumoDoesNotRemain
return self.pop(0)
def wanpai(self):
u'''König'''
return self[-self.WANPAI_NUM:]
def haipai(self):
u'''Verteilung'''
tehais = [ Tehai(), Tehai(), Tehai(), Tehai() ] #Osten(Elternteil)Südwesten Nord
# 4*3 Runden
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 +Alle Arten von Zeichen
NUM_OF_EACH_KIND = 4 #4 Blatt pro Typ
NUM_OF_EACH_NUMBER_PAIS = 9 # M/P/Die Anzahl von S ist 1..Bis zu 9
class Suit:
M = 0 #Mann
P = 1 #Tube
S = 2 #Messen
J = 3 #Charakter
NAMES = {
M: u"Mann",
P: u"Tube",
S: u"Messen",
J: u" ",
}
class Num:
NAMES = {
1: u"einer",
2: u"zwei",
3: u"drei",
4: u"vier",
5: u"Fünf",
6: u"Sechs",
7: u"Sieben",
8: u"Acht",
9: u"Neun",
}
class Tsuhai:
E = 1
S = 2
W = 3
N = 4
HAK = 5
HAT = 6
CHU = 7
NAMES = {
E: u"Osten",
S: u"Süden",
W: u"Westen",
N: u"Norden",
HAK: u"Weiß",
HAT: u"Abwehrmittel",
CHU: u"Während ~",
}
@classmethod
def all(cls):
u'''Alle Fliesen'''
return [cls(suit, num)
for suit in cls.Suit.NAMES
for num in range(1, cls.NUM_OF_EACH_NUMBER_PAIS+1)
if suit != cls.Suit.J
] + [ cls(cls.Suit.J, num) for num in cls.Tsuhai.NAMES.keys() ]
@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.Tsuhai.E),
cls(cls.Suit.J, cls.Tsuhai.S),
cls(cls.Suit.J, cls.Tsuhai.W),
cls(cls.Suit.J, cls.Tsuhai.N),
cls(cls.Suit.J, cls.Tsuhai.HAK),
cls(cls.Suit.J, cls.Tsuhai.HAT),
cls(cls.Suit.J, cls.Tsuhai.CHU),
]
@classmethod
def chuchanpai(cls):
u'''Nakahari'''
yaochupai = cls.yaochupai()
return [ x for x in cls.all() if x not in yaochupai ]
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 - 1
def is_next(self, other, index=1):
u'''Ob es die nächste Nummer ist'''
if self.suit != self.Suit.J: #Kein Brief
if self.suit == other.suit: #Die gleiche Art von Fliesen
if other.num == (self.num + index): #Ordnungsnummer
return True
return False
def is_prev(self, other, index=1):
u'''Ob es die vorherige Nummer ist'''
return self.is_next(other, -index)
@classmethod
def is_syuntsu(cls, first, second, third):
u'''Ob es Junko ist'''
#return second.is_prev(first) and second.is_next(third)
return first.is_next(second) and first.is_next(third, 2)
def __repr__(self):
#return str((self.suit, self.num)) #Taple-Anzeige
if self.suit == self.Suit.J:
return self.Tsuhai.NAMES[self.num].encode('utf-8')
else:
return (self.Num.NAMES[self.num] + self.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):
u'''Vom Index abrufen'''
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)
@classmethod
def from_name(cls, name):
u'''Holen Sie sich vom Namen'''
for x in cls.all():
if name == repr(x):
return x
return None
class Tehai(list):
u'''Handwerk'''
@staticmethod
def sorter(a, b):
u'''Wie macht man'''
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
@classmethod
def aggregate(cls, tehai):
u'''{牌 Samen:Anzahl der Blätter}Aggregat in Form von'''
hash = { x[0]: len(list(x[1])) for x in itertools.groupby(tehai.rihai()) }
#Geben Sie den Schlüssel (sortierte Kacheln) zusammen zurück
return hash, sorted(hash.keys(), cmp=cls.sorter)
def show(self):
u'''Anzeige in leicht lesbarer Form'''
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.Tsuhai.NAMES[pai.num] + u"|"
line2 += u" |"
print line1.encode("utf-8")
print line2.encode("utf-8")
@classmethod
def search_syuntsu(cls, pais, keys):
u'''Finde Junko
Das Argument ist aggregiert()Übergeben Sie in der gleichen Form wie der Rückgabewert von.'''
for i in range( len(keys)-2 ): #Die letzten 2 Blätter müssen nicht überprüft werden
tmp = pais.copy()
first = keys[i]
if tmp[first] >= 1:
try:
second = keys[i+1]
third = keys[i+2]
except IndexError as e:
#Es gibt keine verbleibenden 2 Typen
continue
if not Pai.is_syuntsu(first, second, third):
continue
if tmp[second] >= 1 and tmp[third] >= 1:
tmp[first] -= 1
tmp[second] -= 1
tmp[third] -= 1
#Junko gefunden,Verbleibende Fliesen
yield (first, second, third), tmp
@classmethod
def search_kohtu(cls, pais, keys):
u'''Finde die Gravur
Das Argument ist aggregiert()Übergeben Sie in der gleichen Form wie der Rückgabewert von.'''
for i, p in enumerate(keys):
tmp = pais.copy()
if tmp[p] >= 3:
tmp[p] -= 3
#Gravur gefunden,Verbleibende Fliesen
yield (p, p, p), tmp
Es war eine schreckliche Sache, in gutem Zustand zu schreiben. Aber nein. Es ist ärgerlich, es nicht mehr zu reparieren.
Es könnte ein wenig verdächtig sein, wie auf 9 Gesichter zu warten. Ich kann es nicht richtig überprüfen, weil es zu viele Arten des Wartens gibt ...
Es ist nur eine Warteform und es ist kein Rollenurteil enthalten.
Außerdem bin ich erschöpft und kann es kaum erwarten, Shichitoko und Kokushi Musou zu sehen. Nun, ich denke, es kann mit ein wenig Sorgfalt getan werden, um den Agari-Typ zu unterscheiden.
mj2.py
def check_tenpai(tehai):
u'''Überprüfen Sie die Form des Gehörs'''
# TODO:Ich habe auf Shichitoko und Kokushi Musou gewartet und nicht nachgesehen
assert(len(tehai) == 13)
# (Atama,Gesicht,Warten)Form von
candidate = set()
def check_machi(mentsu, tartsu):
u'''Untersuchen Sie die Form des Wartens'''
assert(len(mentsu) == 3)
keys = sorted(tartsu.keys(), cmp=Tehai.sorter)
#print mentsu, tartsu, keys
def check_tanki():
u'''Einzelpferd warten Scheck'''
for i, p in enumerate(keys):
tmp = tartsu.copy()
if tmp[p] == 3:
#Das verbleibende Gesicht ist eingraviert
assert(len(tmp) == 2)
tmp[p] -= 3
tanki = { pai: num for pai, num in tmp.items() if num > 0 }.keys()
#Tauche ins Gesicht
ins = tuple( sorted(mentsu + [(p, p, p)]) )
candidate.add( ((), ins, tuple(tanki)) )
else:
#Das verbleibende Gesicht ist Junko
first = p
try:
second = keys[i+1]
third = keys[i+2]
except IndexError as e:
continue
if not Pai.is_syuntsu(first, second, third):
continue
tmp[first] -= 1
tmp[second] -= 1
tmp[third] -= 1
tanki = { pai: num for pai, num in tmp.items() if num > 0 }.keys()
#Tauche ins Gesicht
ins = tuple( sorted(mentsu + [(first, second, third)]) )
candidate.add( ((), ins, tuple(tanki)) )
def check_non_tanki():
u'''Wartecheck außer einem einzelnen Pferd'''
for i, p in enumerate(keys):
tmp = tartsu.copy()
#Sparrow Head Check
if not tmp[p] >= 2:
continue
tmp[p] -= 2
atama = (p, p)
for j, q in enumerate(keys):
#Doppelseitig
try:
next = keys[j+1]
if q.is_next(next):
ins = tuple( sorted(mentsu) )
candidate.add( (atama, ins, (q, next) ) )
break
except IndexError as e:
pass
#Passend zu
try:
next = keys[j+1]
if q.is_next(next, 2):
ins = tuple( sorted(mentsu) )
candidate.add( (atama, ins, (q, next) ) )
break
except IndexError as e:
pass
#Also geh
if tmp[q] >= 2:
ins = tuple( sorted(mentsu) )
candidate.add( (atama, ins, (q, q) ) )
break
check_tanki()
check_non_tanki()
#Suche nach 3 Gesichtern
pais, keys = Tehai.aggregate(tehai)
#print pais, keys
if True:
#Ich frage mich, ob es rekursiv gemacht wird
def search_mentsu(depth, proc):
searchers = [Tehai.search_syuntsu, Tehai.search_kohtu]
#Junko/Suche nach Gravur
def inner(pais, mentsu = [], nest = 0):
if nest < depth:
for search in searchers:
for m, a in search(pais, keys):
inner(a, mentsu + [m], nest+1)
else:
proc(mentsu, pais)
inner(pais)
search_mentsu(3, lambda mentsu, pais:
check_machi(mentsu, { x[0]:x[1] for x in pais.items() if x[1] > 0 })
)
else:
#Wenn Sie so solide schreiben
searchers = [Tehai.search_syuntsu, Tehai.search_kohtu]
for p1 in searchers:
for p2 in searchers:
for p3 in searchers:
#Anwenden
for m1, a1 in p1(pais, keys):
for m2, a2 in p2(a1, keys):
for m3, a3 in p3(a2, keys):
mentsu = [m1, m2, m3]
#Verbleibende Fliesen
tartsu = { x[0]:x[1] for x in a3.items() if x[1] > 0 }
check_machi(mentsu, tartsu)
return candidate
Das zum Debuggen.
mj2.py
class Debug:
u'''for debug'''
TEST_HOHRA = [
[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], #Wann
[0, 8, 9, 17, 18, 26, 27, 28, 29, 30, 31, 32, 33, 9], #Quietschend
[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
]
TEST_TENPAI = [
[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8], #Echtes Churenpoto
[1, 2, 3, 4, 5, 5, 5, 6, 20, 20, 21, 22, 23], #Kan-chan Shabo(Junko ist verschlungen)
[13, 14, 15, 18, 19, 19, 20, 21, 24, 24, 24, 31, 31], #Ryanmen Kan-chan
[25, 25, 25, 1, 2, 3, 11, 12, 13, 11, 23, 23, 23], #Ryanmen Tanki
[25, 25, 25, 1, 2, 3, 11, 12, 13, 11, 12, 23, 24], #Ryanmen
[1, 2, 3, 4, 4, 6, 7, 8, 9, 10, 11, 29, 29], #Shabo
]
@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_hohra(cls, idx = None):
u'''Abschlussprüfung'''
return cls.tehai_from_indexes(cls.TEST_HOHRA[idx])
@classmethod
def test_tenpai(cls, idx = 0):
u'''Formtest hören'''
return cls.tehai_from_indexes(cls.TEST_TENPAI[idx])
@classmethod
def gen_tehai(cls, num = 14):
u'''Treffen Sie eine entsprechende Vereinbarung'''
assert(num == 13 or num == 14)
yama = Yama()
return Tehai([ yama.tsumo() for x in range(num) ])
@classmethod
def gen_hohra(cls):
u'''Machen Sie eine geeignete Agari-Form'''
tehai = Tehai()
def gen_syuntsu():
u'''Mach Junko'''
first = Pai.from_index(random.choice(range(Pai.TOTAL_KIND_NUM)))
if first.suit == Pai.Suit.J:
#Charaktere können nicht Junko sein
return None
if first.num > 7:
# (7 8 9)Das Obige kann nicht Junko sein
return None
second = Pai(first.suit, first.num+1)
third = Pai(first.suit, first.num+2)
if tehai.count(first) == 4 or tehai.count(second) == 4 or tehai.count(third) == 4:
#Unzureichende Restnummer
return None
return [first, second, third]
def gen_kohtu():
u'''Gravur machen'''
pai = Pai.from_index(random.choice(range(Pai.TOTAL_KIND_NUM)))
if tehai.count(pai) >= 2:
#Unzureichende Restnummer
return None
return [pai, pai, pai]
def gen_atama():
u'''Machen Sie einen Spatzenkopf'''
pai = Pai.from_index(random.choice(range(Pai.TOTAL_KIND_NUM)))
if tehai.count(pai) >= 3:
#Unzureichende Restnummer
return None
return [pai, pai]
tehai.extend(gen_atama()) #Spatzenkopf
#Wenn Junko und Kokuko die gleiche Erscheinungswahrscheinlichkeit haben, werden wir sie gewichten.
weighted_choices = [(gen_syuntsu, 3), (gen_kohtu, 1)]
population = [val for val, cnt in weighted_choices for i in range(cnt)]
while len(tehai) < 14:
ret = random.choice(population)()
if ret is not None:
tehai.extend(ret)
return tehai
@classmethod
def gen_tenpai(cls):
u'''Stellen Sie eine geeignete Hörform her'''
tehai = cls.gen_hohra()
assert(len(tehai) == 14)
#Ziehen Sie ein Stück aus der Agari-Form heraus
tehai.pop(random.randrange(len(tehai)))
return tehai
class Test:
u'''for test'''
@classmethod
def check_tenho(cls):
u'''Tenwa überprüfen'''
import sys
for cnt in (x for x in itertools.count()):
print >>sys.stderr, cnt
yama = Yama()
oya, _, _, _ = yama.haipai()
ret = check_hohra(oya)
if ret:
print "---------------------------------------------"
print cnt
oya.show()
for atama, mentsu in ret:
print atama, mentsu
break
@classmethod
def check_machi(cls, times = 100):
u'''Überprüfen Sie viel Warten'''
for x in range(times):
tehai = Debug.gen_tenpai()
ret = check_tenpai(tehai.rihai())
if not ret:
#Wenn ich hierher komme, bin ich nicht temperiert. Der Punkt ist eine Fehlfunktion. Das zu modifizierende Handwerk.
print oya
print [ Pai.from_name(repr(x)).index for x in oya ]
print "complete."
if __name__ == '__main__':
Test.check_machi()
Selbst wenn Sie viele Hörformen überprüfen, werden Sie sie vorerst wahrscheinlich nicht verpassen ... Die Frage ist, ob ich alle Wartezeiten richtig auflisten kann ...
Ich denke, es gibt Raum für Verbesserungen, weil ich viele verschwenderische Dinge tue.
Bitte lassen Sie mich wissen, wenn es irgendwelche Fehler gibt.
Wenn Sie das Warten von echtem Kuren Baotou überprüfen, sieht es so aus.
Die erste Zeile ist ein Handwerk.
[Ichiman, Ichiman, Ichiman,Niman,Sanman,Shiman,Geh,Rokuman,Nanaman,Hachiman,Kuman,Kuman,Kuman]
() ((Ichiman, Ichiman, Ichiman), (Sanman,Shiman,Geh), (Rokuman,Nanaman,Hachiman), (Kuman, Kuman, Kuman)) (Niman,)
() ((Ichiman, Ichiman, Ichiman), (Niman,Sanman,Shiman), (Geh,Rokuman,Nanaman), (Kuman, Kuman, Kuman)) (Hachiman,)
(Kuman, Kuman) ((Ichiman,Niman,Sanman), (Shiman,Geh,Rokuman), (Nanaman,Hachiman, Kuman)) (Ichiman, Ichiman)
(Ichiman, Ichiman) ((Ichiman,Niman,Sanman), (Rokuman,Nanaman,Hachiman), (Kuman, Kuman, Kuman)) (Shiman,Geh)
(Kuman, Kuman) ((Ichiman, Ichiman, Ichiman), (Niman,Sanman,Shiman), (Geh,Rokuman,Nanaman)) (Hachiman, Kuman)
(Kuman, Kuman) ((Ichiman, Ichiman, Ichiman), (Shiman,Geh,Rokuman), (Nanaman,Hachiman, Kuman)) (Niman,Sanman)
(Kuman, Kuman) ((Ichiman, Ichiman, Ichiman), (Niman,Sanman,Shiman), (Nanaman,Hachiman, Kuman)) (Geh,Rokuman)
(Ichiman, Ichiman) ((Sanman,Shiman,Geh), (Rokuman,Nanaman,Hachiman), (Kuman, Kuman, Kuman)) (Ichiman,Niman)
(Ichiman, Ichiman) ((Ichiman,Niman,Sanman), (Shiman,Geh,Rokuman), (Nanaman,Hachiman,Kuman)) (Kuman,Kuman)
() ((Ichiman, Ichiman, Ichiman), (Niman,Sanman,Shiman), (Rokuman,Nanaman,Hachiman), (Kuman, Kuman, Kuman)) (Geh,)
(Ichiman, Ichiman) ((Ichiman,Niman,Sanman), (Shiman,Geh,Rokuman), (Kuman, Kuman, Kuman)) (Nanaman,Hachiman)
Passt das wirklich zu dir?