麻将胡牌,听牌算法

算法分析参照下面的blog麻将胡牌算法

我用lua写了一个简化的麻将算法,只考虑麻将字牌和万

牌编号1~9对应1-9万,10-16是字牌

下面是lua代码

local print = print
local tconcat = table.concat
local tinsert = table.insert
local srep = string.rep
local type = type
local pairs = pairs
local tostring = tostring
local next = next

function print_r(root)
    local cache = {  [root] = "." }
    local function _dump(t,space,name)
        local temp = {}
        for k,v in pairs(t) do
            local key = tostring(k)
            if cache[v] then
                tinsert(temp,"+" .. key .. " {" .. cache[v].."}")
            elseif type(v) == "table" then
                local new_key = name .. "." .. key
                cache[v] = new_key
                tinsert(temp,"+" .. key .. _dump(v,space .. (next(t,k) and "|" or " " ).. srep(" ",#key),new_key))
            else
                tinsert(temp,"+" .. key .. " [" .. tostring(v).."]")
            end
        end
        return tconcat(temp,"\n"..space)
    end
    print(_dump(root, "",""))
end

local Hu = {}

function analyze(cards, zi)
    print_r(cards)
    print("zi", zi)
    if not next(cards) then
        return true
    end
    local start
    local over
    if zi then
        start = 10
        over = 16
    else
        start = 1
        over = 9
    end
    local finish = true
    for i = start, over do
        if cards[i] and cards[i] ~= 0 then
            start = i
            finish = false
            break
        end
    end
    if finish then -- 手牌为空
        return true
    end
    print("start", start)
    local result
    if cards[start] and cards[start] >= 3 then -- 刻牌
        cards[start] = cards[start] - 3
        result = analyze(cards , zi)
        cards[start] = cards[start] + 3
        return result
    end
    if not zi and cards[start +1] and cards[start + 2] and cards[start + 1] > 0 and cards[start + 2] > 0 then
        cards[start ] = cards[start ] - 1
        cards[start + 1] = cards[start + 1] - 1
        cards[start + 2] = cards[start + 2] - 1
        result = analyze(cards, zi)
        cards[start ] = cards[start ] + 1
        cards[start + 1] = cards[start + 1] + 1
        cards[start + 2] = cards[start + 2] + 1
        return result
    end
    return false
end

function fmod( arr, num)
    local count = 0
    for k, v in pairs(arr) do
        count = count + v
    end
    return count % num
end

--是否可胡牌
function Hu:win( cards)
    local jiangPos
    local yuShu
    local jiangExisted = false
    local wan = {}
    local zi = {}
    for k, v in pairs(cards) do
        if k < 10 then
            wan[k] = v
        else
            zi[k] = v
        end
    end
    -- wan
    yuShu = fmod(wan, 3)
    if yuShu == 1 then
        return false
    elseif yuShu == 2 then
        jiangPos = wan
        jiangExisted = true
    end
    --zi
    yuShu = fmod(zi, 3)
    if yuShu == 1 then
        return false
    elseif yuShu == 2  then
        if jiangExisted then
            return false
        else
            jiangPos = zi
        end
    end

    if jiangPos == wan then
       if not analyze(zi, true) then
            return false
        end
    elseif not analyze(wan, false) then
        return false
    end
    if not jiangPos then -- no jiang
        return false
    end
    -- jiang
    local success = false
    for k, v in pairs(jiangPos) do
        if v >= 2 then
            jiangPos[k] = v - 2
            if analyze(jiangPos, jiangPos == zi) then
                success = true
            end
            jiangPos[k] = v
            if success then
                break
            end
        end
    end
    return success
end

--怎么听牌
function Hu:ting(cards)
    local success = false
    local post = {}
    local will = {}
    for k ,v in pairs(cards) do
        if v > 0 then
            cards[k] = cards[k] - 1
            print_r(cards)
            local willCards = {}
            for i = 1, 16 do
                if i ~= k then
                    if cards[i] then
                        cards[i] = cards[i] + 1
                    else
                        cards[i] = 1
                    end
                    success = self:win(cards)
                    cards[i] = cards[i] - 1
                    if success then
                        table.insert(willCards, i)
                    end
                end
            end
            cards[k] = cards[k] + 1
            if next(willCards) then
                will[k] = willCards
            end
        end
    end
    return will
end

local player = {
    [1]    = 1,
    [2] = 1,
    [3] = 1,
    [4] = 3,

    [10] = 3,
    [12] = 1,
    [13] = 1,
}
print_r(Hu:ting(player))
return Hu
时间: 2024-10-14 01:27:32

麻将胡牌,听牌算法的相关文章

成都麻将胡牌问题算法

题设: * 成都麻将只能包括3种类型:筒(D),万(W),条(T).没有“门.东南西北.红中”. * 每种牌都是数字从1到9,每个数字有4张,共36张.筒(D),万(W),条(T)均一样. *  * 胡牌规则如下:  * 1.手里面的牌最多只有两种类型,即必须打缺一种,不能出现:条,筒,万都存在的情况. * 2.必须有一个对子,即两张相同的牌,比如:两个2筒,两个4条等.  * 3.剩余的牌,每3张需要凑成一个有效牌,比如:3个一样的牌(3个2筒), * 或者3个顺子(1条2条3条),如果所有的

麻将胡牌

啊真不容易,本来觉得自己肯定写不出来,然后竟然写出来了,真是非常开心了~ 主要思路还是递归,受以前算法设计课上的排列树启发,在有多种可能的情况下,就一个一个试嘛 题目: 有三种胡牌牌型 普通牌型,14张牌,形如:3+3+3+3+2.其中数字2代表两张相同的牌可成一组,形如XX.数字3代表三张相同或者连续的牌可成一组,形如XXX.XYZ. 龙七对,14张形如:2+2+2+2+2+2+2. 带杠,即普通牌型里三张一样的牌XXX可以升级成XXXX,称为一道杠.每多一道杠,牌总数可以增加一张.最多可以有

斗地主牌型基本算法升级版本

斗地主牌型基本算法升级版本 好久没更新博客了,前段时间和朋友一起开了一个公司 做APP,最后失败了.现在又开始做棋牌游戏了,最近在看网狐的源码,发现里面斗地主的基本算法太强大了,现在想想我原来的算法简直是弱爆了,分享一下 希望能对你有一点点帮助.以下主要涉及到判断牌型,牌型大小比较2块,如果你想了解更多关于棋牌游戏的东西请访问我的 棋牌游戏专栏. 一.判断牌型 定义一个结构来表示每张相同牌的信息. //分析结构 structtagAnalyseResult { BYTE cbFourCount;

斗地主滑动选牌&amp;&amp;出牌(Cocos Creator)

本文主要讲解以下几个方面: card model 滑动处理 阴影 选择 出牌 Card Model   首先,牌有两个属性:数字.花型:   ps:本文现在是,用数字和花型来组成一张牌,有空可以再用另一种形式走一遍,比如用54个数字(0-53)来表示一副牌. CardInfo.js //花型 var CardSuit = cc.Enum ({ none: 0, spade: 1, //黑桃 heart: 2, //红心 club: 3, //梅花 diamond: 4,//方块 }); //数字

癞子麻将胡牌算法实现

最先实现的就是算法的实现. 需求:碰杠胡  ,不能吃 ,不能听 ,仅仅能自摸胡,当中癞子能够做随意牌可是不能碰和杠. 写的时候还不会玩麻将,还是老板教的.^_^ 最麻烦的是胡牌算法.之前搜到的都是不包括癞子正常的胡牌,用的是%3余2,当中余数2就是余的将的意思. 可是有癞子就不能这么用了.仅仅好自己写一个了. 一个有136张牌,万,饼,条,东西南北中发白34种牌. 有四个癞子是直接就胡牌的,最坏的情况是有3个癞子,可是假设遍历一遍不用逻辑推断就有34X34X34接近4万次. 想一下假设能胡牌,最

麻将胡牌算法研究

麻将通常有13张牌,在打的时候随着吃,碰越来越少.总数应该维持在3*n + 1,n=0~4,比如1张,4张,7张或10张.胡牌时,加一张(可能是自摸或吃碰来的一张)组成n个顺子或暗刻,外加一个麻将对. 这里要研究的要点是: 1. 给出3n + 2张牌如何判断是否已经胡牌,所有的胡牌可能组合: 2. 如果给出3n+1张牌如何判断是否已经挺牌,挺哪些牌. 这两个问题其实主要是第一个问题,也就是如何判断3n +2 张牌是否胡牌的问题.后者可以简单地通过实验加34种麻将牌之一看是否胡牌来判断是否挺牌,以

完美洗牌&amp;洗牌

完美洗牌问题,给定一个数组a1,a2,a3,...an,b1,b2,b3..bn,把它最终设置为b1,a1,b2,a2,...bn,an这样的. O(n)的算法,O(n)的空间. 对于前n个数,映射为f(i)=2 * i + 1, 0 <= i < n / 2; 比如0->1, 1->3 对于后n个数,映射为f(i)=2(i - n/2), n / 2 <= i < n; 比如n/2->0, n/2 + 1->2... 并且f(i) =2(i - n/2)=

实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例)

1.namedtuple:命名元组,可以创建一个没有方法只有属性的类 from collections import namedtuple card = namedtuple('card',['rank','suit']) # rank 牌面大小,suit牌面的花色 # card其实就是namedtuple创建的一个类,其属性就是rank和suit c1 = card(2,'红心 ') # c1是实例化的对象 print(c1) print(c1.suit) 运行结果: card(rank=2,

Python代码样例列表

├─algorithm│       Python用户推荐系统曼哈顿算法实现.py│      NFA引擎,Python正则测试工具应用示例.py│      Python datetime计时程序的实现方法.py│      python du熊学斐波那契实现.py│      python lambda实现求素数的简短代码.py│      Python localtime()方法计算今天是一年中第几周.py│      Python math方法算24点代码详解.py│      Pyth