Header

首先这里不是用打表这种对于提高打牌技术没有实际意义的 baka 方法。

特殊型(国士,七对型)听牌先按下,字牌因为没有什么难度请读者自行作为课后作業。这里先只考慮由 1~9 的万,条,筒组成的牌形。

众所周知标准和牌形是由一对将+四面子组成的。听牌则有单骑,两面,嵌张。对于如下简单的情形的只要是稍会麻将的就能不难看出是听 2 5 筒的(请忽略最右的白牌)。

那么来分析一下人类玩家在看到这一手牌时做了什么样的思考,然后如何把这样的思考转化为算法。

表示法

首先,根據花色拆为 (12366 索), (345566 万), (24 索) 三组。

我们要一个在 APL 中表示手牌的方法。假设己经有做了分组,那么如上圖的手牌就可以用一个 nested array 表示

      ⊢hand←(1 2 3 6 6)(3 4 5 5 6 7)(3 4)
┌─────────┬───────────┬───┐
│1 2 3 6 6│3 4 5 5 6 7│3 4│
└─────────┴───────────┴───┘

然而这样的表示对于处理没有什么助益,所以要把每一组编码成一个长度为9的array,对应每种花色 1~9 的牌每张出现的数量。

enc←{⍺←9⊣⎕IO←1 ⋄ ((⊢∘≢⌸⍵)@(∪⍵))⍺⍴0}
      enc 1 2 3 6 6
1 1 1 0 0 2 0 0 0
      enc¨hand
┌─────────────────┬─────────────────┬─────────────────┐
│1 1 1 0 0 2 0 0 0│0 0 1 1 2 1 1 0 0│0 0 1 1 0 0 0 0 0│
└─────────────────┴─────────────────┴─────────────────┘

己完成的面子

在上面所示的听牌中,人类可以一眼看出三组中 345 567 万是己完成的面子,那这「一眼」中发生了什么?

Lemma: 当(标准听牌形)听牌时, $0=3|\omega$ 的组必然都组成面子,且不包括听牌。

证明: 当一组中有牌不能组成面子时,亦不能和其他花色的组形成将或面子,故不能滿足手牌中同时只有一个听牌形,不为听牌。

那么,用什么样的方法可以判斷呢,人类做的是一个順子/刻子的解离。在 APL 里这样写就会很麻煩。

对于 $3=\omega$ , 1 2 3, 2 3 4, 4 5 6, 这样的順子在编码后的表示

      enc¨(1 2 3)(2 3 4)(4 5 6)
┌─────────────────┬─────────────────┬─────────────────┐
│1 1 1 0 0 0 0 0 0│0 1 1 1 0 0 0 0 0│0 0 0 1 1 1 0 0 0│
└─────────────────┴─────────────────┴─────────────────┘

相信一部分读者己经发现規律了。

对于 $6=\omega$ 的复合刻子 1 2 2 3 3 4, 3 3 4 4 5 5, 1 2 3 3 4 5

      enc¨(1 2 2 3 3 4)(3 3 4 4 5 5)(1 2 3 3 4 5)
┌─────────────────┬─────────────────┬─────────────────┐
│1 2 2 1 0 0 0 0 0│0 0 2 2 2 0 0 0 0│1 1 2 1 1 0 0 0 0│
└─────────────────┴─────────────────┴─────────────────┘

这样似乎看不出来有什么,但 reshape 一下编码的结果就显而了。

      {3 3⍴enc ⍵}¨(1 2 2 3 3 4)(3 3 4 4 5 5)(1 2 3 3 4 5)
┌─────┬─────┬─────┐
│1 2 2│0 0 2│1 1 2│
│1 0 0│2 2 0│1 1 0│
│0 0 0│0 0 0│0 0 0│
└─────┴─────┴─────┘

那么如果是 1 2 2 2 3 3 3 4 4 这样的呢

      +⌿3 3⍴enc 1 2 2 2 3 3 3 4 4
3 3 3

如果再复合刻子呢?

      ((⊂3∘|),⊂)+⌿3 3⍴enc 1 1 1 1 2 2 3 3 4
┌─────┬─────┐
│2 2 2│5 2 2│
└─────┴─────┘

只要 mod 3 就可以了。

只是还有个小问題,比如 2 3 7 这样的特例,不过只要限定是连续的就行了。

      3 3⍴enc 2 3 7
0 1 1
0 0 0
1 0 0

因此

Theorem: 对于听牌形中连续的 $0=3|\omega$ 组,可以用 APL function

{(⊃∧.=,)3|+⌿3 3⍴⍵}

判断是否为完成的面子。