gpt4 book ai didi

为 5 张扑克牌赋值的算法

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:46:38 25 4
gpt4 key购买 nike

我正在开发一个扑克游戏作为大学项目,我们目前的任务是编写一个算法来计算一手 5 张牌,以便可以相互比较两手的分数以确定哪一手牌更好。手牌的分数与随机牌等抽牌时可能形成什么牌的概率无关。 - 手牌的分数仅基于手牌中的 5 张牌,而不是其他牌在甲板上。

我们得到的示例解决方案是为每种类型的扑克牌给出一个默认分数,该分数反射(reflect)了这手牌的好坏 - 例如:

//HAND TYPES:
ROYAL_FLUSH = 900000
STRAIGHT_FLUSH = 800000
...
TWO_PAIR = 200000
ONE_PAR = 100000

然后如果比较相同类型的两手牌,手牌的点数应该计入手牌的分数。

例如,可以使用以下公式对一手牌进行评分:

HAND_TYPE + (each card value in the hand)^(the number of occurences of that value)

因此,对于三个 Q 和两个 7 的满堂彩,得分为:

600000 + 12^3 + 7^2

这个公式在大多数情况下都有效,但我已经确定,在某些情况下,两只相似的手可以返回完全相同的分数,而实际上应该打败另一只。这方面的一个例子是:

hand1 = 4C, 6C, 6H, JS, KC
hand2 = 3H, 4H, 7C, 7D, 8H

这两只手都有一对,所以他们各自的分数是:

100000 + 4^1 + 6^2 + 11^1 + 13^1 = 100064
100000 + 3^1 + 4^1 + 7^2 + 8^1 = 100064

这导致平局,显然一对 7 胜过一对 6。

我如何改进这个公式,甚至我可以使用什么更好的公式?

顺便说一句,在我的代码中,手牌存储在每张牌的值按升序排列的数组中,例如:

[2H, 6D, 10C, KS, AS]

编辑:

由于以下答案,这是我的最终解决方案:

    /**
* Sorts cards by putting the "most important" cards first, and the rest in decreasing order.
* e.g. High Hand: KS, 9S, 8C, 4D, 2H
* One Pair: 3S, 3D, AH, 7S, 2C
* Full House: 6D, 6C, 6S, JC, JH
* Flush: KH, 9H, 7H, 6H, 3H
*/
private void sort() {
Arrays.sort(hand, Collections.reverseOrder()); // Initially sorts cards in descending order of game value
if (isFourOfAKind()) { // Then adjusts for hands where the "most important" cards
sortFourOfAKind(); // must come first
} else if (isFullHouse()) {
sortFullHouse();
} else if (isThreeOfAKind()) {
sortThreeOfAKind();
} else if (isTwoPair()) {
sortTwoPair();
} else if (isOnePair()){
sortOnePair();
}
}

private void sortFourOfAKind() {
if (hand[0].getGameValue() != hand[HAND_SIZE - 4].getGameValue()) { // If the four of a kind are the last four cards
swapCardsByIndex(0, HAND_SIZE - 1); // swap the first and last cards
} // e.g. AS, 9D, 9H, 9S, 9C => 9C, 9D, 9H, 9S, AS
}

private void sortFullHouse() {
if (hand[0].getGameValue() != hand[HAND_SIZE - 3].getGameValue()) { // If the 3 of a kind cards are the last three
swapCardsByIndex(0, HAND_SIZE - 2); // swap cards 1 and 4, 2 and 5
swapCardsByIndex(HAND_SIZE - 4, HAND_SIZE - 1); // e.g. 10D, 10C, 6H, 6S, 6D => 6S, 6D, 6H, 10D, 10C
}
}

