--[[经典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 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 PokerUtil = class("PokerUtil") -- 所有传入参数均为{tp, val, cid}结构集合 function PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil:checkShunzi( cards ) local LessNum = 5 if cards and type(cards)~="table" then return false end if self:checkOwnEr(cards) or #cards < LessNum then return false end--牌中是否带2 或者牌张数不够 return self:checkSZ(cards) end -- 检测顺子,至少两张 function PokerUtil:checkSZ(cards) local LessNum = 2 if cards and type(cards)~="table" then return false end if self:checkOwnEr(cards) or #cards < LessNum then return false end--牌中是否带2 或者牌张数不够 local tmpCards = clone(cards) table.sort(tmpCards, sortCardsFunc) local idx = 1 local result = true for i=2,#tmpCards do if tmpCards[idx].val+1 ~= tmpCards[i].val then result = false break else idx = idx + 1 end end return result end -- 检测连对 function PokerUtil:checkLianDui(cards) local LessNum = 4 if cards and type(cards)~="table" then return false end if self:checkOwnEr(cards) or #cards < LessNum or #cards%2~=0 then return false end--牌中是否带2 或者牌张数不够 local tmpCards = clone(cards) local classify = self:classifyCards(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 return self:checkSZ(tmp) end -- 检测三带一(最后四张才能3带一?) function PokerUtil: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 PokerUtil: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 own3 = false for _,v in ipairs(classify) do if #v == 3 then own3 = true break end end return own3 end -- 检测四带一 function PokerUtil: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 -- 检测四带2 function PokerUtil:check4And2(cards) local LessNum = 6 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 PokerUtil: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 PokerUtil:checkBomb( cards ) return self:checkFour(cards) end -- 检测飞机555666 555666777等+同等数量的对牌,或者双倍单牌 function PokerUtil:checkPlan( cards, shaoDai ) shaoDai = shaoDai or true 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 checkShun = {} 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 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>=4 and cNum<=16) or (maxLen>=3 and cNum<=15) end return result end --牌型 local OUT_TYPE = { SINGLE_CARD = 1, --//单牌 DUI_ZI = 2, --//对子 THREE_AND_TWO = 3, --//三带二 SHUN_ZI = 4, --//顺子 LIAN_DUI = 5, --//连对(至少2连对) AIRPLANE = 6, --//飞机 FOUR_AND_THREE = 7, --//四带三 BOMB = 8, --//炸弹 FOUR_AND_ONE = 9, --//四带一 THREE_AND_ONE = 10, --三带一 THREE = 11, --三个 FOUR_AND_TWO = 12, --//四带2 NONE = 100, --不适用类型 } local TYPE_STRING = { [OUT_TYPE.SINGLE_CARD] = "单牌", --//单牌 [OUT_TYPE.DUI_ZI] = "对子", --//对子 [OUT_TYPE.THREE_AND_TWO] = "三带二", --//三带二 [OUT_TYPE.SHUN_ZI] = "顺子", --//顺子 [OUT_TYPE.LIAN_DUI] = "连对", --//连对 [OUT_TYPE.AIRPLANE] = "飞机", --//飞机 [OUT_TYPE.FOUR_AND_THREE] = "四带三", --//四带三 [OUT_TYPE.BOMB] = "炸弹", --//炸弹 [OUT_TYPE.FOUR_AND_ONE] = "四带一", --//四带一 [OUT_TYPE.NONE] = "错误类型", --//错误类型 } PokerUtil.OUT_TYPE = OUT_TYPE function PokerUtil:getTypeString( tp ) return TYPE_STRING[tp] or "TP错误" end -- 检测牌型 function PokerUtil: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:check4And2(parseData) then return OUT_TYPE.FOUR_AND_TWO 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 -------------------------------------------------------------------------------------- -- 牌型提示 -------------------------------------------------------------------------------------- --单张提示 cards@{{tp=, val=, cid=,}...} target@{tp=, val=, cid=,} -- fixed function PokerUtil:getSingleTip( cards, target ) local target = target[1] if target.val == ER_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 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 PokerUtil:getDoubleTip( cards, targets ) local target = targets[1] local classify = self:classifyCardsEx(cards) local twos = {} local threes = {} local fours = {} for valStr,cds in pairs(classify) do if tonumber(valStr) > target.val and #cds>=2 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 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 if #fours>=2 then --升序排列 table.sort(fours, function ( a, b ) return a[1].val < b[1].val end) 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 PokerUtil:getThreeTip( cards, targets ) if #cards < #targets then return nil end local tclassify = self:classifyCards(targets) local target = self:getSameNumEx(tclassify, 3)[1][1]--同时包含四带一 local classify = self:classifyCardsEx(cards) local threes = {} local singles = {} local twos = {} local fours = {} 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]) elseif #cds == 2 then table.insert(twos, cds) 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 -- 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 -- for _,v in ipairs(twos) do -- table.insert(singles, v[1]) -- table.insert(singles, v[2]) -- end -- local result = {} -- if #threes==1 then -- if #singles >= 2 then -- table.insert(threes[1], singles[1]) -- table.insert(threes[1], singles[2]) -- table.insert(result, threes[1]) -- return result -- else -- return nil -- end -- else -- if #singles >= 2 then -- for _,v in ipairs(threes) do -- local cv = clone(v) -- table.insert(cv, singles[1]) -- table.insert(cv, singles[2]) -- table.insert(result, cv) -- end -- return result -- else--多个三张,玩家自己拆牌 return threes -- end -- end end -- 三带二提示 -- fixed function PokerUtil:getThreeAnd2Tip( cards, targets ) if #cards < #targets then return nil end local tclassify = self:classifyCards(targets) local target = self:getSameNumEx(tclassify, 3)[1][1]--同时包含四带一 local classify = self:classifyCardsEx(cards) local threes = {} local singles = {} local twos = {} local fours = {} 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]) elseif #cds == 2 then table.insert(twos, cds) 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 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 for _,v in ipairs(twos) do table.insert(singles, v[1]) table.insert(singles, v[2]) end local result = {} if #threes==1 then if #singles >= 2 then table.insert(threes[1], singles[1]) table.insert(threes[1], singles[2]) table.insert(result, threes[1]) return result else return nil end else if #singles >= 2 then for _,v in ipairs(threes) do local cv = clone(v) table.insert(cv, singles[1]) table.insert(cv, singles[2]) table.insert(result, cv) end return result else--多个三张,玩家自己拆牌 return threes end end end -- 三带一提示 not fixed function PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil:getSubLine( parseCards ) local sub = {} for i=#parseCards,1,-1 do if parseCards[i] and parseCards[i-1] then if parseCards[i].val-1~=parseCards[i-1].val 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 return sub end -- 从连续的牌组中获得顺子 function PokerUtil:getSzTip( hands, targets ) local tmpNoKey = clone(hands) table.sort(targets, sortCardsFunc) local minVal = targets[1].val local targetNum = #targets if #tmpNoKeyminVal and tonumber(valStr)~=ER_VAL then if #cds == 4 then if self.isChai then table.insert(tmpCards, cds[1]) end else table.insert(tmpCards, cds[1]) end end end if #tmpCards>=2 then table.sort(tmpCards, sortCardsFunc) end --确保tmpCards是连续的 local subLines = self:getSubLine(tmpCards) local result = {} for _,v in ipairs(subLines) do if #v >= targetNum then local rst = self:getSzTip(v, targets) if rst and #rst>0 then for _,group in ipairs(rst) do table.insert(result, group) end end end end local tmp = {} for _,v in pairs(result) do table.insert(tmp, 1, v) end return tmp end -- 获取连对提示 -- fixed function PokerUtil:getLianduiTip( cards, targets ) table.sort(targets, sortCardsFunc) local tclassify = self:classifyCards(targets) local target = self:getSameNum(tclassify, 2) local tmpTarget = {} for _,v in pairs(target) do table.insert(tmpTarget, v[1]) end if #tmpTarget>1 then table.sort(tmpTarget, sortCardsFunc) end local cclassify = self:classifyCardsEx(cards) local tmps = {} for valStr, cds in pairs(cclassify) do if tonumber(valStr)~=ER_VAL then if #cds == 2 then tmps[valStr] = cds elseif #cds == 3 then tmps[valStr] = {cds[1], cds[2]} elseif #cds == 4 then if self.isChai then tmps[valStr] = {cds[1], cds[2]} end end end end --所有的两张的牌(key-value结构) local tmpSrc = {} for _,v in pairs(tmps) do table.insert(tmpSrc, v[1]) end local tmpShunzi= self:getShunziTip(tmpSrc, tmpTarget) if #tmpShunzi > 0 then local tmpResult = {} for _,v in pairs(tmpShunzi) do local tmp = {} for _,card in pairs(v) do table.insert(tmp, clone(tmps[tostring(card.val)])) end table.insert(tmpResult, clone(tmp)) end for _,group in ipairs(tmpResult) do for _,v in ipairs(group) do while #v>2 do table.remove(v, #v) end end end return tmpResult else return nil end end -- 获取炸弹提示 function PokerUtil:getBombTip( cards, targets ) local tclassify = self:classifyCards(targets) local target = self:getSameNum(tclassify, 4) if #target >= 1 then target = target[1] end local cclassify = self:classifyCards(cards) local tmps = self:getSameNumExEx(cclassify, 4) local result = {} for _,v in pairs(tmps) do if target[1].val < v[1].val then table.insert(result, v) end end return result end -- 获取牌组中所有炸弹 function PokerUtil:getAllBomb( cards, isAaaBomb ) if isAaaBomb == nil then isAaaBomb = false end if not isAaaBomb then if #cards<4 then return {} end end local parseHands = self:parseCards(cards) local cclassify = self:classifyCards(parseHands) local tmps = self:getSameNumExEx(cclassify, 4) local tmp = {} if isAaaBomb then --是否拥有AAA local tmpThrees = self:getSameNumExEx(cclassify, 3) for _,v in pairs(tmpThrees) do if v[1].val == A_VAL and #v == 3 then table.insert(tmp, v) break end end end for _,v in pairs(tmps) do table.insert(tmp, v) end if #tmp>=2 then table.sort(tmp, function (a, b) return a[1].val > b[1].val end) end return tmp end -- 获取飞机提示(手牌足够) function PokerUtil:getPlanTip( cards, targets ) 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 PokerUtil: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_AND_TWO then result = self:getThreeTip(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 PokerUtil:getTip( 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 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_AND_TWO 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 tmp elseif tp == OUT_TYPE.AIRPLANE 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 PokerUtil: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 PokerUtil:checkOnceOut( handCards ) local tp = self:checkType(handCards) 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 if tp == OUT_TYPE.FOUR_AND_TWO then--4带2 return false , tp 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_ONE or tp==OUT_TYPE.THREE or tp==OUT_TYPE.LIAN_DUI or tp==OUT_TYPE.AIRPLANE), 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 PokerUtil: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 > targetVal then result = false break end end return result end -- 检测是否拆了炸弹 function PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 PokerUtil: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 return PokerUtil