zoukankan      html  css  js  c++  java
  • 麻将胡牌算法研究

    麻将通常有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种胡牌结果。

  • 相关阅读:
    【NOIP2007】守望者的逃离
    20200321(ABC)题解 by 马鸿儒 孙晨曦
    20200320(ABC)题解 by 王一帆
    20200319(ABC)题解 by 王一帆 梁延杰 丁智辰
    20200314(ABC)题解 by 董国梁 蒋丽君 章思航
    20200309(ABC)题解 by 梁延杰
    20200307(DEF)题解 by 孙晨曦
    20200306(ABC)题解 by 孙晨曦
    20200305(DEF)题解 by 孙晨曦
    20200303(ABC)题解 by 王锐,董国梁
  • 原文地址:https://www.cnblogs.com/zhuawang/p/6624740.html
Copyright © 2011-2022 走看看