# coding=utf-8
import sys
import math
import codecs
isDebug = False
isTiaoShi = True
isFengZui = True
MAJONG = [
101,102,103,104,105,106,107,108,109,
101,102,103,104,105,106,107,108,109,
101,102,103,104,105,106,107,108,109,
101,102,103,104,105,106,107,108,109,
201,202,203,204,205,206,207,208,209,
201,202,203,204,205,206,207,208,209,
201,202,203,204,205,206,207,208,209,
201,202,203,204,205,206,207,208,209,
301,302,303,304,305,306,307,308,309,
301,302,303,304,305,306,307,308,309,
301,302,303,304,305,306,307,308,309,
301,302,303,304,305,306,307,308,309,
401,402,403,404,405,406,407,
401,402,403,404,405,406,407,
401,402,403,404,405,406,407,
401,402,403,404,405,406,407,
]
MAJIANG_TYPE = [
101,102,103,104,105,106,107,108,109,
201,202,203,204,205,206,207,208,209,
301,302,303,304,305,306,307,308,309,
401,402,403,404,405,406,407,
]
#將手裏的耗子全部拿出來,並且對剩餘的手牌排序
#param mahjongList 手牌列表 haoziPai 耗子列表
#return 自己所有的耗子列表
def check_haozi_sort(mahjongList, haoziPaiList):
printLog('當前的手牌爲:',mahjongList)
mahjongList.sort()
printLog('排序完成之後手牌爲:',mahjongList)
haoziList = []
for index in range(len(mahjongList)-1, -1, -1):
for x in range(len(haoziPaiList)):
if haoziPaiList[x] == mahjongList[index]:
haoziList.append(mahjongList[index])
mahjongList.pop(index)
break
printLog('移除耗子之後的手牌爲:')
printLog(mahjongList)
printLog('手裏的耗子列表:', haoziList)
return haoziList
#將手牌分爲萬條筒、 字
def split_list(mahjongList):
wttList = []
ziList = []
for index in range(len(mahjongList)):
mjType = mahjongList[index] // 100
#萬
if mjType == 1 or mjType == 2 or mjType == 3:
wttList.append(mahjongList[index])
elif mjType == 4:
ziList.append(mahjongList[index])
else:
printLog("沒有這種麻將類型", mjType)
sys.exit(0)
return wttList, ziList
#檢查組合 先檢查刻,再檢查順
#return 返回組成的刻,順,以及檢查完之後剩餘的手牌列表
def check_zuhe_ke_shun( mjList, isFeng=False):
mjListCopy = mjList[:]
shunziList = []
keList = []
#自己的數量 先判斷能自然形成的,不加耗子的
if len(mjListCopy) >= 3:
keList = check_ke(mjListCopy)
if len(mjListCopy) >= 3:
#如果是字牌,並且是封嘴的時候,去檢測一下風順子
if isFeng:
if isFengZui:
shunziList = check_shunzi(mjListCopy, isFeng)
else:
shunziList = check_shunzi(mjListCopy, isFeng)
# #組成的刻子現在是這樣的
# if len(keList) > 0:
# printLog('組成刻子:', keList)
# if len(shunziList) > 0:
# printLog('組成順子:', shunziList)
# #檢測完之後的手牌爲
# if len(mjListCopy) > 0:
# printLog('檢測完之後的手牌', mjListCopy)
return keList, shunziList, mjListCopy
#檢查組合 先檢查順,再檢查刻
#return 返回組成的刻,順,以及檢查完之後剩餘的手牌列表
def check_zuhe_shun_ke( mjList, isFeng=False):
mjListCopy = mjList[:]
shunziList = []
keList = []
#自己的數量 先判斷能自然形成的,不加耗子的
if len(mjListCopy) >= 3:
#如果是字牌,並且是封嘴的時候,去檢測一下風順子
if isFeng:
if isFengZui:
shunziList = check_shunzi(mjListCopy, isFeng)
else:
shunziList = check_shunzi(mjListCopy, isFeng)
if len(mjListCopy) >= 3:
keList = check_ke(mjListCopy)
# #組成的刻子現在是這樣的
# if len(keList) > 0:
# printLog('組成刻子:', keList)
# if len(shunziList) > 0:
# printLog('組成順子:', shunziList)
# #檢測完之後的手牌爲
# if len(mjListCopy) > 0:
# printLog('檢測完之後的手牌', mjListCopy)
return keList, shunziList, mjListCopy
#mjList 風 給所有的風進行排序
#return [[403,2],[402,1],[401,1]]
def feng_sort(mjList):
mjlsit_sort = []
if len(mjList) == 0:
return mjlsit_sort
mjList.sort()
mjlsit_sort = []
count = 1
curValue = mjList[0]
for x in range(1, len(mjList)):
if mjList[x] == curValue:
count = count + 1
else:
tmpList = []
tmpList.append(curValue)
tmpList.append(count)
mjlsit_sort.append(tmpList)
curValue = mjList[x]
count = 1
tmpList = []
tmpList.append(curValue)
tmpList.append(count)
mjlsit_sort.append(tmpList)
printLog('排完前的數組爲:',mjlsit_sort)
mjlsit_sort.sort(key=takeSecond)
mjlsit_sort.reverse()
printLog('排完序的數組爲:',mjlsit_sort)
return mjlsit_sort
def takeSecond(elem):
return elem[1]
#將手中的字牌去分成 [東南西北] ,[中發白]
def split_feng_zi(mjList):
fenglist = []
ziList = []
if len(mjList) == 0:
return fenglist,ziList
mjListCopy = mjList[:]
mjListCopy.sort()
for x in range(len(mjListCopy)):
if mjListCopy[x] >= 405:
ziList.append(mjListCopy[x])
else:
fenglist.append(mjListCopy[x])
return fenglist,ziList
#檢查風順子 fengList 當前的[東南西北]或者[中發白]
#mjList 這個參數的主要目的是再檢查出自己牌型有風順子之後, 將組合完成的從自己的手牌裏面移除掉
#return 返回的是組成的風順子列表
def chenck_feng_shun(fengList, mjList):
fengListCopy = fengList[:]
feng_shun_list = []
if len(fengListCopy) >= 3:
curIndex = 0
for index in range(fengListCopy[0][1]):
tmpList = []
while curIndex < len(fengListCopy):
curCount = fengListCopy[curIndex][1]
if curCount > 0:
tmpList.append(fengListCopy[curIndex][0])
fengListCopy[curIndex][1] = curCount - 1
if len(tmpList) == 3:
curIndex = 0
feng_shun_list.append(tmpList)
break
else:
curIndex = curIndex + 1
if curIndex >= len(fengListCopy):
curIndex = 0
break
else:
curIndex = curIndex + 1
continue
printLog('當前的風牌手牌', feng_shun_list)
if len(feng_shun_list) > 0:
for x in range(len(feng_shun_list)):
mjList.pop(mjList.index(feng_shun_list[x][0]))
mjList.pop(mjList.index(feng_shun_list[x][1]))
mjList.pop(mjList.index(feng_shun_list[x][2]))
return feng_shun_list
#檢查手牌裏面的刻, 這個是不用耗子就能直接做刻子的
def check_ke(mjList):
mjListCopy = mjList[:]
mjListCopy2 = mjList[:]
keList = []
for index in range(len(mjListCopy)):
if len(mjList) < 3:
break
tmpValue = mjListCopy[index]
try:
#找到一個就移除一個,如果能找到最後面,說明是對的
value0 = mjListCopy2.index(tmpValue)
mjListCopy2.pop(mjListCopy2.index(tmpValue))
value1 = mjListCopy2.index(tmpValue)
mjListCopy2.pop(mjListCopy2.index(tmpValue))
value2 = mjListCopy2.index(tmpValue)
mjListCopy2.pop(mjListCopy2.index(tmpValue))
tmpList = []
tmpList.append(tmpValue)
tmpList.append(tmpValue)
tmpList.append(tmpValue)
keList.append(tmpList)
except ValueError, e:
continue
#所有的檢測都檢測完了,這個時候 要對真正的手牌進行移除了
if len(keList) > 0:
for index in range(len(keList)):
mjList.pop(mjList.index(keList[index][0]))
mjList.pop(mjList.index(keList[index][0]))
mjList.pop(mjList.index(keList[index][0]))
return keList
else:
return keList
#檢查手牌裏面的順子, 這個是不用耗子就能直接做順子的
def check_shunzi(mjList, isFeng=False):
shunziList = []
mjListCopy = mjList[:]
tmpIndex = 0
if not isFeng:
for index in range(len(mjListCopy)):
#如果數組的長度小於3了就不用做檢測了
if len(mjList) < 3:
break
tmpValue = mjListCopy[index]
try:
#先檢測一下這個順子的有沒有
value0 = mjList.index(tmpValue)
value1 = mjList.index(tmpValue+1)
value2 = mjList.index(tmpValue+2)
#上面檢測成功了,說明有,現在要移除掉
mjList.pop(mjList.index(tmpValue))
mjList.pop(mjList.index(tmpValue+1))
mjList.pop(mjList.index(tmpValue+2))
tmpList = []
tmpList.append(tmpValue)
tmpList.append(tmpValue+1)
tmpList.append(tmpValue+2)
shunziList.append(tmpList)
except ValueError, e:
continue
return shunziList
else:
#檢測風順子
fengList, ziList = split_feng_zi(mjListCopy)
feng_sort_list = feng_sort(fengList)
zi_sort_list = feng_sort(ziList)
feng_shun_list = chenck_feng_shun(feng_sort_list, mjList)
zi_shun_list = chenck_feng_shun(zi_sort_list, mjList)
feng_shun_list = feng_shun_list + zi_shun_list
return feng_shun_list
#檢測手裏面有兩張牌,加耗子之後組成刻子(只有耗子玩法纔去調用這個方法)
#return 返回刻子列表和需要的耗子數量
def check_2n_ke(mjList, haoziId):
mjListCopy = mjList[:]
mjListCopy2 = mjList[:]
keList = []
needHaoziCount = 0
for index in range(len(mjListCopy)):
if len(mjList) < 2:
break
tmpValue = mjListCopy[index]
try:
#找到一個就移除一個,如果能找到最後面,說明是對的
value0 = mjListCopy2.index(tmpValue)
mjListCopy2.pop(mjListCopy2.index(tmpValue))
value1 = mjListCopy2.index(tmpValue)
mjListCopy2.pop(mjListCopy2.index(tmpValue))
tmpList = []
tmpList.append(haoziId)
tmpList.append(tmpValue)
tmpList.append(tmpValue)
keList.append(tmpList)
needHaoziCount = needHaoziCount + 1
except ValueError, e:
continue
if len(keList) > 0:
for index in range(len(keList)):
mjList.pop(mjList.index(keList[index][1]))
mjList.pop(mjList.index(keList[index][1]))
return keList, needHaoziCount
else:
return keList,needHaoziCount
#檢測手裏面有兩張牌,加耗子之後組成順子(只有耗子玩法纔去調用這個方法)
#return 返回順子列表和需要的耗子數量
def check_2n_shun(mjList, haoziId, isFeng=False):
mjListCopy = mjList[:]
shunziList = []
needHaoziCount = 0
if not isFeng:
for index in range(len(mjListCopy)):
if len(mjList) < 2:
break
tmpValue = mjListCopy[index]
#這個檢測的是檢測靠着
try:
#先檢測一下這個順子的有沒有
value0 = mjList.index(tmpValue)
value1 = mjList.index(tmpValue + 1)
#上面檢測成功了,說明有,現在要移除掉
mjList.pop(mjList.index(tmpValue))
mjList.pop(mjList.index(tmpValue+1))
tmpList = []
tmpList.append(haoziId)
tmpList.append(tmpValue)
tmpList.append(tmpValue+1)
needHaoziCount = needHaoziCount + 1
shunziList.append(tmpList)
continue
except ValueError, e:
pass
#這個檢測是間隔一個的
try:
#先檢測一下這個順子的有沒有
value0 = mjList.index(tmpValue)
value1 = mjList.index(tmpValue + 2)
#上面檢測成功了,說明有,現在要移除掉
mjList.pop(mjList.index(tmpValue))
mjList.pop(mjList.index(tmpValue+2))
tmpList = []
tmpList.append(tmpValue)
tmpList.append(haoziId)
tmpList.append(tmpValue+2)
needHaoziCount = needHaoziCount + 1
shunziList.append(tmpList)
except ValueError, e:
continue
return shunziList, needHaoziCount
else:
fengList, ziList = split_feng_zi(mjListCopy)
feng_sort_list = feng_sort(fengList)
zi_sort_list = feng_sort(ziList)
feng_shun_list, needHaoziCount1 = check_2n_feng_shun(feng_sort_list,haoziId, mjList)
zi_shun_list, needHaoziCount2 = check_2n_feng_shun(zi_sort_list, haoziId,mjList)
feng_shun_list = feng_shun_list + zi_shun_list
needHaoziCount = needHaoziCount1 + needHaoziCount2
return feng_shun_list, needHaoziCount
#檢測風順子
def check_2n_feng_shun(fengList, haoziId, mjList):
fengListCopy = fengList[:]
feng_shun_list = []
needHaoziCount = 0
if len(fengListCopy) >= 2:
curIndex = 0
for index in range(fengListCopy[0][1]):
tmpList = []
while curIndex < len(fengListCopy):
curCount = fengListCopy[curIndex][1]
if curCount > 0:
tmpList.append(fengListCopy[curIndex][0])
fengListCopy[curIndex][1] = curCount - 1
if len(tmpList) == 2:
needHaoziCount = needHaoziCount + 1
tmpList.append(haoziId)
curIndex = 0
feng_shun_list.append(tmpList)
break
else:
curIndex = curIndex + 1
if curIndex >= len(fengListCopy):
curIndex = 0
break
else:
curIndex = curIndex + 1
continue
if len(feng_shun_list) > 0:
for x in range(len(feng_shun_list)):
mjList.pop(mjList.index(feng_shun_list[x][0]))
mjList.pop(mjList.index(feng_shun_list[x][1]))
printLog('當前的風牌手牌', feng_shun_list)
return feng_shun_list, needHaoziCount
def printLog(*args):
if isDebug:
for str in args:
if isinstance(str, basestring):
print(str.decode('UTF-8').encode('GBK'))
else:
print(str)
def printNow(*args):
if isTiaoShi:
for str in args:
if isinstance(str, basestring):
print(str.decode('UTF-8').encode('GBK'))
else:
print(str)
def has_object( objList, obj ):
for x in range(len(objList)):
if objList[x] == obj:
return True
return False
#去檢測將
def check_jiang(mjList, jiangType, haoziId, haoziList):
mjListCopy = mjList[:]
jiangList = []
needHaoziCount = 0
canjiang = False
if has_object(mjListCopy, jiangType):
mjListCopy.pop(mjListCopy.index(jiangType))
if has_object(mjListCopy, jiangType):
mjList.pop(mjList.index(jiangType))
mjList.pop(mjList.index(jiangType))
jiangList.append(jiangType)
jiangList.append(jiangType)
mjList = mjListCopy
canjiang = True
return canjiang, jiangList, needHaoziCount
else:
if haoziId != 0 and len(haoziList) >= 1:
mjList.pop(mjList.index(jiangType))
jiangList.append(jiangType)
jiangList.append(haoziId)
haoziList.pop(0)
needHaoziCount = 1
canjiang = True
mjList = mjListCopy
return canjiang, jiangList, needHaoziCount
else:
return canjiang, jiangList, needHaoziCount
def can_hu_ke_shun(mjList, haoziId, haoziList):
#拆分萬條筒風
wttList, ziList = split_list(mjList)
#檢測 先不帶耗子 萬條筒風 刻 順 剩餘手牌 組合
keList,shunziList,handCardList = check_zuhe_ke_shun(wttList)
zikList, zisList,ziHandCardList = check_zuhe_ke_shun(ziList, True)
#只有有耗子的時候纔去檢測添加耗子
if haoziId != 0:
printLog('帶耗子檢測:')
allList = keList + shunziList + zikList + zisList
#如果手裏面的已經組成四副了 說明肯定能胡了
if len(allList) >= 4:
allHands = handCardList + ziHandCardList
return True, allList, allHands
else:
haoziKeList, haoziCount1 = check_2n_ke(handCardList, haoziId)
haoziShunList, haoziCount2 = check_2n_shun(handCardList, haoziId)
zikeList,haoziCount3 = check_2n_ke(ziHandCardList, haoziId)
zi_shun_list = []
haoziCount4 = 0
if isFengZui:
zi_shun_list,haoziCount4 = check_2n_shun(ziHandCardList,haoziId, True)
leftAllHand = ziHandCardList + handCardList
needAllHaoziCount = haoziCount1 + haoziCount2 + haoziCount3 + haoziCount4 + len(leftAllHand) * 2
leftAllHandList = []
for x in range(len(leftAllHand)):
tmpList=[]
tmpList.append(leftAllHand[x])
tmpList.append(haoziId)
tmpList.append(haoziId)
leftAllHandList.append(tmpList)
allList = allList + haoziKeList + haoziShunList + zikeList + zi_shun_list
handCards = handCardList + ziHandCardList
if needAllHaoziCount <= len(haoziList):
return True, allList + leftAllHandList, []
else:
return False,allList, handCards
else:
printLog('不帶耗子檢測:')
#組合完成了,沒耗子的 這個時候就要判斷生成的鋪了,如果生成的鋪是4個,並且手裏面的剩餘牌正好是一對,則說明能胡
allList = keList + shunziList + zikList + zisList
allHands = handCardList + ziHandCardList
if len(allList) == 4:
return True, allList, allHands
else:
if len(allHands) == 0:
return True, allList, allHands
else:
return False,allList, allHands
def can_hu_shun_ke(mjList, haoziId, haoziList):
#拆分萬條筒風
wttList, ziList = split_list(mjList)
#檢測 先不帶耗子 萬條筒風 刻 順 剩餘手牌 組合
keList,shunziList,handCardList = check_zuhe_shun_ke(wttList)
printLog('字')
zikList, zisList,ziHandCardList = check_zuhe_shun_ke(ziList, True)
#只有有耗子的時候纔去檢測添加耗子
if haoziId != 0:
printLog('帶耗子檢測:')
allList = keList + shunziList + zikList + zisList
#如果手裏面的已經組成四副了, 說明肯定能胡了
if len(allList) >= 4:
allHands = handCardList + ziHandCardList
return True, allList, allHands
else:
haoziKeList, haoziCount1 = check_2n_ke(handCardList, haoziId)
haoziShunList, haoziCount2 = check_2n_shun(handCardList, haoziId)
zikeList,haoziCount3 = check_2n_ke(ziHandCardList, haoziId)
zi_shun_list = []
haoziCount4 = 0
if isFengZui:
zi_shun_list,haoziCount4 = check_2n_shun(ziHandCardList,haoziId, True)
leftAllHand = ziHandCardList + handCardList
needAllHaoziCount = haoziCount1 + haoziCount2 + haoziCount3 + haoziCount4 + len(leftAllHand) * 2
leftAllHandList = []
for x in range(len(leftAllHand)):
tmpList=[]
tmpList.append(leftAllHand[x])
tmpList.append(haoziId)
tmpList.append(haoziId)
leftAllHandList.append(tmpList)
allList = allList + haoziKeList + haoziShunList + zikeList + zi_shun_list
handCards = handCardList + ziHandCardList
if needAllHaoziCount <= len(haoziList):
return True, allList+leftAllHandList, []
else:
return False,allList, handCards
else:
printLog('不帶耗子檢測:')
#組合完成了,沒耗子的 這個時候就要判斷生成的鋪了,如果生成的鋪是4個,並且手裏面的剩餘牌正好是一對,則說明能胡
allList = keList + shunziList + zikList + zisList
allHands = handCardList + ziHandCardList
if len(allList) == 4:
return True, allList, allHands
else:
return False,allList, allHands
def check_ting(mjList, haoziId, haoziList):
#檢測聽牌的話,就是將自己的手牌給移除一張,再加上一張任意牌,看看能不能胡
#mjList 現在已經移除掉所有的耗子牌了,
mjListCopy = mjList[:]
ting_cards = []
for index in range(len(mjListCopy)):
mjListCopy2 = mjList[:]
mjValue = mjListCopy2.pop(index)
hu_cards = []
for addMjIndex in range(len(MAJIANG_TYPE)):
mjListCopy3 = mjListCopy2[:]
mjListCopy3.append(MAJIANG_TYPE[addMjIndex])
mjListCopy3.sort()
for i in range(len(mjListCopy3)):
mjListCopy4 = mjListCopy3[:]
canjiang, jiangList, needHaoziCount = check_jiang(mjListCopy4, mjListCopy3[i], haoziId, haoziList)
if canjiang:
canhu,allList, allHands = can_hu_ke_shun(mjListCopy4, haoziId, haoziList)
if canhu:
if needHaoziCount == 1:
haoziList.append(haoziId)
hu_cards.append(MAJIANG_TYPE[addMjIndex])
break
else:
canhu, allList, allHands = can_hu_shun_ke(mjListCopy4, haoziId, haoziList)
if canhu:
if needHaoziCount == 1:
haoziList.append(haoziId)
hu_cards.append(MAJIANG_TYPE[addMjIndex])
break
else:
if needHaoziCount == 1:
haoziList.append(haoziId)
continue
else:
continue
if len(hu_cards) > 0:
try:
value = ting_cards.index(mjValue)
ting_cards[value+1] = hu_cards
except ValueError, e:
ting_cards.append(mjValue)
ting_cards.append(hu_cards)
if len(ting_cards) > 0:
printNow('當前的牌型可以聽')
for index in range(0, len(ting_cards) - 1, 2):
printNow('打:', ting_cards[index])
printNow('聽:', ting_cards[index+1])
return ting_cards
def check_hu(mjList, haoziId, haoziList):
canhu = False
allList = []
allHands = []
for i in range(len(mjList)):
mjListCopy4 = mjList[:]
canjiang, jiangList, needHaoziCount = check_jiang(mjListCopy4, mjList[i], haoziId, haoziList)
if canjiang:
canhu,allList, allHands = can_hu_ke_shun(mjListCopy4, haoziId, haoziList)
if canhu:
allList.append(jiangList)
break
else:
canhu, allList, allHands = can_hu_shun_ke(mjListCopy4, haoziId, haoziList)
if canhu:
allList.append(jiangList)
break
else:
if needHaoziCount == 1:
haoziList.append(haoziId)
continue
else:
continue
return canhu, allList, allHands
def get_max_hu():
pass
def init(mjList, modePai, haoziPaiList, isTestTing):
canhu = False
allList = []
allHands = []
mahjongList = mjList
modePai = modePai
mahjongList.append(modePai)
haoziPaiList = haoziPaiList
haoziPai = haoziPaiList[0]
#將手牌裏面的耗子牌移除掉,並且記錄耗子的數量
haoziList = check_haozi_sort(mahjongList,haoziPaiList)
if isTestTing:
tingCards = check_ting(mahjongList, haoziPai, haoziList)
return canhu, allList, allHands
else:
canhu,allList,allHands = check_hu(mahjongList, haoziPai, haoziList)
haoziSort = feng_sort(haoziList)
if len(haoziPaiList) > 1:
count = 0
for index in range(len(haoziSort)):
if haoziPai == haoziSort[index][0]:
count = haoziSort[index][1]
curCount = 0
for x in range(len(allList)):
for y in range(len(allList[x])):
if allList[x][y] == haoziPai:
curCount = curCount + 1
if curCount > count:
allList[x][y] = haoziPaiList[1]
printNow(canhu)
return canhu,allList,allHands
def chenck_fengshun(mjList, haoziId):
mjList.sort()
allLenth = len(mjList)
fengKeList = []
fengShunList = []
needHaoziCount = 0
#數量能正好組成撲
if allLenth % 3 == 0:
mjListCopy = mjList[:]
#拿出刻子
fengKeList = check_ke(mjListCopy)
fengSort = feng_sort(mjListCopy)
#檢測風順子
fengShunList = chenck_feng_shun(fengSort, mjListCopy)
if len(mjListCopy) > 0: #說明刻子沒拿完
fengSort = feng_sort(mjListCopy)
if len(fengSort) == 2:
needHaoziCount = 3
fengSort = feng_sort(mjList)
fengShunList = chenck_feng_shun(fengSort, mjList)
if len(mjList) == 0:
needHaoziCount = 0
else:
needHaoziCount = 3
else:
needHaoziCount = 0
else:
fengKeList = check_ke(mjList)
needHaoziCount = 3 - len(mjList) % 3
printNow('需要的耗子數量爲', needHaoziCount)
mjList = [ 401,401,401,402,402,404]
chenck_fengshun(mjList, 0)
麻將算法-支持單耗子-雙耗子-多耗子
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.