0

I'm currently making a hand evaluator for poker (5 card). Firstly I deal the hands (not from the same deck) and then I check if each has a pair, three of a kind etc, once a match is found lets say a pair of aces, the hands rank will be set to 2 (1-10, 10 being best) and the value of the card will also be set so 14 for ace (1-14, ace highest).

My problem is trying to sort the suckers, I've tried to overload the operator and then I tried to use sort and made a bool func that checks rank. Am I at least on the right path? Using sort didnt actually seem to sort them it just printed them out hand1,hand2,hand3 etc without any indication of even checking handrank and value (I used the bool func as the 3rd parameter..

I have looked around for an hour or so and this is my last resort so any help whatsoever would be much appreciated.

Also Hand is a class that generates a vector of 5 cards, checking if pair etc is done within the hand upon generation and hand rank and value are private class members.

Thanks!

    bool operator > (const Hand &h1) const
{
    return !((*this) < h1.handRank);
}
bool operator < (const Hand &h1) const
{
    if(handRank < h1.handRank)
    {
       return handRank < h1.handRank;
    }
    if(handRank == h1.handRank)
    {
       return highestValue < h1.highestValue;
    }

}

Hands are created in main as hand1, 2 etc.

Each hand containsa vector of 5 cards, each card has a value and a suit.

