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