了解麻将规则非常好,但具有类似扑克或罗密欧的背景也足以理解这个问题。
在麻将中,14张牌(类似于扑克牌)被排列成4组和一对。一个顺子(“123”)总是使用恰好3张牌,既不多也不少。同种类的一组(“111”)也由恰好3张牌组成。这导致总共需要14张牌,即3 * 4 + 2。
有各种例外情况,例如Kan或Thirteen Orphans,在此不相关。颜色和值范围(1-9)对算法也不重要。
一手牌由13张牌组成,每次轮到我们时,我们可以拿一张新牌并必须弃掉任何一张牌,以保持13张牌 - 除非我们能够使用新拿的牌赢得游戏。
一手牌可以组成4副牌和1对牌时,被称为"ready"。只需要交换1张牌就能达到"tenpai"或"1 from ready"的状态。其他任何手牌都有一个"shanten-number"来表示需要交换多少张牌才能达到"tenpai"状态。所以,shanten number为1的手牌需要交换1张牌才能达到"tenpai"状态(相应地需要交换2张牌才能达到"ready"状态)。shanten number为5的手牌需要交换5张牌才能达到"tenpai"状态,以此类推。
我正在尝试计算手牌的shanten number。在Google上搜索了几个小时并阅读了多篇关于这个话题的文章和论文后,似乎这仍然是一个未解决的问题(除了暴力方法)。我找到的最接近的算法依赖于机会,即它不能100%地检测出正确的shanten number。
规则:
我将简要解释实际规则(简化版),然后提出我的想法来解决这个任务。在麻将中,有4种颜色,其中3种是像纸牌游戏(A、红桃等)一样的普通颜色,称为“万”、“筒”和“索”。这些颜色分别从1到9,并且可以用于形成顺子以及相同种类的组合。第四种颜色称为“字牌”,只能用于相同种类的组合,而不能用于顺子。七种字牌将被称为“东、南、西、北、红中、发财、白板”。
让我们看一个听牌的例子:
2p, 3p, 3p, 3p, 3p, 4p, 5m, 5m, 5m, W, W, W, E
。接下来我们选择一个E
。这是一个完整的麻将手牌(准备好了),由一个2-4筒的顺子(记住,筒可以用于顺子)、一个3筒的刻子、一个5万的刻子、一个W的刻子和一个E的对子组成。改变我们最初的手牌略微为
2p, 2p, 3p, 3p, 3p, 4p, 5m, 5m, 5m, W, W, W, E
,我们得到了一张1向听的手牌,即需要额外一张牌才能进入听牌状态。在这种情况下,将一张2p换成一张3p可以使我们回到听牌状态,因此通过抽取一张3p和一张E,我们获胜。
1p,1p,5p,5p,9p,9p,E,E,E,S,S,W,W
是一手两向听的牌组。其中有1个刻子和5个对子。为了完成这手牌组,我们需要再得到一个对子,所以当我们选择其中的1p、5p、9p、S或W中的一个时,就需要弃掉另外一个对子。例如:我们选择一个1饼并丢掉一个W,则手牌现在是1向听,如下所示:1p,1p,1p,5p,5p,9p,9p,E,E,E,S,S,W
。接下来,我们等待出现5p、9p或S中的任意一张牌。假设我们拿到了5p并且丢掉了剩下的W,则手牌会变成这样:1p,1p,1p,5p,5p,5p,9p,9p,E,E,E,S,S
。这手牌处于听牌状态,可以通过获得9饼或者S来完成。
算法
正如所述,我想计算手牌的向听数。我的想法是将牌分成4组,根据它们的颜色进行分类。接下来,所有牌都按其各自组内的集合排序,以便我们最终得到雀头组中的三张牌、对子或单张牌,或者在3个普通组中还有顺子。完成的组被忽略。对子被计算,最终数字递减(我们最终需要1对)。单张牌加入到此数字中。最后,我们将数字除以2(因为每次我们选择一张好的牌使我们更接近听牌时,我们可以摆脱另一张不需要的牌)。
然而,我无法证明这个算法是正确的,而且我也很难将顺子合并到包含许多接近范围的牌的困难组中。欢迎任何类型的想法。我正在开发.NET,但伪代码或任何可读语言也是受欢迎的。