lua学习笔记---6.斗地主牌型判定逻辑

644 阅读4分钟

加载斗地主工具类、创建斗地主类以及牌型

local CardUtils = require "qilaiUtils"  --加载文件
local CardsType = 
{
    Single = 1,         -- 单张
    DuiZi = 2,          -- 对子
    ShunZi = 3,         -- 顺子
    LianDui = 4,        -- 连对
    Three = 5,          -- 三张
    ThreeTakeOne = 6,   -- 三带一
    ThreeTakeTwo = 7,   -- 三带二
    FourTakeTwo = 8,    -- 四带二
    FeiJi = 9,          -- 三张(333444)/三张带一(33344455/33344445/33334444)/三带两对(3334445566)
    Boom = 10,          -- 炸弹
    BoomBoom = 11,      -- 王炸
    None = 12           -- 不符合牌型
}
local DDZLogic = {}

记牌器:将选中的牌转换成(牌值对应数量的键值对)

function DDZLogic:toCardMap(selectedCards)
    local map = {}
    -- size对应选中牌的数量
    map.size = #selectedCards
    for i = 1,20 do
        map[i] = 0
    end
    for i = 1,#selectedCards do
        local value = CardUtils:getCardValue(selectedCards[i])
        map[value] = map[value] + 1
    end
    return map
end

判断是否是单张

function DDZLogic:isSingle(cards)   -- cards:记牌后的结果
    return cards.size == 1
end

判断是否是对子

function DDZLogic:isDuiZi(cards)
    if cards.size ~= 2 then
        return false
    end
    for i = 1, #cards do
        if cards[i] ~= 0 then
            return 2 == cards[i]
        end
    end
end

获取牌中对子的数量

function DDZLogic:getDuiZiCount(cards)
    local count = 0
    for i = 1,#cards do
        if cards[i] == 2 then
            count = count + 1
        end
    end
    return count
end

判断是否是顺子

function DDZLogic:isShunZi(cards)
    if cards.size < 5 then
        return false
    end

    for i = 1, #cards do
        if cards[i] == 1 then
            -- 遍历从1开始到i + cards.size-1对应的数量都为1
            for j = 1,cards.size - 1 do
                local cardNum = cards[i + j]
                if cardNum ~= 1 then
                    return false
                end
            end
            return true
        end
    end
    return false    --没有顺子
end

判断是否是连对

function DDZLogic:isLianDui(cards)
    if cards.size < 6 or ( cards.size >= 6 and cards.size % 2 == 1 )then
        return false
    end
    for i = 1, #cards do
        if cards[i] == 2 then
            -- 遍历从1开始到i + cards.size-1对应的数量都为2
            for j = 1,cards.size / 2 - 1 do
                local cardNum = cards[i + j]
                if cardNum ~= 2 then
                    -- print("-----")
                    return false
                end
            end
            return true
        end
    end
    return false
end

判断是否是三张

function DDZLogic:isThree(cards)
    if cards.size ~= 3 then
        return false
    end
    for i = 1, #cards do
        if cards[i] ~= 0 then
            return 3 == cards[i]
        end
    end
end

判断是否是三带一

function DDZLogic:isThreeTakeOne(cards)
    if cards.size ~= 4 then
        return false
    end

    for i = 1,#cards do
        if cards[i] == 3 then
            return true
        end
    end
    return false
end

判断是否是三带一对

function DDZLogic:isThreeTakeTwo(cards)
    if cards.size ~= 5 then
        return false
    end
    local hasTwo = false
    local hasThree = false
    for i = 1,#cards do
        if 2 == cards[i] then
            hasTwo = true
        elseif 3 == cardNum then
            hasThree = true 
        end
    end
    return hasTwo and hasThree
end

判断是否是四带二

function DDZLogic:isFourTakeTwo(cards)
    if cards.size ~= 6 then
        return false
    end

    for i = 1,#cards do
        if cards[i] == 4 then
            return true
        end
    end
    return false
end

判断是否是飞机

function DDZLogic:isFeiJi(cards)
    if cards.size < 6 then
        return false
    end

    -- 3 * n 的情况
    if cards.size % 3 == 0 then
        local feijiLength = cards.size / 3  --飞机总长度
        local length = 0 -- 记录的长度
        for i = 1,#cards do
            local cardNum = cards[i]
            if cardNum == 3 then 
                length = length + 1
                if feijiLength == length then 
                    return true
                end
            else
                length = 0
            end
        end
    end

    -- (3 + 1) * n的情况
    if cards.size % 4 == 0 then
        local feijiLength = cards.size / 4  --飞机总长度
        local length = 0 -- 记录的长度
        for i = 1,#cards do
            local cardNum = cards[i]
            if cardNum >= 3 then 
                length = length + 1
                if feijiLength == length then 
                    return true
                end
            else
                length = 0
            end
        end
    end

    -- (3 + 2) * n 的情况
    if cards.size % 5 == 0 then
        local feijiLength = cards.size / 5  --飞机总长度
        local length = 0 -- 记录的长度
        for i = 1,#cards do
            local cardNum = cards[i]
            if cardNum == 3 then 
                length = length + 1
                if feijiLength == length then 
                    -- 从i往后到结尾,所有的牌值对应的数量不能为1和3
                    for j = i + 1,#cards do
                        local cardNum = cards[j]
                        if 1 == cardNum or 3 == cardNum then
                            return false
                        end
                    end
                    return true
                end
            else
                -- length = 0
                if cardNum == 1 then  -- 当出现数量为1
                    return false
                end
                if length > 0 then    -- 之前已经出现了3张
                    return false
                end
            end
        end
    end

    return false
end

判断是否是炸弹

function DDZLogic:isBoom(cards)
    if cards.size ~= 4 then
        return false
    end
    for i = 1,#cards do
        if cards[i] == 4 then
            return true
        end
    end
    return false
end

-- 判断是否是王炸
function DDZLogic:isBoomBoom(cards)
    if cards.size ~= 2 then
        return false
    end

    return cards[18] == 1 and cards[19] == 1
end

获取选中牌的类型

function DDZLogic:getCardsType(selectedCards)    
    local cards = self:toCardMap(selectedCards) --转为记牌器
    if self:isSingle(cards) then
        return CardsType.Single
    end
    if self:isDuiZi(cards) then
        return CardsType.DuiZi
    end
    if self:isShunZi(cards) then
        return CardsType.ShunZi
    end
    if self:isLianDui(cards) then
        return CardsType.LianDui
    end
    if self:isBoom(cards) then
        return CardsType.Boom
    end
    if self:isThree(cards) then
        return CardsType.Three
    end
    if self:isThreeTakeOne(cards) then
        return CardsType.ThreeTakeOne
    end
    if self:isThreeTakeTwo(cards) then
        return CardsType.ThreeTakeTwo
    end
    if self:isFourTakeTwo(cards) then
        return CardsType.FourTakeTwo
    end
    if self:isBoomBoom(cards) then
        return CardsType.BoomBoom
    end
    if self:isFeiJi(cards) then
        return CardsType.FeiJi
    end
    return CardsType.None
end

测试代码

local selectedCards = {0x14, 0x24, 0x35, 0x15, 0x25, 0x36, 0x16, 0x26, 0x38, 0x18}
local type = DDZLogic:getCardsType(selectedCards)
print(type)