欢迎光临散文网 会员登陆 & 注册

日麻折腾笔记Java篇(1)——和牌的判断

2020-11-01 21:26 作者:天羽ちよこ  | 我要投稿

手牌和牌时的组成

日本麻将除了特殊牌形(七对和国士)以外,都是 a个顺子+b个刻子+1个雀头 的形状,这里不管是门清还是非门清,都是这样。其中a、b均大于等于0。

我们可以将手牌分解成上面的形式,如果能够满足条件,则为和牌,然而手牌的组成有很多种,比如下面的手牌(九莲宝灯):

11123455678999s

我们可以分解为

111 234 55 678 999

可以和牌

也可以分解为

11 123 345 567 8 999

无法和牌

可以看到关键在于怎么对手牌中的顺子和刻子分组

从雀头入手

不管怎么分组,手牌都要有一个雀头,所以我们先确定雀头

手牌中,数量大于等于2的牌都能作为雀头

当确定好雀头之后,就要将剩余的手牌分解为 顺子+刻子的情况,在上面的示例中,当选取5s作为雀头后,剩余的牌为 111234678999 ,我可以将 11123 认为是 111+23的形式,也可以是 11+123的形式,用程序也是比较方便实现的。

我的思路

将手牌排序后,找到n个雀头

对于每个雀头,都执行下面的判断逻辑

  1. 去除雀头,得到剩余手牌P

  2. 对P按照牌进行分组后排序

  3. 对于排序后的牌,如果是连续三张牌,则将这三张牌作为一个顺子

  4. 将顺子的三张牌从P中删除

  5. 重复2-3-4步骤,直到无顺子

  6. 对P进行分组

  7. 如果某牌数量是3,则将这三张牌作为一个刻子

  8. 将刻子从P中删除

  9. 重复6-7-8步骤,直到无刻子

  10. 如果P现在无牌,则表示此时能够和牌,如果有牌,表示不能和牌

是否听牌的判断

和牌和听牌不太一样,和牌是14张,听牌是13张,不管是不是门清状态,听牌必定币和牌少一张,少的是哪张牌呢?必定是下面三种情况中的其中一种

  1. 听雀头

  2. 听刻子中的一张

  3. 听顺子中的一张

也就是已有的手牌,加上上面三种中的其中一种,能够和牌,那我只需要将可能和牌的牌都列出来,每种都判断是否和牌就可以了。

对于自己的程序写的有没有问题,可以用九莲宝灯来验证一下

类的定义

首先是类型的枚举,定义了万、索、筒、字四种牌

public enum Type {

    m,

    s,

    p,

    z;

}

一张牌是由数字+类型组成的,所以牌类如下

public class Pai implements Comparable<Pai> {

    private Integer number;

    private Type type;

    ... getters

    ... setters


对于字牌,一共有东南西北中发白,七种类型,对应的number取值为1到7,在编码时还需要注意字牌是无法组成顺子的。

对于一场比赛,牌的数量类型都是早就决定好不会变的,唯一变的就是牌的顺序,我们只需定义好一个所有牌的集合,在有需要生成牌山的时候,直接将其打乱使用即可。

宝牌是否要在class Pai中定义?由于每场比赛,宝牌是变化的,与场况有关,所以不太适合放在其中。但是有一个例外——赤宝牌,我本想在Pai中增加一个属性aka/red,标示是否是赤宝牌,但想到现在只是在对手牌进行和牌、听牌的判断,增加这个字段与否和现在要解决的问题无关,索性就不管了,宝牌之类,留着后面再统一处理吧。


日麻折腾笔记Java篇(1)——和牌的判断的评论 (共 条)

分享到微博请遵守国家法律