• 麻将胡牌算法研究


    麻将通常有13张牌,在打的时候随着吃,碰越来越少。总数应该维持在3*n + 1,n=0~4,比如1张,4张,7张或10张。胡牌时,加一张(可能是自摸或吃碰来的一张)组成n个顺子或暗刻,外加一个麻将对。

    这里要研究的要点是:

    1. 给出3n + 2张牌如何判断是否已经胡牌,所有的胡牌可能组合;

    2. 如果给出3n+1张牌如何判断是否已经挺牌,挺哪些牌。

    这两个问题其实主要是第一个问题,也就是如何判断3n +2 张牌是否胡牌的问题。后者可以简单地通过实验加34种麻将牌之一看是否胡牌来判断是否挺牌,以及挺哪些牌。

     

    如何判断3n +2张牌是否胡牌

    麻将牌包括:

    1条~9条

    1万~9万

    1饼~9饼

    东西南北中发白

    34种牌,34×4=136张牌。

    给每张牌设一个编号

    1条~9条     -------à 0 ~8

    1万~9万     ------à 9~17

    1饼~9饼     ------à 18~26

    东西南北中发白    -----à 27~33

     

    1 牌的存储

    设一个宏,就是牌的种类

    #define MAX_TILE_INDEX 34

    所摸的牌就可以存在一个长度为34的数组中

    int tiles[MAX_TILE_INDEX];

    数组的每个成员最大值为4,因为每张牌的总数为4,就算摸到暗杠也不过是4. 所有数组成员加起来应该是3n + 2

     

    2 结果的存储

    每个胡牌必定是若干顺子/暗刻,外加一个麻将对,用一个简单的结构或类大概就是:

    {

             int nSequence[4][3];

             int nPair[2];  //或直接nPair,不用数组就可以表示麻将对了

    }

     

    给定的3n + 2张牌普通只胡一种情况,但特殊情况也可能有多种胡法,比如4个一万,4个两万,4个3万,2个四万

    胡牌至少可以:

    i. 4个1万,2万和3万的顺子,外加4万的麻将对;

    ii. 1个1万,2万和3万的顺子,1万暗刻,2万暗刻,3万暗刻,以及4万麻将对。

    这些结果都应该被存起来,胡牌应该以最大番数计算。

    C++可以用一个vector模板来实现结果列表,java可以考虑用哈希表。

     

    3. 胡牌判断算法

    判断胡牌与否

    判断胡牌与否的过程:

    3.1. 首先判断总牌数是否为3n + 2,如果不是肯定不胡牌

    3.2. 遍历所有牌,找到所有一种牌数量大于2的情况,也就是ntile[index] >= 2,然后把这两张牌(对子)去掉,记录到结果中的nPair。然后就剩下3n张牌了,再判断剩下的3n张牌是否能组成顺子或是暗刻,如果可以全部组成,那么这把牌就胡了,否则需要遍历一下把其他牌当对子的可能性。

    关于第二步中如何判断3n 张牌可否组成顺子或暗刻

    从第一张(种)牌开始往后检查,每张牌有5种可能, 0, 1, 2,3,4。如果是0,直接检查下一张(种);

    i. 如果是1张或两张,要胡牌的话他(们)必须和后面两张组成顺子,如果不能组成顺子,肯定不胡。如果可以组成顺子,把顺子牌取出,存入临时结果,接着处理剩下的牌;

    ii. 如果是3张,要胡牌有两种可能,一是3张当作一个暗刻,还有一种可能是这3张都与后面的牌组成顺子。这里有检查这两种情况。比如3个一万,3个两万和3个三万。既可以以三暗刻算,也可以按三个顺子算。这两种在最后算番的时候不一样。

    iii. 如果是4张,胡牌的话必须要跟后面两张牌组成一个顺子,然后本张(种)就剩3种了,然后继续2.2的步骤就可以了。

    整个检查过程可以用一个函数递归调用就可以了,每次处理一张,如果不能凑成顺子或暗刻的话就推出返回错误,如果函数处理时总牌数为0,则所有牌都已处理完了,返回成功,结果也已经存在结果里了,把结果加入结果列表。

    4. 挺牌检查

    挺牌时应该是3*n + 1张牌。遍历34种牌,加入3n +1 ,这时就是3n+2了,根据刚才的算法算是否胡牌,如果胡牌,刚加入的那张牌就是挺牌。

     

    5. 测试过程与结果

    1. 挺牌检查 –选用了非常复杂的九莲宝灯,也就是3个一万(或条,饼),3个九万(或条饼),其他2万到8万(或条饼)。这种牌是挺从1万到9万,共9张挺牌。算法可以正确算出。

    2. 胡牌检查 –选用了4个一万,4个二万,4个三万,以及2个4万,算法正确列出了3种胡牌结果。

  • 相关阅读:
    asp.net core 集成JWT(一)
    Microsoft.Extensions.DependencyInjection中的Transient依赖注入关系,使用不当会造成内存泄漏
    Microsoft.Extensions.DependencyInjection的Singleton依赖注入关系,只是对于同一个ServiceProvider是单例的
    ASP.NET Core MVC中,如何将视图文件生成的html代码通过字符串返回
    SpringBoot魔法堂:说说带智能提示的spring-boot-starter
    Maven魔法堂:安装Oracle JDBC Driver依赖的那些坑
    TypeScript魔法堂:函数类型声明其实很复杂
    TypeScript魔法堂:枚举的超实用手册
    C#获取文件与文件夹默认图标(2006-3-22 新增示例代码与程序)
    【学习笔记】Team Explorer for Microsoft Visual Studio2015 安装时发生严重错误
  • 原文地址:https://www.cnblogs.com/zhuawang/p/6624740.html
Copyright © 2020-2023  润新知