Poker game hand check

Hi, I’m doing a simple project where there are 2 players “playing” poker. I am now at the part where I need to check for whose hand is bigger and what kind of hand they have. I’m kind of stuck with getting started on the logic. I know I need to do the biggest hand to the smallest hand (Royal Flush, fullhouse etc)

So far I can’t seem to find a way to do it other than to individual checking those conditions and brute force my way through.

I’m using arrays for both players and the 5 cards on the table(P1Hand[ ] , P2Hand[ ], TableHand[ ] ). Could anyone help me with this?

Computers are fast, and you’re just checking two hands, so there’s no reason to be super-optimal performance-wise here.

Checking for a flush is really easy - just check if all the suits are the same. Pairs, Three and Four of a kind is also pretty easy - check the first card, then check if there’s matching values in the remainder. Repeat for the second card for four of a kind, the second and third for three of a kinda, and so on. Essentially you have to nested for-loops.

Straigths are a lot easier if you sort the hand first. Just use Array.Sort with a sort that checks for the card’s value, and then check if each card in succession is one off each other.

A house is just HasPair && HasThreeOfAKind.

In short, it’s just coding stuff, so it should be fine.

If you’re doing Texas Hold’em (which it sounds like), you’ll want to construct a hand that combines the cards in the player’s hand with the cards on the table before you do the check.

Well, I’m stuck at three/four of a kind… So far how I have done my checks is pretty basic using 2 for loops (to check for pairs) and going through my entire array of Cards. So do i use a triple for loop to check for three of a kind and 4 for loops to check for 4 of a kind?

My pair check:

public void GetHand()
    {

        int samecardcounter = 0;
        int sametypecounter = 0;

        SortCards();
      
        for (int i = 0; i < fullHand.Length; i++)
        {
            for (int j = i + 1; j < fullHand.Length; j++)
            {
                //Pair check
                if (fullHand[i].Cn == fullHand[j].Cn)
                {
                    if(HighestCard != null && HighestCard.Cn < fullHand[i].Cn)
                    {
                        HighestCard = fullHand[i];
                    }
                    else if(HighestCard == null)
                    {
                        HighestCard = fullHand[i];
                    }
                    samecardcounter++;
                }
                else if (fullHand[i].suit == fullHand[j].suit)
                {
                    sametypecounter++;
                }
            }
        }

        if (samecardcounter == 0 && sametypecounter == 0)
        {
            dhand = DHand.HIGHCARD;
        }
        else if (samecardcounter == 1 && sametypecounter < 5)
        {
            dhand = DHand.ONEPAIR;
        }
        else if (samecardcounter == 2 && sametypecounter < 5)
        {
            dhand = DHand.TWOPAIR;
        }
    }

i basically use counters to determine if its a pair or 2 pairs. I also check the suits so that the biggest hand they have is a pair or 2 pairs.

It feels off to me and I can’t pinpoint out what. I’ve been going around in circles and kinda hoping someone can point me to the right direction

[EDIT: do ignore the fact i did not check if it was a straight and set the dHand to a highcard its all just testing for now]

You sort the cards by their ranks.
Then you do the checks in a logical order
i.e.

if straight flush
  if royal
else if flush
else if 5 of a kind (if supported)
else if 4 of a kind
else if full house
else if 3 of a kind
else if two pairs
else if (strong) pair
else // check for highest card

That way each check comes logically after all previous have failed, so you can narrow down your logic in each.
The only exception being royal check that simply confirms the suit after the straight flush has been detected.

I also implore you to make a full hand combination check, build up full statistics, and test this against a list of proven poker winning combinations, until you nail the hand detection algorithm, as this is very easy to do wrong.

Joker adds another layer of complexity. Though this is a very nice programming practice, I did this two or three times in life, and really enjoyed it.

