用正则表达式计算顺子扑克牌手?

5

有没有一个正则表达式来计算顺子扑克牌手?

我使用字符串来表示排序后的牌,例如:

AAAAK#sssss = 4 aces and a king, all of spades.
A2345#ddddd = straight flush, all of diamonds.

在Java中,我正在使用以下正则表达式:

regexPair = Pattern.compile(".*(\\w)\\1.*#.*");
regexTwoPair = Pattern.compile(".*(\\w)\\1.*(\\w)\\2.*#.*");
regexThree = Pattern.compile(".*(\\w)\\1\\1.*#.*");
regexFour = Pattern.compile(".*(\\w)\\1{3}.*#.*");
regexFullHouse = Pattern.compile("((\\w)\\2\\2(\\w)\\3|(\\w)\\4(\\w)\\5\\5)#.*");
regexFlush = Pattern.compile(".*#(\\w)\\1{4}");

如何使用正则表达式计算连续值? 编辑 我开了另一个问题来解决同样的问题,但是使用字符的ASCII值,以便正则表达式更短。详见这里
谢谢!

12
我见过使用正则表达式的所有奇怪事情中,这个可能是第二最奇怪的 :-) - paxdiablo
5
不要使用正则表达式来完成此任务。 - Thom Smith
2
@Jens:那就是永恒存在的“如何使用正则表达式验证电子邮件地址?”问题。通常是为了确保地址另一端有人而提出的,但提问者似乎不理解nobody@nowhere.com是有效的,但(可能,我实际上没有检查过)背后没有任何人。最好的方法是发送一封激活类型的电子邮件进行检查。N小时内没有激活,请求将被丢弃。 - paxdiablo
1
@pax 我认为使用正则表达式来验证电子邮件是否有效是有意义的。这样,您可以捕获那些否则会让用户等待永远不会到来的电子邮件的拼写错误。 - NullUserException
我只想说,这是一个非常优秀的正则表达式应用程序,我不知道为什么有人会说不要使用这种方法(这也是我第一次找到它的原因,因为我正在寻找是否有人在使用这种方法)。 - RegularExpression
显示剩余2条评论
2个回答

5

我必须承认,正则表达式并不是我首选的工具。我可以几乎肯定地说,任何能够对未排序的纸牌进行操作的正则表达式都会比等效的过程式代码更加丑陋和难以阅读。

假设纸牌按面值排序(否则您列出的正则表达式也无法工作),并且您必须使用正则表达式,您可以使用类似于以下结构:

2345A|23456|34567|...|9TJQK|TJQKA

检测手牌的面值部分。

实际上,根据我所了解到的这里的“标准”手牌,应按以下顺序检查以降低优先级:

Royal/straight flush: "(2345A|23456|34567|...|9TJQK|TJQKA)#(\\w)\\1{4}"
Four of a kind:       ".*(\\w)\\1{3}.*#.*"
Full house:           "((\\w)\\2\\2(\\w)\\3|(\\w)\\4(\\w)\\5\\5)#.*"
Flush:                ".*#(\\w)\\1{4}"
Straight:             "(2345A|23456|34567|...|9TJQK|TJQKA)#.*"
Three of a kind:      ".*(\\w)\\1\\1.*#.*"
Two pair:             ".*(\\w)\\1.*(\\w)\\2.*#.*"
One pair:             ".*(\\w)\\1.*#.*"
High card:            (none)

基本上,这些与您的相同,只是我添加了皇家同花顺和顺子。只要按顺序检查它们,您应该可以从手中获得最佳分数。由于在那一点上,高牌是您唯一可能拥有的分数,因此没有高牌的正则表达式。

我还将环形顺子(wrap-around)从A2345更改为2345A,因为它们将以这种方式排序。


同意。运行上述正则表达式,然后运行过程代码以检查顺子。这应该很简单-遍历字符串并确保它们是连续的。 - cincodenada
1
@cincodenada:是的,这就是我会做的方式。但有时候,提问者可能有一个特定的原因来做某件事情(例如,他们可能正在使用只能使用正则表达式的工具/框架)。因此,虽然我会建议可能有更好的方法,但我仍然会尽力帮助他们。一开始我并不太赞同这个想法,但现在我可以看到它会使他们的源代码变得更小和更优雅 :-) - paxdiablo
没错,这就是为什么我评论了你的答案而没有自己发表观点。不过,这也是一个很好的提醒,要给提问者以怀疑的余地。谢谢 :) - cincodenada
我发现你的正则表达式有点混乱和难以理解,所以我在我的答案中重新编写了它。 - James

0

我重新编写了这个正则表达式,因为我发现它令人沮丧和困惑。对于这种类型的逻辑,分组更具有意义。使用javascript中的标准数组排序方法进行排序,因此卡片的顺序很奇怪,它们按字母顺序排列。我用JavaScript完成了我的工作,但是该正则表达式也可以应用于Java。

hands = [
    { regex: /(2345A|23456|34567|45678|56789|6789T|789JT|89JQT|9JKQT|AJKQT)#(.)\2{4}.*/g , name: 'Straight flush' },
    { regex: /(.)\1{3}.*#.*/g , name: 'Four of a kind' },
    { regex: /((.)\2{2}(.)\3{1}#.*|(.)\4{1}(.)\5{2}#.*)/g , name: 'Full house' },
    { regex: /.*#(.)\1{4}.*/g , name: 'Flush' },
    { regex: /(2345A|23456|34567|45678|56789|6789T|789JT|89JQT|9JKQT|AJKQT)#.*/g , name: 'Straight' },
    { regex: /(.)\1{2}.*#.*/g , name: 'Three of a kind' },
    { regex: /(.)\1{1}.*(.)\2{1}.*#.*/g , name: 'Two pair' },
    { regex: /(.)\1{1}.*#.*/g , name: 'One pair' },
  ];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接