[C++] 麻将胡牌算法

您所在的位置:网站首页 日本麻将牌数量 [C++] 麻将胡牌算法

[C++] 麻将胡牌算法

2024-04-30 03:11| 来源: 网络整理| 查看: 265

麻将的玩法规则众多,核心的玩法是一致的,本文将根据联发科2017年编程挑战赛的复赛题规则来实现。

牌的表示方式 ABCDEFGHI代表一到九萬,abcdefghi代表一到九条,123456789代表一到九饼

三种胡牌牌型

普通牌型,14张牌,形如:3+3+3+3+2。其中数字2代表两张相同的牌可成一组,形如XX。数字3代表三张相同或者连续的牌可成一组,形如XXX、XYZ。 龙七对,14张形如:2+2+2+2+2+2+2。 带杠,即普通牌型里三张一样的牌XXX可以升级成XXXX,称为一道杠。每多一道杠,牌总数可以增加一张。最多可以有4道杠,因此带杠的胡牌,牌总数最多可以达18张。

样例

ABCeee345456DD 胡牌,组牌方式为 ABC+eee+345+456+DD,普通牌型。 ABeeee345456DD 炸胡,因为AB两张牌未能形成组牌。 AAAABC123456333 炸胡,虽然看似组牌OK(AAA+ABC+124+345+456+333)但是不符合任何一种胡牌牌型。 AADDFF1133aagg 胡牌,暗七对。 AAAABBBBCCCCDDDD88 胡牌,3+3+3+3+2牌型,升级了4道杠。 AAA123789 炸胡,不符合任何一种牌型。 AAA111345666DEF88 炸胡,不符合任何一种牌型。 算法实现思路

1、普通牌型为3n+2的形式,和龙7对均为14张牌,若有杠则最多有18张牌,因此第一步可以判定,如果牌数小于14或者大于18,则必定不能胡牌;

2、对牌进行从小到大排序,方便后续判断。如果手牌数是14张,可以先判定是否是龙7对(对对胡),其特点是每张奇数位的牌都和它后一位的牌相等。如果不是对对胡,则进入步骤3;

3、3n+2形式的普通牌型里面有一个对子,因此判断是不是胡牌牌型,可以先找出其中的一个对子。一张牌可能有2张也可能有4张,可以组成对子也可能组成暗杠或者杠,又或者是和后面的牌组成顺子。不管情况有多少种,对子一定是出现在重复的牌之中,只要每次遍历去除一个对子即可。接下来进入步骤4;

4、去除一个对子后,判定是否是3n牌型,即是否是全部由顺子或者暗杠组成。由于牌已经经过排序,所以只要观察第一张牌即可。

如果第一张牌的数量只有一张或者两张,则这张牌必须和后面的牌组成顺子,否则不能胡牌。如果存在这样的顺子,去除这个顺子 如果第一张牌的数量有三张或者四张,则可能组成一个暗杠,或者是和后面的牌组成顺子(先不考虑有杠的情况),去除这个暗杠(顺子)

一直循环以上的判断,满足条件则去掉这三张牌,直到牌数为0时,返回“胡牌”,否则回到步骤3中,将之前去除的对子放回,继续删除下一个对子。如果步骤3中尝试过所有的对子还没能满足胡牌条件时,则返回“不胡牌”;

5、如果牌数为15张,则至少包含一个4张牌的杠,否则不胡牌。如果包含多个杠,则依次遍历删除一个杠,再进入步骤3,判断是不是3n牌型。如果遍历完所有的杠后还不能胡牌,则返回“不胡牌”;

6、如果牌数是16张,则至少包含2个杠,依次遍历删一对杠的组合,余下同步骤5类似。同理,牌数为17张和18张时方法类似。

C++源代码 #include #include #include using std::vector; using std::cout; template void showVector(vector & lst); vector findReptPos(vector & lst); bool isDDH(const vector & lst); bool isHU3N(vector & lst); vector delDUI(const vector & lst, const int x); bool is3N(vector lst); int numOfFirst(vector lst); bool checkGroup(vector lst, const int num); void delGroup(vector & lst, const int num); vector delGANG(const vector & lst, const int x); vector findGangPos(const vector & lst); int main(int argc, char **argv) { char *mahjong = argv[1]; vector lst; for (int i = 0; mahjong[i] != '\0'; ++i) { lst.push_back(mahjong[i]); } std::sort(lst.begin(), lst.end()); // 从小到大排序 /*cout 18)) { cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3