麻将胡牌算法带癞子 python实现
姐姐:你去幫我和閨蜜打麻將?
學霸哥哥:可是我不會打麻將呀!
姐姐:你不是學霸嗎?我教你一個麻將公式,我閨蜜可是單身喲!
學霸哥哥:什么公式?
姐姐:麻將胡牌公式: AAA*M+ABC*N+BB,WMN可以為任意數,胡牌里面有且只有一對!
學霸哥哥:原來麻將還可以這樣玩。好的 地址微信發給我,馬上到!
通過這個對話,我想大家應該都能明白麻將的胡牌公式是怎么樣了,如果只是簡單的麻將胡牌,我想算法實現起來就比較的簡單。
第一步:
我們挑出所有的對子(如果牌中一個對子就沒有,那么就不能胡牌)
第二步:
一次從牌里面去掉對子
第三步:
每次for循環跳3個數,看這3個數是否為ABC,AAA.如果都滿足這樣的條件,則這一副牌就可以胡牌。如果不滿足這個條件,則沒有胡牌。
這個我們用python實現算法就比較的簡單,也比較的好理解。下面我們給出python的胡牌實現算法!這個里面多增加了一個7對的胡牌,大家可以看一下,看是否理解這個算法,也可以自己復制一下代碼,跑一下看一下效果。
def hupaiAlgorithm(self,handStr):a =handStr[:]if len(a) % 3 != 2:return Falsedouble = []for x in set(a):if a.count(x) >= 2:double.append(x)if len(double) == 0:return False#7對胡牌qidui = Trueif len(a) == 14:for x in set(a):if a.count(x) not in [2, 4]:qidui = Falsebreakelse:qidui = Falseif qidui:return True a1 = a.copy()a2 = [] for x in double:a1.remove(x)a1.remove(x)a2.append((x, x))for i in range(int(len(a1) / 3)):if a1.count(a1[0]) == 3:a2.append((a1[0],) * 3)a1 = a1[3:]elif a1[0] in a1 and a1[0] + 1 in a1 and a1[0] + 2 in a1: a2.append((a1[0], a1[0] + 1, a1[0] + 2))a1.remove(a1[0] + 2)a1.remove(a1[0] + 1)a1.remove(a1[0])else:a1 = a.copy()a2 = []breakelse:return Trueelse:return False如果上面的胡牌算法理解了,那么恭喜你,你接下來就可以看一下帶萬能牌的四川麻將胡牌算法了!
最終的測試效果
首先我們來理解一下帶萬能牌的四川麻將如何才能胡牌,帶完成牌的意思就是,萬能牌可以代替任何一張麻將牌,只要最后的麻將能,滿足那個公式就能胡牌。這個是重點,必須要理解這個重點,才能完成萬能牌的胡牌算法!
我們結合上面正常麻將的胡牌思路,大家再想一想,如果正常牌不能胡牌,帶萬能牌能胡牌,是不是我們萬能牌就只能代替下面3種情況才能胡牌:
我們看這手牌:112245777萬能萬能
1.當有2張牌不能成為ABC時,替換中間一張牌使牌成為ABC,比如45,萬能牌變成345或者是456.
2.當牌中的對子>1,且不能滿足7對胡牌的時候。萬能牌代替牌中的任何一個對子,比如在我們舉例的牌里面?萬能牌就只能代替1或者是2.?
通過我們2萬能牌的替換:
這手牌就變成了下面這種情況
112245777萬能萬能=》11122345777.
我們通過這樣的變化,是不是就可以胡牌了。
3.當牌中沒有一個對子的時候,萬能牌就只能替換成其中的某一張牌,成為一個對子看是否滿足胡牌的公式。
比如:1234567萬能
這點萬能牌就可以替換成1,4,7其中的任何一張牌,使牌變成:1123456,12344567,12345677.
萬能牌能替換的這3種方式,這點大家有沒有理解,如果理解了,接下來我們就可以來討論,具體的算法怎么實現了。如果沒有理解的同學,可以反復觀看幾次,必須要先理解這3點的替換思路才能夠更好的理解算法。(這點我們不討論7對的特殊胡牌算法)。
還有一點就是萬能牌使用的次數只能小于等于萬能牌的數量,這點也很重要。
通過上面的講解我們就能很好的實現算法了,我們只需要在正常的胡牌算法里面改動一下就能實現萬能牌的胡牌算法了。大體思路還是按照正常的胡牌算法來,只是在需要使用萬能牌的時候,我們替換一下萬能牌,然后把萬能牌的數量-1,最后看使用萬能牌的數量使用超過了已有的萬能牌數量。里面增加一個7對的萬能牌胡牌算法!
def hupaiAlgorithm(self,handStr,laziCnt):a =handStr[:]a2=handStr[:]if (len(a)+laziCnt) % 3 != 2:return False,a2double = []if laziCnt >0:for x in set(a): if x not in double:double.append(x)for x in set(a):if a.count(x) >= 2 and x not in double:double.append(x)if len(double) == 0:# print('和牌失敗:無對子')return False,a2if laziCnt == 0:qidui = Trueif len(a) == 14:for x in set(a):if a.count(x) not in [2, 4]:qidui = Falsebreakelse:qidui = Falseif qidui:return True,a2 else:for card in a:cardArr=[[],[],[],[]]for card in a:iCnt = a.count(card)# print("iCnt:",iCnt,"handCards:",a)if card not in cardArr[iCnt-1]:cardArr[iCnt-1].append(card)if len(cardArr[0])+len(cardArr[2]) == laziCnt:huCard=[]for i in range(4):if i==0:huCard = huCard + cardArr[i]*2else:huCard = huCard + cardArr[i]*(i+1)huCard.sort() return True,huCarda1 = a.copy()a2 = [] # a2用來存放和牌后分組的結果。for x in double:if x in a1:a1.remove(x)if x in a1:a1.remove(x) a2.append((x, x))nUseLaziCnt =0index = 0isNohuCard = Falsewhile(len(a1)>0 and isNohuCard == False):a1Card = a1[0]if a1.count(a1Card)==3:a2.append((a1Card,) * 3)a1 = a1[3:] elif a1Card in a1 and a1Card + 1 in a1 and a1Card + 2 in a1 and( int(a1Card/10) == int((a1Card+1)/10) and int((a1Card+1)/10) == int((a1Card+2)/10) ): # 這里注意,11,2222,33,和牌結果22,123,123,則連續的3個可能不是相鄰的。a2.append((a1Card, a1Card + 1, a1Card + 2))a1.remove(a1Card + 2)a1.remove(a1Card + 1)a1.remove(a1Card)elif((a1Card in a1 and a1Card+1 in a1 and (int(a1Card//10) == int((a1Card+1)//10))) or (a1Card in a1 and a1Card+2 in a1 and (int(a1Card//10) == int((a1Card+2)//10)) )) and (nUseLaziCnt<laziCnt):a2.append((a1Card, a1Card + 1, a1Card + 2)) if a1Card in a1: a1.remove(a1Card)if a1Card+1 in a1: a1.remove(a1Card + 1)if a1Card+2 in a1: a1.remove(a1Card + 2)nUseLaziCnt = nUseLaziCnt +1elif a1.count(a1Card)==2 and (nUseLaziCnt<laziCnt):a2.append((a1Card, a1Card, a1Card)) if a1Card in a1: a1.remove(a1Card)if a1Card in a1: a1.remove(a1Card)nUseLaziCnt = nUseLaziCnt +1 else:if len(a1)==1 and (laziCnt -nUseLaziCnt) ==2 :a2.append([a1Card]*3)if a1Card in a1: a1.remove(a1Card)else: a1 = a.copy()a2 = [] isNohuCard = Trueif isNohuCard == False:return True,a2 else:return False,handStr算法里面有一個7對的胡牌算法:
這里來講解一下如何實現的。7對胡牌,最后胡牌里面就是?全是對子?或者有4條。有且只有這2種牌型。我們就很好實現了,我們定義一個多維數組,一次記錄牌出現1,2,3,4張的情況。我們只需要把出現一張牌的數量和3張牌的數量相加。2則是否剛好等于萬能麻將的數量就可以了。
for card in a:cardArr=[[],[],[],[]]for card in a:iCnt = a.count(card)# print("iCnt:",iCnt,"handCards:",a)if card not in cardArr[iCnt-1]:cardArr[iCnt-1].append(card)if len(cardArr[0])+len(cardArr[2]) == laziCnt:huCard=[]for i in range(4):if i==0:huCard = huCard + cardArr[i]*2else:huCard = huCard + cardArr[i]*(i+1)huCard.sort() return True,huCard你品,你細細品一下,看是不是這個道理。下面給大家看一個截圖,帶萬能麻將的胡牌效率。
一個萬能牌的情況,理論上4個萬能和1個萬能使用的時間差不多,都是毫秒級別的。如果這個四川萬能麻將的胡牌算法,能滿足一切的需求。
有了這個核心的胡萬能牌算法,接下來得?聽牌算法,是否胡萬能的算法就很容易實現了!?
總結
以上是生活随笔為你收集整理的麻将胡牌算法带癞子 python实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 直流电机的电流、转速、电压的关系
- 下一篇: verilog乘法器以及booth编码改