int consecutiveRankCheck(List<Card> sortedHand, int start, int count) {
  for(int i = start; i < sortedHand.Count - 1; i++) { // the master card to check against
    if(sortedHand.Count - i -1 < count) break; // abandon if we have less than 'count' amount of cards remained
    int match = 1; // count the first card as the first match
    for(int j = i + 1; j < sortedHand.Count; j++) { // check the remaining cards
      if(sortedHand[i].rank != sortedHand[j].rank) { // if not equal, try with another card
        break;
      } else { // if equal, increase match count and test for condition
        if(++match == count) return i; // enough consecutive ranks were found
      }
    }
  }
  return -1; // not enough consecutive ranks were found
}

This code will return an index of the first rank that has consecutive matches. (Haven’t tested it though, maybe it just does something silly :slight_smile: )
This you can use for all of-a-kind checks (just by checking if >= 0), but also for checking full house and two pairs, where you expect to find two different indices. For this you’re supposed to use the last result and feed it as the start of the subsequent one.

I.e. because full house should be either LLLSS or LLSSS (L = large rank, S = small rank)
and it comes after you’ve checked for 5- and 4-of-a-kind
you can expect this to work

bool isFullHouse(List<Card> sortedHand) {
  var index = consecutiveRankCheck(sortedHand, 0, 3); // you intentionally start with 3 cards first
  if(index >= 0 && consecutiveRankCheck(sortedHand, index + 3, 2) >= 0) return true;
  index = consecutiveRankCheck(sortedHand, 0, 2);
  if(index >= 0 && consecutiveRankCheck(sortedHand, index + 2, 3) >= 0) return true;
  return false;
}

There are numerous ways to achieve this, some are more clever than the others, this is only to illustrate the point.

edit:
Though in the above case, starts could’ve been hardcoded, this approach starts to pay off with two pairs, because there are three possible configurations.

XLLSS
LLXSS
LLSSX

bool isTwoPairs(List<Card> sortedHand) {
  var index = consecutiveRankCheck(sortedHand, 0, 2);
  if(index >= 0 && consecutiveRankCheck(sortedHand, index + 2, 2) >= 0) return true;
  return false;
}

Alternatively, you can return the actual indices, so that you can identify the actual two pair (or full house) combination when it comes to discerning which player has the strongest ranks.

(int index1, int index2) isTwoPairs(List<Card> sortedHand) {
  var index1 = consecutiveRankCheck(sortedHand, 0, 2);
  if(index1 >= 0) {
    var index2 = consecutiveRankCheck(sortedHand, index1 + 2, 2);
    if(index2 >= 0) return (index1, index2);
  }
  return (-1, -1);
}

Or

bool tryGetTwoPairs(List<Card> sortedHand, out int index1, out int index2) {
  index1 = consecutiveRankCheck(sortedHand, 0, 2);
  if(index1 >= 0) {
    index2 = consecutiveRankCheck(sortedHand, index1 + 2, 2);
    if(index2 >= 0) return true;
  }
  index2 = -1;
  return false;
}

You then simply

var sortedHand = sortHand(handCards);
if(tryGetTwoPairs(sortedHand, out var tpf1, out var tpf2)) {
  Debug.Log($"Found two pairs of {sortedHand[tpf1].rank} and {sortedHand[tpf2].rank}");
}

Now that I’ve found some of my old code, there is another approach as well.
You can also work from the simple pair, and move up the ladder.

This code would automatically select the cards that were part of the winning combination (‘HELD’ cards). This information can be subsequently used to analyze whether the cards belong to a previously detected winning combination, allowing you to evaluate the hand bottom-up.

Just a food for thought.

Btw, if you’re doing joker as well, this is how to make sure you’re in control. (These tips will work if you have exactly 1 joker in the deck, I’m not sure otherwise.)

  • always sort the joker as the least ranking card (rank 0, or even -1).
  • do your normal evaluation, ignoring the joker.
  • then re-evaluate the winning combination in the 2nd pass, but joker should automatically snap to a more powerful win.

for example
high card => one pair; i.e. K246J = KK246
one pair => 3 of a kind; i.e. KK24J => KKK24
two pairs => full house; i.e. KK88J => KKK88
3 of a kind => 4 of a kind; i.e. KKK2J => KKKK2
4 of a kind => 5 of a kind; i.e. KKKKJ => KKKKK