private void sortThreeOfAKind() { // If the 3 of a kind cards are the middle 3 cards
if (hand[0].getGameValue() != hand[HAND_SIZE - 3].getGameValue() && hand[HAND_SIZE - 1].getGameValue() != hand[HAND_SIZE - 3].getGameValue()) { // swap cards 1 and 4
swapCardsByIndex(0, HAND_SIZE - 2); // e.g. AH, 8D, 8S, 8C, 7D => 8C, 8D, 8S, AH, 7D
} else if (hand[0].getGameValue() != hand[HAND_SIZE - 3].getGameValue() && hand[HAND_SIZE - 4].getGameValue() != hand[HAND_SIZE - 3].getGameValue()) {
Arrays.sort(hand); // If the 3 of a kind cards are the last 3,
swapCardsByIndex(HAND_SIZE - 1, HAND_SIZE - 2); // reverse the order (smallest game value to largest)
} // then swap the last two cards (maintain the large to small ordering)
} // e.g. KS, 9D, 3C, 3S, 3H => 3H, 3S, 3C, 9D, KS => 3H, 3S, 3C, KS, 9D

private void sortTwoPair() {
if (hand[0].getGameValue() != hand[HAND_SIZE - 4].getGameValue()) { // If the two pairs are the last 4 cards
for (int i = 0; i < HAND_SIZE - 1; i++) { // "bubble" the first card to the end
swapCardsByIndex(i, i + 1); // e.g. AH, 7D, 7S, 6H, 6C => 7D, 7S, 6H, 6C, AH
}
} else if (hand[0].getGameValue() == hand[HAND_SIZE - 4].getGameValue() && hand[HAND_SIZE - 2].getGameValue() == hand[HAND_SIZE - 1].getGameValue()) { // If the two pairs are the first and last two cards
swapCardsByIndex(HAND_SIZE - 3, HAND_SIZE - 1); // swap the middle and last card
} // e.g. JS, JC, 8D, 4H, 4S => JS, JC, 4S, 4H, 8D
}

private void sortOnePair() { // If the pair are cards 2 and 3, swap cards 1 and 3
if (hand[HAND_SIZE - 4].getGameValue() == hand[HAND_SIZE - 3].getGameValue()) { // e.g QD, 8H, 8C, 6S, 4J => 8C, 8H, QD, 6S, 4J
swapCardsByIndex(0, HAND_SIZE - 3);
} else if (hand[HAND_SIZE - 3].getGameValue() == hand[HAND_SIZE - 2].getGameValue()) { // If the pair are cards 3 and 4, swap 1 and 3, 2 and 4
swapCardsByIndex(0, HAND_SIZE - 3); // e.g. 10S, 8D, 4C, 4H, 2H => 4C, 4H, 10S, 8D, 2H
swapCardsByIndex(HAND_SIZE - 4, HAND_SIZE - 2);
} else if (hand[HAND_SIZE - 2].getGameValue() == hand[HAND_SIZE - 1].getGameValue()) { // If the pair are the last 2 cards, reverse the order
Arrays.sort(hand); // and then swap cards 3 and 5
swapCardsByIndex(HAND_SIZE - 3, HAND_SIZE - 1); // e.g. 9H, 7D, 6C, 3D, 3S => 3S, 3D, 6C, 7D, 9H => 3S, 3D, 9H, 7D, 6C
}
}

/**
* Swaps the two cards of the hand at the indexes taken as parameters
* @param index1
* @param index2
*/
private void swapCardsByIndex(int index1, int index2) {
PlayingCard temp = hand[index1];
hand[index1] = hand[index2];
hand[index2] = temp;
}

/**
* Gives a unique value of any hand, based firstly on the type of hand, and then on the cards it contains
* @return The Game Value of this hand
*
* Firstly, a 24 bit binary string is created where the most significant 4 bits represent the value of the type of hand
* (defined as constants private to this class), the last 20 bits represent the values of the 5 cards in the hand, where
* the "most important" cards are at greater significant places. Finally, the binary string is converter to an integer.
*/
public int getGameValue() {
String handValue = addPaddingToBinaryString(Integer.toBinaryString(getHandValue()));

for (int i = 0; i < HAND_SIZE; i++) {
handValue += addPaddingToBinaryString(Integer.toBinaryString(getCardValue(hand[i])));
}

return Integer.parseInt(handValue, 2);
}

