--[[经典16张 0x01, 0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, //黑桃 0x12, 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, //红桃 0x22, 0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d, //梅花 0x32, 0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d, //方块 ]] --[[15张 0x01,0x02, 0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, //黑桃 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, //红桃 0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d, //梅花 0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d, //方块 ]] local GUI_VAL = 0x0e --鬼的牌值 local ER_VAL = 0x0d --2的牌值 local A_VAL = 0x0c --A的牌值 function pokerParse( card ) local tp = math.floor(card/16) local val = card%16 -- print("---------tp : "..tp.." val : "..val) return tp, val end function pokerPng( card ) local tp , val = pokerParse(card) return string.format("pdk_cards_%d_%d.png", tp, val) end -- 对牌进行排序 function pokerSortPdkCards( cards ) local tmp = {} for _,card in ipairs(cards) do local tp, val = pokerParse(card) table.insert(tmp, {tp=tp, val=val, cid=card}) end table.sort(tmp, function (a, b) if a.val == b.val then return a.tp < b.tp else return a.val > b.val end end) return tmp end -- 牌的排序函数 local function sortCardsFunc( a, b ) return a.val < b.val end -- 获取剩余牌(parseCards) local function getLeft( src, target ) local have = {} for _,v in ipairs(target) do have[tostring(v.cid)] = v end local left = {} for _,v in pairs(src) do if not have[tostring(v.cid)] then table.insert(left, v) end end return left end local hejiangPokerUtil = class("hejiangPokerUtil") -- 所有传入参数均为{tp, val, cid}结构集合 function hejiangPokerUtil:ctor(param) if param.isChai==nil then param.isChai = false end if param.isFAT==nil then--four and three param.isFAT = false end self.isChai = param.isChai self.isFAT = param.isFAT end -- 对牌组按照value进行分类 function hejiangPokerUtil:classifyCards( cards ) local tmpCards = clone(cards) local result = {} for _,v in pairs(tmpCards) do if not result[tostring(v.val)] then result[tostring(v.val)] = {} end table.insert(result[tostring(v.val)], v) end local tmp = {} for _,v in pairs(result) do table.insert(tmp, v) end return tmp end -- 对牌组按照value进行分类 返回key-value结构 function hejiangPokerUtil:classifyCardsEx( cards ) local tmpCards = clone(cards) local result = {} for _,v in pairs(tmpCards) do if not result[tostring(v.val)] then result[tostring(v.val)] = {} end table.insert(result[tostring(v.val)], v) end return result end -- 检测牌的点数是否相同 function hejiangPokerUtil:checkSameVal( cards ) if cards and type(cards)~="table" then return false end if #cards <= 0 then return false end local targetVal = cards[1].val local result = true for _,v in pairs(cards) do if v.val ~= targetVal then result = false break end end return result end -- 检测牌组中是否带2 function hejiangPokerUtil:checkOwnEr(cards) if cards and type(cards)~="table" then return false end local result = false for _,v in pairs(cards) do if v.val == ER_VAL then result = true break end end return result end -- 检测牌组中是否包含某一张牌 function hejiangPokerUtil:checkOwnX( cards, card) if cards and type(cards)~="table" then return false end local result = false for _,v in pairs(cards) do if v.val == card.val then result = true break end end return result end -- 将牌解析成{tp, val ,cid}牌组 function hejiangPokerUtil:parseCards( cards ) local result = {} for _,v in ipairs(cards) do local tp, val = pokerParse(v) table.insert(result, {tp=tp, val=val, cid=v}) end return result end -- 从分类牌组中查找到指定数量牌的集合 function hejiangPokerUtil:getSameNum( classify, num ) local result = {} for _,v in pairs(classify) do if #v == num then table.insert(result, v) end end return result end -- 从分类牌组中查找到指定数量牌的集合,包括大于num的牌组 function hejiangPokerUtil:getSameNumEx( classify, num ) local result = {} for _,v in pairs(classify) do if #v >= num then table.insert(result, v) end end return result end -- 从分类牌组中查找到指定数量牌的集合,包括大于num的牌组 key-val存储 function hejiangPokerUtil:getSameNumExEx( classify, num ) local result = {} for k,v in pairs(classify) do if #v >= num then result[tostring(k)] = v end end return result end -------------------------------------------------------------------------------------- -- 检测牌型 -------------------------------------------------------------------------------------- -- 检测是否是对子 function hejiangPokerUtil:checkDui( cards ) if cards and type(cards)~="table" then return false end if #cards ~= 2 then return false end return self:checkSameVal(cards) end -- 检测3不带 function hejiangPokerUtil:checkThree( cards ) if cards and type(cards)~="table" then return false end if #cards ~= 3 then return false end return self:checkSameVal(cards) end -- 检测4张 function hejiangPokerUtil:checkFour( cards ) if cards and type(cards)~="table" then return false end if #cards ~= 4 then return false end return self:checkSameVal(cards) end -- 检测是否顺子,至少5张 function hejiangPokerUtil:checkShunzi( cards ) local LessNum = 5 if cards and type(cards)~="table" then return false end if #cards < LessNum then return false end--牌中是否带2 或者牌张数不够 return self:checkSZ(cards) end -- 检测顺子,至少两张 function hejiangPokerUtil:checkSZ(cards) local LessNum = 2 if cards and type(cards)~="table" then return false end if #cards < LessNum then return false end--牌中是否带2 或者牌张数不够 local tmpCards = clone(cards) table.sort(tmpCards, sortCardsFunc) local idx = 1 local result = true local classify = self:classifyCards(tmpCards) local isHaveGui,guiNum = self:checkHaveGui(classify) local isHaveDui = false for i,v in pairs(classify) do if #v >=2 then isHaveDui = true break end end local targetNum = #tmpCards if tmpCards[targetNum-1].val == targetNum and tmpCards[targetNum].val == 14 and (not isHaveDui) then return true elseif tmpCards[targetNum-2].val == targetNum-1 and tmpCards[targetNum-1].val == 13 and tmpCards[targetNum].val == 14 and (not isHaveDui) then return true end for i=2,#tmpCards do if tmpCards[idx].val == 12 and tmpCards[idx].val+1 == tmpCards[i].val and tmpCards[1].val == 1 then idx = idx + 1 elseif tmpCards[idx].val == 13 and tmpCards[1].val == 1 then idx = idx + 1 elseif tmpCards[idx].val == 3 and tmpCards[idx].val+9 == tmpCards[i].val then idx = idx + 1 --[[elseif tmpCards[i].val == 13 and tmpCards[1].val ~= 1 then local needgui = tmpCards[1].val-1 if guiNum >= needgui then guiNum = guiNum - needgui idx = idx + 1 else result = false break end--]] elseif tmpCards[idx].val+1 ~= tmpCards[i].val and (tmpCards[i].val ~= 14) then local needgui = tmpCards[i].val - tmpCards[idx].val-1 if tmpCards[i].val == 13 and tmpCards[1].val == 1 then idx = idx + 1 elseif tmpCards[i].val == 12 and tmpCards[i+1] and tmpCards[i+1].val == 13 then if tmpCards[1].val == 1 then idx = idx + 1 else local needgui = tmpCards[1].val - 1 if guiNum >= needgui then guiNum = guiNum - needgui idx = idx + 1 else result = false break end end elseif tmpCards[i].val == 12 and tmpCards[1].val == 1 and guiNum > 0 then guiNum = guiNum - 1 idx = idx + 1 elseif needgui < 0 then --有相等的牌,必定不是顺子 result = false break elseif guiNum >= needgui then guiNum = guiNum - needgui idx = idx + 1 else result = false break end else idx = idx + 1 end end return result end -- 检测连对 function hejiangPokerUtil:checkLianDui(cards) local LessNum = 4 if cards and type(cards)~="table" then return false end if #cards < LessNum or #cards%2~=0 then return false end--牌中是否带2 或者牌张数不够 local tmpCards = clone(cards) local yclassify = self:classifyCards(tmpCards) local classify = self:classifyCardsEx(tmpCards) --[[if #classify*2 ~= #tmpCards then return false end -- 确保每组牌四两张 for _,v in pairs(classify) do if #v~=2 then return false end end--]] table.sort(tmpCards, sortCardsFunc) local tmp = {} --[[for i=1,#tmpCards do if i%2==1 then table.insert(tmp, tmpCards[i]) end end--]] for i,v in pairs(classify) do table.insert(tmp, v[1]) end return self:checkSZ(tmp) end -- 检测三带一(最后四张才能3带一?) function hejiangPokerUtil:check3And1( cards ) local LessNum = 4 if cards and type(cards)~="table" then return false end if #cards ~= LessNum then return false end-- 或者牌张数不够 local classify = self:classifyCards(cards) local own3 = false for _,v in ipairs(classify) do if #v == 3 then own3 = true break end end return own3 end -- 检测三带二 function hejiangPokerUtil:check3And2( cards ) local LessNum = 5 if cards and type(cards)~="table" then return false end if #cards ~= LessNum then return false end--牌张数不够 local classify = self:classifyCards(cards) local isHaveGui,guiNum = self:checkHaveGui(classify) local own3 = false for _,v in ipairs(classify) do if #v == 3 or (#v == 2 and guiNum == 1) or (guiNum == 2) then own3 = true break end end return own3 end -- 检测四带一 function hejiangPokerUtil:check4And1(cards) local LessNum = 5 if cards and type(cards)~="table" then return false end if #cards ~= LessNum then return false end--或者牌张数不够 local classify = self:classifyCards(cards) local own4 = false for _,v in ipairs(classify) do if #v == 4 then own4 = true break end end return own4 end -- 检测四带3 function hejiangPokerUtil:check4And3( cards ) local LessNum = 7 if cards and type(cards)~="table" then return false end if #cards ~= LessNum then return false end--或者牌张数不够 local classify = self:classifyCards(cards) local own4 = false for _,v in ipairs(classify) do if #v == 4 then own4 = true break end end return own4 end -- 检测 炸弹 function hejiangPokerUtil:checkBomb( cards ) return self:checkFour(cards) end -- 检测 是否有鬼牌 cards传已经解析过的牌 function hejiangPokerUtil:checkHaveGui( cards )--返回传递的牌里是否有鬼,和鬼的张数 local ishaveGui = false local guiNum = 0 for i,v in pairs(cards) do if v[1].val == 14 then ishaveGui = true guiNum = #v break end end return ishaveGui,guiNum end -- 检测 是否有鬼牌 cards没有解析过 function hejiangPokerUtil:checkHaveGui1( cards )--返回传递的牌里是否有鬼,和鬼的张数 local ishaveGui = false local guiNum = 0 local parseData = {} for _,v in ipairs(cards) do local tp, val = pokerParse(v) table.insert(parseData, {tp=tp, val=val, cid=v}) end local tCards = self:classifyCards(parseData) for i,v in pairs(tCards) do if v[1].val == 14 then ishaveGui = true guiNum = #v break end end return ishaveGui,guiNum end -- 检测飞机555666 555666777等+同等数量的对牌,或者双倍单牌 function hejiangPokerUtil:checkPlan( cards, shaoDai ) shaoDai = shaoDai or false local LessNum = 6 -- 6+4 9+6 local cNum = #cards -- print("-------------------------checkPlan num: "..cNum) if not shaoDai then--是否少带 if cNum~=6 and cNum~=10 and cNum~=15 then return false end end if cards and type(cards)~="table" then return false end if #cards < LessNum then return false end--或者牌张数不够 local classify = self:classifyCards(cards) local result = false local ThreeCount = 0 local TowCount = 0 local checkShun = {} local isHaveGui,guiNum = self:checkHaveGui(classify) if self.isChai then--区分炸弹是否可拆 for _,v in ipairs(classify) do if #v >= 3 then ThreeCount = ThreeCount + 1 table.insert(checkShun, v[1]) end end else for _,v in ipairs(classify) do if #v == 3 then ThreeCount = ThreeCount + 1 table.insert(checkShun, v[1]) end if #v == 2 then TowCount = TowCount + 1 end end if guiNum == 1 and ThreeCount == 1 and TowCount >= 1 then return true elseif guiNum == 2 and (ThreeCount == 1 or TowCount >= 2) then return true elseif guiNum == 3 and (ThreeCount == 1 or TowCount >= 1) then return true end end if ThreeCount <= 1 then return false end if #checkShun >= 2 then table.sort(checkShun, sortCardsFunc) end -- print("three count : " ..ThreeCount) if ThreeCount == 2 then result = (self:checkSZ(checkShun) and cNum<=10) elseif ThreeCount == 3 then result = (self:checkSZ(checkShun) and cNum<=15) if not result then--三张四张作为翅膀带出去 local firstTwo = {checkShun[1], checkShun[2]} result = (self:checkSZ(firstTwo) and cNum<=10) if not result then local lastTwo = {checkShun[2], checkShun[3]} result = (self:checkSZ(lastTwo) and cNum<=10) end end else local maxLen = 1 local bCount = 1 local i, j=1, 2 for i=1,#checkShun-1 do if checkShun[i].val + 1 == checkShun[j].val then bCount = bCount + 1 if bCount>maxLen then maxLen = bCount end else if bCount>maxLen then maxLen = bCount end bCount = 1 end i=i+1 j=j+1 end result = maxLen>=3 and cNum<=15 end return result end --牌型 local OUT_TYPE = { SINGLE_CARD = 1, --//单牌 DUI_ZI = 2, --//对子 THREE = 3, --三个 THREE_AND_TWO = 4, --//三带二张 THREE_AND_DUI = 5, --//三带一对 SHUN_ZI = 6, --//顺子 LIAN_DUI = 7, --//连对(至少2连对) AIRPLANE = 8, --//飞机 AIRPLANE_TOW = 9, --//飞机带散牌 AIRPLANE_DUI = 10, --//飞机带对 BOMB = 11, --//炸弹 THREE_AND_ONE = 80, --三带一(最后一首才会出现) NONE = 100, --不适用类型 } local TYPE_STRING = { [OUT_TYPE.SINGLE_CARD] = "单牌", --//单牌 [OUT_TYPE.DUI_ZI] = "对子", --//对子 [OUT_TYPE.THREE] = "三不带", --//三个 [OUT_TYPE.THREE_AND_TWO] = "三带二", --//三带二 [OUT_TYPE.THREE_AND_DUI] = "三带一对", --//三带一对 [OUT_TYPE.SHUN_ZI] = "顺子", --//顺子 [OUT_TYPE.LIAN_DUI] = "连对", --//连对 [OUT_TYPE.AIRPLANE] = "飞机", --//飞机 [OUT_TYPE.AIRPLANE_TOW] = "飞机", --//飞机 [OUT_TYPE.AIRPLANE_DUI] = "飞机", --//飞机 [OUT_TYPE.BOMB] = "炸弹", --//炸弹 [OUT_TYPE.NONE] = "错误类型", --//错误类型 } hejiangPokerUtil.OUT_TYPE = OUT_TYPE function hejiangPokerUtil:getTypeString( tp ) return TYPE_STRING[tp] or "TP错误" end --获取一张服务器下发的牌值装换成客户端用到的牌值 function hejiangPokerUtil:getCardValue( card ) local tp, val = pokerParse(card) return val end --[[-- 检测牌型 function hejiangPokerUtil:checkType( cards ) local cNum = #cards if cNum <= 0 then return OUT_TYPE.NONE end if cNum == 1 then return OUT_TYPE.SINGLE_CARD end local parseData = {} for _,v in ipairs(cards) do local tp, val = pokerParse(v) table.insert(parseData, {tp=tp, val=val, cid=v}) end if #parseData >=2 then table.sort(parseData, sortCardsFunc) end local tt = {} local ttt = {} local tpCardinfo = {} local classify = self:classifyCardsEx(parseData) local isHaveGui,guiNum = self:checkHaveGui(classify) for i,v in pairs(parseData) do if v.val ~= GUI_VAL then table.insert(tt,v.val) table.insert(ttt,v) end end local function tsort(a,b) return a > b end table.sort(tt, tsort) table.sort(ttt, sortCardsFunc) if (cNum+guiNum < 3) then if (tt[1] == tt[cNum]) then if cNum+guiNum == 1 then return OUT_TYPE.SINGLE_CARD elseif cNum+guiNum == 2 then return OUT_TYPE.DUI_ZI end end elseif (tt[1] == tt[cNum]) then if cNum+guiNum == 3 then return OUT_TYPE.THREE elseif cNum+guiNum == 4 then return OUT_TYPE.BOMB end else local a = {} for i=1,4 do a[i] = {} end local valueList = {} for k,v in pairs(cards) do local value = self:getCardValue(v) valueList[value] = valueList[value] or 0 valueList[value] = valueList[value] + 1 end for k,v in pairs(valueList) do table.insert(a[v],k) end if self:checkPlan(parseData) then return OUT_TYPE.AIRPLANE elseif self:checkShunzi(parseData) then return OUT_TYPE.SHUN_ZI end if cNum%2 == 0 then--偶数张 (三带一 连对 炸弹) if self:checkLianDui(parseData) then return OUT_TYPE.LIAN_DUI elseif self:checkBomb(parseData) then return OUT_TYPE.BOMB else return OUT_TYPE.NONE end else--奇数张 (三带二 顺子 四带一) if self:check3And2(parseData) then return OUT_TYPE.THREE_AND_TWO elseif self:checkShunzi(parseData) then return OUT_TYPE.SHUN_ZI else return OUT_TYPE.NONE end end end end--]] --[[-- 检测牌型 function hejiangPokerUtil:checkType( cards ) local cNum = #cards if cNum == 1 then return OUT_TYPE.SINGLE_CARD end local parseData = {} for _,v in ipairs(cards) do local tp, val = pokerParse(v) table.insert(parseData, {tp=tp, val=val, cid=v}) end if #parseData >=2 then table.sort(parseData, sortCardsFunc) end if cNum == 2 then if self:checkDui(parseData) then return OUT_TYPE.DUI_ZI else return OUT_TYPE.NONE end elseif cNum == 3 then if self:checkThree(parseData) then return OUT_TYPE.THREE end return OUT_TYPE.NONE else --顺子 飞机 if self:checkPlan(parseData) then if self:check4And3(parseData) and self.isFAT then return OUT_TYPE.FOUR_AND_THREE else return OUT_TYPE.AIRPLANE end elseif self:checkShunzi(parseData) then return OUT_TYPE.SHUN_ZI end if cNum%2 == 0 then--偶数张 (三带一 连对 炸弹) if self:check3And1(parseData) then return OUT_TYPE.THREE_AND_ONE elseif self:checkLianDui(parseData) then return OUT_TYPE.LIAN_DUI elseif self:checkBomb(parseData) then return OUT_TYPE.BOMB else return OUT_TYPE.NONE end else--奇数张 (三带二 顺子 四带一) if self:check3And2(parseData) then return OUT_TYPE.THREE_AND_TWO elseif self:checkShunzi(parseData) then return OUT_TYPE.SHUN_ZI elseif self:check4And1(parseData) then if self.isChai then--炸弹可拆则为3带2 return OUT_TYPE.THREE_AND_TWO else return OUT_TYPE.NONE--OUT_TYPE.FOUR_AND_ONE end elseif self:check4And3(parseData) then return OUT_TYPE.FOUR_AND_THREE else return OUT_TYPE.NONE end end end end--]] function hejiangPokerUtil:getGuiByClassifyCards( classify ) for valStr,cds in pairs(classify) do if tonumber(valStr) == GUI_VAL then return cds end end return {} end -------------------------------------------------------------------------------------- -- 牌型提示 -------------------------------------------------------------------------------------- --单张提示 cards@{{tp=, val=, cid=,}...} target@{tp=, val=, cid=,} -- fixed function hejiangPokerUtil:getSingleTip( cards, target ) local target = target[1] if target.val == ER_VAL or target.val == GUI_VAL then return nil end local classify = self:classifyCardsEx(cards) local singles = {} local twos = {} local threes = {} local fours = {} for valStr,cds in pairs(classify) do if tonumber(valStr) > target.val or tonumber(valStr)==ER_VAL or tonumber(valStr)==GUI_VAL then if #cds == 1 then table.insert(singles, cds[1]) elseif #cds == 2 then table.insert(twos, cds[1]) table.insert(twos, cds[2]) elseif #cds == 3 then table.insert(threes, cds[1]) table.insert(threes, cds[2]) table.insert(threes, cds[3]) elseif #cds == 4 then--炸弹是否可拆决定 if self.isChai then table.insert(threes, cds[1]) table.insert(threes, cds[2]) table.insert(threes, cds[3]) table.insert(threes, cds[4]) end end end end if #singles>=2 then --降序排列 table.sort(singles, function ( a, b ) return a.val > b.val end) end if #twos>=2 then --升序排列 table.sort(twos, function ( a, b ) return a.val < b.val end) end if #threes>=2 then --升序排列 table.sort(threes, function ( a, b ) return a.val < b.val end) end for _,v in ipairs(twos) do table.insert(singles, 1, v) end for _,v in ipairs(threes) do table.insert(singles, 1, v) end return singles end -- 对子提示cards@{{tp=, val=, cid=,}...} targets@{{tp=, val=, cid=,},{tp=, val=, cid=,}} -- fixed function hejiangPokerUtil:getDoubleTip( cards, targets ) local target = targets[1] if target.val >= ER_VAL then return nil end local classify = self:classifyCardsEx(cards) local isHaveGui,guiNum = self:checkHaveGui(classify) local sigle = {} local twos = {} local threes = {} local fours = {} local gui = self:getGuiByClassifyCards(classify) for valStr,cds in pairs(classify) do if tonumber(valStr) > target.val and #cds>=2 and tonumber(valStr) ~= GUI_VAL then if #cds == 2 then table.insert(twos, cds) elseif #cds == 3 then table.insert(threes, clone({cds[1], cds[2]})) elseif #cds == 4 then--炸弹是否可拆决定 if self.isChai then table.insert(fours, clone({cds[1], cds[2]})) end end else if guiNum > 0 and #gui > 0 and tonumber(valStr) > target.val and tonumber(valStr) ~= GUI_VAL then table.insert(sigle, clone({cds[1], gui[1]})) end end end if #twos>=2 then --降序排列 table.sort(twos, function ( a, b ) return a[1].val > b[1].val end) end if #sigle>=2 then --升序排列 table.sort(sigle, function ( a, b ) return a[1].val < b[1].val end) end if #threes>=2 then --升序排列 table.sort(threes, function ( a, b ) return a[1].val < b[1].val end) end if #fours>=2 then --升序排列 table.sort(fours, function ( a, b ) return a[1].val < b[1].val end) end for _,v in ipairs(sigle) do table.insert(twos, 1, v) end for _,v in ipairs(threes) do table.insert(twos, 1, v) end for _,v in pairs(fours) do table.insert(twos, 1, v) end return twos end -- 三张提示 -- fixed function hejiangPokerUtil:getThreeTip( cards, targets ) local minVal = self:getCardsMin(targets,OUT_TYPE.THREE) local targetNum = #targets local cclassify = self:classifyCardsEx(cards) local isHaveGui,guiNum = self:checkHaveGui(cclassify) local gui = self:getGuiByClassifyCards(cclassify) if #cards < 3 then return end local valueList = {} local cardList = {} for k,v in ipairs(cards) do local value = v.val if v ~= GUI_VAL then valueList[value] = valueList[value] or 0 valueList[value] = valueList[value] + 1 cardList[value] = cardList[value] or {} table.insert(cardList[value], v) end end local result ={} for i = minVal + 1, 13 do local _tpIdx = i; local _tpCount = 0; local _tpReplace2 = {} local tpNotAllLai = false; local _haveLai = guiNum; valueList[_tpIdx] = valueList[_tpIdx] or 0; if valueList[_tpIdx] + _haveLai >= 3 then local _tpNum = 3 - valueList[_tpIdx]; _tpNum = _tpNum >= 0 and _tpNum or 0; local lai = guiNum - _haveLai + 1 for p = 1, _tpNum do table.insert(_tpReplace2,gui[lai]) lai = lai + 1 end for _m = 1, 3 - _tpNum do table.insert(_tpReplace2, cardList[_tpIdx][_m]) tpNotAllLai = true; end _haveLai = _haveLai - _tpNum; _tpCount = _tpCount + 3 _tpIdx = _tpIdx + 1 if _tpCount == 3 then table.insert(result,_tpReplace2) end end end; local resultex = {} if #result > 0 then for i = #result,1,-1 do table.insert(resultex,result[i]) end end return resultex --[[if #cards < #targets then return nil end local tclassify = self:classifyCards(targets) local ttarget1 = self:getSameNum(tclassify, 3) local target if next(ttarget1) ~= nil then target = ttarget1[1][1] else local ttarget2 = self:getSameNum(tclassify, 2) if guiNum == 1 then target = ttarget2[1][1] elseif guiNum == 2 then local ttarget3 = self:getSameNum(tclassify, 1) target = ttarget3[1][1] elseif guiNum == 3 then target = {["tp"] = 0,["cid"] = 14,["val"] = 14} end end local classify = self:classifyCardsEx(cards) local isHaveGui,guiNum = self:checkHaveGui(classify) local threes = {} local singles = {} local twos = {} local fours = {} local gui = self:getGuiByClassifyCards(classify) for valStr,cds in pairs(classify) do if tonumber(valStr) > target.val and #cds>=3 then if #cds == 3 then table.insert(threes, cds) elseif #cds == 4 then--炸弹是否可拆决定 --if self.isChai then table.insert(threes, {cds[1], cds[2], cds[3]}) --end end else if #cds == 1 then table.insert(singles, cds[1]) if guiNum > 1 and #gui > 1 and tonumber(valStr) > target.val and tonumber(valStr) ~= GUI_VAL then table.insert(threes, {cds[1], gui[1], gui[2]}) end elseif #cds == 2 then table.insert(twos, cds) if guiNum > 0 and #gui > 0 and tonumber(valStr) > target.val and tonumber(valStr) ~= GUI_VAL then table.insert(threes, {cds[1], cds[2], gui[1]}) end elseif #cds == 4 then table.insert(fours, cds) end end end if #threes <= 0 then return nil end if #threes>=2 then --降序排列 table.sort(threes, function ( a, b ) return a[1].val > b[1].val end) end return threes--]] end -- 三带二提示 -- fixed function hejiangPokerUtil:getThreeAnd2Tip( cards, targets ) local minVal = self:getCardsMin(targets,OUT_TYPE.THREE_AND_TWO) local targetNum = #targets local cclassify = self:classifyCardsEx(cards) local isHaveGui,guiNum = self:checkHaveGui(cclassify) local gui = self:getGuiByClassifyCards(cclassify) if #cards < 5 then return end local valueList = {} local cardList = {} for k,v in ipairs(cards) do local value = v.val if v ~= GUI_VAL then valueList[value] = valueList[value] or 0 valueList[value] = valueList[value] + 1 cardList[value] = cardList[value] or {} table.insert(cardList[value], v) end end local result ={} for i = minVal + 1, 13 do local _tpIdx = i; local _tpCount = 0; local _tpReplace2 = {} local tpNotAllLai = false; local _haveLai = guiNum; valueList[_tpIdx] = valueList[_tpIdx] or 0; if valueList[_tpIdx] + _haveLai >= 3 then local _tpNum = 3 - valueList[_tpIdx]; _tpNum = _tpNum >= 0 and _tpNum or 0; local lai = guiNum - _haveLai + 1 for p = 1, _tpNum do table.insert(_tpReplace2,gui[lai]) lai = lai + 1 end for _m = 1, 3 - _tpNum do table.insert(_tpReplace2, cardList[_tpIdx][_m]) tpNotAllLai = true; end _haveLai = _haveLai - _tpNum; _tpCount = _tpCount + 3 _tpIdx = _tpIdx + 1 if _tpCount == 3 then table.insert(result,_tpReplace2) end end end; local resultex = {} if #result > 0 then for i = #result,1,-1 do table.insert(resultex,result[i]) end end return resultex end -- 三带一提示 not fixed function hejiangPokerUtil:getThreeAnd1Tip(cards, targets) local tclassify = self:classifyCards(targets) local target = self:getSameNum(tclassify, 3) local cclassify = self:classifyCards(cards) local tmps = self:getSameNum(cclassify, 3) if #tmps == 0 then return nil end local result = {} for _,v in ipairs(tmps) do if v[1].val > target[1].val then table.insert(result, v) end end local tmpOnes = self:getSameNum(cclassify, 1) local ones = {} for _,v in pairs(tmpOnes) do table.insert(ones, v[1]) end local twos = self:getSameNum(cclassify, 2) for _,v in ipairs(twos) do table.insert(ones, v[1]) table.insert(ones, v[2]) end if #ones >=1 then return {result, ones[1]} else return nil end end -- 四带一提示 function hejiangPokerUtil:getFourAnd1( cards, targets ) local tclassify = self:classifyCards(targets) local target = self:getSameNum(tclassify, 4) local cclassify = self:classifyCards(cards) local tmps = self:getSameNum(cclassify, 4) if #tmps == 0 then return nil end local result = {} for _,v in ipairs(tmps) do if v[1].val > target[1].val then table.insert(result, v) end end local tmpOnes = self:getSameNum(cclassify, 1) local ones = {} for _,v in pairs(tmpOnes) do table.insert(ones, v[1]) end local twos = self:getSameNum(cclassify, 2) for _,v in ipairs(twos) do table.insert(ones, v[1]) table.insert(ones, v[2]) end local threes = self:getSameNum(cclassify, 3) for _,v in ipairs(threes) do table.insert(ones, v[1]) table.insert(ones, v[2]) table.insert(ones, v[3]) end if #ones >= 1 then return {result, ones[1]} else--牌不够数 return nil end end -- 四带三提示(前提是牌足够) -- fixed function hejiangPokerUtil:getFourAnd3( cards, targets ) if #cards < #targets then return nil end local tclassify = self:classifyCards(targets) local target = self:getSameNum(tclassify, 4)[1][1] local classify = self:classifyCardsEx(cards) local threes = {} local singles = {} local twos = {} local fours = {} local targetFours = {} for valStr,cds in pairs(classify) do if tonumber(valStr) > target.val and #cds>=4 then table.insert(targetFours, cds) else if #cds == 1 then table.insert(singles, cds[1]) elseif #cds == 2 then table.insert(twos, cds) elseif #cds == 3 then table.insert(threes, cds) elseif #cds == 4 then table.insert(fours, cds) end end end if #threes <= 0 then return nil end if #targetFours>=2 then --降序排列 table.sort(targetFours, function ( a, b ) return a[1].val > b[1].val end) end if #singles>=2 then --升序排列 table.sort(singles, function ( a, b ) return a.val < b.val end) end if #twos>=2 then --升序排列 table.sort(twos, function ( a, b ) return a[1].val < b[1].val end) end if #threes>=2 then --升序排列 table.sort(threes, function ( a, b ) return a[1].val < b[1].val end) end for _,v in ipairs(twos) do table.insert(singles, v[1]) table.insert(singles, v[2]) end for _,v in ipairs(threes) do table.insert(singles, v[1]) table.insert(singles, v[2]) table.insert(singles, v[3]) end local result = {} if #targetFours==1 then if #singles >= 3 then table.insert(targetFours[1], singles[1]) table.insert(targetFours[1], singles[2]) table.insert(targetFours[1], singles[3]) table.insert(result, targetFours[1]) return result else return nil end else if #singles >= 3 then for _,v in ipairs(targetFours) do local cv = clone(v) table.insert(v, singles[1]) table.insert(v, singles[2]) table.insert(v, singles[3]) table.insert(result, cv) end return result else--多个四张,玩家自己拆牌 return targetFours end end end -- 检测牌组是否是连续的parseCards@sorted function hejiangPokerUtil:getSubLine( parseCards ) local sub = {} local tCards = self:classifyCards(parseCards) local isHaveGui,guiNum = self:checkHaveGui(tCards) for i=#parseCards,1,-1 do if parseCards[i] and parseCards[i-1] and parseCards[i].val ~= GUI_VAL and parseCards[i-1].val ~= GUI_VAL then if parseCards[i].val-1~=parseCards[i-1].val then if guiNum > 0 then guiNum = guiNum - 1 else --断开了 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 end else if i == 2 then table.insert(sub, clone(parseCards)) end end end end return sub end -- 从连续的牌组中获得顺子 function hejiangPokerUtil:getSzTip( hands, targets ) local tmpNoKey = clone(hands) table.sort(targets, sortCardsFunc) local minVal = targets[1].val local targetNum = #targets if #tmpNoKey= 1)) then break end; local _tpNum = 1 - valueList[_tpIdx]; _tpNum = _tpNum >= 0 and _tpNum or 0; local lai = guiNum - _haveLai + 1 for p = 1, _tpNum do table.insert(_tpReplace2,gui[lai]) lai = lai + 1 end for _m = 1, 1 - _tpNum do table.insert(_tpReplace2, cardList[_tpIdx][_m]) tpNotAllLai = true; end _haveLai = _haveLai - _tpNum; _tpCount = _tpCount + 1; _tpIdx = _tpIdx + 1 end if _tpCount == targetNum then table.insert(result,_tpReplace2) end end targetNum = targetNum - 1 valueList[13] = valueList[13] or 0 if isMinSz and (valueList[13] and valueList[13] > 0) then--找一下少一张牌的然后补2 for i = minVal + 1, 13 - targetNum do local _tpIdx = i; local _tpCount = 0; local _tpReplace2 = {} local tpNotAllLai = false; local _haveLai = guiNum; while _tpCount < #cards and _tpCount < targetNum and _tpIdx <= 12 do valueList[_tpIdx] = valueList[_tpIdx] or 0; if (not (valueList[_tpIdx] + _haveLai >= 1)) then break end; local _tpNum = 1 - valueList[_tpIdx]; _tpNum = _tpNum >= 0 and _tpNum or 0; local lai = guiNum - _haveLai + 1 for p = 1, _tpNum do table.insert(_tpReplace2,gui[lai]) lai = lai + 1 end for _m = 1, 1 - _tpNum do table.insert(_tpReplace2, cardList[_tpIdx][_m]) tpNotAllLai = true; end _haveLai = _haveLai - _tpNum; _tpCount = _tpCount + 1; _tpIdx = _tpIdx + 1 end if _tpCount == targetNum then if _tpReplace2[1].val == 1 or (_tpReplace2[targetNum-1].val == targetNum and _tpReplace2[targetNum].val == 14 ) then if cardList[13] and cardList[13][1] then table.insert(_tpReplace2, cardList[13][1])--补一张2 table.insert(result,_tpReplace2) end end end end end local resultex = {} if #result > 0 then for i = #result,1,-1 do table.insert(resultex,result[i]) end end return resultex end -- 获取连对提示 -- fixed function hejiangPokerUtil:getLianduiTip( cards, targets ) local minVal = self:getCardsMin(targets,OUT_TYPE.LIAN_DUI) local targetNum = #targets local cclassify = self:classifyCardsEx(cards) local isHaveGui,guiNum = self:checkHaveGui(cclassify) local gui = self:getGuiByClassifyCards(cclassify) local valueList = {} local cardList = {} for k,v in ipairs(cards) do local value = v.val if v ~= GUI_VAL then valueList[value] = valueList[value] or 0 valueList[value] = valueList[value] + 1 cardList[value] = cardList[value] or {} table.insert(cardList[value], v) end end local result ={} for i = minVal + 1, 14 - targetNum/2 do local _tpIdx = i; local _tpCount = 0; local _tpReplace2 = {} local tpNotAllLai = false; local _haveLai = guiNum; while _tpCount < #cards and _tpCount < targetNum and _tpIdx <= 12 do valueList[_tpIdx] = valueList[_tpIdx] or 0; if (not (valueList[_tpIdx] + _haveLai >= 2)) then break end; local _tpNum = 2 - valueList[_tpIdx]; _tpNum = _tpNum >= 0 and _tpNum or 0; local lai = guiNum - _haveLai + 1 for p = 1, _tpNum do table.insert(_tpReplace2,gui[lai]) lai = lai + 1 end for _m = 1, 2 - _tpNum do table.insert(_tpReplace2, cardList[_tpIdx][_m]) tpNotAllLai = true; end _haveLai = _haveLai - _tpNum; _tpCount = _tpCount + 2; _tpIdx = _tpIdx + 1 end if _tpCount == targetNum then table.insert(result,_tpReplace2) end end if minVal == 0 and targetNum == 4 then--如果出的是aa22,则加上2233的提示 local _haveLai = guiNum; local _tpCount = 0; local _tpReplace2 = {} valueList[13] = valueList[13] or 0; if (valueList[13] + _haveLai >= 2) then local _tpNum = 2 - valueList[13]; _tpNum = _tpNum >= 0 and _tpNum or 0; local lai = guiNum - _haveLai + 1 for p = 1, _tpNum do table.insert(_tpReplace2,gui[lai]) lai = lai + 1 end for _m = 1, 2 - _tpNum do table.insert(_tpReplace2, cardList[13][_m]) end _haveLai = _haveLai - _tpNum; _tpCount = _tpCount + 2; end valueList[1] = valueList[1] or 0; if (valueList[1] + _haveLai >= 2) then local _tpNum = 2 - valueList[1]; _tpNum = _tpNum >= 0 and _tpNum or 0; local lai = guiNum - _haveLai + 1 for p = 1, _tpNum do table.insert(_tpReplace2,gui[lai]) lai = lai + 1 end for _m = 1, 2 - _tpNum do table.insert(_tpReplace2, cardList[1][_m]) end _haveLai = _haveLai - _tpNum; _tpCount = _tpCount + 2; end if _tpCount == targetNum and valueList[13] > 0 and valueList[1] > 0 then table.insert(result,_tpReplace2) end end local resultex = {} if #result > 0 then for i = #result,1,-1 do table.insert(resultex,result[i]) end end return resultex end -- 获取炸弹提示 function hejiangPokerUtil:getBombTip( cards, targets ) local minVal = self:getCardsMin(targets,OUT_TYPE.BOMB) local cclassify = self:classifyCardsEx(cards) local isHaveGui,guiNum = self:checkHaveGui(cclassify) local gui = self:getGuiByClassifyCards(cclassify) local valueList = {} local cardList = {} for k,v in ipairs(cards) do local value =v.val if v ~= GUI_VAL then valueList[value] = valueList[value] or 0 valueList[value] = valueList[value] + 1 cardList[value] = cardList[value] or {} table.insert(cardList[value], v) end end local result ={} local _tpIndex = 1 for _i14 = minVal+1, 13 do local _tpReplace4 = {} valueList[_i14] = valueList[_i14] or 0 if (valueList[_i14] > 0 and valueList[_i14] + guiNum >= 4) then local _tpNum4 = 4 - valueList[_i14]; _tpNum4 = _tpNum4 >= 0 and _tpNum4 or 0 for _l4 = 1, _tpNum4 do table.insert(_tpReplace4,gui[_l4]) end for _m4 = 1, 4 - _tpNum4 do table.insert(_tpReplace4,cardList[_i14][_m4]) end table.insert(result,_tpReplace4) end end local resultex = {} if #result > 0 then for i = #result,1,-1 do table.insert(resultex,result[i]) end end return resultex end -- 获取牌组中所有炸弹 function hejiangPokerUtil:getAllBomb( cards, isAaaBomb ) local parseHands = self:parseCards(cards) local cclassify = self:classifyCardsEx(parseHands) local isHaveGui,guiNum = self:checkHaveGui(cclassify) local gui = self:getGuiByClassifyCards(cclassify) local valueList = {} local cardList = {} for k,v in ipairs(parseHands) do local value =v.val if v ~= GUI_VAL then valueList[value] = valueList[value] or 0 valueList[value] = valueList[value] + 1 cardList[value] = cardList[value] or {} table.insert(cardList[value], v) end end local result ={} local _tpIndex = 1 for _i14 = 1, 13 do local _tpReplace4 = {} valueList[_i14] = valueList[_i14] or 0 if (valueList[_i14] > 0 and valueList[_i14] + guiNum >= 4) then local _tpNum4 = 4 - valueList[_i14]; _tpNum4 = _tpNum4 >= 0 and _tpNum4 or 0 for _l4 = 1, _tpNum4 do table.insert(_tpReplace4,gui[_l4]) end for _m4 = 1, 4 - _tpNum4 do table.insert(_tpReplace4,cardList[_i14][_m4]) end table.insert(result,_tpReplace4) end end return result end -- 获取飞机提示(手牌足够) function hejiangPokerUtil:getPlanTip( cards, targets ) local minVal = self:getCardsMin(targets,OUT_TYPE.AIRPLANE) local targetNum = #targets local cclassify = self:classifyCardsEx(cards) local isHaveGui,guiNum = self:checkHaveGui(cclassify) local gui = self:getGuiByClassifyCards(cclassify) local valueList = {} local cardList = {} for k,v in ipairs(cards) do local value = v.val if v ~= GUI_VAL then valueList[value] = valueList[value] or 0 valueList[value] = valueList[value] + 1 cardList[value] = cardList[value] or {} table.insert(cardList[value], v) end end local result ={} local needCardNum = 6 if targetNum == 9 then needCardNum = 9 elseif targetNum == 12 then needCardNum = 12 end for i = minVal + 1, 14 - needCardNum/3 do local _tpIdx = i; local _tpCount = 0; local _tpReplace2 = {} local tpNotAllLai = false; local _haveLai = guiNum; while _tpCount < #cards and _tpCount < needCardNum and _tpIdx <= 12 do valueList[_tpIdx] = valueList[_tpIdx] or 0; if (not (valueList[_tpIdx] + _haveLai >= 3)) then break end; local _tpNum = 3 - valueList[_tpIdx]; _tpNum = _tpNum >= 0 and _tpNum or 0; local lai = guiNum - _haveLai + 1 for p = 1, _tpNum do table.insert(_tpReplace2,gui[lai]) lai = lai + 1 end for _m = 1, 3 - _tpNum do table.insert(_tpReplace2, cardList[_tpIdx][_m]) tpNotAllLai = true; end _haveLai = _haveLai - _tpNum; _tpCount = _tpCount + 3; _tpIdx = _tpIdx + 1 end if _tpCount == needCardNum or (_tpCount == 6 and needCardNum == 10) then function checkIsHaveA2(tmptb)--判断是否有a2 if tmptb and next(tmptb) ~= nil then local isHaveA = false local isHave2 = false for i,v in pairs(tmptb) do if v.val == 12 then isHaveA = true elseif v.val == 13 then isHave2 = true end end return isHaveA and isHave2 end end if _tpCount == 6 and checkIsHaveA2(_tpReplace2) then--3顺aaa222最小 else table.insert(result,_tpReplace2) end end end local resultex = {} if #result > 0 then for i = #result,1,-1 do table.insert(resultex,result[i]) end end return resultex --[[local tclassify = self:classifyCards(targets) local target = self:getSameNum(tclassify, 3) local cclassify = self:classifyCards(cards) local tmps = self:getSameNumEx(cclassify, 3) if #target > #tmps then return nil end local tmpThree = {} for _,v in pairs(tmps) do if v[1].val > target[1][1].val then while #v>3 do table.remove(v, #v) end table.insert(tmpThree, v) end end if #tmpThree > 1 then table.sort(tmpThree, function ( a, b ) return a[1].val < b[1].val end) end local tmp = {}--一维数组 for _,v in pairs(tmpThree) do for _,c in ipairs(v) do table.insert(tmp, c) end end if #target > #tmpThree then return nil end if #target == 2 then--两组 if #tmpThree > 2 then local t = {} t = {tmpThree[1], tmpThree[2]} tmpThree = clone(t) end if math.abs(tmpThree[1][1].val-tmpThree[2][1].val)==1 then local left = getLeft(cards, tmp) if #left<4 then return nil else local tail = clone(left) while #tail>4 do table.remove(tail, #tail) end for _,v in pairs(tmpThree) do for _,c in pairs(v) do table.insert(tail, c) end end return {tail} end else return nil end elseif #target == 3 then--三组 if #tmpThree > 3 then local t = {} t = {tmpThree[1], tmpThree[2], tmpThree[3]} tmpThree = clone(t) end if self:checkSZ({tmpThree[1][1], tmpThree[2][1], tmpThree[3][1]}) then local left = getLeft(cards, tmp) if #left<4 then return nil else local tail = clone(left) while #tail>6 do table.remove(tail, #tail) end return {tmpThree, tail} end else return nil end end return nil --]] end -- 获取牌型提示 function hejiangPokerUtil:getOnlyTip( handCards, cards ) if #handCards < #cards then return nil end local parseHands = self:parseCards(handCards) local parseCards = self:parseCards(cards) local tp = self:checkType(cards) if tp >= OUT_TYPE.NONE then return nil end local result = nil if tp == OUT_TYPE.SINGLE_CARD then result = self:getSingleTip(parseHands, parseCards) elseif tp == OUT_TYPE.DUI_ZI then result = self:getDoubleTip(parseHands, parseCards) elseif tp == OUT_TYPE.THREE then result = self:getThreeTip(parseHands, parseCards) elseif tp == OUT_TYPE.THREE_AND_TWO or tp == OUT_TYPE.THREE_AND_DUI then result = self:getThreeAnd2Tip(parseHands, parseCards) elseif tp == OUT_TYPE.SHUN_ZI then result = self:getShunziTip(parseHands, parseCards) elseif tp == OUT_TYPE.LIAN_DUI then result = self:getLianduiTip(parseHands, parseCards) if result==nil then return nil end local tmp = {} for _,group in ipairs(result) do local t = {} for _,vv in ipairs(group) do for _,v in ipairs(vv) do table.insert(t, v) end end table.insert(tmp, clone(t)) end result = tmp -- return tmp elseif tp == OUT_TYPE.AIRPLANE then result = self:getPlanTip(parseHands, parseCards) elseif tp == OUT_TYPE.FOUR_AND_THREE then result = self:getFourAnd3(parseHands, parseCards) elseif tp == OUT_TYPE.BOMB then result = self:getBombTip(parseHands, parseCards) elseif tp == OUT_TYPE.FOUR_AND_ONE then result = self:getFourAnd1(parseHands, parseCards) end if tp~= OUT_TYPE.BOMB then local bombs = self:getAllBomb(handCards) if #bombs==1 then if result then table.insert(result, bombs[1]) --[[for _,v in pairs(bombs) do end]]-- else result={bombs[1]} --result = bombs[1] end end end if result and #result==1 then return result end return nil end -- 获取只有一种牌型提示 function hejiangPokerUtil:getTip( handCards, cards ) if #handCards < #cards then return nil end if app.room.isMustBomb and app.room.isMustBomb == 1 then return nil end local parseHands = self:parseCards(handCards) local parseCards = self:parseCards(cards) local tp = self:checkType(cards) if app.room.lastOutType and app.room.lastOutType >0 and app.room.lastOutType < OUT_TYPE.NONE then tp = app.room.lastOutType end if tp >= OUT_TYPE.NONE then return nil end if tp == OUT_TYPE.SINGLE_CARD then return self:getSingleTip(parseHands, parseCards) elseif tp == OUT_TYPE.DUI_ZI then local result = self:getDoubleTip(parseHands, parseCards) return result elseif tp == OUT_TYPE.THREE then return self:getThreeTip(parseHands, parseCards) elseif tp == OUT_TYPE.THREE_AND_TWO or tp == OUT_TYPE.THREE_AND_DUI then return self:getThreeAnd2Tip(parseHands, parseCards) elseif tp == OUT_TYPE.SHUN_ZI then local result = self:getShunziTip(parseHands, parseCards) return result elseif tp == OUT_TYPE.LIAN_DUI then local result = self:getLianduiTip(parseHands, parseCards) if result==nil then return nil end --[[local tmp = {} for _,group in ipairs(result) do local t = {} for _,vv in ipairs(group) do for _,v in ipairs(vv) do table.insert(t, v) end end table.insert(tmp, clone(t)) end--]] return result elseif tp == OUT_TYPE.AIRPLANE or tp == OUT_TYPE.AIRPLANE_TOW or tp == OUT_TYPE.AIRPLANE_DUI then return self:getPlanTip(parseHands, parseCards) elseif tp == OUT_TYPE.FOUR_AND_THREE then return self:getFourAnd3(parseHands, parseCards) elseif tp == OUT_TYPE.BOMB then return self:getBombTip(parseHands, parseCards) elseif tp == OUT_TYPE.FOUR_AND_ONE then return self:getFourAnd1(parseHands, parseCards) else return nil end end -- 第一手出牌提示 function hejiangPokerUtil:getFirstTip( handCards ) if #handCards<=0 then return nil end local parseHands = self:parseCards(handCards) local classify = self:classifyCardsEx(parseHands) local singles = {} local fours = {} for valStr,cds in pairs(classify) do if #cds == 1 then table.insert(singles, cds) elseif #cds == 2 then table.insert(singles, cds) elseif #cds == 3 then table.insert(singles, cds) elseif #cds == 4 then table.insert(fours, cds) end end if #singles > 0 then if #singles>=2 then table.sort(singles, function ( a, b ) return a[1].val > b[1].val end) end return singles else if #fours>0 then return fours end end end -- 检测最后一手牌能否一次出完 function hejiangPokerUtil:checkOnceOut( handCards ) local tp = self:checkType(handCards) or OUT_TYPE.NONE if tp == OUT_TYPE.THREE_AND_TWO then --[[if self.isChai then --将3带2还原成4带1 local parseHands = self:parseCards(handCards) if self:check4And1(parseHands) then tp = OUT_TYPE.FOUR_AND_ONE end end--]] end if tp == OUT_TYPE.AIRPLANE then--还原4带3 --[[if self.isFAT then local parseHands = self:parseCards(handCards) if self:check4And3(parseHands) then tp = OUT_TYPE.FOUR_AND_THREE end end--]] end print("----------------------------------once out : ", tp) if tp < OUT_TYPE.NONE then return (tp==OUT_TYPE.SINGLE_CARD or tp==OUT_TYPE.DUI_ZI or tp==OUT_TYPE.SHUN_ZI or tp==OUT_TYPE.THREE_AND_TWO or tp==OUT_TYPE.THREE_AND_DUI or tp==OUT_TYPE.THREE or tp==OUT_TYPE.LIAN_DUI or tp==OUT_TYPE.AIRPLANE or tp==OUT_TYPE.AIRPLANE_DUI or tp==OUT_TYPE.AIRPLANE_TOW or tp==OUT_TYPE.THREE_AND_ONE), tp else--unwork dead code --检测是否是三个带不全 if #handCards > 4 then return false, tp else --不检测三带一 --[[local parseHands = self:parseCards(handCards) local classify = self:classifyCards(parseHands) local tmps = self:getSameNum(classify, 3) if #tmps>=1 then return true, tp else return false, tp end--]] end end return false , tp end -- 判断牌是否是手牌中最大的牌 function hejiangPokerUtil:isMaxCard(handCards, card) local targetTp, targetVal = pokerParse(card) local parseHands = self:parseCards(handCards) local result = true for _,v in pairs(parseHands) do if v.val ~= GUI_VAL and v.val > targetVal then result = false break end end return result end -- 检测是否拆了炸弹 function hejiangPokerUtil:isChaiBombs( handCards, selects ) local parseSelects = self:parseCards(selects) --检测手上是否有炸弹 local bombs = self:getAllBomb(handCards) if #bombs > 0 then for _,bomb in pairs(bombs) do if self:checkOwnX(parseSelects, bomb[1]) then local classifySelects = self:classifyCardsEx(parseSelects) local target = classifySelects[tostring(bomb[1].val)] if #target < 4 then return true end end end else return false end return false end -- 判断三带不全出牌 function hejiangPokerUtil:checkThreeOut( handCards ,targets) local parseHands = self:parseCards(handCards) local parseTargets = self:parseCards(targets) local handsThree = self:getSameNumExEx(parseHands) local targetThree = self:getSameNumExEx(parseTargets) local handVal = nil local targetVal = nil for k,v in pairs(targetThree) do targetVal = tonumber(k) end for k,v in pairs(handsThree) do handVal = tonumber(k) end if targetVal and handVal then return targetVal < handVal end return false end -- function hejiangPokerUtil:leftCards( handCards, targets) local result = {} local ts = {} for _,group in pairs(targets) do for _,card in pairs(group) do table.insert(ts, card.cid)--将能出的牌汇集到一起 end end for _,hcid in pairs(handCards) do local own = false for _,tcid in pairs(ts) do if hcid == tcid then--包含了同一张牌 own = true end end if not own then table.insert(result, hcid) end end return result end -- 提示,只剩大于最小牌的牌 function hejiangPokerUtil:leftCardsEx( handCards, targets) local result = {} local ts = {} local minVal = 100 for _,group in pairs(targets) do for _,card in pairs(group) do table.insert(ts, card.cid)--将能出的牌汇集到一起 if card.val < minVal then minVal = card.val--能出牌的最小张 end end end for _,hcid in pairs(handCards) do local own = false for _,tcid in pairs(ts) do local _, val = pokerParse(hcid) if hcid == tcid or val >= minVal then own = true end end if not own then table.insert(result, hcid) end end return result end -- function hejiangPokerUtil:leftSingleCards( handCards, targets) local result = {} local ts = {} for _,card in pairs(targets) do if card.cid == nil and type(card)=='table' and #card>0 then for _,v in ipairs(card) do table.insert(ts, v.cid) end else table.insert(ts, card.cid) end end for _,hcid in pairs(handCards) do local own = false for _,tcid in pairs(ts) do if hcid == tcid then own = true end end if not own then table.insert(result, hcid) end end return result end --是否是AAA function hejiangPokerUtil:isAAA( cards ) if #cards ~= 3 then return false end local result = true for i,v in ipairs(cards) do local _, val = pokerParse(v) if val ~= A_VAL then result = false break end end return result end function hejiangPokerUtil:checkType(cards) local cardsLen = table.nums(cards) if cardsLen == 0 then return end local valueList = {} local cardList = {} local laiCount = 0 local a = {} for k,v in ipairs(cards) do local value = self:getCardValue(v) if value == GUI_VAL then laiCount = laiCount + 1 else valueList[value] = valueList[value] or 0 valueList[value] = valueList[value] + 1 cardList[value] = cardList[value] or {} table.insert(cardList[value], v) end end if laiCount == cardsLen then if laiCount == 1 then return OUT_TYPE.SINGLE_CARD elseif laiCount == 2 then return OUT_TYPE.DUI_ZI elseif laiCount == 3 then return OUT_TYPE.THREE end end for k,v in ipairs(valueList) do a[v] = a[v] or {} table.insert(a[v], v) end local typesEx = {} --默认纯赖子不可打出 if cardsLen == 1 and table.nums(valueList) == 1 then --单张 table.insert(typesEx, "单张") return OUT_TYPE.SINGLE_CARD elseif cardsLen == 2 and table.nums(valueList) == 1 then --对子 table.insert(typesEx, "对子") return OUT_TYPE.DUI_ZI elseif cardsLen == 3 and table.nums(valueList) == 1 then --三张 table.insert(typesEx, "三张") return OUT_TYPE.THREE else if cardsLen == 4 and table.nums(valueList) == 1 then --炸弹 table.insert(typesEx, "炸弹") return OUT_TYPE.BOMB else --三带一 if cardsLen == 4 and table.nums(valueList) <= 3 then for i = 1, 13 do local cardsEx = {} local laiCountEx = laiCount local valueCountEx = valueList[i] or 0 if valueCountEx >= 1 and valueCountEx <= 3 and valueCountEx + laiCountEx >= 3 then local userLaiCount = 3 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for i = 1, userLaiCount do table.insert(cardsEx, 0x0e) end for i = 1, 2 - userLaiCount do table.insert(cardsEx, cardList[i]) end --三代二 table.insert(typesEx, "三代一") return OUT_TYPE.THREE_AND_ONE end end end --三代二 if cardsLen == 5 and table.nums(valueList) <= 3 then for i = 1, 13 do local cardsEx = {} local laiCountEx = laiCount local valueCountEx = valueList[i] or 0 if valueCountEx >= 1 and valueCountEx <= 3 and valueCountEx + laiCountEx >= 3 then local userLaiCount = 3 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for i = 1, userLaiCount do table.insert(cardsEx, 0x0e) end for i = 1, 2 - userLaiCount do table.insert(cardsEx, cardList[i]) end --三代二 table.insert(typesEx, "三代二") return OUT_TYPE.THREE_AND_TWO end end end --顺子 if cardsLen >= 5 then for i = 1, 12 do local iEx = i local countEx = 0 local cardsEx = {} local laiCountEx = laiCount while iEx <= 12 and countEx < cardsLen do local valueCountEx = valueList[iEx] or 0 if valueCountEx + laiCountEx >= 1 then local userLaiCount = 1 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for i = 1, userLaiCount do table.insert(cardsEx, 0x0f) end for i = 1, 1 - userLaiCount do table.insert(cardsEx, cardList[i]) end iEx = iEx + 1 countEx = countEx + 1 laiCountEx = laiCountEx - userLaiCount else break end end if countEx == cardsLen then --顺子 table.insert(typesEx, "顺子") return OUT_TYPE.SHUN_ZI end end local parseData = {} for _,v in ipairs(cards) do local tp, val = pokerParse(v) table.insert(parseData, {tp=tp, val=val, cid=v}) end if #parseData >=2 then table.sort(parseData, sortCardsFunc) end if self:checkShunzi(parseData) then return OUT_TYPE.SHUN_ZI end end --连对 if cardsLen % 2 == 0 and cardsLen >= 4 then for i = 1, 13 do local iEx = i local countEx = 0 local cardsEx = {} local laiCountEx = laiCount while iEx <= 13 and countEx < cardsLen do local valueCountEx = valueList[iEx] or 0 if valueCountEx + laiCountEx >= 2 then local userLaiCount = 2 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for i = 1, userLaiCount do table.insert(cardsEx, 0x0f) end for i = 1, 2 - userLaiCount do table.insert(cardsEx, cardList[i]) end iEx = iEx + 1 countEx = countEx + 2 laiCountEx = laiCountEx - userLaiCount else break end end if countEx == cardsLen then --连对 if cardsLen > 4 and valueList[13] and valueList[13] >= 1 then--连对只有AA22可以出,KKAA22和QQKKAA22都不可以出 else table.insert(typesEx, "连对") return OUT_TYPE.LIAN_DUI end end end if valueList[13] and (valueList[13] >= 1 and valueList[13] < 3) and valueList[1] and valueList[1] >= 1 and (cardsLen/2 == table.nums(valueList) + math.floor(laiCount/2) or cardsLen/2 == table.nums(valueList))then local isliandui = true for i,v in pairs(valueList) do if v > 2 and i ~= 14 then isliandui = false end end if true == isliandui then return OUT_TYPE.LIAN_DUI end end end --三顺 if cardsLen % 3 == 0 and cardsLen >= 6 then for i = 1, 13 do local iEx = i local countEx = 0 local cardsEx = {} local laiCountEx = laiCount while iEx <= 13 and countEx < cardsLen do local valueCountEx = valueList[iEx] or 0 if valueCountEx + laiCountEx >= 3 then local userLaiCount = 3 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for i = 1, userLaiCount do table.insert(cardsEx, 0x0f) end for i = 1, 3 - userLaiCount do table.insert(cardsEx, cardList[i]) end iEx = iEx + 1 countEx = countEx + 3 laiCountEx = laiCountEx - userLaiCount else break end end if countEx == cardsLen then --三顺 if cardsLen > 6 and valueList[13] and valueList[13] >= 1 then--三顺只有AAA222可以出,KKKAAA222和QQQKKKAAA222都不可以出 else table.insert(typesEx, "三顺") return OUT_TYPE.AIRPLANE end end end if valueList[13] and valueList[13] >= 1 and valueList[1] and valueList[1] >= 1 and cardsLen/3 == table.nums(valueList) + math.floor(laiCount/3) then if cardsLen == 6 then return OUT_TYPE.AIRPLANE elseif cardsLen == 9 then if (valueList[12] and valueList[12] >= 1) or (valueList[2] and valueList[2] >= 1) or laiCount == 3 then return OUT_TYPE.AIRPLANE end elseif cardsLen == 12 then if laiCount == 3 and (valueList[12] and valueList[12] >= 1) or (valueList[2] and valueList[2] >= 1) then return OUT_TYPE.AIRPLANE elseif (valueList[12] and valueList[12] >= 1) and (valueList[2] and valueList[2] >= 1) or (valueList[3] and valueList[3] >= 1) and (valueList[2] and valueList[2] >= 1) then return OUT_TYPE.AIRPLANE end end end end --飞机 if cardsLen % 5 == 0 and cardsLen >= 10 and table.nums(valueList) <= cardsLen / 5 * 3 then for i = 1, 13 do local iEx = i local countEx = 0 local cardsEx = {} local laiCountEx = laiCount while iEx <= 13 and countEx < cardsLen / 5 do local valueCountEx = valueList[iEx] or 0 if valueCountEx + laiCountEx >= 3 then local userLaiCount = 3 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for i = 1, userLaiCount do table.insert(cardsEx, 0x0f) end for i = 1, 3 - userLaiCount do table.insert(cardsEx, cardList[i]) end iEx = iEx + 1 countEx = countEx + 1 laiCountEx = laiCountEx - userLaiCount else break end end if countEx == cardsLen / 5 then --飞机 local threeNum = 0 for i,v in pairs(valueList) do if v >= 3 then threeNum = threeNum + 1 end end if threeNum > 2 then else table.insert(typesEx, "飞机") return OUT_TYPE.AIRPLANE_TOW end end end if valueList[13] and valueList[13] >= 1 and valueList[1] and valueList[1] >= 1 and valueList[13]+valueList[1]+laiCount>=6 then return OUT_TYPE.AIRPLANE_TOW end end end end return OUT_TYPE.NONE end --根据牌类型获取最小值 function hejiangPokerUtil:getCardsMin(cards,cardtype) local cardsLen = table.nums(cards) if cardsLen == 0 then return end local valueList = {} local cardList = {} local laiCount = 0 local a = {} for k,v in ipairs(cards) do local value = v.val if value == GUI_VAL then laiCount = laiCount + 1 else valueList[value] = valueList[value] or 0 valueList[value] = valueList[value] + 1 cardList[value] = cardList[value] or {} table.insert(cardList[value], v) end end if laiCount == cardsLen then return end for k,v in ipairs(valueList) do a[v] = a[v] or {} table.insert(a[v], v) end local typesEx = {} --默认纯赖子不可打出 if cardtype == OUT_TYPE.SINGLE_CARD and cardsLen == 1 and table.nums(valueList) == 1 then for i,v in pairs(cardList) do return v[1].val end elseif cardtype == OUT_TYPE.DUI_ZI and cardsLen == 2 and table.nums(valueList) == 1 then --对子 table.insert(typesEx, "对子") for i,v in pairs(cardList) do return v[1].val end elseif cardtype == OUT_TYPE.THREE and cardsLen == 3 and table.nums(valueList) == 1 then --三张 table.insert(typesEx, "三张") for i,v in pairs(cardList) do return v[1].val end else if cardtype == OUT_TYPE.BOMB and cardsLen == 4 and table.nums(valueList) == 1 then --炸弹 table.insert(typesEx, "炸弹") for i,v in pairs(cardList) do return v[1].val end else --三代二 if cardtype == OUT_TYPE.THREE_AND_TWO and cardsLen == 5 and table.nums(valueList) <= 3 then for i = 13, 1,-1 do local cardsEx = {} local laiCountEx = laiCount local valueCountEx = valueList[i] or 0 if valueCountEx >= 1 and valueCountEx <= 3 and valueCountEx + laiCountEx >= 3 then local userLaiCount = 3 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for k = 1, userLaiCount do table.insert(cardsEx, 0x0f) end for k = 1, 2 - userLaiCount do table.insert(cardsEx, cardList[k]) end --三代二 table.insert(typesEx, "三代二") return i end end end --顺子 if cardtype == OUT_TYPE.SHUN_ZI and cardsLen >= 5 then for i = 1, 12 do local iEx = i local countEx = 0 local cardsEx = {} local laiCountEx = laiCount while iEx <= 12 and countEx < cardsLen do local valueCountEx = valueList[iEx] or 0 if valueCountEx + laiCountEx >= 1 then local userLaiCount = 1 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for k = 1, userLaiCount do table.insert(cardsEx, 0x0f) end for k = 1, 1 - userLaiCount do table.insert(cardsEx, cardList[k]) end iEx = iEx + 1 countEx = countEx + 1 laiCountEx = laiCountEx - userLaiCount else break end end if countEx == cardsLen then --顺子 table.insert(typesEx, "顺子") for k = cardsLen,1,-1 do if cards[k].val == 13 then return 0 end end return i end end local isMinTime = 0 for i,v in pairs(cards) do if v.val == 13 then isMinTime = isMinTime + 1 return 0 elseif v.val ==1 or v.val==12 then isMinTime = isMinTime + 1 end end if isMinTime >= 2 then return 0 end return 0 end --连对 if cardtype == OUT_TYPE.LIAN_DUI and cardsLen % 2 == 0 and cardsLen >= 4 then for i = 1, 13 do local iEx = i local countEx = 0 local cardsEx = {} local laiCountEx = laiCount while iEx <= 13 and countEx < cardsLen do local valueCountEx = valueList[iEx] or 0 if valueCountEx + laiCountEx >= 2 then local userLaiCount = 2 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for k = 1, userLaiCount do table.insert(cardsEx, 0x0f) end for k = 1, 2 - userLaiCount do table.insert(cardsEx, cardList[k]) end iEx = iEx + 1 countEx = countEx + 2 laiCountEx = laiCountEx - userLaiCount else break end end if countEx == cardsLen then --连对 table.insert(typesEx, "连对") for k = cardsLen,1,-1 do if cards[k].val == 13 then return 0 end end return i end end for k = cardsLen,1,-1 do if cards[k].val == 13 then return 0 end end end --三顺 if (cardtype >= OUT_TYPE.AIRPLANE and cardtype <= OUT_TYPE.AIRPLANE_DUI) and cardsLen % 3 == 0 and cardsLen >= 6 then for i = 1, 12 do local iEx = i local countEx = 0 local cardsEx = {} local laiCountEx = laiCount while iEx <= 12 and countEx < cardsLen do local valueCountEx = valueList[iEx] or 0 if valueCountEx + laiCountEx >= 3 then local userLaiCount = 3 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for k = 1, userLaiCount do table.insert(cardsEx, 0x0f) end for k = 1, 3 - userLaiCount do table.insert(cardsEx, cardList[k]) end iEx = iEx + 1 countEx = countEx + 3 laiCountEx = laiCountEx - userLaiCount else break end end if countEx == cardsLen then --三顺 table.insert(typesEx, "三顺") return i end end if cardsLen == 6 and valueList[13] and valueList[13] >= 1 and valueList[12] and valueList[12] >= 1 and cardsLen/3 == table.nums(valueList) + math.floor(laiCount/3) then--AAA222 return 0-- 三A三2 end end --飞机 if (cardtype >= OUT_TYPE.AIRPLANE and cardtype <= OUT_TYPE.AIRPLANE_DUI) and cardsLen % 5 == 0 and cardsLen >= 10 and table.nums(valueList) <= cardsLen / 5 * 3 then for i = 1, 12 do local iEx = i local countEx = 0 local cardsEx = {} local laiCountEx = laiCount while iEx <= 12 and countEx < cardsLen / 5 do local valueCountEx = valueList[iEx] or 0 if valueCountEx + laiCountEx >= 3 then local userLaiCount = 3 - valueCountEx userLaiCount = userLaiCount > 0 and userLaiCount or 0 for k = 1, userLaiCount do table.insert(cardsEx, 0x0f) end for k = 1, 3 - userLaiCount do table.insert(cardsEx, cardList[k]) end iEx = iEx + 1 countEx = countEx + 1 laiCountEx = laiCountEx - userLaiCount else break end end if countEx == cardsLen / 5 then --飞机 table.insert(typesEx, "飞机") return i end end end end end return 1 end return hejiangPokerUtil