straights should be tackled in a custom fashion, but you can always tell if there is a possible straight, because you’ll have nothing detected so far when you start the 2nd pass.

Oh and one more thing, for full house the rank that is 3 of a kind is a winner, and so because if you’re doing the thing like I’ve shown for the two pairs, the actual order matters. With LLLSS, L is the winner, with LLSSS, S is a winner.

So this kind of twist makes sense

bool tryGetFullHouse(List<Card> sortedHand, out int index1, out int index2) {
  index1 = consecutiveRankCheck(sortedHand, 0, 3);
  if(index1 >= 0) {
    index2 = consecutiveRankCheck(sortedHand, 3, 2);
    if(index2 >= 0) return true;
  }
  index2 = consecutiveRankCheck(sortedHand, 0, 2);
  if(index2 >= 0) {
    index1 = consecutiveRankCheck(sortedHand, 2, 3);
    if(index1 >= 0) return true;
  }
  index1 = -1;
  index2 = -1;
  return false;
}
var sortedHand = sortHand(handCards);
if(tryGetFullHouse(sortedHand, out var fhf1, out var fhf2)) {
  Debug.Log($"Found full house of {sortedHand[fhf1].rank} and {sortedHand[fhf2].rank}");
}

Firstly what @Baste said, there’s probably no need to optimise such a simple thing.

However I think the you can walk forward through the hand eliminating possibilities that require all cards to meet a criteria, whilst adding in pairs and triples as you find them. With this approach you only loop the hand once.

Something like the below works for a five card stud, hold-em would be a little more complex as you can’t early out so easily… but I expect with a bit of wrangling the sames concepts apply.

(This is psuedo code)

[Flags] public enum HandType {
  HighCard       = 0,
  Pair           = 1 << 0,
  TwoPair        = 1 << 1
  Trips          = 1 << 2,
  Four           = 1 << 3,
  FullHouse      = 1 << 4
  Straight       = 1 << 5,
  Flush          = 1 << 6,
  StraightFlush  = Straight | Flush
}

int lastCardCount = 1;
int bestPairPos;

void GetBestHand() {
  HandType bestHand = HandType.Flush | HandType.Straight;

  hand = SortByRank(hand);            // Makes straight and pair detection easier, algo relies on this completely (suit doesn't matter)

  for (int i =1; i < 5; i++) {        // Note: Start from pos =1 not 0
    CountMatchingCards(pos);
    CheckFlush(pos);
    CheckStraight(pos);
  }

  // We now have the type stored in bestHand
  // For finding the high card on HighCard, Flush or Straight look in hand[4]
  // Except for special case where a Straight has high card of rank 14 (ace), in this case the actual high card depends on hand[3] being a king or a 5
  // For two of a kind you need to look in hand[3] and hand[1] (as no matter what combination it is both of these must hold the high card of the corresponding pair)
  // For full house you can do hand[3] and hand[1] as well just to match, or hand[4] and hand [1] if that makes you feel warmer
  // Trips requires you to look at hand[2], Four of a kind can do the same
  // A single pair needs to use the bestPairPos variable

}

void CheckFlush(int pos) {
  if ((bestHand  & HandType.Flush) != HandType.Flush) return;
  if (hand[0].suit != hand[pos].suit) bestHand  &= ~HandType.Flush; // Can't be a flush
}

void CheckStraight(int pos) {
  if ((bestHand & HandType.Straight)  != HandType.Straight ) return;
  if (pos == 4 && hand[pos].rank == 14 ) return;  // Special case for aces which I count as rank 14
  if (hand[pos-1].rank + 1 != hand[pos].rank) bestHand  &= ~HandType.Straight; // Can't be a straight
}

