Step 1: Determine frequencies of each rank
Ranks range from 2 to 14, where Jack is 11, Queen is 12, King is 13, and Ace is 14.
Make an array rankFreqs of 15 integers, indexed from 0 to 14, so that rankFreqs[6] indicates the number of 6s in a particular hand. Positions 0 and 1 are ignored. The values in the array are first initialized to 0.
int[] rankFreqs = new int[15];
For each card in the hand, increment the value in rankFreqs corresponding to that card's rank.
for (Card card : hand)
rankFreqs[card.getRank()]++;
rankFreqs contains [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 1, 0, 1].
Step 2: Sort the hand, first by rank frequency, and then by rank
In the course of sorting the hand, card x should precede card y if x's rank occurs more often than y's. If both ranks occur the same number of times, then x should precede y if x's rank is greater than y's.
For the hand above, J precedes A (because there are more jacks than aces) and Q precedes 7 (because there are the same number of Qs and 7s, and Q is higher than 7). Here's an implementation using selection sort.
for (int i = 0; i < hand.length; i++)
{
for (int j = i + 1; j < hand.length; j++)
{
int ranki = hand[i].getRank();
int rankj = hand[j].getRank();
int freqi = rankFreqs[ranki];
int freqj = rankFreqs[rankj];
if (freqj > freqi || (freqj == freqi && rankj > ranki))
swap(hand, i, j);
}
}
After sorting, the hand contains:
Step 3: Test for a flush
boolean flush =
hand[0].getSuit() == hand[1].getSuit() &&
hand[0].getSuit() == hand[2].getSuit() &&
hand[0].getSuit() == hand[3].getSuit() &&
hand[0].getSuit() == hand[4].getSuit();
Step 4: Test for a straight
Straights are just as easy, except that we need to test for 5-high straights. These are currently mis-sorted as A5432 and must be re-sorted as 5432A. For any other straight, we just need to test that each card's rank is one higher than the next.
boolean straight;
if (hand[0].getRank() == 14 && hand[1].getRank() == 5 &&
hand[2].getRank() == 4 && hand[3].getRank() == 3 &&
hand[4].getRank() == 2)
{
straight = true; //5-high straight
Card ace = hand[0];
hand[0] = hand[1];
hand[1] = hand[2];
hand[2] = hand[3];
hand[3] = hand[4];
hand[4] = ace;
}
else
{
straight =
hand[0].getRank() == hand[1].getRank() + 1 &&
hand[1].getRank() == hand[2].getRank() + 1 &&
hand[2].getRank() == hand[3].getRank() + 1 &&
hand[3].getRank() == hand[4].getRank() + 1;
}
Step 5: Categorize the hand, testing for the strongest categories first
Now that we've done the hard work, categorizing the hand is easy. Assume we have integer constants defined for categories, such that STRAIGHT_FLUSH > FOUR_OF_A_KIND > FULL_HOUSE > FLUSH > STRAIGHT > THREE_OF_A_KIND > TWO_PAIR > PAIR > HIGH_CARD. We test for the strongest categories first.
if (straight && flush) return STRAIGHT_FLUSH;
if (hand[0].getRank() == hand[3].getRank()) return FOUR_OF_A_KIND;
if (hand[3].getRank() == hand[4].getRank()) return FULL_HOUSE;
if (flush) return FLUSH;
if (straight) return STRAIGHT;
if (hand[0].getRank() == hand[2].getRank()) return THREE_OF_A_KIND;
if (hand[2].getRank() == hand[3].getRank()) return TWO_PAIR;
if (hand[0].getRank() == hand[1].getRank()) return PAIR;
return HIGH_CARD;
Comparing Hands
Having sorted hands and identified their categories, it's easy to determine whether one hand beats another. If hand x's category is greater than y's, then x is the better hand. If they have the same category, then we compare the sorted hands, card by card. If x's card ever outranks y's, then x is the better hand. If all corresponding cards have the same ranks, then the hands are equal, presumably resulting in a split pot.
if (category1 > category2) return 1; //hand 1 is stronger
if (category2 > category1) return 2; //hand 2 is stronger
for (int i = 0; i < 5; i++)
{
int rank1 = hand1[i].getRank();
int rank2 = hand2[i].getRank();
if (rank1 > rank2) return 1; //hand 1 is stronger
if (rank2 > rank1) return 2; //hand 2 is stronger
}
return 0; //hands are equally strong
No comments:
Post a Comment