28

我正在考虑 . 中的扑克手(5 张牌)评估Java。现在我正在寻找简单和清晰,而不是性能和效率。我可能可以编写一个“幼稚”的算法,但它需要大量代码。

我还看到了一些扑克评估库,它们使用散列和按位运算,但它们看起来相当复杂。

扑克手评估的“最干净和最简单”的算法是什么?

4

12 回答 12

34

这是一个非常简短但完整的基于直方图的 Python (2.x) 中的 5 张扑克计分函数。如果转换为 Java,它将变得相当长。

def poker(hands):
    scores = [(i, score(hand.split())) for i, hand in enumerate(hands)]
    winner = sorted(scores , key=lambda x:x[1])[-1][0]
    return hands[winner]

def score(hand):
    ranks = '23456789TJQKA'
    rcounts = {ranks.find(r): ''.join(hand).count(r) for r, _ in hand}.items()
    score, ranks = zip(*sorted((cnt, rank) for rank, cnt in rcounts)[::-1])
    if len(score) == 5:
        if ranks[0:2] == (12, 3): #adjust if 5 high straight
            ranks = (3, 2, 1, 0, -1)
        straight = ranks[0] - ranks[4] == 4
        flush = len({suit for _, suit in hand}) == 1
        '''no pair, straight, flush, or straight flush'''
        score = ([1, (3,1,1,1)], [(3,1,1,2), (5,)])[flush][straight]
    return score, ranks

 >>> poker(['8C TS KC 9H 4S', '7D 2S 5D 3S AC', '8C AD 8D AC 9C', '7C 5H 8D TD KS'])
 '8C AD 8D AC 9C'
于 2013-12-21T05:41:36.230 回答
12

查找表是解决问题最直接和最简单的方法,也是最快的。诀窍是管理表的大小并保持使用模式足够简单以非常快速地处理(时空权衡)。显然,从理论上讲,您可以对可以握住的每只手进行编码并进行一系列评估,然后 --poof-- 一个表查找就完成了。不幸的是,这样的表对于大多数机器来说是巨大的并且难以管理,并且总是会让你在内存被大量换出时颠簸磁盘。

所谓的二加二解决方案是一张 10M 的大牌桌,但实际上涉及为手中的每张牌查找一张牌桌。您不太可能找到更快、更容易理解的算法。

其他解决方案涉及更多压缩表和更复杂的索引,但它们很容易理解并且非常快(尽管比 2+2 慢得多)。这是您看到有关散列等语言的地方 - 将表大小减小到更易于管理的大小的技巧。

在任何情况下,查找解决方案都比 histogram-sort-dance-on-your-head-compare-special-case-and-by-the-way-was-it-a-flush 解决方案快几个数量级,几乎没有其中值得一看。

于 2012-05-04T21:40:44.440 回答
9

