麻将胡牌算法的Java实现

来源:互联网 发布:google翻译软件 编辑:程序博客网 时间:2024/04/29 00:53

最近一个棋牌游戏项目中涉及对麻将胡牌的判定,网上搜了搜虽然看到一些算法,但是感觉都不尽如人意,一般麻将的胡牌为1对和4组三张牌的连牌,所以在网上搜到的算法往往都死死的为了这个目的来实现,而且多数没有考虑到对百塔牌的支持,下面贴上代码:

这是对单张麻将牌进行的一个简单封装,比较简单硬性的将麻将对象设为两个主要属性,一个是类型,一个是类型编号,比如万,比如桶就属于不同的类型,而1万,3万这样的同属于万类型下的不同类型编号,同时给了一个 STANDARD_MAHJONG_NAMES 三维数组常量,用来封装不同格式的麻将名称,比如有些地方二桶就二饼,再比如中文,英文的区别等等,就不多说了,这个类主要提供的核心功能为isCanTwo(MahjongTile mahjongTile),isCanThree(MahjongTile mahjongTileOne, MahjongTile mahjongTileTwo),isCanAny() 三个方法,顾名思义isCanTwo用来判断是否可以跟另外一张麻将牌结成对子,isCanThree 用来判断是否可以跟另外两张麻将结成趟,至于isCanAny()是用来判断该麻将是否具备百搭属性,我的代码中对于isCanAny() 的实现是随便写的,只是假设9万为百搭,至于为什么 type == 1 && typeId == 9 代表的是9万,自己看代码。


下面再贴两个无关紧要的异常类:

这两个类很简单,主要是当MahjongTile对象初始化的时候参数是否正确的判断,比如用十万初始化肯定要抛异常的.在这里就不多说了。


下面贴上核心工具类:


这个类是用来判断胡牌的核心类,它用来判断胡牌的方法为 public static MahjongTile[][] tryCombination(MahjongTile[] mahjongTiles, int twoNum, int threeNum) 这个,
我们看这个方法的内部其实是对另外一个同名方法的 调用,我们来看这个方法的参数,mahjongTiles 这个不用说是带进去判断的麻将对象的数组,twoNum和threeNum的意思分别是需要判断参数mahjongTiles中是否有且仅有twoNum个对子和threeNum个趟,那么一般胡牌判断的话,这两个参数自然一个是1,一个是4了,就是判断麻将是否是1对+4趟,那么为什么这里要这么写呢,主要为了方便扩展,比如很多地方有7小对可以胡牌的,再比如打牌过程中,碰了,杠了的牌,可以直接不去考虑,只要考虑出去碰,杠外还缺几对和几趟就可以胡牌,这样一来,这个方法就显得很灵活,不拘泥于1对+4趟,那么这个方法返回的是一个MahjongTile对象的二维数组是什么意思呢,意思就是当返回为空时,说明判断不成立,当返回的是实打实的数组的时候就说明一定满足你带进去的参数twoNum个对子和threeNum个趟,同时这个实打实的数组就是按照参数要求的组合,比如您带进去twoNum为1threeNum为4的话,那么如果能胡牌,返回的一定是一个第一维长度为5的二维数组,同时第一个元素的长度又为2,对应的是对子,下面的4个元素的长度为3对应的是4趟。 这个方法的核心思想就是递归,每一次执行就找出来一个对子,或者一组三张联牌,然后把还需要的组合递归下去,具体算法可以仔细看代码,本人写代码不太喜欢写太多注释,好在代码比较短,容易懂。


在该类的public static void main(String[] args)方法下有判断胡牌的实例代码。


原创文章,转载请注明原地址

1 3