/**
* @param binary
* @return the same binary string padded to 4 bits long
*/
private String addPaddingToBinaryString(String binary) {
switch (binary.length()) {
case 1: return "000" + binary;
case 2: return "00" + binary;
case 3: return "0" + binary;
default: return binary;
}
}

/**
* @return Default value for the type of hand
*/
private int getHandValue() {
if (isRoyalFlush()) { return ROYAL_FLUSH_VALUE; }
if (isStraightFlush()) { return STRAIGHT_FLUSH_VALUE; }
if (isFourOfAKind()) { return FOUR_OF_A_KIND_VALUE; }
if (isFullHouse()) { return FULL_HOUSE_VALUE; }
if (isFlush()) { return FLUSH_VALUE; }
if (isStraight()) { return STRAIGHT_VALUE; }
if (isThreeOfAKind()) { return THREE_OF_A_KIND_VALUE; }
if (isTwoPair()) { return TWO_PAIR_VALUE; }
if (isOnePair()) { return ONE_PAIR_VALUE; }
return 0;
}

/**
* @param card
* @return the value for a given card type, used to calculate the Hand's Game Value
* 2H = 0, 3D = 1, 4S = 2, ... , KC = 11, AH = 12
*/
private int getCardValue(PlayingCard card) {
return card.getGameValue() - 2;
}

最佳答案

有 10 种公认的扑克手牌:

9 - Royal flush
8 - Straight flush (special case of royal flush, really)
7 - Four of a kind
6 - Full house
5 - Flush
4 - Straight
3 - Three of a kind
2 - Two pair
1 - Pair
0 - High card

如果不算花色,则只有 13 种可能的牌值。卡值是:

2 - 0
3 - 1
4 - 2
5 - 3
6 - 4
7 - 5
8 - 6
9 - 7
10 - 8
J - 9
Q - 10
K - 11
A - 12

手牌编码需要 4 位,纸牌编码也需要 4 位。您可以用 24 位编码一整只手。

皇家同花顺是 1001 1100 1011 1010 1001 1000 (0x9CBA98)

7 高顺子是 0100 0101 0100 0011 0010 0001 (0x454321)

两对,10s 和 5s(和一个 A)将是 0010 1000 1000 0011 0011 1100 (0x28833C)

我假设您有判断自己手牌的逻辑。在这方面,您可能已经编写了代码来按从左到右的顺序排列卡片。所以皇家同花顺将被安排为 [A,K,Q,J,10]。然后,您可以使用以下逻辑构造代表手的数字:

int handValue = HandType; (i.e. 0 for high card, 7 for Four of a kind, etc.)
for each card
handValue = (handValue << 4) + cardValue (i.e. 0 for 2, 9 for Jack, etc.)

结果将是每手牌的唯一值,并且您可以确定同花总是打败顺子,K 高葫芦总是打败 7 高葫芦,等等。

标准化手

上述算法取决于对扑克牌进行归一化,最重要的牌优先。因此,例如,手牌 [K,A,10,J,Q](所有花色相同)是皇家同花顺。它被规范化为 [A,K,Q,J,10]。如果给你手 [10,Q,K,A,J],它也会被标准化为 [A,K,Q,J,10] . [7,4,3,2,4] 是一对 4。它将被规范化为 [4,4,7,3,2]

如果没有规范化,就很难为每一手牌创建一个唯一的整数值,并保证一对 4 总是会击败一对 3。

幸运的是,对手牌进行分类是弄清楚手牌是什么的一部分。您可以在不排序的情况下做到这一点,但是对五个项目进行排序只需要很少的时间,而且它使很多事情变得容易得多。它不仅使确定顺子更容易,还将常见的牌组合在一起,这使得查找对子、三元组和四元组更容易。

对于顺子、同花和大牌,您需要做的就是排序。对于其他人,您必须进行第二次排序,按分组进行排序。例如,满屋是 xxxyy,一对是 xxabc,(abc 按顺序),等等。不管怎样,这些工作基本上都是为你完成的。您所要做的就是将掉队者移到最后。

关于为 5 张扑克牌赋值的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42380183/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com