within each hand int handrank and int highestvalue(value of the highestcard in the current winning hand, eg 2 pair containing aces and 6's, aces would be the highest value)

I have found whether a hand has a pair or a flush etc I just need to sort all of the hands in order of which would win, I'm stuck on how to compare all of the hands at once and see whether one wins or whether for example two have a royal flush

beardedranga
  • 31
  • 1
  • 3
  • What's your code? You have a vector of hands, where each hand contains a vector of cards? – Neil Kirk Mar 22 '15 at 03:15
  • Please provide the code you've written so far. Clarify what you mean by "the operator". – i_am_jorf Mar 22 '15 at 03:15
  • 1
    How could we possibly help you fix your `<` operator without seeing the code you wrote for it? – Matt Phillips Mar 22 '15 at 03:15
  • "My code doesn't work. Please fix it for me." Not only do we not fix your code for you but, even if were inclined to, we cannot fix code we cannot see. – Lightness Races in Orbit Mar 22 '15 at 03:22
  • 4
    Okay that `operator <` is wildly broken. It doesn't even return a value on all code paths, let alone define a valid strict weak ordering. – Lightness Races in Orbit Mar 22 '15 at 03:22
  • 1
    The opposite of < is not >. It is >= – Neil Kirk Mar 22 '15 at 03:23
  • You realize there are a couple dozen off-the-sheld fast poker hand evaluators available, right? I'm rather fond of my own: http://lcrocker.github.io/onejoker/ – Lee Daniel Crocker Mar 27 '15 at 00:29
  • The general procedure for a simple poker hand evaluator like this (i.e., one that just codes close-to-the-rules rather than using mathematical tricks) is this: Sort the hand by rank. Check for all suits equal and set a flag. Then go through each of the hand types top-down: is it a straight flush, is it quads, is it a full house, etc., down to no pair. – Lee Daniel Crocker Mar 27 '15 at 00:33

2 Answers2

1

This is a snippet from a test harness that deals and scores 5 card hands. Perhaps it will help you do what you're trying to do.

#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <tuple>
#include <vector>

enum HandScore
{
    high_card,
    one_pair,
    two_pair,
    three_of_a_kind,
    straight,
    flush,
    full_house,
    four_of_a_kind,
    straight_flush,
    royal_flush,
    num_scores,
};
const char* const HandScoreNames[num_scores] =
{
    "High Card",
    "One Pair",
    "Two Pair",
    "Three of a Kind",
    "Straight",
    "Flush",
    "Full House",
    "Four of a Kind",
    "Straight Flush",
    "Royal Flush",
};
const int kStartingRank = 2;
const int kNumRanks = 13;
const int kNumSuits = 4;
const int kCardsPerHand = 5;
const int kCardsPerDeck = 52;

struct Card
{
    Card(int suit_ = 0, int rank_ = kStartingRank) : rank(rank_), suit(suit_) {}
    bool operator<(const Card& other) const
    {
        return std::tie(rank, suit) < std::tie(other.rank, other.suit);
    }
    int rank;
    int suit;
};

struct Hand
{
    Hand() : cards(kCardsPerHand) {}
    HandScore GetScore()
    {
        HandScore score = high_card;
        std::sort(cards.begin(), cards.end());
        int counts[kNumRanks] = {};
        int suits[kNumSuits] = {};
        for(size_t i = 0; i < cards.size(); ++i)
        {
            ++counts[cards[i].rank - kStartingRank];
            ++suits[cards[i].suit];
        }
        int pair_count = 0;
        int three_count = 0;
        int four_count = 0;
        for(int i = 0; i < kNumRanks; ++i)
        {
            if(counts[i] == 2)
            {
                ++pair_count;
            }
            else if(counts[i] == 3)
            {
                ++three_count;
            }
            else if(counts[i] == 4)
            {
                ++four_count;
            }
        }
        bool is_flush = false;
        for(int i = 0; i < kNumSuits; ++i)
        {
            if(suits[i] == kCardsPerHand)
            {
                is_flush = true;
                break;
            }
        }
        const int spread5  = cards[cards.size() - 1].rank - cards[0].rank;
        const int spread4 = cards[cards.size() - 2].rank - cards[0].rank;
        if(is_flush)
        {
            score = flush;
            if(spread5 == 4)
            {
                if(cards[0].rank == 10)
                {
                    score = royal_flush;
                }
                else
                {
                    score = straight_flush;
                }
            }
            //special check for 2345A
            else if(spread5 == 12 && spread4 == 3 && cards[0].rank == 2 && cards[cards.size() - 1].rank == 14)
            {
                score = straight_flush;
            }
        }
        else
        {
            if(spread5 == 4)
            {
                score = straight;
            }
            //special check for 2345A
            else if(spread5 == 12 && spread4 == 3 && cards[0].rank == 2 && cards[cards.size() - 1].rank == 14)
            {
                score = straight;
            }
            else if(four_count == 1)
            {
                score = four_of_a_kind;
            }
            else if(three_count == 1)
            {
                if(pair_count == 1)
                {
                    score = full_house;
                }
                else
                {
                    score = three_of_a_kind;
                }
            }
            else if(pair_count == 2)
            {
                score = two_pair;
            }
            else if(pair_count == 1)
            {
                score = one_pair;
            }
        }
        return score;
    }
    std::vector<Card> cards;
};

struct Deck
{
    Deck() : cards(kCardsPerDeck)
    {
        for(int s = 0; s < kNumSuits; ++s)
        {
            for(int r = 0; r < kNumRanks; ++r)
            {
                cards[s * kNumRanks + r] = Card(s, r + kStartingRank);
            }
        }
    }
    void shuffle()
    {
        std::random_shuffle(cards.begin(), cards.end());
    }
    void deal(Hand& h)
    {
        for(size_t i = 0; i < h.cards.size(); ++i)
        {
            h.cards[i] = cards[i];
        }
    }
    std::vector<Card> cards;
};

int main()
{
    std::srand(static_cast<unsigned int>(std::time(0)));
    Deck deck;
    Hand hand;
    int scores[num_scores] = {};
    const int num_hands = 1000;
    const int num_width = static_cast<int>(std::log10(num_hands) + 1);
    for(int i = 0; i < num_hands; ++i)
    {
        deck.shuffle();
        deck.deal(hand);
        ++scores[hand.GetScore()];
    }
    std::cout << "Results for " << num_hands << " Hands:" << std::endl;
    for(int i = 0; i < num_scores; ++i)
    {
        std::cout << std::setw(num_width) << std::right << scores[i] << " - " << HandScoreNames[i] << std::endl;
    }
    return 0;
}
Retired Ninja
  • 4,785
  • 3
  • 25
  • 35
  • Use `const char *const HandScoreNames` and `HandScore GetScore() const` – Neil Kirk Mar 22 '15 at 03:32
  • `GetScore` isn't const because it modifies the `cards` vector. – Retired Ninja Mar 22 '15 at 03:37
  • It can be const, you just need to make it so that it doesn't modify the cards vector :) – Neil Kirk Mar 22 '15 at 03:38
  • My desire, in this test harness as I noted, was to modify the vector. That is the reason it is not const. – Retired Ninja Mar 22 '15 at 03:39
  • I don't think you desired for GetScore to modify the vector, it was just easier to implement that way. – Neil Kirk Mar 22 '15 at 03:40
  • You're right, you caught me. I am completely incapable of making a copy to sort and score or making the member variable mutable. Apparently I am also guilty of not calling the function `SortAndScore` since the sorting was for display purposes that are not shown in this **test harness**. – Retired Ninja Mar 22 '15 at 03:43
-1

You're probably going to have to roll your own functions to sort through the cards yourself.

Prepare each function to find the required cards for a hand, starting from a Royal Flush down to a pair. Then, iterator through each function one by one until a matching hand is found.

You're also going to want to store the suit in order to be able to detect flushes.

CinchBlue
  • 6,046
  • 1
  • 27
  • 58