跑得快划牌提示Lua
local GameTipUtil = class('GameTipUtil') local cmd = appdf.req(appdf.GAME_SRC .. 'qipai.runfasthn.src.models.CMD_Game') function GameTipUtil:ctor(o, param) self.cardData = {} end local ER_VALUE = 50 --2不算做顺子 所以排除 只有黑桃2 --错误 cmd.CT_ERROR = 0 --单牌 cmd.CT_SINGLE = 1 --//顺子 cmd.CT_SINGLE_LINE = 2 --//对连 cmd.CT_DOUBLE_LINE = 3 --//飞机 cmd.CT_THREE_LINE = 4 --三带一 3带1必须在只剩4张才能出 cmd.CT_THREE_LINE_TAKE_SINGLE = 5 --三带一对 cmd.CT_THREE_LINE_TAKE_DOUBLE = 6 --炸弹类型 cmd.CT_BOMB = 7 --三带二单 cmd.CT_THREE_LINE_TAKE_TWOSINGLE = 8 --对牌类型 cmd.CT_DOUBLE = 9 --三条 cmd.CT_THREE = 10 -- //飞机有带单 cmd.CT_THREE_LINE_ONE = 11 -- //飞机带翅膀 cmd.CT_THREE_LINE_WING = 12 -- //四带三 4带3 必须是七张 cmd.CT_FOUR_LINE_TAKE_THREE = 13 --工具方法函数------start------ --取模 function GameTipUtil:mod(a, b) return a - math.floor(a / b) * b end --获得牌的颜色(0 -- 4) function GameTipUtil:GetCardColor(cbCardData) return math.floor(cbCardData / 16) end --获得牌的数值(1 -- 13) function GameTipUtil:GetCardValue(cbCardData) return GameTipUtil:mod(cbCardData, 16) end --获得牌的逻辑数值 function GameTipUtil:GetCardLogicValue(cbCardData) local nValue = GameTipUtil:GetCardValue(cbCardData) return nValue <= 2 and nValue + 13 or nValue end -- 牌的排序函数 local function sortCardsFunc(a, b) local logicA = GameTipUtil:GetCardLogicValue(a) local logicB = GameTipUtil:GetCardLogicValue(b) return logicA < logicB end function GameTipUtil:pokerParse(card) local tp = math.floor(card / 16) local val = card % 16 -- print("---------tp : "..tp.." val : "..val) return tp, val end -- 将牌解析成{tp, val ,cid}牌组 function GameTipUtil:parseCards(cards) local result = {} dump(cards, 'cards===========') for _, v in ipairs(cards) do local tp, val = self:pokerParse(v) table.insert(result, {tp = tp, val = val, cid = v}) end return result end function GameTipUtil:checkSameVal(cards) if cards == nil or #cards <= 0 then print("card == nil or #cards <= 0 返回") return end -- dump(cards,"cards checkSameVal") local targetValue = self:GetCardLogicValue(cards[1]) -- dump(targetValue,"targetValue") for _, v in pairs(cards) do if self:GetCardLogicValue(v) ~= targetValue then -- dump(self:GetCardLogicValue(v),"targetValue") return false end end print("返回真") return true end function GameTipUtil:getLeft(src, target) if src == nil or target == nil then print("获取剩余牌张失败-有值为空") return end local have = {} for _, v in ipairs(target) do have[tostring(v)] = v end local left = {} for _, v in ipairs(src) do if not have[tostring(v)] then table.insert(left, v) end end return left end --用于单张判断是否加入了 function GameTipUtil:checkSingleIsInTable(checkTable, value) -- dump(checkTable,"单张判断") if checkTable == nil then return false end for k, v in pairs(checkTable) do local temp = self:GetCardLogicValue(v) if temp == value then -- print("单张判断返回true") return true end end -- print("单张判断返回false") return false end -- 对牌组按照value进行分类 function GameTipUtil:classifyCards(cards) local tmpCards = clone(cards) local result = {} for _, v in pairs(tmpCards) do if not result[tostring(self:GetCardLogicValue(v))] then result[tostring(self:GetCardLogicValue(v))] = {} end table.insert(result[tostring(self:GetCardLogicValue(v))], v) end local tmp = {} for _, v in pairs(result) do table.insert(tmp, v) end return tmp end --用于是否有对子或者两张以上判断 function GameTipUtil:checkIsInTable(checkTable, value, num) local tempCount = 0 for k, v in pairs(checkTable) do local temp = self:GetCardLogicValue(v) if temp == value then tempCount = tempCount + 1 end if tempCount >= num then return true end end return false end function GameTipUtil:checkSz(tmpCards, num, limit) table.sort(tmpCards, sortCardsFunc) -- dump(tmpCards,"tmpCards") -- dump(#tmpCards - num,"#tmpCards - num") -- dump(num,"num") if #tmpCards - num + 1 < limit and #tmpCards ~= 2 then return end local result = {} result.cardData = {} result.count = 0 local idx = num for i = idx + 1, #tmpCards do if self:GetCardLogicValue(tmpCards[idx]) + 1 ~= self:GetCardLogicValue(tmpCards[i]) then break else table.insert(result.cardData, tmpCards[idx]) result.count = result.count + 1 idx = idx + 1 end end --这个判断 由于是后一位补 前一位 所以会缺失最后一个数据 if tmpCards[idx - 1] and self:GetCardLogicValue(tmpCards[idx - 1]) + 1 == self:GetCardLogicValue(tmpCards[idx]) then table.insert(result.cardData, tmpCards[idx]) result.count = result.count + 1 end -- dump(tmpCards,"tmpCards-=====") if #tmpCards == 2 then print("两张专有判断") local isShun = self:GetCardLogicValue(tmpCards[1]) + 1 == self:GetCardLogicValue(tmpCards[2]) -- dump(isShun,"isShun-=====") if isShun then result.cardData = tmpCards result.count = 2 end end -- dump(result,"result=====") return result end function GameTipUtil:checkSigleSz(tmpCards, num, limit) table.sort(tmpCards, sortCardsFunc) -- dump(tmpCards,"tmpCards") dump(#tmpCards - num,"#tmpCards - num") -- dump(num,"num") if #tmpCards - num + 1 < limit and #tmpCards ~= 2 then print("不满足 #tmpCards - num < limit and #tmpCards ~= 2 ") return end local result = {} result.cardData = {} result.count = 0 local idx = num for i = idx + 1, #tmpCards do if self:GetCardLogicValue(tmpCards[idx]) + 1 ~= self:GetCardLogicValue(tmpCards[i]) then break else table.insert(result.cardData, tmpCards[idx]) result.count = result.count + 1 idx = idx + 1 end end --这个判断 由于是后一位补 前一位 所以会缺失最后一个数据 if tmpCards[idx - 1] and self:GetCardLogicValue(tmpCards[idx - 1]) + 1 == self:GetCardLogicValue(tmpCards[idx]) then table.insert(result.cardData, tmpCards[idx]) result.count = result.count + 1 end -- dump(tmpCards,"tmpCards-=====") if #tmpCards == 2 then -- print("两张专有判断") local isShun = self:GetCardLogicValue(tmpCards[1]) + 1 == self:GetCardLogicValue(tmpCards[2]) -- dump(isShun,"isShun-=====") if isShun then result.cardData = tmpCards result.count = 2 end end dump(result,"result=====") return result end --工具方法函数------end------ --分析牌张------start------ --分析所有的单牌 不管对子和其他的 function GameTipUtil:AnalyseSingle(cardData) dump(cardData, 'cardData') if cardData == nil then print('分析单牌为空 ') return end local singleCard = {} singleCard.AllSingleCardCount = 0 singleCard.SingleCardData = {} -- singleCard.SingleLogicData = {} --解析poker的单张 for i = 1, #cardData do local bLogicValue = self:GetCardLogicValue(cardData[i]) if not self:checkSingleIsInTable(singleCard.SingleCardData, bLogicValue) then singleCard.AllSingleCardCount = singleCard.AllSingleCardCount + 1 -- table.insert( singleCard.SingleLogicData, bLogicValue ) table.insert(singleCard.SingleCardData, cardData[i]) end end --返回手牌排序 table.sort(singleCard.SingleCardData, sortCardsFunc) return singleCard end --分析获得所有的对子牌 为什么要加逻辑数据呢 自己算不就好了 function GameTipUtil:AnalyseDouble(cardData) -- dump(cardData,"cardData") local DoubleCard = {} DoubleCard.AllDoubleCardCount = 0 DoubleCard.DoubleCardData = {} -- DoubleCard.DoubleLogicData = {} for i = 1, #cardData do local bLogicValue = self:GetCardLogicValue(cardData[i]) if self:checkIsInTable(cardData, bLogicValue, 2) then if not self:checkIsInTable(DoubleCard.DoubleCardData, bLogicValue, 2) then DoubleCard.AllDoubleCardCount = DoubleCard.AllDoubleCardCount + 1 table.insert(DoubleCard.DoubleCardData, cardData[i]) end end end --对子数量除2 DoubleCard.AllDoubleCardCount = DoubleCard.AllDoubleCardCount / 2 return DoubleCard end --分析获得所有的三张牌 拆掉所有 function GameTipUtil:AnalyseThree(cardData) -- dump(cardData,"cardData") local ThreeCard = {} ThreeCard.AllThreeCardCount = 0 ThreeCard.ThreeCardData = {} for i = 1, #cardData do local bLogicValue = self:GetCardLogicValue(cardData[i]) if self:checkIsInTable(cardData, bLogicValue, 3) then if not self:checkIsInTable(ThreeCard.ThreeCardData, bLogicValue, 3) then ThreeCard.AllThreeCardCount = ThreeCard.AllThreeCardCount + 1 table.insert(ThreeCard.ThreeCardData, cardData[i]) end end end --三张数量除3 ThreeCard.AllThreeCardCount = ThreeCard.AllThreeCardCount / 3 return ThreeCard end --分析获得所有的炸弹牌 拆掉所有 function GameTipUtil:AnalyseFour(cardData) -- dump(cardData,"cardData") local FourCard = {} FourCard.AllFourCardCount = 0 FourCard.FourCardData = {} for i = 1, #cardData do local bLogicValue = self:GetCardLogicValue(cardData[i]) if self:checkIsInTable(cardData, bLogicValue, 4) then if not self:checkIsInTable(FourCard.FourCardData, bLogicValue, 4) then FourCard.AllFourCardCount = FourCard.AllFourCardCount + 1 table.insert(FourCard.FourCardData, cardData[i]) end end end --四张数量除3 FourCard.AllFourCardCount = FourCard.AllFourCardCount / 4 return FourCard end --分析牌张------end------ -- singleCard.AllSingleCardCount = 0 -- singleCard.SingleCardData = {} -- DoubleCard.AllDoubleCardCount = 0 -- DoubleCard.DoubleCardData = {} -- ThreeCard.AllThreeCardCount = 0 -- ThreeCard.ThreeCardData = {} -- FourCard.AllFourCardCount = 0 -- FourCard.FourCardData = {} function GameTipUtil:checkShunzi(sData) print("进入顺子判断") local lessNum = 5 local shuZiResult = {} shuZiResult.cardData = {} shuZiResult.Count = 0 if sData == nil then print("没有数据 返回初始值") return shuZiResult end local tmpCards = clone(sData.SingleCardData) local tmpCount = clone(sData.AllSingleCardCount) --首先排除 黑桃2 的影响 for k, v in pairs(tmpCards) do if v == 50 then table.remove(tmpCards, 50) tmpCount = tmpCount - 1 end end --顺子起码有五张 if tmpCount < lessNum then print("少于五张 返回初始值") return shuZiResult end --接下来再进行顺子的判断 从第一张组开头进行传入 一组一组判断 最后取最大的 for i, v in ipairs(tmpCards) do local tmpTable = self:checkSz(tmpCards, i, 5) --存储结果 dump(tmpTable,"tmpTable顺子临时值") if tmpTable ~= nil and tmpTable.count > shuZiResult.Count then shuZiResult.cardData = tmpTable.cardData shuZiResult.Count = tmpTable.count end end dump(shuZiResult,"shuZiResult") if shuZiResult.Count < 5 then print("顺子数据少于5:" .. shuZiResult.Count) shuZiResult.Count = 0 shuZiResult.cardData = {} end return shuZiResult end -- DoubleCard.AllDoubleCardCount = 0 -- DoubleCard.DoubleCardData = {} --连对 起码要四张 才能出牌 function GameTipUtil:checkDui(sData) print("进入对连判断") local lessNum = 2 local lianDuiResult = {} lianDuiResult.cardData = {} lianDuiResult.Count = 0 if sData == nil then return lianDuiResult end local tmpCards = clone(sData.DoubleCardData) local tmpCount = clone(sData.AllDoubleCardCount) --黑桃和A不会有对子 --对子起码有四张 计算是一对一对计算的 这里小于 2 if tmpCount < lessNum then return lianDuiResult end table.sort(tmpCards, sortCardsFunc) --接下来再进行顺子的判断 从第一张组开头进行传入 一组一组判断 最后取最大的 local classify = self:classifyCards(tmpCards) -- dump(tmpCards,"对连牌") -- dump(classify,"对连牌-classify") -- 确保每组牌是两张 for _, v in pairs(classify) do if #v ~= 2 then return lianDuiResult end end --将对子数据先按值排序 再取其中一个 根据单顺 判断 local tmp = {} for i = 1, #tmpCards do if i % 2 == 1 then table.insert(tmp, tmpCards[i]) end end -- dump(tmp,"对子转化成单数据") for i, v in ipairs(tmp) do local tmpTable = self:checkSz(tmp, i, 2) -- dump(i,"i=======") -- dump(tmpTable,"tmpTable=======") --存储结果 if tmpTable ~= nil and tmpTable.count > lianDuiResult.Count then lianDuiResult.cardData = tmpTable.cardData lianDuiResult.Count = tmpTable.count end end -- dump(lianDuiResult,"lianDuiResult 判断顺子返回的") --还原数据 local temp = lianDuiResult.cardData lianDuiResult.cardData = {} -- dump(classify,"分组数据classify") -- dump(temp,"temp 储存的返回数据") for _, v in pairs(classify) do for _, k in pairs(temp) do -- dump(self:GetCardLogicValue(v[1]),"self:GetCardLogicValue(v[1]) 储存的返回数据") -- dump(k,"k 储存的返回数据") if self:GetCardLogicValue(v[1]) == self:GetCardLogicValue(k) then for _, j in pairs(v) do table.insert(lianDuiResult.cardData, j) end end end end lianDuiResult.Count = lianDuiResult.Count * 2 dump(lianDuiResult,"lianDuiResult") return lianDuiResult end --判断两张牌是不是对子 function GameTipUtil:checkduizi( sData ) if sData == nil then return end -- dump(sData,"sData?????") dump(self:checkSameVal(sData),"checkduizi") if self:checkSameVal(sData) then -- print("checkduizi true") return true end -- print("checkduizi false") return false end --判断三张 原本是用来 判断三张的 根据需求 暂时不使用 function GameTipUtil:checkThree(sData) if sData == nil then return end local Result = {} Result.cardData = {} Result.Count = 0 local tmpCards = clone(sData) dump(tmpCards,"checkThree-tmpCards") dump(self:checkSameVal(tmpCards),"self:checkSameVal(tmpCards)") if self:checkSameVal(tmpCards) then Result.cardData = tmpCards Result.Count = 3 end return Result end function GameTipUtil:checkPlan(sData) -- print("进入飞机判断") if sData == nil then return end local planeResult = {} planeResult.cardData = {} planeResult.Count = 0 local tmpCards = clone(sData.ThreeCardData) local tmpCount = clone(sData.AllThreeCardCount) local classify = self:classifyCards(tmpCards) -- dump(classify, '三张转化成单数据') local ThreeCount = 0 local checkShun = {} for _, v in ipairs(classify) do if #v >= 3 then ThreeCount = ThreeCount + 1 table.insert(checkShun, v[1]) end end --三张 带两张 if ThreeCount == 1 then print('三张不能作为飞机 直接return') local leftCard = self:getLeft(self.cardData,tmpCards) if #leftCard>=2 then planeResult.cardData = tmpCards planeResult.Count = 5 -- dump(leftCard,"leftCard") for i=1,2 do table.insert( planeResult.cardData, leftCard[i] ) end end return planeResult end if #checkShun >= 2 then table.sort(checkShun, sortCardsFunc) end --两个三张才能是顺子 for i, v in ipairs(checkShun) do local tmpTable = self:checkSz(checkShun, i, 2) -- dump(tmpTable,"tmpTable=======") --存储结果 if tmpTable ~= nil and tmpTable.count > planeResult.Count then planeResult.cardData = tmpTable.cardData planeResult.Count = tmpTable.count end end --还原数据 local temp = planeResult.cardData planeResult.cardData = {} for _, v in pairs(classify) do for _, k in pairs(temp) do if self:GetCardLogicValue(v[1]) == self:GetCardLogicValue(k) then for _, j in pairs(v) do table.insert(planeResult.cardData, j) end end end end planeResult.Count = planeResult.Count * 3 local leftCard = self:getLeft(self.cardData, planeResult.cardData) -- dump(leftCard, '除了三张以外的牌张') --处理带牌 table.sort(leftCard, sortCardsFunc) -- dump(ThreeCount, '处理带牌---三张数量') if planeResult.Count/3 == 2 and #leftCard >= 4 then -- print("进入 2 ") for i = 1, 4 do table.insert(planeResult.cardData, leftCard[i]) planeResult.Count = planeResult.Count + 1 end elseif planeResult.Count/3 == 3 and #leftCard >= 6 then -- print("进入 3 ") for i = 1, 6 do table.insert(planeResult.cardData, leftCard[i]) planeResult.Count = planeResult.Count + 1 end end -- dump(planeResult, 'planeResult========') return planeResult end --炸弹连 四代三 这两个选择 function GameTipUtil:checkBomb(sData) -- print("进入四张判断") if sData == nil then return end local bombResult = {} bombResult.cardData = {} bombResult.Count = 0 local tmpCards = clone(sData.FourCardData) local tmpCount = clone(sData.AllFourCardCount) --分析函数 local classify = self:classifyCards(tmpCards) -- dump(classify, '四张分组数据') --一般来说 就是四带三 if tmpCount == 1 then local leftCard = self:getLeft(self.cardData, tmpCards) -- dump(leftCard, 'leftCard') bombResult.cardData = tmpCards if #leftCard >= 3 then table.sort(leftCard, sortCardsFunc) for i = 1, 3 do table.insert(bombResult.cardData, leftCard[i]) end end bombResult.Count = 7 end --炸弹连 if tmpCount >= 2 then local checkShun = {} for _, v in ipairs(classify) do if #v == 4 then table.insert(checkShun, v[1]) end end if #checkShun >= 2 then table.sort(checkShun, sortCardsFunc) end -- dump(checkShun,"checkShun 检测顺子的排序") --两个四张才能是 炸弹顺 for i, v in ipairs(checkShun) do local tmpTable = self:checkSz(checkShun, i, 2) -- dump(tmpTable,"tmpTable=======") --存储结果 if tmpTable ~= nil and tmpTable.count > bombResult.Count then bombResult.cardData = tmpTable.cardData bombResult.Count = tmpTable.count end end -- dump(bombResult,"bombResult 还原之前") --还原数据 local temp = bombResult.cardData bombResult.cardData = {} for _, v in pairs(classify) do for _, k in pairs(temp) do if self:GetCardLogicValue(v[1]) == self:GetCardLogicValue(k) then for _, j in pairs(v) do table.insert(bombResult.cardData, j) end end end end bombResult.Count = bombResult.Count * 4 -- dump(bombResult,"bombResult 还原之后") end return bombResult end --最终调用方法------start------ function GameTipUtil:GetTipType(cardData) if cardData == nil then print('GetTipType传入牌张为空值') return end --总数据 self.cardData = cardData dump(cardData,"GetTipType-------") local util = GameTipUtil:new() if #cardData <= 4 then dump(cardData,"cardData 三张以下 不做处理") return cardData end local sData = util:AnalyseSingle(cardData) local dData = util:AnalyseDouble(cardData) local tData = util:AnalyseThree(cardData) local fData = util:AnalyseFour(cardData) --顺子判断 2 不算 dump(sData,"顺子数据") local shunZiResult = self:checkShunzi(sData) -- 连对判断 -- dump(dData,"分析的dData对子数据") local lianDuiResult = self:checkDui(dData) --飞机判断 local PlanResult = self:checkPlan(tData) --四张判断 local bombResult = self:checkBomb(fData) dump(shunZiResult,"shunZiResult") dump(lianDuiResult,"lianDuiResult") dump(PlanResult,"PlanResult") dump(bombResult,"bombResult") local FinalResult = {} local tempCount = 0 if shunZiResult and shunZiResult.Count > tempCount then tempCount = shunZiResult.Count FinalResult = shunZiResult.cardData end if lianDuiResult and lianDuiResult.Count > tempCount then tempCount = lianDuiResult.Count FinalResult = lianDuiResult.cardData end if PlanResult and PlanResult.Count > tempCount then tempCount = PlanResult.Count FinalResult = PlanResult.cardData end if bombResult and bombResult.Count > tempCount then tempCount = bombResult.Count FinalResult = bombResult.cardData end dump(FinalResult,"最终选择结果FinalResult") return FinalResult end --最终调用方法------end------ return GameTipUtil
需求:1.去掉 3个 A,3个2, 一个 K(服务器)
2.提示换牌 由大到小 (凑成其他牌型提示优先级降低,匹配牌型优先)
3.3带2提示优先单张
4.出牌最多的选择
1 = "0x1" 方块 A
2 = "0x2" 方块 2
3 = "0x3" 方块 3
4 = "0x4" 方块 4
5 = "0x5" 方块 5
6 = "0x6" 方块 6
7 = "0x7" 方块 7
8 = "0x8" 方块 8
9 = "0x9" 方块 9
10 = "0xa" 方块 10
11 = "0xb" 方块 J
12 = "0xc" 方块 Q
13 = "0xd" 方块 K
14 = "0xe"
15 = "0xf"
16 = "0x10"
17 = "0x11" 梅花 A
18 = "0x12" 梅花 2
19 = "0x13" 梅花 3
20 = "0x14" 梅花 4
21 = "0x15" 梅花 5
22 = "0x16" 梅花 6
23 = "0x17" 梅花 7
24 = "0x18" 梅花 8
25 = "0x19" 梅花 9
26 = "0x1a" 梅花 10
27 = "0x1b" 梅花 J
28 = "0x1c" 梅花 Q
29 = "0x1d" 梅花 K
30 = "0x1e"
31 = "0x1f"
32 = "0x20"
33 = "0x21" 红桃 A
34 = "0x22" 红桃 2
35 = "0x23" 红桃 3
36 = "0x24" 红桃 4
37 = "0x25" 红桃 5
38 = "0x26" 红桃 6
39 = "0x27" 红桃 7
40 = "0x28" 红桃 8
41 = "0x29" 红桃 9
42 = "0x2a" 红桃 10
43 = "0x2b" 红桃 J
44 = "0x2c" 红桃 Q
45 = "0x2d" 红桃 K
46 = "0x2e"
47 = "0x2f"
48 = "0x30"
49 = "0x31" 黑桃 A
50 = "0x32" 黑桃 2
51 = "0x33" 黑桃 3
52 = "0x34" 黑桃 4
53 = "0x35" 黑桃 5
54 = "0x36" 黑桃 6
55 = "0x37" 黑桃 7
56 = "0x38" 黑桃 8
57 = "0x39" 黑桃 9
58 = "0x3a" 黑桃 10
59 = "0x3b" 黑桃 J
60 = "0x3c" 黑桃 Q
61 = "0x3d" 黑桃 K
62 = "0x3e"
63 = "0x3f"
64 = "0x40"