void CountMatchingCards(int pos) {
  if ((bestHand & HandType.Four) == HandType.Four) return;     // If you found four this can't be anything else
  if ((bestHand & HandType.FullHouse) == HandType.FullHouse) return;    // If you found full house this can't be anything else
  if (hand[pos-1].rank == hand[pos].rank){
    lastCardCount++;
    if (lastCardCount == 4) bestHand  = HandType.Four;
  } else {
    if (lastCardCount == 3) {
      if ((bestHand & HandType.Pair) == HandType.Pair) bestHand = HandType.FullHouse;
      bestHand  = HandType.Trips;
    } else if (lastCardCount == 2) {
      if ((bestHand & HandType.Pair) == HandType.Pair) bestHand = HandType.TwoPair;
      bestHand = HandType.Pair;
      bestPairPos = pos;
    }
    lastCardCount = 1;
  }
}

One problem with code like this is its not super easy to tell whats going on at first glance as it relies on implicit properties of the sorted set.

PS there could by logic errors in here, the concept is sound, but its purely typed in to a browser.

PPS If we are going for pure speed optimisation there still may be optimisations possible along the lines of some of things suggested by others above (i.e. if (hand[1] == hand[3]) then we must have trips of four of a kind, if (hand[0] + 4 = hand[4]) we must have a straight … but is this really an optimisation as we still need to loop to check suit).

Balancing these optimisations vs the core loop approach probably requires looking at probability distributions of hands (and if doing this do you take it further by considering actual hand data which takes in to account that people are more likely to hold onto certain cards/combinations).

We can also take it further by considering the sort as part of the process, e.g. it might be more efficient to determine if we have a flush or straight while we do the sort.

Fun stuff …

EDIT: Added case of aces in a straight.

EDIT: Kicker logic not included, not sure I have the time to figure out a way to bake the logic in across all scenarios without doing another loop (not that it matters but my goal was a solution with a single loop :slight_smile: )

So… I don’t know why. I read this thread and it made me interested in seeing if I could do this in an O(N) way with as little to no garbage as possible.

