如何验证 Rummikub 与 Jokers 的组合

Bar*_*lom 5 language-agnostic algorithm

在 Rummikub 游戏中,对于那些不知道的人来说,您有 4 种颜色的图块,上面有 13 个不同的数字(因此 4 x 13 = 52 个独特的图块),您必须使用它们来分组。有两种组:

  • 不同的颜色,相同的数字(例如R1-B1-G1
  • 相同的颜色,数字序列(例如G6-G7-G8

我正在编写获取图块列表并检查它是否是有效组合的代码。到目前为止,它有效并且非常简单。

当我们引入小丑牌时,事情就变得困难了。您可以将它们用作任何图块来完成组合(例如G6-R6-J),并且可以使用多个(例如R4-R5-J-J-R8)。

我想我应该分两步验证与小丑的组合:

  1. 将所有小丑替换为他们所代表的牌。
  2. 使用现有代码验证“规范化”组(除非步骤 1 抛出错误,因为它已经看到组合无效)。

现在,如何执行步骤 1?我认为如果每组只允许有一个小丑,那就相当简单了:

  • 如果与百搭牌相邻的牌颜色相同,并且右边的牌比左边的牌高 2,则用中间的数字替换
  • 如果相邻的图块数量相同但颜色不同,则用尚未出现的颜色替换。
  • 如果小丑在开头或结尾,则相同,但稍作修改

不幸的是,允许使用多个小丑,这使得问题变得更加复杂,并且我一直在思考如何解决这个问题。

小智 5

最近,我编写了一款 Android Rummikub 游戏,也许我的代码可以帮助您(或者可能为时已晚;但仍然可以帮助其他人)。我不确定其中是否存在错误。因为我还没有检查太多。

我假设数字0~105。
对应卡牌为黑红黄绿及鬼卡(B1~0、B13~12、R1~13...G13~51、B1~52...G13~103 GHOST1~104、GHOST2~105)

这是代码:

public boolean isLegal(List<Byte> cards)
{
    byte ghostNum = 0; 
    byte ghostRemain = 0;
    byte size = (byte) cards.size();
    if (size == 0)
    {
        return true;
    }
    else if (size < 3)
    {
        return false;
    }

    //get the num of ghostcard
    Collections.sort(cards);
    if (cards.get(size - 1) >= 104)
    {
        ghostNum++;
        if (cards.get(size - 2) >= 104)
        {
            ghostNum++;
        }
    }
    ghostRemain = ghostNum;

    byte[] a = new byte[size - ghostNum];
    byte[] b = new byte[size - ghostNum];
    for (byte i = 0; i < size - ghostNum; i++)
    {
        a[i] = (byte) (cards.get(i) % 13); // the num of the tiles 0~12
        b[i] = (byte) ((cards.get(i) / 13) % 4); // the color of the tiles 0~3(B,R,Y,G)
    }
    Arrays.sort(a);
    Arrays.sort(b);
    // tiles seems in same color
    if (b[0] == b[size - 1 - ghostNum])
    {
        for (int i = 0; i < size - 1 - ghostNum; i++)
        {
            if (a[i + 1] - a[i] != 1)
            {
                ghostRemain = (byte) (ghostRemain - a[i + 1] + a[i] + 1);
                if (ghostRemain < 0)
                {
                    return false;
                }
            }
            if (b[i] != b[i + 1])
            {
                return false;
            }
        }
        return true;
        // tiles in different colors
    }
    else if (b[0] != b[1])
    {
        for (int i = 0; i < size - 1 - ghostNum; i++)
        {
            if (a[i] != a[i + 1])
            {
                return false;
            }
            if (b[i] == b[i + 1])
            {
                return false;
            }
        }
        return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)


Zuu*_*Zuu 4

如果你坚持把第一步作为你做的第一件事,你就是在给自己找麻烦。从这个角度解决问题在计算上效率很低。使用这种方法,你最终要做的就是尝试小丑替身的所有组合。这是一个坏主意。

这是一种毫不费力的替代方法:

  1. 该组是否包含 0 或 1 个非小丑,并且该组是否包含至少 3 个棋子,则成功。
  2. 所有非百搭颜色的颜色都相同,则成功。
  3. 所有棋子是否都像 (1, 2, 小丑, 4) 一样放置,其中所有小丑自动采用比前一个棋子高一的值。如果是这样,那么就成功了。
  4. 如果以上都不成立,则失败。

依次执行所有这些检查,您将发现一组棋子是否是有效的组。

对于第 3 步,您必须考虑某些序列可能是相反的,例如 (joker, 3, 2, 1)。要检测这种情况,您可以快速扫描非小丑,看看它们是递增还是递减,然后考虑到这一点(然后小丑的值将比前一个少一)。

请注意,只有在步骤 2 中颜色才有意义,并且只有在步骤 3 中数字才有意义。