Four-of-a-Kind, Three-of-a-kind, and a Full House (Poker VII)

To effectively evaluate poker hands, the next sequence after a straight, straight flush, and flush draw (covered in last week’s Lesson) is to evaluate four-of-a-kind, then three-of-a-kind, and (while you’re at it) a full house.

After the hand of playing cards is sorted by value, the four-of-a-kind test has only two possible solutions: the first four cards all have the same value or the last four cards all have the same value. Here’s the fourkind() function I wrote to test both conditions:

/* only two possible hand patterns for
   four-of-a-kind */
int fourkind(struct playing_card p[])
{
    /* test the first four cards */
    if( p[0].value==p[1].value && p[1].value==p[2].value && p[2].value==p[3].value )
        return(TRUE);
    /* test the last four cards */
    if( p[1].value==p[2].value && p[2].value==p[3].value && p[3].value==p[4].value )
        return(TRUE);

    return(FALSE);
}

The if statements are logically complex but serve the task of identifying the two possible patterns for a four-of-a-kind draw. When all the card values compare positively, TRUE is returned.

I used a similar approach to evaluate a three-of-a-kind draw. In this pattern, the first three cards, middle three cards, or last three cards must have the same values to generate a true condition. Here is my threekind() function:

/* three possible hand patterns for
   three-of-a-kind */
int threekind(struct playing_card p[])
{
    /* test the first three cards */
    if( p[0].value==p[1].value && p[1].value==p[2].value )
        return(TRUE);
    /* test the next three cards */
    if( p[1].value==p[2].value && p[2].value==p[3].value )
        return(TRUE);
    /* test the last three cards */
    if( p[2].value==p[3].value && p[3].value==p[4].value )
        return(TRUE);

    return(FALSE);
}

After coding these two functions, I ran some tests. I updated the playing_card hand[][] array to add some positives for four-of-a-kind and three-of-a-kind draws, as well as keeping some of the positive matches for straights and flushes. You can view the full code for this draft on Github. Here’s sample output:

Hand 1: 5♦ 5♠ 6♦ 9♦ 9♥
Hand 2: 2♠ 4♠ 6♠ 10♠ K♠ - Flush
Hand 3: 6♠ 7♣ 7♥ 9♥ J♦
Hand 4: 4♥ 5♥ 6♥ 7♥ 8♥ - Straight Flush
Hand 5: A♠ A♥ A♦ A♣ K♥ - Four-of-a-kind
Hand 6: A♦ 4♣ 4♠ 4♥ 4♦ - Four-of-a-kind
Hand 7: 5♠ 5♣ 5♦ 9♣ J♥ - Three-of-a-kind
Hand 8: A♠ 9♥ 9♦ 9♣ Q♥ - Three-of-a-kind
Hand 9: A♠ A♥ K♦ K♣ K♥ - Three-of-a-kind

The next logical hand to evaluate is a full house, which is a combination three-of-a-kind and a pair. After much sweat and gnashing of teeth, I determined that a separate fullhouse() function would be redundant to the threekind() function. So I modified the threekind() function to also detect a full house:

/* three possible hand patterns for
   three-of-a-kind  - and full house */
int threekind(struct playing_card p[])
{
    /* test the first three cards */
    if( p[0].value==p[1].value && p[1].value==p[2].value )
    {
        /* also test for full house */
        if( p[3].value==p[4].value )
            return(2);
        else
            return(1);
    }

    /* test the next three cards */
    if( p[1].value==p[2].value && p[2].value==p[3].value )
        return(TRUE);
    
    /* test the last three cards */
    if( p[2].value==p[3].value && p[3].value==p[4].value )
    {
        /* also test for a full house */
        if( p[0].value==p[1].value )
            return(2);
        else
            return(1);
    }

    return(FALSE);
}

With the cards in the hand sorted, only two arrangements are possible for a full house: a pair and three-of-a-kind or three-of-a-kind and a pair. The first and last if tests in the threekind() function check for both conditions.

I also modified the return values from this function: FALSE, or zero, means no pattern was found; 1 (TRUE) means the function found a three-of-a-kind match; 2 is returned for a full house. Modifications were also made to the main() function both to show sample full house draws in the hand[][] array.

Click here to view the full code on Github. Here’s a sample run:

Hand 1: 5♦ 5♠ 6♦ 9♦ 9♥
Hand 2: 2♠ 4♠ 6♠ 10♠ K♠ - Flush
Hand 3: 6♠ 7♣ 7♥ 9♥ J♦
Hand 4: 4♥ 5♥ 6♥ 7♥ 8♥ - Straight Flush
Hand 5: A♠ A♥ A♦ A♣ K♥ - Four-of-a-kind
Hand 6: A♦ 4♣ 4♠ 4♥ 4♦ - Four-of-a-kind
Hand 7: 5♠ 5♣ 5♦ 9♣ 9♥ - Full House
Hand 8: A♠ 9♥ 9♦ 9♣ Q♥ - Three-of-a-kind
Hand 9: A♠ A♥ K♦ K♣ K♥ - Full House

In next week’s Lesson I add the final function, pairs(), which checks for one or two pairs.

Leave a Reply