And I think I got it (mind you I didn’t test this for ALL possible hands… I just threw random things at it and saw if it spat back what I expected).

    //low 4-bits are face 
    public enum CardFace : byte
    {
        None = 0,
        Ace = 1,
        Two = 2,
        Three = 3,
        Four = 4,
        Five = 5,
        Six = 6,
        Seven = 7,
        Eight = 8,
        Nine = 9,
        Ten = 10,
        Jack = 11,
        Queen = 12,
        King = 13
    }

    //bits 5-8 are the suit
    public enum CardSuit : byte
    {
        Diamonds = 16,
        Clubs = 32,
        Hearts = 64,
        Spades = 128
    }

    public enum Card : byte
    {
        None = 0,
        AceDiamonds = CardFace.Ace | CardSuit.Diamonds,
        TwoDiamonds = CardFace.Two | CardSuit.Diamonds,
        ThreeDiamonds = CardFace.Three | CardSuit.Diamonds,
        FourDiamonds = CardFace.Four | CardSuit.Diamonds,
        FiveDiamonds = CardFace.Five | CardSuit.Diamonds,
        SixDiamonds = CardFace.Six | CardSuit.Diamonds,
        SevenDiamonds = CardFace.Seven | CardSuit.Diamonds,
        EightDiamonds = CardFace.Eight | CardSuit.Diamonds,
        NineDiamonds = CardFace.Nine | CardSuit.Diamonds,
        TenDiamonds = CardFace.Ten | CardSuit.Diamonds,
        JackDiamonds = CardFace.Jack | CardSuit.Diamonds,
        QueenDiamonds = CardFace.Queen | CardSuit.Diamonds,
        KingDiamonds = CardFace.King | CardSuit.Diamonds,
        AceClubs = CardFace.Ace | CardSuit.Clubs,
        TwoClubs = CardFace.Two | CardSuit.Clubs,
        ThreeClubs = CardFace.Three | CardSuit.Clubs,
        FourClubs = CardFace.Four | CardSuit.Clubs,
        FiveClubs = CardFace.Five | CardSuit.Clubs,
        SixClubs = CardFace.Six | CardSuit.Clubs,
        SevenClubs = CardFace.Seven | CardSuit.Clubs,
        EightClubs = CardFace.Eight | CardSuit.Clubs,
        NineClubs = CardFace.Nine | CardSuit.Clubs,
        TenClubs = CardFace.Ten | CardSuit.Clubs,
        JackClubs = CardFace.Jack | CardSuit.Clubs,
        QueenClubs = CardFace.Queen | CardSuit.Clubs,
        KingClubs = CardFace.King | CardSuit.Clubs,
        AceHearts = CardFace.Ace | CardSuit.Hearts,
        TwoHearts = CardFace.Two | CardSuit.Hearts,
        ThreeHearts = CardFace.Three | CardSuit.Hearts,
        FourHearts = CardFace.Four | CardSuit.Hearts,
        FiveHearts = CardFace.Five | CardSuit.Hearts,
        SixHearts = CardFace.Six | CardSuit.Hearts,
        SevenHearts = CardFace.Seven | CardSuit.Hearts,
        EightHearts = CardFace.Eight | CardSuit.Hearts,
        NineHearts = CardFace.Nine | CardSuit.Hearts,
        TenHearts = CardFace.Ten | CardSuit.Hearts,
        JackHearts = CardFace.Jack | CardSuit.Hearts,
        QueenHearts = CardFace.Queen | CardSuit.Hearts,
        KingHearts = CardFace.King | CardSuit.Hearts,
        AceSpades = CardFace.Ace | CardSuit.Spades,
        TwoSpades = CardFace.Two | CardSuit.Spades,
        ThreeSpades = CardFace.Three | CardSuit.Spades,
        FourSpades = CardFace.Four | CardSuit.Spades,
        FiveSpades = CardFace.Five | CardSuit.Spades,
        SixSpades = CardFace.Six | CardSuit.Spades,
        SevenSpades = CardFace.Seven | CardSuit.Spades,
        EightSpades = CardFace.Eight | CardSuit.Spades,
        NineSpades = CardFace.Nine | CardSuit.Spades,
        TenSpades = CardFace.Ten | CardSuit.Spades,
        JackSpades = CardFace.Jack | CardSuit.Spades,
        QueenSpades = CardFace.Queen | CardSuit.Spades,
        KingSpades = CardFace.King | CardSuit.Spades
    }

    public enum PokerHandType
    {
        HighCard = 0,
        OnePair = 1,
        TwoPair = 2,
        Triple = 3,
        Straight = 4,
        Flush = 5,
        FullHouse = 6,
        Quad = 7,
        StraightFlush = 8,
        RoyalFlush = 9
    }

    public struct PokerHand
    {
        public PokerHandType HandType;
        public CardFace HighCard; //highest card of the play
        public CardFace Kicker; //alternate 'kicker', if a 4-less card play was done, this is the highest leftover card if it's > the highest played card. Otherwise it's = HighCard
        public int Count;

        public static readonly PokerHand None = new PokerHand();
    }

    public static class CardExtensions
    {

        public static CardSuit GetSuit(this Card card)
        {
            return (CardSuit)((byte)card & (byte)240);
        }

        public static CardFace GetFace(this Card card)
        {
            return (CardFace)((byte)card & 15);
        }

        public static IList<Card> Shuffle(this IList<Card> deck, Random rng = null)
        {
            if (deck == null) throw new System.ArgumentNullException("deck");
            if (rng == null) rng = new Random();

            int j;
            Card temp;
            int cnt = deck.Count;
            for (int i = 0; i < cnt - 1; i++)
            {
                j = rng.Next(i, cnt);
                temp = deck[j];
                deck[j] = deck[i];
                deck[i] = temp;
            }
            return deck;
        }

        public static IEnumerable<Card> Deal(this IList<Card> deck, int count)
        {
            while(count > 0 && deck.Count > 0)
            {
                count--;
                var card = deck[deck.Count - 1];
                deck.RemoveAt(deck.Count - 1);
                yield return card;
            }
        }

    }

    public class SimplePokerRules
    {

        public PokerHand GetBestHand(IEnumerable<Card> cards)
        {
            if (cards == null) return PokerHand.None;

            //gather card info
            int count = 0;
            long matchtable = 0;
            CardFace low = (CardFace)byte.MaxValue;
            CardFace high = CardFace.None;
            CardSuit flush = (CardSuit)byte.MaxValue;
            foreach(var card in cards)
            {
                count++;

                CardFace face = card.GetFace();
                if (face < low) low = face;
                if (face > high) high = face;
                flush &= card.GetSuit();

                //we are going to fill a bit table up with the count of this facevalue... every 4-bits is a face. 
                //This means we can't count higher than 15, but if you passed in a hand that large, that's stupid.
                int offset = ((int)face - 1) * 4;
                long mask = 15L << offset;
                long matchcount = (matchtable & mask) >> offset;
                if (matchcount < 15L) matchcount++;
                matchtable = (matchtable & ~mask) | (matchcount << offset);
            }
            if (count == 0) return PokerHand.None;

            //group the cards
            CardFace lowpair = CardFace.None;
            CardFace highpair = CardFace.None;
            CardFace triple = CardFace.None;
            CardFace quad = CardFace.None;
            CardFace straight_high = CardFace.None;
            int straight_count = 0;
            int straight_len = Math.Min(5, count);
            int c = 0;
            for(int i = 0; i < 14; i++)
            {
                CardFace face = (CardFace)((i % 14) + 1);
                int offset = ((int)face - 1) * 4;
                long mask = 15L << offset;
                int matchcount = (int)((matchtable & mask) >> offset);
                if(matchcount > 0)
                {
                    c++;
                    if(c >= straight_len)
                    {
                        straight_count = c;
                        straight_high = face;
                    }

                    switch (matchcount)
                    {
                        case 1:
                            //do nothing
                            break;
                        case 2:
                            lowpair = highpair;
                            highpair = face;
                            break;
                        case 3:
                            if (triple > highpair)
                            {
                                lowpair = highpair;
                                highpair = triple;
                            }
                            triple = face;
                            break;
                        default:
                            //4 and higher all count as quad
                            if (quad > triple)
                            {
                                if (triple > highpair)
                                {
                                    lowpair = highpair;
                                    highpair = triple;
                                }
                                triple = quad;
                            }
                            else if (quad > highpair)
                            {
                                lowpair = highpair;
                                highpair = quad;
                            }
                            quad = face;
                            break;
                    }
                }
                else
                {
                    c = 0;
                }
            }

            //find our best hand from above information
            if (straight_count >= straight_len && (int)flush != 0 && straight_high == CardFace.Ace)
            {
                return new PokerHand()
                {
                    HandType = PokerHandType.RoyalFlush,
                    HighCard = straight_high,
                    Kicker = high,
                    Count = count
                };
            }
            else if (straight_count >= straight_len && (int)flush != 0)
            {
                return new PokerHand()
                {
                    HandType = PokerHandType.StraightFlush,
                    HighCard = straight_high,
                    Kicker = high,
                    Count = count
                };
            }
            else if (quad != CardFace.None)
            {
                return new PokerHand()
                {
                    HandType = PokerHandType.Quad,
                    HighCard = quad,
                    Kicker = high,
                    Count = count
                };
            }
            else if(triple != CardFace.None && highpair != CardFace.None)
            {
                return new PokerHand()
                {
                    HandType = PokerHandType.FullHouse,
                    HighCard = (CardFace)System.Math.Max((int)triple, (int)highpair),
                    Kicker = high,
                    Count = count
                };
            }
            else if((int)flush != 0)
            {
                return new PokerHand()
                {
                    HandType = PokerHandType.Flush,
                    HighCard = high,
                    Kicker = high,
                    Count = count
                };
            }
            else if(straight_count >= straight_len)
            {
                return new PokerHand()
                {
                    HandType = PokerHandType.Straight,
                    HighCard = high,
                    Kicker = high,
                    Count = count
                };
            }
            else if(triple != CardFace.None)
            {
                return new PokerHand()
                {
                    HandType = PokerHandType.Triple,
                    HighCard = triple,
                    Kicker = high,
                    Count = count
                };
            }
            else if(highpair != CardFace.None && lowpair != CardFace.None)
            {
                return new PokerHand()
                {
                    HandType = PokerHandType.TwoPair,
                    HighCard = highpair,
                    Kicker = high,
                    Count = count
                };
            }
            else if(highpair != CardFace.None)
            {
                return new PokerHand()
                {
                    HandType = PokerHandType.OnePair,
                    HighCard = highpair,
                    Kicker = high,
                    Count = count
                };
            }
            else
            {
                return new PokerHand()
                {
                    HandType = PokerHandType.HighCard,
                    HighCard = high,
                    Kicker = high,
                    Count = count
                };
            }
        }

    }

