--[[ 3~KA2(从小到大) tip: 假设有个梅花3, 具体牌值则是为1,标准牌值是0x11 ]] local defs = require("pk_doudizhu.luaScript.Def_28") local PokerUtil = class("PokerUtil") -- 值 local Value_2 = 0x0d -- 2的具体牌值 local Value_Joker_Little = 0x0e -- 小鬼的具体牌值 local Value_Joker_Big = 0x0f -- 大鬼的具体牌值 -- 从小到大排序 function PokerUtil.sortOrder(a, b) return a < b end -- 从大到小排序 function PokerUtil.sortDesc(a, b) return a > b end -- 从小到大排序(根据扑克值) v指value, t指type function PokerUtil.sortOrder_By_PokerValue(a, b) local v_a = PokerUtil:getCardValue(a) local v_b = PokerUtil:getCardValue(b) if v_a ~= v_b then return v_a < v_b else local t_a = PokerUtil:getCardType(a) local t_b = PokerUtil:getCardType(b) return t_a < t_b end end function PokerUtil:ctor(param) self:initFunction() end -- 获得牌类型 0方块 1梅花 2红桃 3黑桃 function PokerUtil:getCardType(card) return toint(getNumBand(card, 0xf0) / 0x0f) end -- 获得牌的具体牌值 function PokerUtil:getCardValue(card) return getNumBand(card, 0x0f) end function PokerUtil:initFunction() self:initTypeMap() -- self:initTipMap() end -- 定义数组,key是手牌的长度,value则是可能组成长度为key的牌型判断方法 function PokerUtil:initTypeMap() for i = 1, PokerUtil.Card_Max_Length do PokerUtil.Card_Type_Map[i] = {} end -- 单张 table.insert(PokerUtil.Card_Type_Map[1], self.isSingle) -- 对子 table.insert(PokerUtil.Card_Type_Map[2], self.isDouble) -- 三张 table.insert(PokerUtil.Card_Type_Map[3], self.isThree) -- 顺子 for i = PokerUtil.Less_Line, PokerUtil.Max_Line do table.insert(PokerUtil.Card_Type_Map[i], self.isLine) end -- 连对 for i = PokerUtil.Less_Lian_Dui, PokerUtil.Card_Max_Length do if i % 2 == 0 then table.insert(PokerUtil.Card_Type_Map[i], self.isDoubleLine) end end -- 三带一 table.insert(PokerUtil.Card_Type_Map[4], self.isThreeTakeOne) -- 三带二 table.insert(PokerUtil.Card_Type_Map[5], self.isThreeTakeTwo) -- 四带一张 table.insert(PokerUtil.Card_Type_Map[5], self.isFourTakeOneSinle) -- 四带一对 table.insert(PokerUtil.Card_Type_Map[6], self.isFourTakeOneDouble) -- 四带二张单排 table.insert(PokerUtil.Card_Type_Map[6], self.isFourTakeTwoSinle) -- 四带二对子 table.insert(PokerUtil.Card_Type_Map[8], self.isFourTakeTwoDouble) -- 飞机不带 for i = PokerUtil.Less_Plane, PokerUtil.Card_Max_Length do if i % 3 == 0 then table.insert(PokerUtil.Card_Type_Map[i], self.isPlaneNoTake) end end -- 飞机带单 for i = PokerUtil.Less_Plane + 2, PokerUtil.Card_Max_Length do if i % 4 == 0 then table.insert(PokerUtil.Card_Type_Map[i], self.isPlaneTakeSinle) end end -- 飞机带对子 for i = PokerUtil.Less_Plane + 4, PokerUtil.Card_Max_Length do if i % 5 == 0 then table.insert(PokerUtil.Card_Type_Map[i], self.isPlanetakeDouble) end end -- 炸弹 table.insert(PokerUtil.Card_Type_Map[4], self.isBomb) -- 王炸 table.insert(PokerUtil.Card_Type_Map[2], self.isKingBomb) end -- 获得提示(cards是userdata) function PokerUtil:getTip(cards, lastData) print('jxjx 进入getTip') dump(cards, 'cards') dump(lastData, 'lastData') local tipResult = {} local lastCardInfo = self:getCardsType(lastData) if lastCardInfo.cardType < defs.CARD_TYPE.BOMB then local f = PokerUtil.Card_Tip_Map[lastCardInfo.cardType] if f then print(string.format('jxjx..牌型提示..%s', defs.CARD_TYPE_NAME[lastCardInfo.cardType])) -- tipResult = PokerUtil.Card_Tip_Map[lastCardInfo.cardType](self, cards, lastData) -- f是方法 启用initTipMap tipResult = self[f](self, cards, lastData) -- f是str end end -- 添加炸弹 if lastCardInfo.cardType <= defs.CARD_TYPE.BOMB then print('jxjx..炸弹') local result = self:getBombTip(cards, lastData) if table.nums(result) > 0 then for _, bomb in ipairs(result) do table.insert(tipResult, bomb) end end end --王炸 if lastCardInfo.cardType <= defs.CARD_TYPE.BOMB_KING then print('jxjx..王炸') local result = self:getBombKingTip(cards, lastData) if table.nums(result) > 0 then for _, bomb in ipairs(result) do -- 王炸只有1个,虽然多此一举用了循环... table.insert(tipResult, bomb) end end end dump(tipResult, 'jxjx gettip 结果') return tipResult end -- 解析牌值,将牌值分成牌值数量表和牌表 --[[ valueList: key具体牌值, value数量 valueCard: key具体牌值, value标准牌值(16进制转10进制的) ]] function PokerUtil:parseCard(cards) local valueList = {} local valueCard = {} for k,v in ipairs(cards) do local value = self:getCardValue(v) if not valueList[value] then valueList[value] = 0 end if not valueCard[value] then valueCard[value] = {} end valueList[value] = valueList[value] + 1 table.insert(valueCard[value], v) end return valueList, valueCard end -- 解析牌值,将牌值分成牌值数量表和牌表(扩展版) --[[ valueCard: key有序, value标准牌值(16进制转10进制的) ]] function PokerUtil:parseCardEx(cards) local temp = {} for k,v in ipairs(cards) do local value = self:getCardValue(v) if not temp[value] then temp[value] = {} end table.insert(temp[value], v) end local valueCard = {} for _,v in pairs(temp) do table.insert(valueCard, v) end return valueCard end -- 反解析牌值,返回key为数量,value为具体牌值的表 --[[ result: key数量, value具体牌值 ]] function PokerUtil:reParseCard(cards) local valueList = self:parseCard(cards) local result = {{}, {}, {}, {}} -- 一副牌,最多4张 for k,v in pairs(valueList) do table.insert(result[v], k) end return result end -- 通过牌的标准值,转换为具体值 function PokerUtil:changeCardValue_Standard_To_Specific(cards) if type(cards) == 'number' then return self:getCardValue(cards) elseif type(cards) == 'table' then local result = {} for i, v in ipairs(cards) do table.insert(result, self:getCardValue(v)) end return result end return end -- 判断牌组中是否包含炸弹 function PokerUtil:getIsHaveBomb(cards) -- 4张 local reValueList = self:reParseCard(cards) if #reValueList[4] > 0 then return true end -- 王炸 local valueList = self:parseCard(cards) if (valueList[Value_Joker_Little] or 0) > 0 and (valueList[Value_Joker_Big] or 0) > 0 then return true end return false end -- 获得牌类型(返回类型和最小值) function PokerUtil:getCardsType(cards) local result = {min = -1, cardType = defs.CARD_TYPE.NULL} local maxLen = table.nums(cards) if maxLen == 0 then print('jxjx 牌长度错误,获得牌类型,牌长度是0,返回') return result end local tt = {} for k,v in ipairs(cards) do table.insert(tt, self:getCardValue(v)) end table.sort(tt, function(a, b) return a < b end) print('jxjx 获得牌提示,长度是', maxLen) if PokerUtil.Card_Type_Map[maxLen] then print(string.format('jxjx 判断方法共有%d个', #PokerUtil.Card_Type_Map[maxLen])) end for i, fun in ipairs(PokerUtil.Card_Type_Map[maxLen]) do local isType, ct, min = fun(self, tt) if isType then result = {min = min, cardType = ct} print('jxjx 获得牌提示,牌的类型是', defs.CARD_TYPE_NAME[ct]) break end end return result end -- 是否一手出完所有牌 function PokerUtil:checkIsCanOneOutCard(cards, lastData) print('jxjx 是否一手出完所有牌') dump(cards, 'cards>>') dump(lastData, 'lastData>>') -- 压牌(如果有提示牌,并且只有1种) if lastData and table.nums(lastData) > 0 then local tips = self:getTip(cards, lastData) if tips and table.nums(tips) == 1 and #tips[1] == #cards then print('压牌,可以出完一手牌') return true end end -- 自己出牌(判断手中的所有牌是否可以组成某个牌型,并且没有炸弹) if not lastData or table.nums(lastData) <= 0 then local handCardType = self:getCardsType(cards) if handCardType.cardType > defs.CARD_TYPE.NULL and not self:getIsHaveBomb(cards) then print('自己出牌,可以出完一手牌') return true end end print('jxjx 不可一手出完所有牌') return false end -- 是否可以3带1 function PokerUtil:can31() if not app.room then return true end local gameInfo = json.decode(app.room.roomInfo.strGameInfo) return getNumBand(0x01, (gameInfo.sanDai or 0x1)) > 0 end -- 是否可以3带2 function PokerUtil:can32() if not app.room then return true end local gameInfo = json.decode(app.room.roomInfo.strGameInfo) return getNumBand(0x02, (gameInfo.sanDai or 0x2)) > 0 end -- 是否可以4带1 function PokerUtil:can41() return false end -- 是否可以4带2(4带1对子) function PokerUtil:can42() return true end -- 是否可以4带单单(2个单张) function PokerUtil:can411() if not app.room then return true end local gameInfo = json.decode(app.room.roomInfo.strGameInfo) return getNumBand(0x02, (gameInfo.siDai or 0x02)) > 0 end -- 是否可以4带双双(2个对子) function PokerUtil:can422() if not app.room then return true end local gameInfo = json.decode(app.room.roomInfo.strGameInfo) return getNumBand(0x08, (gameInfo.siDai or 0x08)) > 0 end ----------------------------------------------------------------------------------------------------------------- -------------------------------------- 以下是牌型提示 ------------------------------------------------------ ----------------------------------------------------------------------------------------------------------------- -- 获得单张提示 -- tip: 先从1张按顺序获取,在从2张,最后到4张 function PokerUtil:getSingleTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local result = {} local a = {{}, {}, {}, {}} for k,v in pairs(valueList) do table.insert(a[v], k) end for i = 1, 4 do for k2,v2 in pairs(a[i]) do if v2 > lastCardInfo.min then table.insert(result, { valueCard[v2][1] }) end end end return result end -- 获得对子提示 -- tip:直接就是从小到大,直接在2,3,4张中获取,不按是否有3张还是4张的 function PokerUtil:getDuiZiTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local result = {} for i = lastCardInfo.min + 1, 13 do local tpReplace = {} if (valueList[i] or 0) >= 2 then for j = 1, 2 do table.insert(tpReplace, valueCard[i][j]) end table.insert(result, tpReplace) end end return result end -- 获得三张提示 -- tip:直接就是从小到大,直接在3,4张中获取,不按是否有3张还是4张的 function PokerUtil:getSanZhangTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local result = {} for i = lastCardInfo.min + 1, 13 do local tpReplace = {} if (valueList[i] or 0) >= 3 then for j = 1, 3 do table.insert(tpReplace, valueCard[i][j]) end table.insert(result, tpReplace) end end return result end -- 获得顺子提示 -- tips:先for循环最小值+1,直到13-长度(为了减少复杂度);然后在while循环中判断是否有当前出牌的长度的个数 function PokerUtil:getShunZiTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local nowCardsLen = table.nums(cards) local lastCardsLen = table.nums(lastData) local result = {} for i = lastCardInfo.min + 1, 13 - lastCardsLen do local tpIdx = i local tpCount = 0 local tpReplace = {} while tpCount < nowCardsLen and tpCount < lastCardsLen and tpIdx <= 12 do valueList[tpIdx] = valueList[tpIdx] or 0 if valueList[tpIdx] <= 0 then break end table.insert(tpReplace, valueCard[tpIdx][1]) tpCount = tpCount + 1 tpIdx = tpIdx + 1 end if tpCount == lastCardsLen then table.insert(result, tpReplace) end end return result end -- 获得连对提示 -- tip:先for循环最小值+1,直到13-长度/2(为了减少复杂度,这里/2是因为连对中是一半一半相对的);然后在while循环中判断是否有当前出牌的长度的个数 function PokerUtil:getLianDuiTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local nowCardsLen = table.nums(cards) local lastCardsLen = table.nums(lastData) local result = {} for i = lastCardInfo.min + 1, 13 - lastCardsLen / 2 do local tpIdx = i local tpCount = 0 local tpReplace = {} while tpCount < nowCardsLen and tpCount < lastCardsLen and tpIdx <= 12 do valueList[tpIdx] = valueList[tpIdx] or 0 if valueList[tpIdx] <= 1 then break end for j = 1, 2 do table.insert(tpReplace, valueCard[tpIdx][j]) end tpCount = tpCount + 2 tpIdx = tpIdx + 1 end if tpCount == lastCardsLen then table.insert(result, tpReplace) end end return result end -- 获得三顺提示(飞机不带翅膀) -- tip:先for循环最小值+1,直到13-长度/3(为了减少复杂度,这里/3是因为连对中是每3分之1相对的);然后在while循环中判断是否有当前出牌的长度的个数 function PokerUtil:getSanShunTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local nowCardsLen = table.nums(cards) local lastCardsLen = table.nums(lastData) local result = {} for i = lastCardInfo.min + 1, 13 - lastCardsLen / 3 do local tpIdx = i local tpCount = 0 local tpReplace = {} while tpCount < nowCardsLen and tpCount < lastCardsLen and tpIdx <= 12 do valueList[tpIdx] = valueList[tpIdx] or 0 if valueList[tpIdx] <= 2 then break end for j = 1, 3 do table.insert(tpReplace, valueCard[tpIdx][j]) end tpCount = tpCount + 3 tpIdx = tpIdx + 1 end if tpCount == lastCardsLen then table.insert(result, tpReplace) end end return result end -- 获得3带1提示 -- tips:直接获取判断是否有大于等于3张的牌值 function PokerUtil:getSanDaiYiTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local nowCardsLen = table.nums(cards) local result = {} for i = lastCardInfo.min + 1, 13 do local tpReplace = {} if ((valueList[i] or 0) == 3 and nowCardsLen > 3) or ((valueList[i] or 0) > 3 and nowCardsLen > 4) then for j = 1, 3 do table.insert(tpReplace, valueCard[i][j]) end table.insert(result, tpReplace) end end return result end -- 获得3带1对提示(3带2) -- tip:在for循环前,会判断是否有对子 function PokerUtil:getSanDaiYiDuiTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local reValueList = self:reParseCard(cards) local result = {} if table.nums(reValueList[2]) > 0 then for i = lastCardInfo.min + 1, 13 do local tpReplace = {} if (valueList[i] or 0) >= 3 then for j = 1, 3 do table.insert(tpReplace, valueCard[i][j]) end table.insert(result, tpReplace) end end end return result end -- 获得飞机带单提示 -- tip:根据当前循环for的i值,往后延长最长的,如果一个111222,手中有333444555,则会提示444555 function PokerUtil:getAirPlaneSingleTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local nowCardsLen = table.nums(cards) local lastCardsLen = table.nums(lastData) local result = {} if table.nums(valueList) > lastCardsLen / 4 then for i = lastCardInfo.min + 1, 13 - lastCardsLen / 4 do local tpIdx = i local tpCount = 0 local tpReplace = {} while tpCount < nowCardsLen and tpIdx <= 12 do valueList[tpIdx] = valueList[tpIdx] or 0 if valueList[tpIdx] < 3 then break end for j = 1, 3 do table.insert(tpReplace, valueCard[tpIdx][j]) end tpCount = tpCount + 4 tpIdx = tpIdx + 1 end if tpCount == lastCardsLen then table.insert(result, tpReplace) end end end return result end -- 获得飞机带对提示 -- tips:会先判断手牌中2张是否大于等于2个数量,jxtd 这里有bug,因为只会从对子中判断,不会冲超过2张中判断 function PokerUtil:getAirPlaneDuiTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local nowCardsLen = table.nums(cards) local lastCardsLen = table.nums(lastData) local reValueList = self:reParseCard(cards) local result = {} if table.nums(reValueList[2]) >= lastCardsLen / 5 then for i = lastCardInfo.min + 1, 13 - lastCardsLen / 5 do local tpIdx = i local tpCount = 0 local tpReplace = {} while tpCount < nowCardsLen and tpIdx <= 12 do valueList[tpIdx] = valueList[tpIdx] or 0 if valueList[tpIdx] < 3 then break end for j = 1, 3 do table.insert(tpReplace, valueCard[tpIdx][j]) end tpCount = tpCount + 5 tpIdx = tpIdx + 1 end if tpCount == lastCardsLen then table.insert(result, tpReplace) end end end return result end -- 获得4带2单提示 -- tips:先判断手牌是否大于等于6张,然后寻找4个 function PokerUtil:getSiDaiErSingleTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local nowCardsLen = table.nums(cards) local result = {} if nowCardsLen >= 6 then for i = lastCardInfo.min + 1, 13 do local tpReplace = {} if (valueList[i] or 0) >= 4 and nowCardsLen > 4 then for j = 1, 4 do table.insert(tpReplace, valueCard[i][j]) end table.insert(result, tpReplace) end end end return result end -- 获得4带2对提示 -- tips:会先判断手牌中2张是否大于等于2个数量,jxtd 这里有bug,因为只会从对子中判断,不会冲超过2张中判断 function PokerUtil:getSiDaiErDuiTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local nowCardsLen = table.nums(cards) local reValueList = self:reParseCard(cards) local result = {} if table.nums(reValueList[2]) >= 2 then for i = lastCardInfo.min + 1, 13 do local tpReplace = {} if (valueList[i] or 0) >= 4 and nowCardsLen > 4 then for j = 1, 4 do table.insert(tpReplace, valueCard[i][j]) end table.insert(result, tpReplace) end end end return result end -- 获得炸弹提示 function PokerUtil:getBombTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local result = {} local tpIndex = lastCardInfo.cardType < defs.CARD_TYPE.BOMB and 1 or lastCardInfo.min + 1 for i = tpIndex, 13 do local tpReplace = {} if (valueList[i] or 0) >= 4 then for j = 1, 4 do table.insert(tpReplace, valueCard[i][j]) end table.insert(result, tpReplace) end end return result end -- 获得王炸提示 function PokerUtil:getBombKingTip(cards, lastData) local valueList, valueCard = self:parseCard(cards) local result = {} if (valueList[Value_Joker_Little] or 0) > 0 and (valueList[Value_Joker_Big] or 0) > 0 then local tpReplace = {} table.insert(tpReplace, 0x4e) table.insert(tpReplace, 0x4f) table.insert(result, tpReplace) end return result end ----------------------------------------------------------------------------------------------------------------- -------------------------------------- 以下是检查牌型 ------------------------------------------------------ ----------------------------------------------------------------------------------------------------------------- --[[ cards 是具体牌值,即1~K,从小到大排序 ]] -- 是否是单张 function PokerUtil:isSingle(cards) return true, defs.CARD_TYPE.SINGLE, cards[1] end -- 是否是对子 function PokerUtil:isDouble(cards) if cards[1] == cards[2] then return true, defs.CARD_TYPE.DUIZI,cards[1] end return false end -- 是否是三张(不带) function PokerUtil:isThree(cards) if cards[1] == cards[2] and cards[2] == cards[3] then return true, defs.CARD_TYPE.SANZHANG, cards[1] end return false end -- 是否是顺子 function PokerUtil:isLine(cards) local isHaveKindOr2 = false for i, val in ipairs(cards) do if val == Value_Joker_Little or val == Value_Joker_Big or val == Value_2 then isHaveKindOr2 = true break end end -- 顺子中不允许包括2,大王,小王 if isHaveKindOr2 then return false end -- 检查单张总长度是否与传入相同,因为顺子是必须都是单个值 local reValueList = self:reParseCard(cards) if table.nums(reValueList[1]) ~= #(cards) then return false end -- 判断是否为顺子,计算最大值与最小值的差的绝对值是否与总长度-1相同 if math.abs(cards[1] - cards[#cards]) == #cards - 1 then return true, defs.CARD_TYPE.SHUNZI, cards[1] end return false end -- 是否是双顺(连对) function PokerUtil:isDoubleLine(cards) local isHaveKindOr2 = false for i, val in ipairs(cards) do if val == Value_Joker_Little or val == Value_Joker_Big or val == Value_2 then isHaveKindOr2 = true break end end -- 顺子中不允许包括2,大王,小王 if isHaveKindOr2 then return false end -- 检查2张的个数是否与总长度的一半相同,因为连对是必须都是对子值 local reValueList = self:reParseCard(cards) if table.nums(reValueList[2]) ~= #(cards) / 2 then return false end -- 判断是否为对子,计算最大值与最小值的差的绝对值是否与总长度/2-1相同 if math.abs(cards[1] - cards[#cards]) == #cards/2 - 1 then return true, defs.CARD_TYPE.SHUANGSHUN, cards[1] end return false end -- 是否是三带一(单张) function PokerUtil:isThreeTakeOne(cards) if not self:can31() then return false end local reValueList = self:reParseCard(cards) if table.nums(reValueList[3]) == 1 then return true, defs.CARD_TYPE.SANDAIYI, reValueList[3][1] end return false end -- 是否是三带二(对子) function PokerUtil:isThreeTakeTwo(cards) if not self:can32() then return false end local reValueList = self:reParseCard(cards) if table.nums(reValueList[3]) == 1 and table.nums(reValueList[2]) == 1 then return true, defs.CARD_TYPE.SANDAIDUI, reValueList[3][1] end return false end -- 是否是四带一(单) function PokerUtil:isFourTakeOneSinle(cards) if not self:can41() then return false end local reValueList = self:reParseCard(cards) if table.nums(reValueList[4]) == 1 then return true, defs.CARD_TYPE.SIDAIYI, reValueList[4][1] end return false end -- 是否是四带一对(对子) function PokerUtil:isFourTakeOneDouble(cards) if not self:can42() then return false end local reValueList = self:reParseCard(cards) if table.nums(reValueList[4]) == 1 and table.nums(reValueList[2]) == 1 then return true, defs.CARD_TYPE.SIDAIYIDUI, reValueList[4][1] end return false end -- 是否是四带二单张 function PokerUtil:isFourTakeTwoSinle(cards) if not self:can411() then return false end local reValueList = self:reParseCard(cards) if table.nums(reValueList[4]) == 1 then return true, defs.CARD_TYPE.SIDAIER, reValueList[4][1] end return false end -- 是否是四带二对子 function PokerUtil:isFourTakeTwoDouble(cards) if not self:can422() then return false end local reValueList = self:reParseCard(cards) if table.nums(reValueList[4]) == 1 and table.nums(reValueList[2]) == 2 then return true, defs.CARD_TYPE.SIDAIERDUI, reValueList[4][1] end return false end -- 是否是三顺(飞机不带333444) function PokerUtil:isPlaneNoTake(cards) local isHaveKindOr2 = false for i, val in ipairs(cards) do if val == Value_Joker_Little or val == Value_Joker_Big or val == Value_2 then isHaveKindOr2 = true break end end -- 三顺中不允许包括2,大王,小王 if isHaveKindOr2 then return false end -- 检查3张的个数是否与总长度的/3相同,因为三顺是必须都是三个个值 local reValueList = self:reParseCard(cards) if table.nums(reValueList[3]) ~= #(cards) / 3 then return false end -- 判断是否为对子,计算最大值与最小值的差的绝对值是否与总长度/2-1相同 if math.abs(cards[1] - cards[#cards]) == #cards/3 - 1 then return true, defs.CARD_TYPE.SANSHUN, cards[1] end return false end -- 是否是飞机带单 function PokerUtil:isPlaneTakeSinle(cards) -- if not self:can31() then -- return false -- end local reValueList = self:reParseCard(cards) local t3 = reValueList[3] local t4 = reValueList[4] for i = #t3, 1, -1 do -- 移除三张中带2的值 if t3[i] == Value_2 then table.remove(t3, i) end end for i = #t4, 1, -1 do -- 移除四张中带2的值 if t4[i] == Value_2 then table.remove(t4, i) end end local tpLianMin = self:tpLian(t3, t4, #cards/4) if tpLianMin then return true, defs.CARD_TYPE.AIRPLANE_SINGLE, tpLianMin.min end return false end -- 是否是飞机带对子 function PokerUtil:isPlanetakeDouble(cards) -- if not self:can32() then -- return false -- end local reValueList = self:reParseCard(cards) local t2 = reValueList[2] local t3 = reValueList[3] local t4 = reValueList[4] for i = #t3, 1, -1 do -- 移除三张中带2的值 if t3[i] == Value_2 then table.remove(t3, i) end end for i = #t4, 1, -1 do -- 移除四张中带2的值 if t4[i] == Value_2 then table.remove(t4, i) end end local tpLianMin = self:tpLian(t3, t4, #cards/5) if tpLianMin then -- 判断除飞机长度外,组成对子的是否能超过飞机的个数 local canBeDuiZiCount = #t2 + #t3 + #t4 * 2 -- 炸弹算2个对子,所以t4要*2 print(string.format('%d可组成对子,飞机长度是%d', canBeDuiZiCount, tpLianMin.feiLen)) local isMoreThan_2DuiZi = (canBeDuiZiCount - tpLianMin.feiLen) >= tpLianMin.feiLen if not isMoreThan_2DuiZi then return false end return true, defs.CARD_TYPE.AIRPLANE_DUAD, tpLianMin.min end return false end -- 飞机的判断 -- tip:主要是根据3张,4张中,通过while循环获取与传入的飞机长度feiLen相同长度的值 function PokerUtil:tpLian(la3, la4, feiLen) local feiLen = feiLen or 0 local lc = {} for _,v in ipairs(la3) do table.insert(lc, v) end for _,v in ipairs(la4) do table.insert(lc, v) end if table.nums(lc) <= 0 then return nil end table.sort(lc, function (a, b) return a < b end) local lenEx = 1 local feiji = {} local lcLen = table.nums(lc) for k,v in ipairs(lc) do lenEx = 1 local j = k + 1 while j <= lcLen and (feiLen == 0 or lenEx < feiLen) do if lc[j] ~= lc[j-1] + 1 then -- 判断是否是连续的 break end j = j + 1 lenEx = lenEx + 1 end if lenEx == feiLen then table.insert(feiji, { feiLen = lenEx, min = lc[k], }) end end if table.nums(feiji) > 0 then table.sort(feiji, function (a, b) return b.feiLen ~= a.feiLen and b.feiLen - a.feiLen or b.min - a.min end) return feiji[1] else return nil end end -- 是否是炸弹 function PokerUtil:isBomb(cards) local tag = true local v = cards[1] for i, val in ipairs(cards) do if v ~= val then tag = false break end end if tag then return true, defs.CARD_TYPE.BOMB, cards[1] end return false end -- 是否是王炸 function PokerUtil:isKingBomb(cards) if cards[1] == Value_Joker_Little and cards[2] == Value_Joker_Big then return true, defs.CARD_TYPE.BOMB_KING, cards[1] end return false end ----------------------------------------------------------------------------------------------------------------- ---------------------------------------- 以下是配置 -------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- -- 配置 PokerUtil.Card_Max_Length = 20 -- 手牌最多的个数 PokerUtil.Less_Line = 5 -- 顺子最小长度 PokerUtil.Max_Line = 12 -- 顺子最大长度(3~A) PokerUtil.Less_Lian_Dui = 6 -- 最小组成的连对长度 PokerUtil.Less_Plane = 6 -- 最小组成的飞机长度 PokerUtil.Card_Type_Map = {} -- 牌类型方法表 PokerUtil.Card_Tip_Map = {} -- 牌提示方法表 -- 牌型提示对应的方法(后面对应的是方法) PokerUtil.Card_Tip_Map = { [defs.CARD_TYPE.NULL] = nil, [defs.CARD_TYPE.SINGLE] = 'getSingleTip', [defs.CARD_TYPE.DUIZI] = 'getDuiZiTip', [defs.CARD_TYPE.SANZHANG] = 'getSanZhangTip', [defs.CARD_TYPE.SHUNZI] = 'getShunZiTip', [defs.CARD_TYPE.SHUANGSHUN] = 'getLianDuiTip', [defs.CARD_TYPE.SANSHUN] = 'getSanShunTip', [defs.CARD_TYPE.SANDAIYI] = 'getSanDaiYiTip', [defs.CARD_TYPE.SANDAIDUI] = 'getSanDaiYiDuiTip', [defs.CARD_TYPE.SIDAIYI] = nil, [defs.CARD_TYPE.SIDAIYIDUI] = nil, [defs.CARD_TYPE.SIDAIER] = 'getSiDaiErSingleTip', [defs.CARD_TYPE.SIDAIERDUI] = 'getSiDaiErDuiTip', [defs.CARD_TYPE.AIRPLANE_SINGLE] = 'getAirPlaneSingleTip', [defs.CARD_TYPE.AIRPLANE_DUAD] = 'getAirPlaneDuiTip', [defs.CARD_TYPE.BOMB] = 'getBombTip', [defs.CARD_TYPE.BOMB_KING] = 'getBombKingTip', } -- 初始化牌提示方法,不能用表驱动,因为子类重写时,调用的话,还是用的父类方法 -- function PokerUtil:initTipMap() -- PokerUtil.Card_Tip_Map = { -- [defs.CARD_TYPE.NULL] = nil, -- [defs.CARD_TYPE.SINGLE] = self.getSingleTip, -- [defs.CARD_TYPE.DUIZI] = self.getDuiZiTip, -- [defs.CARD_TYPE.SANZHANG] = self.getSanZhangTip, -- [defs.CARD_TYPE.SHUNZI] = self.getShunZiTip, -- [defs.CARD_TYPE.SHUANGSHUN] = self.getLianDuiTip, -- [defs.CARD_TYPE.SANSHUN] = self.getSanShunTip, -- [defs.CARD_TYPE.SANDAIYI] = self.getSanDaiYiTip, -- [defs.CARD_TYPE.SANDAIDUI] = self.getSanDaiYiDuiTip, -- [defs.CARD_TYPE.SIDAIYI] = nil, -- [defs.CARD_TYPE.SIDAIYIDUI] = nil, -- [defs.CARD_TYPE.SIDAIER] = self.getSiDaiErSingleTip, -- [defs.CARD_TYPE.SIDAIERDUI] = self.getSiDaiErDuiTip, -- [defs.CARD_TYPE.AIRPLANE_SINGLE] = self.getAirPlaneSingleTip, -- [defs.CARD_TYPE.AIRPLANE_DUAD] = self.getAirPlaneDuiTip, -- [defs.CARD_TYPE.BOMB] = self.getBombTip, -- [defs.CARD_TYPE.BOMB_KING] = self.getBombKingTip, -- } -- end return PokerUtil