Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function to determine whether a poker hand is a straight?

For a homework assignment I was given a Card class that has enumerated types for the Rank and Suit. I am required to compare two poker hands (each hand is an ArrayList of 5 cards) and decide the winner.

The isStraight() function is really bothering me, because I have to start over the count after the Ace. For example,

QUEEN, KING, ACE, TWO, THREE

Is still considered a straight. What is the best way to code this functionality?

Here is the Rank/Suit enumerated type code, if that helps.

public enum Rank
{
    TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), EIGHT(8), NINE(9),
    TEN(10), JACK(11), QUEEN(12), KING(13), ACE(14);

    private final int points;

    private Rank(int points)
    {
        this.points = points;
    }

    public int points()
    {
        return this.points;
    }
}

public enum Suit
{
    DIAMONDS, CLUBS, HEARTS, SPADES;
}
like image 331
Logan Serman Avatar asked Feb 09 '09 22:02

Logan Serman


4 Answers

You do realize that by the rules of any poker game I've ever played or heard of a straight cannot wrap right? Ace can be low [A,2,3,4,5] or high [10,J,Q,K,A] but it can't wrap. According to those rules (not yours) I've implemented something similar before. Basically you sort the array and walk it, making sure the current card is one higher than the previous. In the first iteration, if it is an ace, then you explicitly check for [A,2,3,4,5]. If it is you return true and if it isn't you continue with the normal straight logic. This should set you in the right direction.

like image 124
shsteimer Avatar answered Oct 22 '22 15:10

shsteimer


You could write a fancy algorithm to return true despite the number of possible cards but if you realize there are only 10 valid combinations on a sorted hand, you could just look for these:

2-6, 3-7, 4-8, 5-9, 6-T, 7-J, 8-Q, 9-K, T-A, (2-5,A)
like image 38
Austin Salonen Avatar answered Oct 22 '22 15:10

Austin Salonen


A nice approach for resolving poker hands in general is to assign each card a bit value with bit ((rank-2)*2) bit set as well as bit (suit+28) set, (so 2=1, 3=4, 4=16, etc. up to A=0x1000000). Then add together all the cards (call that result 'Sum'. Compute V1=(Sum & 0x2AAAAAA)>>1, V0=(Sum & 0x1555555), and V2=V1 & V0. Also OR together the values for the five cards, and compute V3=OrValue & 0xF0000000;

  1. For a pair, V1 will have a single bit set, V0 will have multiple bits set, and V2 will be zero.
  2. For two-pair, V1 will have two bits set and V2 will equal zero.
  3. For a three-of-a-kind, V1 will have a single bit set, and V2 will equal V1.
  4. For a straight, V0 will either be 0x1000055 or else a power-of-two multiple of 0x155.
  5. For a flush, V2 will have precisely one bit set.
  6. For a full house, V1 will have two bits set, and V2 will be non-zero.
  7. For four-of-a-kind, either V1 will be twice v0, with both having one bit set, or V0 will have precisely two bits set and V1 will be zero.
  8. For a straight flush, conditions for straight and flush will be met.

This tests required for this approach should be implementable quickly with a minimal amount of branching.

like image 3
supercat Avatar answered Oct 22 '22 16:10

supercat


Since there's only 5 cards in you list, you could sort it and determine the difference between 2 consecutive cards. If it contains an ace, you need to consider it as a low card too. if all the differences are 1 (or -1, depending on the sort order), you have your straight.

like image 2
Rik Avatar answered Oct 22 '22 16:10

Rik