Technically the algo is card count agnostic… but the “flush” rules fall apart on anything over 5 card since I resolve flushes on ALL cards.

Also I wanted to set it up so that all cards could be represented in an enum. This way I could do something like this:

var deck = System.Enum.GetValues(typeof(Card)).Cast<Card>().Where(c => c != Card.None).ToList().Shuffle().Shuffle();
var rules = new SimplePokerRules();

var hand1 = rules.GetBestHand(deck.Deal(5));
var hand2 = rules.GetBestHand(deck.Deal(5));

if(hand1.HandType > hand2.HandType || (hand1.HandType == hand2.HandType && hand1.HighCard > hand2.HighCard))
{
    Console.WriteLine("Player 1 Wins With: " + hand1.HandType);
}
else if(hand2.HandType > hand1.HandType || (hand1.HandType == hand2.HandType && hand2.HighCard > hand1.HighCard))
{
    Console.WriteLine("Player 2 Wins With: " + hand2.HandType);
}
else
{
    Console.WriteLine("DRAW");
}

Anyways… that was fun.

3 Likes

@lordofduct props for general solution. I had a quick read… is kicker correct? It seems like its always getting set to high, which for example if both players had two Kings and no Aces would be wrong, it should be their next highest card not the King. Maybe there’s an early out or special case I missed.

