Skip to content

sniperHW/mahjong

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 

Repository files navigation

麻将胡牌检测算法

麻将最基本的胡牌是4 * 3 + 2,即14张牌,分成4组,每组3张,这里的一组可以是刻子也可以是顺子,再加一对作为将牌。

首先排除掉一对将牌,分析余下的4个分组,其中每个分组由3张牌组成,这组牌要么是顺子要么是刻子。我们可以用一个2进制位来表示这组牌的类型,例如0表示刻子,1表示顺子。

那么对于4组牌来说,只需要4个位就足够了,总共有2^4 = 16种分组模式。

下面我们来分析一个符合条件的4分组:

{1,2,3},{5,5,5},{1,2,3},{4,4,4}

这个分组对应的模式是{1010},我们可以对这个分组进行排序,规则是顺子比刻子大,相同类型的按首牌从小到大牌,排序后我们得到

{4,4,4},{5,5,5},{1,2,3},{1,2,3}

对应的模式为{0011}

对4分组排序后{0011},{0101},{1010}全部变成了{0011},由此只剩下5个模式即

{0000},{0001},{0011},{0111},{1111}

现在来考虑胡牌检测算法,先移除掉一对将牌,然后遍历5个模式,尝试从牌中移除一组牌,如果成功继续移除下一组,如果全部移除成功表明可以胡牌,

如果移除某一组失败则尝试另外一个模式,如果所有5个模式都尝试过没有一个可以成功,表明无法胡牌。

对4分组的排序一方面减少了模式的数量,另一方面表明,在移除一个分组的时候,只需要按照牌面从小到大的顺序移除即可,例如:

下面给出一个拍好序的胡牌方案,描述算法的执行过程:

{7,7,7},{8,8,8},{1,2,3},{4,5,6} 方案是{0011}

对牌整理之后得到的数对数组为:

{1,1},{2,1},{3,1},{4,1},{5,1},{6,1},{7,3},{8,3}

首先第一个位是0,算法遍历数对数组尝试移除刻字。发现7的数量>2因此移除{7,7,7}。

第二位也是0移除{8,8,8}

剩下数对数组为:

{1,1},{2,1},{3,1},{4,1},{5,1},{6,1},{7,0},{8,0}

接着第3位为1移除顺子{1,2,3}

最后1位也是1移除顺子{4,5,6}

算法结束。

接下来我们把将牌也考虑进去,如果我们先移除4个分组,再检查剩下的牌是否构成将牌是否有问题,考虑如下输入牌面:

{1,1,1,2,3,2,3,4,3,4,5,7,8,9}

如果按上面的规则移除4分组将会得到

{1,2,3},{1,2,3},{3,4,5},{7,8,9},{1,4}

剩下的1和4无法组成将牌,如果我们先移除将牌{1,1}将能得到正确的结果

{1,2,3},{2,3,4},{3,4,5},{7,8,9}。

因此,必须首先移除将牌,再对剩余牌做模式移除。为了避免移除错误的将牌使得可以胡的牌面被检查错误, 算法需要尝试将所有数量大于1的牌做将牌(如果后面的检查成功则无需检查其他将牌)。

About

algorithm for mahjong

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published