您实际上不需要任何高级功能,都可以按位完成:(来源: http: //www.codeproject.com/Articles/569271/A-Poker-hand-analyzer-in-JavaScript-using-bit-数学

(这实际上是用 JavaScript 编写的,但是如果需要,您可以从 Java 中评估 JavaScript,所以这应该不是问题。此外,它尽可能短,所以即使是为了说明方法......) :

首先,你将你的牌分成两个数组:等级 (cs) 和花色 (ss),为了表示花色,你将使用 1、2、4 或 8(即 0b0001、0b0010、...):

var J=11, Q=12, K=13, A=14, C=1, D=2, H=4, S=8;

现在这是魔术:

function evaluateHand(cs, ss) {
    var pokerHands = ["4 of a Kind", "Straight Flush","Straight","Flush","High Card","1 Pair","2 Pair","Royal Flush", "3 of a Kind","Full House"];

    var v,i,o,s = 1 << cs[0] | 1 << cs[1] | 1 << cs[2] | 1 << cs[3] | 1 << cs[4];
    for (i = -1, v = o = 0; i < 5; i++, o = Math.pow(2, cs[i] * 4)) {v += o * ((v / o & 15) + 1);}
    v = v % 15 - ((s / (s & -s) == 31) || (s == 0x403c) ? 3 : 1);
    v -= (ss[0] == (ss[1] | ss[2] | ss[3] | ss[4])) * ((s == 0x7c00) ? -5 : 1);
    return pokerHands[v];
}

用法:

evaluateHand([A,10,J,K,Q],[C,C,C,C,C]); // Royal Flush

现在它所做的(非常简单)是当有 2 时将 1 放入s 的第 3 位,当有 3 时放入第 4 位,依此类推,所以对于上面的示例s看起来像这样:

0b111110000000000

对于 [A,2,3,4,5] 它看起来像这样

0b100 0000 0011 1100

等等

v使用 4 位来记录同一张牌的多次出现,所以它有 52 位长,如果你有 3 个 A 和 2 个 K,它的 8 个 MSB 位如下所示:

0111 0011 ...

最后一行然后检查同花顺或同花顺或皇家同花顺 (0x7c00)。

于 2015-11-22T10:20:26.807 回答
4

这是我用来帮助最初填充查找表的五张牌比较的简单方法:

我没有尽可能简洁,而是优先考虑类型安全和清晰、自记录的代码。如果你不熟悉我使用的 Guava 类型,你可以浏览他们的文档

我将在此处包含代码(减去底部枚举常量的静态导入),尽管在答案中舒适地查看确实太长了。

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Ordering.from;
import static com.google.common.collect.Ordering.natural;
import static java.util.Comparator.comparing;
import static java.util.Comparator.comparingInt;

import java.util.Comparator;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.function.Function;

import com.google.common.collect.EnumMultiset;
import com.google.common.collect.Multiset;
import com.google.common.collect.Multiset.Entry;
import com.google.common.collect.Ordering;

public class Hand implements Comparable<Hand> {
    public final Category category;

    private final LinkedList<Rank> distinctRanks = new LinkedList<>();

    public Hand(Set<Card> cards) {
        checkArgument(cards.size() == 5);
        Set<Suit> suits = EnumSet.noneOf(Suit.class);
        Multiset<Rank> ranks = EnumMultiset.create(Rank.class);
        for (Card card : cards) {
            suits.add(card.suit);
            ranks.add(card.rank);
        }
        Set<Entry<Rank>> entries = ranks.entrySet();
        for (Entry<Rank> entry : byCountThenRank.immutableSortedCopy(entries)) {
            distinctRanks.addFirst(entry.getElement());
        }
        Rank first = distinctRanks.getFirst();
        int distinctCount = distinctRanks.size();
        if (distinctCount == 5) {
            boolean flush = suits.size() == 1;
            if (first.ordinal() - distinctRanks.getLast().ordinal() == 4) {
                category = flush ? STRAIGHT_FLUSH : STRAIGHT;
            }
            else if (first == ACE && distinctRanks.get(1) == FIVE) {
                category = flush ? STRAIGHT_FLUSH : STRAIGHT;
                // ace plays low, move to end
                distinctRanks.addLast(distinctRanks.removeFirst());
            }
            else {
                category = flush ? FLUSH : HIGH_CARD;
            }
        }
        else if (distinctCount == 4) {
            category = ONE_PAIR;
        }
        else if (distinctCount == 3) {
            category = ranks.count(first) == 2 ? TWO_PAIR : THREE_OF_A_KIND;
        }
        else {
            category = ranks.count(first) == 3 ? FULL_HOUSE : FOUR_OF_A_KIND;
        }
    }

    @Override
    public final int compareTo(Hand that) {
        return byCategoryThenRanks.compare(this, that);
    }

    private static final Ordering<Entry<Rank>> byCountThenRank;

    private static final Comparator<Hand> byCategoryThenRanks;

    static {
        Comparator<Entry<Rank>> byCount = comparingInt(Entry::getCount);
        Comparator<Entry<Rank>> byRank = comparing(Entry::getElement);
        byCountThenRank = from(byCount.thenComparing(byRank));
        Comparator<Hand> byCategory = comparing((Hand hand) -> hand.category);
        Function<Hand, Iterable<Rank>> getRanks =
                (Hand hand) -> hand.distinctRanks;
        Comparator<Hand> byRanks =
                comparing(getRanks, natural().lexicographical());
        byCategoryThenRanks = byCategory.thenComparing(byRanks);
    }

    public enum Category {
        HIGH_CARD,
        ONE_PAIR,
        TWO_PAIR,
        THREE_OF_A_KIND,
        STRAIGHT,
        FLUSH,
        FULL_HOUSE,
        FOUR_OF_A_KIND,
        STRAIGHT_FLUSH;
    }

    public enum Rank {
        TWO,
        THREE,
        FOUR,
        FIVE,
        SIX,
        SEVEN,
        EIGHT,
        NINE,
        TEN,
        JACK,
        QUEEN,
        KING,
        ACE;
    }

    public enum Suit {
        DIAMONDS,
        CLUBS,
        HEARTS,
        SPADES;
    }

    public enum Card {
        TWO_DIAMONDS(TWO, DIAMONDS),
        THREE_DIAMONDS(THREE, DIAMONDS),
        FOUR_DIAMONDS(FOUR, DIAMONDS),
        FIVE_DIAMONDS(FIVE, DIAMONDS),
        SIX_DIAMONDS(SIX, DIAMONDS),
        SEVEN_DIAMONDS(SEVEN, DIAMONDS),
        EIGHT_DIAMONDS(EIGHT, DIAMONDS),
        NINE_DIAMONDS(NINE, DIAMONDS),
        TEN_DIAMONDS(TEN, DIAMONDS),
        JACK_DIAMONDS(JACK, DIAMONDS),
        QUEEN_DIAMONDS(QUEEN, DIAMONDS),
        KING_DIAMONDS(KING, DIAMONDS),
        ACE_DIAMONDS(ACE, DIAMONDS),

        TWO_CLUBS(TWO, CLUBS),
        THREE_CLUBS(THREE, CLUBS),
        FOUR_CLUBS(FOUR, CLUBS),
        FIVE_CLUBS(FIVE, CLUBS),
        SIX_CLUBS(SIX, CLUBS),
        SEVEN_CLUBS(SEVEN, CLUBS),
        EIGHT_CLUBS(EIGHT, CLUBS),
        NINE_CLUBS(NINE, CLUBS),
        TEN_CLUBS(TEN, CLUBS),
        JACK_CLUBS(JACK, CLUBS),
        QUEEN_CLUBS(QUEEN, CLUBS),
        KING_CLUBS(KING, CLUBS),
        ACE_CLUBS(ACE, CLUBS),

        TWO_HEARTS(TWO, HEARTS),
        THREE_HEARTS(THREE, HEARTS),
        FOUR_HEARTS(FOUR, HEARTS),
        FIVE_HEARTS(FIVE, HEARTS),
        SIX_HEARTS(SIX, HEARTS),
        SEVEN_HEARTS(SEVEN, HEARTS),
        EIGHT_HEARTS(EIGHT, HEARTS),
        NINE_HEARTS(NINE, HEARTS),
        TEN_HEARTS(TEN, HEARTS),
        JACK_HEARTS(JACK, HEARTS),
        QUEEN_HEARTS(QUEEN, HEARTS),
        KING_HEARTS(KING, HEARTS),
        ACE_HEARTS(ACE, HEARTS),

        TWO_SPADES(TWO, SPADES),
        THREE_SPADES(THREE, SPADES),
        FOUR_SPADES(FOUR, SPADES),
        FIVE_SPADES(FIVE, SPADES),
        SIX_SPADES(SIX, SPADES),
        SEVEN_SPADES(SEVEN, SPADES),
        EIGHT_SPADES(EIGHT, SPADES),
        NINE_SPADES(NINE, SPADES),
        TEN_SPADES(TEN, SPADES),
        JACK_SPADES(JACK, SPADES),
        QUEEN_SPADES(QUEEN, SPADES),
        KING_SPADES(KING, SPADES),
        ACE_SPADES(ACE, SPADES);

        public final Rank rank;

        public final Suit suit;

        Card(Rank rank, Suit suit) {
            this.rank = rank;
            this.suit = suit;
        }
    }
}
于 2014-01-07T02:17:35.383 回答
4

这是 dansalmo 程序的修改版本,适用于手持式:

def holdem(board, hands):
    scores = [(evaluate((board + ' ' + hand).split()), i) for i, hand in enumerate(hands)]
    best = max(scores)[0]
    return [x[1] for x in filter(lambda(x): x[0] == best, scores)]

def evaluate(hand):
    ranks = '23456789TJQKA'
    if len(hand) > 5: return max([evaluate(hand[:i] + hand[i+1:]) for i in range(len(hand))])
    score, ranks = zip(*sorted((cnt, rank) for rank, cnt in {ranks.find(r): ''.join(hand).count(r) for r, _ in hand}.items())[::-1])
    if len(score) == 5: # if there are 5 different ranks it could be a straight or a flush (or both)
        if ranks[0:2] == (12, 3): ranks = (3, 2, 1, 0, -1) # adjust if 5 high straight
        score = ([1,(3,1,2)],[(3,1,3),(5,)])[len({suit for _, suit in hand}) == 1][ranks[0] - ranks[4] == 4] # high card, straight, flush, straight flush
    return score, ranks

def test():
    print holdem('9H TC JC QS KC', [
        'JS JD', # 0
        'AD 9C', # 1 A-straight
        'JD 2C', # 2
        'AC 8D', # 3 A-straight
        'QH KH', # 4
        'TS 9C', # 5
        'AH 3H', # 6 A-straight
        '3D 2C', # 7
      # '8C 2C', # 8 flush
    ])

test()

Holdem() 返回获胜手牌的索引列表。在 test() 示例中是 [1, 3, 6],因为三手拿着 A 的牌瓜分了底池,如果没有注释同花手,则为 [8]。

于 2015-11-02T20:12:42.743 回答
4

Python 3 版本

def poker(hands):
    scores = [(i, score(hand.split())) for i, hand in enumerate(hands)]
    winner = sorted(scores , key=lambda x:x[1])[-1][0]
    return hands[winner]

def score(hand):
    ranks = '23456789TJQKA'
    rcounts = {ranks.find(r): ''.join(hand).count(r) for r, _ in hand}.items()
    score, ranks = zip(*sorted((cnt, rank) for rank, cnt in rcounts)[::-1])
    if len(score) == 5:
        if ranks[0:2] == (12, 3): #adjust if 5 high straight
            ranks = (3, 2, 1, 0, -1)
        straight = ranks[0] - ranks[4] == 4
        flush = len({suit for _, suit in hand}) == 1
        '''no pair, straight, flush, or straight flush'''
        score = ([(1,), (3,1,1,1)], [(3,1,1,2), (5,)])[flush][straight]
    return score, ranks

 >>> poker(['8C TS KC 9H 4S', '7D 2S 5D 3S AC', '8C AD 8D AC 9C', '7C 5H 8D TD KS'])
 '8C AD 8D AC 9C'

基本上必须用 (1,) 替换 1 以避免 int 到元组比较错误。

于 2020-03-04T21:30:26.590 回答
2

如果您将手表示为例如Card对象的数组,那么我将有方法用于循环遍历该数组并确定它是否具有 2-of-a-kind、flush 等 - 如果有,是什么类型它是; 因此,如果一手牌有三个 5,您可以让该3ofaKind()方法返回 5。然后我会建立一个可能性层次结构(例如 3 种高于 2 种)并从那里开始工作。方法本身应该很容易编写。

于 2012-04-28T13:36:22.840 回答
1

如果你只是想了解它是如何工作的,那么简单的算法是:

HandStrength(ourcards,boardcards)
{
    ahead = tied = behind = 0
    ourrank = Rank(ourcards,boardcards)
    /* Consider all two-card combinations
    of the remaining cards. */
    for each case(oppcards)
    {
        opprank = Rank(oppcards,boardcards)
        if(ourrank>opprank)
            ahead += 1
        else if(ourrank==opprank)
            tied += 1
        else /* < */
            behind += 1
    }
    handstrength = (ahead+tied/2) / (ahead+tied+behind)
    return(handstrength)
}

它来自 Darse Billings 的“计算机扑克中的算法和评估”。

于 2012-05-06T21:17:10.043 回答
1

这是 Kotlin 中基于规则的简单实现:

class PokerHand constructor(hand: String) : Comparable<PokerHand> {

companion object {
    const val WIN = 1
    const val TIE = 0
    const val LOSS = -1
}

val cards: List<Card>

val isStraightFlush: Boolean
    get() = isStraight && isFlush

val isFourOfAKind: Boolean
    get() = cards.groupBy { it.weight }.map { it.value }.any { it.size == 4 }

val isFullHouse: Boolean
    get() = cards.groupBy { it.weight }.map { it.value }.size == 2

val isFlush: Boolean
    get() = cards.groupBy { it.suit }.map { it.value }.size == 1

val isStraight: Boolean
    get() = cards.map { it.weight.ordinal } == (cards[0].weight.ordinal..cards[0].weight.ordinal + 4).toList()

val isThreeOfAKind: Boolean
    get() = cards.groupBy { it.weight }.map { it.value }.any { it.size == 3 }

val isTwoPair: Boolean
    get() = cards.groupBy { it.weight }.map { it.value }.filter { it.size == 2 }.count() == 2

val isPair: Boolean
    get() = cards.groupBy { it.weight }.map { it.value }.any { it.size == 2 }

init {
    val cards = ArrayList<Card>()
    hand.split(" ").forEach {
        when (it.length != 2) {
            true -> throw RuntimeException("A card code must be two characters")
            else -> cards += Card(Weight.forCode(it[0]), Suit.forCode(it[1]))
        }
    }
    if (cards.size != 5) {
        throw RuntimeException("There must be five cards in a hand")
    }
    this.cards = cards.sortedBy { it.weight.ordinal }
}

override fun compareTo(other: PokerHand): Int = when {
    (this.isStraightFlush || other.isStraightFlush) ->
        if (this.isStraightFlush) if (other.isStraightFlush) compareByHighCard(other) else WIN else LOSS
    (this.isFourOfAKind || other.isFourOfAKind) ->
        if (this.isFourOfAKind) if (other.isFourOfAKind) compareByHighCard(other) else WIN else LOSS
    (this.isFullHouse || other.isFullHouse) ->
        if (this.isFullHouse) if (other.isFullHouse) compareByHighCard(other) else WIN else LOSS
    (this.isFlush || other.isFlush) ->
        if (this.isFlush) if (other.isFlush) compareByHighCard(other) else WIN else LOSS
    (this.isStraight || other.isStraight) ->
        if (this.isStraight) if (other.isStraight) compareByHighCard(other) else WIN else LOSS
    (this.isThreeOfAKind || other.isThreeOfAKind) ->
        if (this.isThreeOfAKind) if (other.isThreeOfAKind) compareByHighCard(other) else WIN else LOSS
    (this.isTwoPair || other.isTwoPair) ->
        if (this.isTwoPair) if (other.isTwoPair) compareByHighCard(other) else WIN else LOSS
    (this.isPair || other.isPair) ->
        if (this.isPair) if (other.isPair) compareByHighCard(other) else WIN else LOSS
    else -> compareByHighCard(other)
}

private fun compareByHighCard(other: PokerHand, index: Int = 4): Int = when {
    (index < 0) -> TIE
    cards[index].weight === other.cards[index].weight -> compareByHighCard(other, index - 1)
    cards[index].weight.ordinal > other.cards[index].weight.ordinal -> WIN
    else -> LOSS
}

}

实施细节:

  • 用编码的手实例化,例如2H 3H 4H 5H 6H
  • 评估这手牌是否是“同花顺”、“四类”、“满屋”等的方法。这些在 Kotlin 中很容易表达。
  • 实现Comparable<PokerHand>使用简单的规则方法评估另一手牌,例如同花顺击败同类的四,击败满堂,等等。

来源在这里

于 2018-12-13T06:54:17.747 回答
1

我用 C++ 和 Javascript 编写了一个扑克手评估器。基本上,该程序会将随机挑选的一组卡片转换为 1 和 0 的 3d 数组。通过将卡片转换为这种格式,我就能够编写函数来测试从最高点开始的每种类型的手。

总而言之,我的程序会生成随机牌,将它们转换为由红心、方块、黑桃和梅花组成的 3D 数组,其中 1 代表我拥有的一张牌。然后我会测试 3D 数组,看看我是否有皇家同花顺,然后是同花顺,然后是 4 种,直到检测到匹配。一旦在测试同花之后检测到匹配,那么我的程序就不必测试顺子、3 个同类等,因为同花胜过顺子。

以下是我的程序输出的数据:

我的随机卡片:

Table Cards
{ Value: '9', Suit: 'H' }
{ Value: 'A', Suit: 'H' }
{ Value: '9', Suit: 'D' }
{ Value: '7', Suit: 'S' }
{ Value: '6', Suit: 'S' }

代表我的卡片的 3D 数组:

 A  2  3  4  5  6  7  8  9  10 J  Q  K  A

Spades
[ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0 ]
Diamonds
[ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ]
Clubs
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
Hearts
[ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]

使用上面的值,我可以看出我有一对 9s 和一个 A、7、6 的起脚牌。

您可以看到该数组包含两次 A。这是因为您想测试从 A 开始的同花顺。所以 (A,2,3,4,5)。

如果你想测试 7 张卡片而不是 5 张卡片,你也可以使用这个系统。您可以将用户 2 卡与桌面上的 5 一起包含在我的系统中并运行它。您也可以对桌上的其他玩家做同样的事情并比较结果。

希望这会有帮助。

于 2020-02-09T10:18:17.243 回答
0

这是翻译成R的算法,用 6 张牌进行测试,对应于由以下结果给出的 42.504 种组合:

C65

扑克手的组合。由于处理限制(它将对应于 2.598.960 组合),未使用 13 卡组进行测试。

该算法用一个字符串来表示一手牌的价值,由两部分组成:

  • 5 个字符,按顺序卡数(例如“31100”表示三种)
  • 卡号由从“B”(Deuce)到“N”(Ace)的字母计算(例如,“NILH”表示 Ace、Queen、9 和 8)。它以字母“B”开头,因为在 A2345 扑克手牌中,A 出现在“2”之前,“2”(A)将具有值“A”。

因此,例如,“32000NB”将是三个 A 和两个平的 Full House。

扑克手值字符串便于比较和排序

library(tidyverse)
library(gtools)

hand_value <- function(playerhand) {

  numbers <- str_split("23456789TJQKA", "")[[1]]
  suits <- str_split("DCHS", "")[[1]]

  playerhand <- data.frame(card = playerhand) %>% separate(card, c("number", "suit"), sep = 1)

  number_values <- data.frame(number = numbers, value = LETTERS[2:14], stringsAsFactors = FALSE)

  playerhand_number <- playerhand %>% 
    group_by(number) %>% 
    count(number) %>%
    inner_join(number_values, by = "number") %>%
    arrange(desc(n), desc(value))

  playerhand_suit <- playerhand %>% 
    group_by(suit) %>% 
    count(suit) %>%
    arrange(desc(n))

  if (nrow(playerhand_number) == 5)
    {
      if (playerhand_number[1,1] == 'A' & playerhand_number[2,1] == '5')
        playerhand_number <- data.frame(playerhand_number[,1:2], value = str_split("EDCBA", "")[[1]], stringsAsFactors = FALSE)
      straight <- asc(playerhand_number[1,3]) - asc(playerhand_number[5,3]) == 4
    } else
      straight = FALSE

  flush <- nrow(playerhand_suit) == 1

  if (flush)
    {
    if (straight)
      playerhand_number <- data.frame(playerhand_number[,c(1,3)], n = c(5, 0, 0, 0, 0), stringsAsFactors = FALSE) else
      playerhand_number <- data.frame(playerhand_number[,c(1,3)], n = c(3, 1, 1, 2, 0), stringsAsFactors = FALSE)
    } else
    {
    if (straight)
      playerhand_number <- data.frame(playerhand_number[,c(1,3)], n = c(3, 1, 1, 1, 0), stringsAsFactors = FALSE)
    }  

  playerhand_value <- append(append(c(playerhand_number$n), rep("0", 5 - nrow(playerhand_number))), c(playerhand_number$value))
  playerhand_value <- paste(playerhand_value, collapse = '')

  playerhand_value

}

使用上述示例的相同手测试功能:

l <- c("8C TS KC 9H 4S", "7D 2S 5D 3S AC", "8C AD 8D AC 9C", '7C 5H 8D TD KS')
t <- as_tibble(l)
t <- t %>% mutate(hand = str_split(value, " ")) %>% select(hand)
t <- t %>% mutate(value = sapply(t[,1]$hand, hand_value)) %>% arrange(desc(value))
paste(t[[1]][[1]], collapse = " ")

返回相同的结果:

[1] "8C AD 8D AC 9C"

希望能帮助到你。

于 2018-10-06T11:45:04.667 回答
0
 public class Line
{
    private List<Card> _cardsToAnalyse;

    public Line()
    {
        Cards = new List<Card>(5);
    }

    public List<Card> Cards { get; }


    public string PriceName { get; private set; }


    public int Result()
    {
        _cardsToAnalyse = Cards;
        var valueComparer = new CardValueComparer();


        _cardsToAnalyse.Sort(valueComparer);

        if (ContainsStraightFlush(_cardsToAnalyse))
        {
            PriceName = "Straight Flush";
            return PayTable.StraightFlush;
        }

        if (ContainsFourOfAKind(_cardsToAnalyse))
        {
            PriceName = "Quadra";
            return PayTable.FourOfAKind;
        }

        if (ContainsStraight(_cardsToAnalyse))
        {
            PriceName = "Straight";
            return PayTable.Straight;
        }

        if (ContainsFullen(_cardsToAnalyse))
        {
            PriceName = "Full House";
            return PayTable.Fullen;
        }

        if (ContainsFlush(_cardsToAnalyse))
        {
            PriceName = "Flush";
            return PayTable.Flush;
        }

        if (ContainsThreeOfAKind(_cardsToAnalyse))
        {
            PriceName = "Trinca";
            return PayTable.ThreeOfAKind;
        }

        if (ContainsTwoPairs(_cardsToAnalyse))
        {
            PriceName = "Dois Pares";
            return PayTable.TwoPairs;
        }

        if (ContainsPair(_cardsToAnalyse))
        {
            PriceName = "Um Par";
            return PayTable.Pair;
        }

        return 0;
    }

    private bool ContainsFullen(List<Card> _cardsToAnalyse)
    {
        var valueOfThree = 0;

        // Search for 3 of a kind
        Card previousCard1 = null;
        Card previousCard2 = null;

        foreach (var c in Cards)
        {
            if (previousCard1 != null && previousCard2 != null)
                if (c.Value == previousCard1.Value && c.Value == previousCard2.Value)
                    valueOfThree = c.Value;
            previousCard2 = previousCard1;
            previousCard1 = c;
        }

        if (valueOfThree > 0)
        {
            Card previousCard = null;

            foreach (var c in Cards)
            {
                if (previousCard != null)
                    if (c.Value == previousCard.Value)
                        if (c.Value != valueOfThree)
                            return true;
                previousCard = c;
            }

            return false;
        }

        return false;
    }

    private bool ContainsPair(List<Card> Cards)
    {
        Card previousCard = null;

        foreach (var c in Cards)
        {
            if (previousCard != null)
                if (c.Value == previousCard.Value)
                    return true;
            previousCard = c;
        }

        return false;
    }

    private bool ContainsTwoPairs(List<Card> Cards)
    {
        Card previousCard = null;
        var countPairs = 0;
        foreach (var c in Cards)
        {
            if (previousCard != null)
                if (c.Value == previousCard.Value)
                    countPairs++;
            previousCard = c;
        }

        if (countPairs == 2)
            return true;

        return false;
    }

    private bool ContainsThreeOfAKind(List<Card> Cards)
    {
        Card previousCard1 = null;
        Card previousCard2 = null;

        foreach (var c in Cards)
        {
            if (previousCard1 != null && previousCard2 != null)
                if (c.Value == previousCard1.Value && c.Value == previousCard2.Value)
                    return true;
            previousCard2 = previousCard1;
            previousCard1 = c;
        }

        return false;
    }

    private bool ContainsFlush(List<Card> Cards)
    {
        return Cards[0].Naipe == Cards[1].Naipe &&
               Cards[0].Naipe == Cards[2].Naipe &&
               Cards[0].Naipe == Cards[3].Naipe &&
               Cards[0].Naipe == Cards[4].Naipe;
    }

    private bool ContainsStraight(List<Card> Cards)
    {
        return Cards[0].Value + 1 == Cards[1].Value &&
               Cards[1].Value + 1 == Cards[2].Value &&
               Cards[2].Value + 1 == Cards[3].Value &&
               Cards[3].Value + 1 == Cards[4].Value
               ||
               Cards[1].Value + 1 == Cards[2].Value &&
               Cards[2].Value + 1 == Cards[3].Value &&
               Cards[3].Value + 1 == Cards[4].Value &&
               Cards[4].Value == 13 && Cards[0].Value == 1;
    }

    private bool ContainsFourOfAKind(List<Card> Cards)
    {
        Card previousCard1 = null;
        Card previousCard2 = null;
        Card previousCard3 = null;

        foreach (var c in Cards)
        {
            if (previousCard1 != null && previousCard2 != null && previousCard3 != null)
                if (c.Value == previousCard1.Value &&
                    c.Value == previousCard2.Value &&
                    c.Value == previousCard3.Value)
                    return true;
            previousCard3 = previousCard2;
            previousCard2 = previousCard1;
            previousCard1 = c;
        }

        return false;
    }

    private bool ContainsStraightFlush(List<Card> Cards)
    {
        return ContainsFlush(Cards) && ContainsStraight(Cards);
    }
}
于 2020-04-14T10:39:08.030 回答