|
- --[[经典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 #tmpNoKey<targetNum then return nil end
- local count = #tmpNoKey-targetNum
- if count == 0 then return {tmpNoKey} end
- local getMS = function ( tab, len )
- if #tab < len then return nil end
- local rst = {}
- for i=#tab,1,-1 do
- if #rst<len then
- table.insert(rst, 1, tab[i])
- else
- break
- end
- end
- return rst
- end
- local result = {}
- for i=#tmpNoKey,1,-1 do
- local rst = getMS(tmpNoKey, targetNum)
- if rst then
- table.insert(result, 1, clone(rst))
- table.remove(tmpNoKey, #tmpNoKey)
- else
- break
- end
- end
- return result
- end
-
- -- 顺子提示
- -- fixed
- function PokerUtil:getShunziTip( cards, targets )
- local classify = self:classifyCardsEx(cards)
- table.sort(targets, sortCardsFunc)
- local minVal = targets[1].val
- local targetNum = #targets
- local tmpCards = {}
-
- for valStr,cds in pairs(classify) do
- if tonumber(valStr)>minVal 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
|