--[[ (1)压单张 a.默认弹最小单张,若单张中含有对子、顺子、三张组合,则优先不拆,最后再拆; b.若能压牌中含炸弹,则永不拆炸弹,直接弹炸弹。 (2)压对子 a.默认弹最小对子,若对子可组合成连对,则优先不拆,最后再拆; b.若能压牌中含对子+三张/炸弹,则永不拆三张、炸弹; c.若能压牌中只有三张(+炸弹),则拆三张; d.若能压牌中只有炸弹,则直接弹炸弹。 如,上家55,本家有667788JJJ,则点“提示”,牌弹起的顺序为66、88、77。 (3)压三张 a.默认弹最小三张,若只有2单张,则最小三张和2单张弹起,点“提示”,三张轮换; b.默认弹最小三张,若三张中含有飞机,则优先不拆,最后再拆; c.若能压牌中含三张、飞机、炸弹,则永远不拆炸弹; d.若能压牌只有炸弹,则直接弹炸弹。 如,上家555,本家有666777888349J,则点“提示”,牌弹起的顺序为666、888、777。 (4)压顺子:直接弹最小顺子,点击轮换。 (5)压连对:直接弹最小连对,点击轮换。 (6)压飞机:直接弹最小飞机,点击轮换。 (7)压炸弹:直接弹最小炸弹,点击轮换。 5、压牌时,手动滑牌,则滑什么牌相应的弹起什么牌。 6、主动出牌时,手动滑牌:飞机-连对-顺子 (1)如果有飞机,则只显示最小飞机主牌; (2)如果没有飞机,有连对,则弹起最小连对; (3)如果没有飞机、连对,则弹起最小顺子; (4)如果都没有,则全部弹起。 ]] local PokerUtil = require('pk_doudizhu.luaScript.Views.Room.PokerUtil') -- 基类文件 local newPokerUtil = class("newPokerUtil", PokerUtil) local isResetSelectCard = true -- 是否启动滑动手牌并返回特殊的牌型 local Value_2 = 0x0d -- 2的标准值 local Value_Joker_Little = 0x0e -- 小鬼的标准值 local Value_Joker_Big = 0x0f -- 大鬼的标准值 function newPokerUtil:ctor(param) newPokerUtil.super.ctor(self, param) end -- 重写单张提示 function newPokerUtil:getSingleTip(cards, lastData) local lastCardInfo = self:getCardsType(lastData) local result = {} -- 将非王牌,带2的牌,炸弹牌,组合在一起(用于判断连续值) -- 移除手牌中的炸弹 local cards = clone(cards) local t = self:parseCardEx(cards) local temp = {} for _, v in ipairs(t) do if #v < 4 then -- 插入大于1张,非炸弹的牌 for _, val in ipairs(v) do table.insert(temp, val) end end end -- 移除手牌中的王牌和2 local nt = self:removeValue_Joker_And_2(temp) local lineTable = self:getSubLineEx(nt) -- 所有可以连在一起的集合(扩展版) for i = #lineTable, 1, -1 do -- 移除顺子集合中小于最小长度的顺子 if #lineTable[i] < PokerUtil.Less_Line then table.remove(lineTable, i) end end -- 将顺子所有牌整到同一个表 local szCard = {} for _, v in ipairs(lineTable or {}) do for _, card in ipairs(v) do table.insert(szCard, card) end end -- 同顺表,非顺表,异顺表 local cbsCard, cnbsCard, lcbsCard = {}, {}, {} cbsCard, cnbsCard, lcbsCard = self:parseShunZi(cards, szCard) local p_tc = self:parseCardEx(cnbsCard) local p_tl = self:parseCardEx(lcbsCard) table.sort(p_tc, function(a, b) return self:getCardValue(a[1]) < self:getCardValue(b[1]) end) table.sort(p_tl, function(a, b) return self:getCardValue(a[1]) < self:getCardValue(b[1]) end) local temp_two = {} local temp_three = {} -- 插入非顺表中单个值,2,3备用 for i, v in pairs(p_tc) do if #v == 1 then table.insert(result, v) elseif #v == 2 then table.insert(temp_two, v) elseif #v == 3 then table.insert(temp_three, v) end end -- 插入异顺表中单个值,2,3备用 for i, v in pairs(p_tl) do if #v == 1 then table.insert(result, v) elseif #v == 2 then table.insert(temp_two, v) elseif #v == 3 then table.insert(temp_three, v) end end -- 排序后,插入异顺表和非顺表中两个的值 table.sort(temp_two, function(a, b) return self:getCardValue(a[1]) < self:getCardValue(b[1]) end) for i, v in ipairs(temp_two) do table.insert(result, {v[1]}) -- 插入单个表,表里只有1个值 end -- 排序后,插入异顺表和非顺表中三个的值 table.sort(temp_three, function(a, b) return self:getCardValue(a[1]) < self:getCardValue(b[1]) end) for i, v in ipairs(temp_three) do table.insert(result, {v[1]}) -- 插入单个表,表里只有1个值 end -- 插入顺子 local temp_shunzi = clone(lineTable) for i, v in ipairs(temp_shunzi) do table.sort(v, PokerUtil.sortOrder_By_PokerValue) end for _, sz in ipairs(temp_shunzi) do for _, v in ipairs(sz) do table.insert(result, {v}) -- 因为是v是标准值,所以外面要带个{} end end -- 遍历result,把低于target值得移除 for i = #result, 1, -1 do if self:getCardValue(result[i][1]) <= lastCardInfo.min then table.remove(result, i) end end return result end -- 重写对子提示 function newPokerUtil:getDuiZiTip(cards, lastData) local cards = clone(cards) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local result = {} -- 将非王牌,带2的牌,炸弹牌,组合在一起(用于判断连续值) -- 移除手牌中的炸弹 local temp = {} for _, v in pairs(valueCard) do if #v > 1 and #v < 4 then -- 插入大于1张,非炸弹的牌 table.insert(temp, v[1]) -- 插入一个值即可,用于检测连对 end end -- 移除手牌中的王牌和2 local nt = self:removeValue_Joker_And_2(temp) local lineTable = self:getSubLine(nt) -- 所有可以连在一起的集合(扩展版) for i = #lineTable, 1, -1 do -- 移除顺子集合中小于长度2的顺子 if #lineTable[i] < PokerUtil.Less_Lian_Dui / 2 then table.remove(lineTable, i) end end -- 将顺子所有牌整到同一个表 local szCard = {} for _, v in ipairs(lineTable or {}) do for _, card in ipairs(v) do table.insert(szCard, card) end end -- 同顺表,非顺表 local cbsCard, cnbsCard = {}, {} cbsCard, cnbsCard = self:parseShunZi(cards, szCard) local p_tcb = self:parseCardEx(cbsCard) local p_tcn = self:parseCardEx(cnbsCard) table.sort(p_tcb, function(a, b) return self:getCardValue(a[1]) < self:getCardValue(b[1]) end) table.sort(p_tcn, function(a, b) return self:getCardValue(a[1]) < self:getCardValue(b[1]) end) -- 插入非顺表中2个值 for i, v in ipairs(p_tcn) do if #v == 2 then table.insert(result, v) end end -- 插入同顺表中2个值 for i, v in ipairs(p_tcb) do if #v == 2 then table.insert(result, v) end end -- 遍历result,把低于target值得移除 for i = #result, 1, -1 do if self:getCardValue(result[i][1]) <= lastCardInfo.min then table.remove(result, i) end end -- 如果没有对子可压,则从三张里面查找 -- 原来来是只在2张里面做筛选,提示是不包含3张的,但是如果没有2张,即result结果为空,则需要从3张里面去插入 if not next(result) then local temp = self:reParseCard(cards) local three = temp[3] local t = {} for i, v in pairs(three) do table.insert(t, valueCard[v]) end for i, v in ipairs(t) do table.sort(v, PokerUtil.sortOrder) end table.sort(t, function(a, b) return self:getCardValue(a[1]) < self:getCardValue(b[1]) end) for i, v in ipairs(t) do if self:getCardValue(v[1]) > lastCardInfo.min then local temp = {} table.insert(temp, v[1]) table.insert(temp, v[2]) table.insert(result, temp) end end end return result end -- 重写三张提示 function newPokerUtil:getSanZhangTip(cards, lastData) local cards = clone(cards) local valueList, valueCard = self:parseCard(cards) local lastCardInfo = self:getCardsType(lastData) local result = {} -- 将非王牌,带2的牌,炸弹牌,组合在一起(用于判断连续值) -- 移除手牌中的炸弹 local temp = {} for _, v in pairs(valueCard) do if #v == 3 then -- 插入刚好等于3张的牌 table.insert(temp, v[1]) -- 插入一个值即可,用于检测飞机 end end -- 移除手牌中的王牌和2 local nt = self:removeValue_Joker_And_2(temp) local lineTable = self:getSubLine(nt) -- 所有可以连在一起的集合(扩展版) for i = #lineTable, 1, -1 do -- 移除顺子集合中小于长度2的顺子 if #lineTable[i] < PokerUtil.Less_Plane / 3 then table.remove(lineTable, i) end end -- 将顺子所有牌整到同一个表 local szCard = {} for _, v in ipairs(lineTable or {}) do for _, card in ipairs(v) do table.insert(szCard, card) end end -- 同顺表,非顺表 local cbsCard, cnbsCard = {}, {} cbsCard, cnbsCard = self:parseShunZi(cards, szCard) local p_tcb = self:parseCardEx(cbsCard) local p_tcn = self:parseCardEx(cnbsCard) table.sort(p_tcb, function(a, b) return self:getCardValue(a[1]) < self:getCardValue(b[1]) end) table.sort(p_tcn, function(a, b) return self:getCardValue(a[1]) < self:getCardValue(b[1]) end) -- 插入非顺表中3个值 for i, v in ipairs(p_tcn) do if #v == 3 then table.insert(result, v) end end -- 插入同顺表中3个值 for i, v in ipairs(p_tcb) do if #v == 3 then table.insert(result, v) end end -- 遍历result,把低于target值得移除 for i = #result, 1, -1 do if self:getCardValue(result[i][1]) <= lastCardInfo.min then table.remove(result, i) end end return result end -- 重写三带一提示 function newPokerUtil:getSanDaiYiTip(cards, lastData) local nowCardsLen = table.nums(cards) local valueList, valueCard = self:parseCard(cards) local reValueList = self:reParseCard(cards) if nowCardsLen < 4 then -- 手牌数不够 return {} end local threeTips = self:getSanZhangTip(cards, lastData) if not next(threeTips) then return {} end -- 压牌点提示时,若压三带一/二,则除了弹最小三张外,还需要弹起一/二单张(斗地主2.0更新) local result = {} local ovt = clone(reValueList[1]) if #ovt <= 0 then return threeTips end table.sort(ovt, PokerUtil.sortOrder) for _, v in ipairs(threeTips) do for i = 1, 2 do local temp = clone(v) if ovt[i] then table.insert(temp, valueCard[ovt[i]][1]) table.insert(result, temp) end end end return result end -- 重写三带二 function newPokerUtil:getSanDaiYiDuiTip(cards, lastData) local nowCardsLen = table.nums(cards) local valueList, valueCard = self:parseCard(cards) local reValueList = self:reParseCard(cards) if nowCardsLen < 5 then -- 手牌数不够 return {} end if table.nums(reValueList[2]) <= 0 and table.nums(reValueList[3]) <= 0 then -- 如果没有可以组成对子的(这里不加入炸弹,因为炸弹不拆,外部会添加炸弹处理) return {} end local threeTips = self:getSanZhangTip(cards, lastData) if not next(threeTips) then return {} end -- 压牌点提示时,若压三带一/二,则除了弹最小三张外,还需要弹起一/二单张(斗地主2.0更新) local result = {} local tvt = clone(reValueList[2]) if #tvt <= 0 then return threeTips end table.sort(tvt, PokerUtil.sortOrder) for _, v in ipairs(threeTips) do for i = 1, 2 do local temp = clone(v) if tvt[i] then table.insert(temp, valueCard[tvt[i]][1]) table.insert(temp, valueCard[tvt[i]][2]) table.insert(result, temp) end end end return result end -- 重写顺子(把顺子中带炸弹的牌全部移除) function newPokerUtil:getShunZiTip(cards, lastData) local result = newPokerUtil.super.getShunZiTip(self, cards, lastData) local reValueList = self:reParseCard(cards) local bombCard = reValueList[4] -- 保存的是具体牌值 local isHaveBomb = false for i = #result, 1, -1 do isHaveBomb = false for _, val in ipairs(result[i]) do for _, bv in ipairs(bombCard) do if self:getCardValue(val) == bv then isHaveBomb = true break end end if isHaveBomb then break end end if isHaveBomb then table.remove(result, i) end end return result end -- 重写连对(把连对中带炸弹的牌全部移除) function newPokerUtil:getLianDuiTip(cards, lastData) local result = newPokerUtil.super.getLianDuiTip(self, cards, lastData) local reValueList = self:reParseCard(cards) local bombCard = reValueList[4] -- 保存的是具体牌值 local isHaveBomb = false for i = #result, 1, -1 do isHaveBomb = false for _, val in ipairs(result[i]) do for _, bv in ipairs(bombCard) do if self:getCardValue(val) == bv then isHaveBomb = true break end end if isHaveBomb then break end end if isHaveBomb then table.remove(result, i) end end return result end -- 检测牌组是否是连续的(返回连续的表值 cards每个值里面有且只有1个) function newPokerUtil:getSubLine(cards) local sub = {} local parseCards = self:changeCardValue_Standard_To_Specific(cards) for i=#parseCards,1,-1 do if parseCards[i] and parseCards[i-1] then if parseCards[i]-1~=parseCards[i-1] then --断开了 local tmp = {} for j=#parseCards,i,-1 do table.insert(tmp, parseCards[j]) end table.insert(sub, clone(tmp)) for j=#parseCards,i,-1 do table.remove(parseCards, j) end else if i == 2 then table.insert(sub, clone(parseCards)) end end end end -- 内部数据从小到大排序 for i, v in ipairs(sub) do table.sort(v, PokerUtil.sortOrder) end -- 外部数据从小到大排序 table.sort(sub, function(a, b) return a[1] < b[1] end) return sub end -- 获取顺子(返回可以组成顺子牌)(返回的是最多的顺子useLong = fasle) function newPokerUtil:getSubLineEx(cards) if not cards then return {} end -- 是否长度优先 --[[ 长度优先:123455667890 先提示5 多个顺子优先:123455667890 先提示1 ]] local useLong = false -- 长度优先,关闭则是多个顺子优先 -- 先移除手牌中为2的值 local temp = clone(cards) local sub = {} for i = #temp, 1, -1 do local value = self:getCardValue(temp[i]) local tag = false for _, v in ipairs(sub) do local v1 = self:getCardValue(v[#v] - 1) local v2 = value if v1 == v2 then table.insert(v, temp[i]) tag = true if not useLong then break end end end if not tag then table.insert(sub, 1, {}) table.insert(sub[1], temp[i]) end end -- 将所有顺子判断,如果有其中一条顺子包含另一条顺子,则删除短的哪条 local t = clone(sub) table.sort(t, function(a, b) return #a < #b end) if useLong then local temp = {} local tag = true for i = 1, #t do tag = true for j = i + 1, #t do local str1 = table.concat(t[i]) -- 短的 local str2 = table.concat(t[j]) -- 长的 if string.find(str2, str1) then -- 因为是有序的顺子,所以可以这么判断,不然只能双循环一个值一个值判断 tag = false break end end if tag then table.insert(temp, t[i]) end end sub = temp end for i, v in ipairs(sub) do table.sort(v, PokerUtil.sortOrder_By_PokerValue) end return sub end --[[ 参数:手牌(标准值),顺子牌(标准值) 返回: 1.手牌中与顺子相同的值, (有序的key,value对应一个牌值) 2.手牌中与顺子不相同的值, (有序的key,value对应个数表) 3.表1中移除顺子,剩下的值, (有序的key,value对应个数表) ]] function newPokerUtil:parseShunZi(handCards, szCards) local cbsCard_Sinlge = {} -- 同顺表(单个) local cbsCard_Value = {} -- 同顺表(根据数值分类) local cnbsCard = {} -- 非顺表 local lcbsCard = {} -- 移除同顺表顺子的剩下值 local wi = false -- 一个标记,表示是否要插入到同顺表里面 willInsert for i, val in ipairs(handCards) do wi = false for _, v in ipairs(szCards) do if self:getCardValue(v) == self:getCardValue(val) then -- 判断值相同 wi = true table.insert(cbsCard_Sinlge, val) break -- 跳出循环,轮到下一个手牌 end end if not wi then table.insert(cnbsCard, handCards[i]) end end local t = clone(cbsCard_Sinlge) for _, v in ipairs(szCards) do for i, val in ipairs(t) do if val == v then table.remove(t, i) break end end end -- 把相同的值合在一起 lcbsCard = t cbsCard_Value = cbsCard_Sinlge table.sort(cbsCard_Value, PokerUtil.sortOrder_By_PokerValue) table.sort(cnbsCard, PokerUtil.sortOrder_By_PokerValue) table.sort(lcbsCard, PokerUtil.sortOrder_By_PokerValue) return cbsCard_Value, cnbsCard, lcbsCard end -- 选择的牌的处理(飞机,连对,顺子) function newPokerUtil:getCardInSelectCard(selectCards) if not isResetSelectCard then return selectCards end local selectCards = clone(selectCards) local valueList, valueCard = self:parseCard(selectCards) ----------------------------------------------------------------------------- -- <<飞机>> -- 将非王牌,带2的牌,炸弹牌,组合在一起(用于判断连续值) -- 移除手牌中的炸弹 local temp = {} for _, v in pairs(valueCard) do if #v == 3 then -- 插入刚好等于3张的牌 table.insert(temp, v[1]) -- 插入一个值即可,用于检测飞机 end end -- 移除手牌中的王牌和2 local nt = self:removeValue_Joker_And_2(temp) local t = self:getMinInLine(nt, PokerUtil.Less_Plane / 3) local sameTable = self:getSameValueByVal(selectCards, t, 3) if #sameTable > 0 then print('jxjx 滑牌选牌,返回飞机') -- 滑动飞机牌时,若带了其他两张牌,则一起弹起(斗地主2.0更新) local totalCardCount = #sameTable + #sameTable/3 if #selectCards == totalCardCount then return selectCards end return sameTable end ----------------------------------------------------------------------------- -- <<连对>> local temp = {} for _, v in pairs(valueCard) do if #v > 1 and #v < 4 then -- 插入大于1张,非炸弹的牌 table.insert(temp, v[1]) -- 插入一个值即可,用于检测连对 end end -- 移除手牌中的王牌和2 local nt = self:removeValue_Joker_And_2(temp) local t = self:getMinInLine(nt, PokerUtil.Less_Lian_Dui / 2) local sameTable = self:getSameValueByVal(selectCards, t, 2) if #sameTable > 0 then print('jxjx 滑牌选牌,返回连对') return sameTable end ----------------------------------------------------------------------------- -- <<顺子>> local temp = {} for _, v in pairs(valueCard) do if #v ~= 4 then -- 插入非炸弹的牌 table.insert(temp, v[1]) -- 插入一个值即可,用于检测顺子 end end -- 移除手牌中的王牌和2 local nt = self:removeValue_Joker_And_2(temp) local t = self:getMinInLine(nt, PokerUtil.Less_Line) local sameTable = self:getSameValueByVal(selectCards, t, 1) if #sameTable > 0 then print('jxjx 滑牌选牌,返回顺子') return sameTable end return selectCards end -- 获取最大长度的连续值表,长度最低是lessLength function newPokerUtil:getMaxLengthInLine(pCards, lessLength) local subLines = self:getSubLine(pCards) local lessLength = lessLength or 1 local maxLengthIndex = 0 -- 最大长度的index local maxLength = 0 -- 最大长度 for i, v in ipairs(subLines) do if #v > maxLength and #v >= lessLength then maxLength = #v maxLengthIndex = i end end if maxLengthIndex > 0 then return subLines[maxLengthIndex] else return {} end end -- 获取包含最小值的连续值表,长度最低是lessLength function newPokerUtil:getMinInLine(pCards, lessLength) local subLines = self:getSubLine(pCards) for i = #subLines, 1, -1 do if #subLines[i] < lessLength then table.remove(subLines, i) end end if next(subLines) then return subLines[1] else return {} end end -- sCards中,取tCards获得同样具体牌值的数值表 maxCount 单个数值最大个数 function newPokerUtil:getSameValueByVal( sCards, tCards, maxCount) local temp = {} for _, t in ipairs(tCards) do local count = 0 for _, s in ipairs(sCards) do local tVal = self:getCardValue(t) local sVal = self:getCardValue(s) if tVal == sVal and count < maxCount then table.insert(temp, s) count = count + 1 end end end return temp end -- 移除王牌和2 function newPokerUtil:removeValue_Joker_And_2(cards) if not cards then return {} end local t = self:changeCardValue_Standard_To_Specific(cards) -- 返回的是与cards顺序一致的具体牌值表 local nt = {} for i, value in ipairs(t) do if value ~= Value_2 and value ~= Value_Joker_Little and value ~= Value_Joker_Big then table.insert(nt, cards[i]) end end table.sort(nt, PokerUtil.sortOrder_By_PokerValue) return nt end return newPokerUtil