# 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)
麻将算法-支持单耗子-双耗子-多耗子
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.