游戏设计&游戏开发cocos 2dx游戏设计

麻将胡牌算法

2017-09-04  本文已影响808人  小黑_Coder

犹豫工作和自己学习了一些新的东西,今天打开博客吓自己一跳,原来自己这么久没有更新博客了。看来以后还是要坚持每周最少写一篇博客啊。

在讲解麻将胡牌算法之前,先说说为什么写这么一篇博客吧。在做项目中,其实前辈们早就封装好了一些胡牌的检测算法,不过我还算是一个比较喜欢刨根问到底的人,每次调用别人写好的算法的时候总是想知道算法的具体实现。然而在看算法具体实现的时候,发现里面一个二维矩阵有点复杂,并且没有没有注释。所以改换另一条路去研究胡牌算法,先去网上找了找一般胡牌算法实现的原理然后自己写了写,就是下面即将展示给大家的胡牌算法(不含特殊牌型的检测)

1.名词解释

名词 解释
即胡牌必须具备的一个对子
克子 即三个相同的牌
顺子 即同种牌型三个连续的牌
胡牌 即手中的牌除了一对将之外全部能组成克子或者顺子

2.数据结构

2.1.麻将矩阵(二维矩阵)

    mahjongMatrix = {
        [0] = {[-1]=0,[0]=0,[1]=0,[2]=0,[3]=0,[4]=0,[5]=0,[6]=0,[7]=0,[8]=0,[9]=0,[10]=0,[11] = 0}, --万
        [1] = {[-1]=0,[0]=0,[1]=0,[2]=0,[3]=0,[4]=0,[5]=0,[6]=0,[7]=0,[8]=0,[9]=0,[10]=0,[11] = 0}, --筒
        [2] = {[-1]=0,[0]=0,[1]=0,[2]=0,[3]=0,[4]=0,[5]=0,[6]=0,[7]=0,[8]=0,[9]=0,[10]=0,[11] = 0}, --条
    }

2.2.麻将

card = 0x0101 --四位的16进制的数表示一张牌

3.算法核心流程

玩过麻将都应该知道,一般判断手上的牌是否能胡,就是检测手牌除了一对将之后剩下的牌是否能组成克字或顺子并且没有剩余的手牌。

3.1.定义手牌

3.2.将手牌转换成麻将矩阵

-- 麻将类型定义
local mahjongType = {
    [0] = "万",
    [1] = "筒",
    [2] = "条",
}

-- 初始化一个麻将矩阵
function initMahjongMatrix()

    local mahjongMatrix = {}
    for i = 0, 3 do
        mahjongMatrix[i] = {}
        for j = -1, 11 do
            mahjongMatrix[i][j] = 0
        end
    end 
    return mahjongMatrix;
end

-- 打印麻将矩阵
function dumpMahjongMatrix(mahjongMatrix)

    local dumpInfo = "{ "
    for cardType, mahjongList in pairs(mahjongMatrix) do
        for mahjongValue, count in pairs(mahjongList) do
            for i = 1, count do
                dumpInfo = dumpInfo .. mahjongValue .. mahjongType[cardType] .. " "
            end
        end
    end
    dumpInfo = dumpInfo .. "}"
    print(dumpInfo)
end

-- 将手牌转换成麻将矩阵
function cardListConvertToMatrix(cardList)

    local mahjongMatrix = initMahjongMatrix()
    for _, card in pairs(cardList) do
        local cardType = card >> 12
        local cardValue = (card >> 8) & 0x0F
        mahjongMatrix[cardType][cardValue] = mahjongMatrix[cardType][cardValue] + 1
    end
    dumpMahjongMatrix(mahjongMatrix)
    return mahjongMatrix
end

3.3.检测将

-- 深拷贝
function deepCopy(sourceData)

    if type(sourceData) == "table" then
        local temp = {}
        for key, value in pairs(sourceData) do
            temp[key] = deepCopy(value)
        end
        return temp
    end
    return sourceData
end

-- 通过去除麻将矩阵中一个将之后的麻将矩阵列表
function getMahjongMatrixListByRemoveTwoCards(mahjongMatrix)

    local mahjongMatrixList = {}
    for cardType, mahjongList in pairs(mahjongMatrix) do
        for mahjongValue, count in pairs(mahjongList) do
            if count >= 2 then
                local temp = deepCopy(mahjongMatrix)
                temp[cardType][mahjongValue] = temp[cardType][mahjongValue] - 2
                table.insert(mahjongMatrixList, temp);
            end
        end
    end
    return mahjongMatrixList
end

3.4.检测句子和克字

现在便利麻将矩阵,如果只有一张的牌那么这张牌A就只能当作顺子的开头;如果有两张的牌,因为已经有将而这两张也不能组成克子,所以这两张只能当作两个顺子的开头;如果有三张这样的牌,可以组成克子,但是如果让他组成顺子则要求为AAABBBCCC与后面的三张也能组成克子,所以组成顺子或者克子本质是相同的。但是组成克子AAA的通用性要高于组成顺子AAABBBCCC所以当有三个及以上这样牌的时候优先组成克子AAA;如果有四张这样的牌,要能胡牌则需要AAAABBBBCCCC或者AAAABC,对于是先组一个顺子还是一个克子都会回到上述的情况

3.4.1.检测句子

-- 移除麻将矩阵中的句子
function removeThreeLinkCards(mahjongMatrix)

    for cardType, mahjongList in pairs(mahjongMatrix) do
        for mahjongValue, count in pairs(mahjongList) do
            for i=1, count do
                local mahjongValuePlusOneCount = mahjongList[mahjongValue+1]
                local mahjongValuePlusTwoCount = mahjongList[mahjongValue+2]
                if count > 0 and mahjongValuePlusOneCount > 0 and mahjongValuePlusTwoCount > 0 then
                    mahjongList[mahjongValue] = mahjongList[mahjongValue] - 1
                    mahjongList[mahjongValue+1] = mahjongList[mahjongValue+1] - 1
                    mahjongList[mahjongValue+2] = mahjongList[mahjongValue+2] - 1
                end
            end
        end
    end
end

3.4.2.检测克子

-- 检测克子
function removeTheSameThreeCards(mahjongMatrix)
    for cardType, mahjongList in pairs(mahjongMatrix) do
        for mahjongValue, count in pairs(mahjongList) do
            if count >= 3 then
                mahjongList[mahjongValue] = mahjongList[mahjongValue] - 3
            end
        end
    end
end

3.5.是否胡牌

-- 检测矩阵中元素是否全部为0
function checkMatrixAllElemEqualZero(mahjongMatrix)

    for cardType, mahjongList in pairs(mahjongMatrix) do
        for mahjongValue, count in pairs(mahjongList) do
            if count ~= 0 then
                return false
            end
        end
    end
    return true
end

-- 检测是否胡牌
function checkHu(cardList)

    local mahjongMatrix = cardListConvertToMatrix(cardList)
    local mahjongCardList = getMahjongMatrixListByRemoveTwoCards(mahjongMatrix)
    for _, matrix in ipairs(mahjongCardList) do
        removeThreeLinkCards(matrix)
        removeTheSameThreeCards(matrix)
        local result = checkMatrixAllElemEqualZero(matrix)
        if result == true then
            return true
        end
    end
    return false
end

3.6.回答上面的疑问

4.欢迎讨论

Email huliuworld@yahoo.com
Github https://github.com/LHCoder2016/MahjongArithmetic.git

上一篇下一篇

猜你喜欢

热点阅读