Oh yeah, I didn’t have kicker resolve for ace… derp.

Otherwise, I defined the kicker as:
//alternate ‘kicker’, if a 4-less card play was done, this is the highest leftover card if it’s > the highest played card. Otherwise it’s = HighCard

Which technically would be king in your scenario… which well, if isn’t accurate to poker. Welp, sorry, I don’t actually know my poker all that well. I was just playing around last night.

Yep, Ace is greater than King in poker. The only winning combination (in video poker at least, I’m not sure about the rest of them) where Ace is treated as a small rank is a small straight A2345.

There are also two type of jokers in Poker: 1) wildcard (as I explained in post #7 ), and 2) so called bug.

Oh, I know Ace is higher than King. I just forgot to account for it in my hichcard/kicker. I actually account for that in my low straight vs royal straight. This is a bug on my part since I didn’t follow my own rules. JohnnyA mentioning a pair of kings with NO ace is what reminded me of that.

The part I was talking about not knowing poker well is to do with the definition of what a kicker is. It’s why I mentioned the ‘definition’ I operated under (which has nothing to do with ace). Which is less of a bug, and more of a “I don’t know what kicker is I guess, I operated under my best understanding of it”.

1 Like

I know this is a little late, but I can’t help it!

A kicker comes into play when comparing two hands – it’s the card that breaks a tie between two hands with equal rank.

Best to exclude it from the definition of PokerHand and instead track the 5 cards in the player’s hand so that the kicker can be identified later if needed.

In Texas hold-em, the 5 card limit is important to remember since 7 cards are available to each player. The algorithm should pick the best 5 to be part of the players hand as only these 5 are eligible to be kickers. That’s why a split-pot is more common in a game like hold-em.

Right now I am engaged in a similar project, your codes will help me very much, thank you very much! Author - you have quite logical thoughts, but I’m refining this idea, changing it quite a lot
I’ve already made some sketches, if you can call it that . The project will be ready soon and I usually check voltlunchbox.com to see if this thing…
The last time it worked , but there were some mistakes in the code , and then I found your thread, I would never in my life could not have written it myself , I just don’t have knowledge , and it’s sad really , because I study in this field and must possess great knowledge

Impressive approaches to a difficult problem. Great examples on here.