Getting the Best Five-Card Poker Hand from Seven Cards using C#

I recently implemented a playing Card class and a five-card poker Hand class and a SingleDeck class using C#. I remember working on an old project where the goal was to determine the best five-card poker hand from seven cards. For example, if seven cards are (9d 5c 5h Qc Ah Jc Th) then the best five-card hand is (5c-5h-Jc-Qc-Ah), a pair of fives with A, Q, J kickers.

With all the helper functions already coded, I implemented a function that accepts seven cards and finds the best five-card poker hand. In pseudo-code:

get the source seven cards
initialize a curr best five-card hand
loop 21 times (each possible set of 2 from 7)
  remove the indicated two cards
  create candidate five-card hand
  if candidate is better than curr best hand
    best hand = candidate
  end-if
end-loop
return curr best hand

There are only 21 ways to remove two cards from seven cards: (0,1), (0,2) . . (4,6), (5,6) and so for clarity I hard-coded the 21 pairs of indices. I could have used two for-loops instead.

Here’s my function:

static Hand BestFiveFromSeven(List"lt"Card"gt" listSeven)
{
  int[][] removes = new int[21][];
  removes[0] = new int[] { 0, 1 };
  removes[1] = new int[] { 0, 2 };
  removes[2] = new int[] { 0, 3 };
  removes[3] = new int[] { 0, 4 };
  removes[4] = new int[] { 0, 5 };
  removes[5] = new int[] { 0, 6 };
  removes[6] = new int[] { 1, 2 };
  removes[7] = new int[] { 1, 3 };
  removes[8] = new int[] { 1, 4 };
  removes[9] = new int[] { 1, 5 };
  removes[10] = new int[] { 1, 6 };
  removes[11] = new int[] { 2, 3 };
  removes[12] = new int[] { 2, 4 };
  removes[13] = new int[] { 2, 5 };
  removes[14] = new int[] { 2, 6 };
  removes[15] = new int[] { 3, 4 };
  removes[16] = new int[] { 3, 5 };
  removes[17] = new int[] { 3, 6 };
  removes[18] = new int[] { 4, 5 };
  removes[19] = new int[] { 4, 6 };
  removes[20] = new int[] { 5, 6 };

  List"lt"Card"gt" bestFive = 
    listSeven.GetRange(0, count: 5);
  Hand bestHand = new Hand(bestFive);

  for (int j = 0; j "lt" 21; ++j) // each pair to remove
  {
    List"lt"Card"gt" listFive = new List"lt"Card"gt"();
    for (int i = 0; i "lt" 7; ++i)
    {
      if (i == removes[j][0] || i == removes[j][1])
        continue;
      else
        listFive.Add(listSeven[i]);
    }
    Hand candidate = new Hand(listFive);
    if (Hand.Compare(candidate, bestHand) == +1)
    {
      // Console.WriteLine("New Best Hand Found!");
      bestHand = candidate;
    }
  }
  return bestHand;
}

Good fun on a Saturday morning.


Here are three examples of art where a deck of 52 cards has been cut by hand to create a kind of 3D sculpture.


Demo code. Replace “lt” (less-than), “gt”, “lte”, “gte”, “and” with Boolean operator symbols — my lame blog editor sometimes chokes on symbols.

using System;
using System.IO;
using System.Collections.Generic;

namespace Poker
{
  internal class PokerProgram
  {
    static void Main(string[] args)
    {
      Console.WriteLine("\nBegin poker " +
        "best five-card hand from seven cards ");

      SingleDeck deck = new SingleDeck(seed: 15);
      for (int i = 0; i "lt" 8; ++i)
      {
        deck.Shuffle();
        List"lt"Card"gt" listSeven = deck.DealListCards(7);
        Console.Write("\nSeven cards: ");
        for (int j = 0; j "lt" 7; ++j)
          Console.Write(listSeven[j] + " ");
        Console.WriteLine("");

        Hand h = BestFiveFromSeven(listSeven);
        Console.WriteLine("Best hand  : " + h +
          " - " + h.GetHandTypeStr());
      }

      Console.WriteLine("\nEnd ");
      Console.ReadLine();
    } // Main

    // -------------------------------------------------------

    static Hand BestFiveFromSeven(List"lt"Card"gt" listSeven)
    {
      int[][] removes = new int[21][];
      removes[0] = new int[] { 0, 1 };
      removes[1] = new int[] { 0, 2 };
      removes[2] = new int[] { 0, 3 };
      removes[3] = new int[] { 0, 4 };
      removes[4] = new int[] { 0, 5 };
      removes[5] = new int[] { 0, 6 };
      removes[6] = new int[] { 1, 2 };
      removes[7] = new int[] { 1, 3 };
      removes[8] = new int[] { 1, 4 };
      removes[9] = new int[] { 1, 5 };
      removes[10] = new int[] { 1, 6 };
      removes[11] = new int[] { 2, 3 };
      removes[12] = new int[] { 2, 4 };
      removes[13] = new int[] { 2, 5 };
      removes[14] = new int[] { 2, 6 };
      removes[15] = new int[] { 3, 4 };
      removes[16] = new int[] { 3, 5 };
      removes[17] = new int[] { 3, 6 };
      removes[18] = new int[] { 4, 5 };
      removes[19] = new int[] { 4, 6 };
      removes[20] = new int[] { 5, 6 };

      // init best hand to first 5 cards
      List"lt"Card"gt" bestFive =
        listSeven.GetRange(0, count: 5);
      Hand bestHand = new Hand(bestFive);

      for (int j = 0; j "lt" 21; ++j) // each pair to remove
      {
        List"lt"Card"gt" listFive = new List"lt"Card"gt"();
        for (int i = 0; i "lt" 7; ++i)
        {
          if (i == removes[j][0] || i == removes[j][1])
            continue;
          else
            listFive.Add(listSeven[i]);
        }
        Hand candidate = new Hand(listFive);
        if (Hand.Compare(candidate, bestHand) == +1)
        {
          // h1 "gt" h2 : +1
          // Console.WriteLine("New Best Hand Found!");
          bestHand = candidate;
        }
      }
      return bestHand;
    }

    // ------------------------------------------------------

  } // Program

  public class Card : IComparable"lt"Card"gt"
  {
    // 0,1 not used. 11=J, 12=Q, 13=K, 14=A
    public int rank; 
    // 0=clubs, 1=diamonds, 2=hearts, 3=spades
    public int suit; 

    public Card(int rank, int suit)
    {
      this.rank = rank; this.suit = suit;
    }

    public Card(string c)
    {
      char rnk = c[0]; char sut = c[1];
      if (rnk == 'T') this.rank = 10;
      else if (rnk == 'J') this.rank = 11;
      else if (rnk == 'Q') this.rank = 12;
      else if (rnk == 'K') this.rank = 13;
      else if (rnk == 'A') this.rank = 14;
      else this.rank = int.Parse(rnk.ToString());

      if (sut == 'c') this.suit = 0;
      else if (sut == 'd') this.suit = 1;
      else if (sut == 'h') this.suit = 2;
      else if (sut == 's') this.suit = 3;
    }

    public override string ToString()
    {
      string rnk = ""; string sut = "";
      if (this.rank == 10) rnk = "T";
      else if (this.rank == 11) rnk = "J";
      else if (this.rank == 12) rnk = "Q";
      else if (this.rank == 13) rnk = "K";
      else if (this.rank == 14) rnk = "A";
      else rnk = this.rank.ToString();

      if (this.suit == 0) sut = "c";
      else if (this.suit == 1) sut = "d";
      else if (this.suit == 2) sut = "h";
      else if (this.suit == 3) sut = "s";

      return rnk + sut;
    }

    public int CompareTo(Card other)
    {
      // sort cards in a hand from low (Two) to high (Ace)
      if (this.rank.CompareTo(other.rank) == 0)
      {
        return this.suit.CompareTo(other.suit);
      }
      return this.rank.CompareTo(other.rank);
    }

  } // class Card

  // --------------------------------------------------------

  public class Hand
  {
    // 5-card poker hand
    // Hand types: "RoyalFlush", "StraightFlush",
    // "FourKind", "FullHouse", "Flush" , "Straight",
    // "ThreeKind", "TwoPair", "OnePair", "HighCard"

    public List"lt"Card"gt" cards;

    public Hand(List"lt"Card"gt" lst)
    {
      this.cards = new List"lt"Card"gt"();
      for (int i = 0; i "lt" 5; ++i)
        this.cards.Add(lst[i]);
      this.cards.Sort();
    }
    
    public Hand(Card c1, Card c2, Card c3,
      Card c4, Card c5)
    {
      this.cards = new List"lt"Card"gt"();
      this.cards.Add(c1); this.cards.Add(c2);
      this.cards.Add(c3); this.cards.Add(c4);
      this.cards.Add(c5);
      this.cards.Sort();
    }

    public Hand(string s) // s like "Js3h7d7cAd"
    {
      this.cards = new List"lt"Card"gt"();
      this.cards.Add(new Card(s.Substring(0, 2)));
      this.cards.Add(new Card(s.Substring(2, 2)));
      this.cards.Add(new Card(s.Substring(4, 2)));
      this.cards.Add(new Card(s.Substring(6, 2)));
      this.cards.Add(new Card(s.Substring(8, 2)));
      this.cards.Sort();
    }

    public override string ToString()
    {
      string h = "";
      for (int i = 0; i "lt" 4; ++i)
        h += this.cards[i].ToString() + "-";
      h += this.cards[4];
      return h;
    }

    public string ToTerseString()
    {
      string h = "";
      for (int i = 0; i "lt" 4; ++i)
        h += this.cards[i].ToString();
      h += this.cards[4];
      return h;
    }

    // ------------------------------------------------------

    // Hand Type methods:
    // GetHandTypeStr(), GetHandTypeInt(),
    //
    // IsRoyalFlush(), IsStraightFlush(), 
    // IsFourKind(), IsFullHouse(), IsFlush(),
    // IsStraight(), IsThreeKind(), IsTwoPair(),
    // IsOnePair(), IsHighCard()
    //
    // helpers: HasFlush(), HasStraight(),


    // ------------------------------------------------------

    public string GetHandTypeStr()
    {
      if (IsRoyalFlush(this) == true)
        return "RoyalFlush";
      else if (IsStraightFlush(this) == true)
        return "StraightFlush";
      else if (IsFourKind(this) == true)
        return "FourKind";
      else if (IsFullHouse(this) == true)
        return "FullHouse";
      else if (IsFlush(this) == true)
        return "Flush";
      else if (IsStraight(this) == true)
        return "Straight";
      else if (IsThreeKind(this) == true)
        return "ThreeKind";
      else if (IsTwoPair(this) == true)
        return "TwoPair";
      else if (IsOnePair(this) == true)
        return "OnePair";
      else if (IsHighCard(this) == true)
        return "HighCard";
      else
        return "Unknown";
    }

    // ------------------------------------------------------

    public int GetHandTypeInt()
    {
      if (IsRoyalFlush(this) == true)
        return 9;
      else if (IsStraightFlush(this) == true)
        return 8;
      else if (IsFourKind(this) == true)
        return 7;
      else if (IsFullHouse(this) == true)
        return 6;
      else if (IsFlush(this) == true)
        return 5;
      else if (IsStraight(this) == true)
        return 4;
      else if (IsThreeKind(this) == true)
        return 3;
      else if (IsTwoPair(this) == true)
        return 2;
      else if (IsOnePair(this) == true)
        return 1;
      else if (IsHighCard(this) == true)
        return 0;
      else
        return -1;
    }

    // ------------------------------------------------------

    private static bool HasFlush(Hand h)
    {
      if ((h.cards[0].suit == h.cards[1].suit) "and"
          (h.cards[1].suit == h.cards[2].suit) "and"
          (h.cards[2].suit == h.cards[3].suit) "and"
          (h.cards[3].suit == h.cards[4].suit))
        return true;

      return false;
    }

    // ------------------------------------------------------

    private static bool HasStraight(Hand h)
    {
      // check special case of Ace-low straight
      // 2, 3, 4, 5, A when sorted
      if (h.cards[0].rank == 2 "and"
        h.cards[1].rank == 3 "and"
        h.cards[2].rank == 4 "and"
        h.cards[3].rank == 5 "and"
        h.cards[4].rank == 14)
        return true;

      // otherwise, check for 5 consecutive
      if ((h.cards[0].rank == h.cards[1].rank - 1) "and"
        (h.cards[1].rank == h.cards[2].rank - 1) "and"
        (h.cards[2].rank == h.cards[3].rank - 1) "and"
        (h.cards[3].rank == h.cards[4].rank - 1))
        return true;

      return false;
    }

    // ------------------------------------------------------

    private static bool IsRoyalFlush(Hand h)
    {
      if (HasStraight(h) == true "and" HasFlush(h) == true
        "and" h.cards[0].rank == 10)
        return true;
      else
        return false;
    }

    // ------------------------------------------------------

    private static bool IsStraightFlush(Hand h)
    {
      if (HasStraight(h) == true "and" HasFlush(h) == true
        "and" h.cards[0].rank != 10)
        return true;
      else
        return false;
    }

    // ------------------------------------------------------

    private static bool IsFourKind(Hand h)
    {
      // AAAA B or B AAAA if sorted
      if ((h.cards[0].rank == h.cards[1].rank) "and"
        (h.cards[1].rank == h.cards[2].rank) "and"
        (h.cards[2].rank == h.cards[3].rank) "and"
        (h.cards[3].rank != h.cards[4].rank))
        return true;

      if ((h.cards[1].rank == h.cards[2].rank) "and"
        (h.cards[2].rank == h.cards[3].rank) "and"
        (h.cards[3].rank == h.cards[4].rank) "and"
        (h.cards[0].rank != h.cards[1].rank))
        return true;

      return false;
    }

    // ------------------------------------------------------

    private static bool IsFullHouse(Hand h)
    {
      // AAA BB or BB AAA if sorted
      if ((h.cards[0].rank == h.cards[1].rank) "and"
        (h.cards[1].rank == h.cards[2].rank) "and"
        (h.cards[3].rank == h.cards[4].rank) "and"
        (h.cards[2].rank != h.cards[3].rank))
        return true;

      // BB AAA
      if ((h.cards[0].rank == h.cards[1].rank) "and"
        (h.cards[2].rank == h.cards[3].rank) "and"
        (h.cards[3].rank == h.cards[4].rank) "and"
        (h.cards[1].rank != h.cards[2].rank))
        return true;

      return false;
    }

    // ------------------------------------------------------

    private static bool IsFlush(Hand h)
    {
      if (HasFlush(h) == true "and" 
        HasStraight(h) == false)
        return true; // no StraightFlush or RoyalFlush
      else
        return false;
    }

    // ------------------------------------------------------

    private static bool IsStraight(Hand h)
    {
      if (HasStraight(h) == true "and" 
        HasFlush(h) == false) // no SF or RF
        return true;
      else
        return false;
    }

    // ------------------------------------------------------

    private static bool IsThreeKind(Hand h)
    {
      // AAA B C or B AAA C or B C AAA if sorted
      if ((h.cards[0].rank == h.cards[1].rank) "and"
        (h.cards[1].rank == h.cards[2].rank) "and"
        (h.cards[2].rank != h.cards[3].rank) "and"
        (h.cards[3].rank != h.cards[4].rank))
        return true;

      if ((h.cards[1].rank == h.cards[2].rank) "and"
        (h.cards[2].rank == h.cards[3].rank) "and"
        (h.cards[0].rank != h.cards[1].rank) "and"
        (h.cards[3].rank != h.cards[4].rank))
        return true;

      if ((h.cards[2].rank == h.cards[3].rank) "and"
        (h.cards[3].rank == h.cards[4].rank) "and"
        (h.cards[0].rank != h.cards[1].rank) "and"
        (h.cards[1].rank != h.cards[2].rank))
        return true;

      return false;
    }

    // ------------------------------------------------------

    private static bool IsTwoPair(Hand h)
    {
      // AA BB C or AA C BB or C AA BB if sorted
      if ((h.cards[0].rank == h.cards[1].rank) "and"
        (h.cards[2].rank == h.cards[3].rank) "and"
        (h.cards[1].rank != h.cards[2].rank) "and"
        (h.cards[3].rank != h.cards[4].rank))
        return true;  // AA BB C

      if ((h.cards[0].rank == h.cards[1].rank) "and"
        (h.cards[3].rank == h.cards[4].rank) "and"
        (h.cards[1].rank != h.cards[2].rank) "and"
        (h.cards[2].rank != h.cards[3].rank))
        return true;  // AA C BB

      if ((h.cards[1].rank == h.cards[2].rank) "and"
        (h.cards[3].rank == h.cards[4].rank) "and"
        (h.cards[0].rank != h.cards[1].rank) "and"
        (h.cards[2].rank != h.cards[3].rank))
        return true;  // C AA BB

      return false;
    }

    // ------------------------------------------------------

    private static bool IsOnePair(Hand h)
    {
      // AA B C D or B AA C D or B C AA D or B C D AA
      if ((h.cards[0].rank == h.cards[1].rank) "and"
        (h.cards[1].rank != h.cards[2].rank) "and"
        (h.cards[2].rank != h.cards[3].rank) "and"
        (h.cards[3].rank != h.cards[4].rank))
        return true;  // AA B C D

      if ((h.cards[1].rank == h.cards[2].rank) "and"
        (h.cards[0].rank != h.cards[1].rank) "and"
        (h.cards[2].rank != h.cards[3].rank) "and"
        (h.cards[3].rank != h.cards[4].rank))
        return true;  // B AA C D

      if ((h.cards[2].rank == h.cards[3].rank) "and"
        (h.cards[0].rank != h.cards[1].rank) "and"
        (h.cards[1].rank != h.cards[2].rank) "and"
        (h.cards[3].rank != h.cards[4].rank))
        return true;  // B C AA D

      if ((h.cards[3].rank == h.cards[4].rank) "and"
        (h.cards[0].rank != h.cards[1].rank) "and"
        (h.cards[1].rank != h.cards[2].rank) "and"
        (h.cards[2].rank != h.cards[3].rank))
        return true;  // B C D AA

      return false;
    }

    // ------------------------------------------------------

    private static bool IsHighCard(Hand h)
    {
      if (HasFlush(h) == true)
        return false;
      else if (HasStraight(h) == true)
        return false;
      else
      {
        // all remaining have at least one pair
        if ((h.cards[0].rank == h.cards[1].rank) ||
            (h.cards[1].rank == h.cards[2].rank) ||
            (h.cards[2].rank == h.cards[3].rank) ||
            (h.cards[3].rank == h.cards[4].rank))
          return false;
      }

      return true;
    }

    // ------------------------------------------------------

    // Hand comparison methods
    // Hand.Compare() calls:
    // BreakTieStraightFlush(), BreakTieFourKind(),
    // BreakTieFullHouse(), BreakTieFlush(),
    // BreakTieStraight(), BreakTieThreeKind(),
    // BreakTieTwoPair(), BreakTieOnePair(),
    // BreakTieHighCard()

    // ------------------------------------------------------

    public static int Compare(Hand h1, Hand h2)
    {
      // -1 if h1 "lt" h2, +1 if h1 "gt" h2, 0 if h1 == h2

      int h1Idx = h1.GetHandTypeInt();  // like 6
      int h2Idx = h2.GetHandTypeInt();

      // different hand types - easy
      if (h1Idx "lt" h2Idx)
        return -1;
      else if (h1Idx "gt" h2Idx)
        return +1;
      else // same hand types so break tie
      {
        string h1HandType = h1.GetHandTypeStr();
        string h2HandType = h2.GetHandTypeStr();

        if (h1HandType != h2HandType)
          Console.WriteLine("Logic error ");

        if (h1HandType == "RoyalFlush")
          return 0; // two Royal Flush always tie
        else if (h1HandType == "StraightFlush")
          return BreakTieStraightFlush(h1, h2);
        else if (h1HandType == "FourKind")
          return BreakTieFourKind(h1, h2);
        else if (h1HandType == "FullHouse")
          return BreakTieFullHouse(h1, h2);
        else if (h1HandType == "Flush")
          return BreakTieFlush(h1, h2);
        else if (h1HandType == "Straight")
          return BreakTieStraight(h1, h2);
        else if (h1HandType == "ThreeKind")
          return BreakTieThreeKind(h1, h2);
        else if (h1HandType == "TwoPair")
          return BreakTieTwoPair(h1, h2);
        else if (h1HandType == "OnePair")
          return BreakTieOnePair(h1, h2);
        else if (h1HandType == "HighCard")
          return BreakTieHighCard(h1, h2);
      }
      return -2;  // error
    }

    // ------------------------------------------------------

    private static int BreakTieStraightFlush(Hand h1,
      Hand h2)
    {
      // check special case of Ace-low straight flush
      // check one or two Ace-low hands
      // h1 is Ace - low, h2 not Ace - low.h1 is less
      if ((h1.cards[0].rank == 2 "and"
        h1.cards[4].rank == 14) "and"  // because sorted!
        !(h2.cards[0].rank == 2 "and"
        h2.cards[4].rank == 14))
        return -1;
 
      //  h1 not Ace - low, h2 is Ace - low, h1 is better
      else if (!(h1.cards[0].rank == 2 "and"
        h1.cards[4].rank == 14) "and"
        (h2.cards[0].rank == 2 "and"
        h2.cards[4].rank == 14))
        return +1;
      //  two Ace-low hands
      else if ((h1.cards[0].rank == 2 "and"
        h1.cards[4].rank == 14) "and"  // Ace-low
        (h2.cards[0].rank == 2 "and"
        h2.cards[4].rank == 14))  // Ace-low
        return 0;

      //  no Ace-low straight flush so check high cards
      if (h1.cards[4].rank "lt" h2.cards[4].rank)
        return -1;
      else if (h1.cards[4].rank "gt" h2.cards[4].rank)
        return 1;
      else
        return 0;
    }

    private static int BreakTieFourKind(Hand h1,
        Hand h2)
    {
      // the off-card is at [0] or at [4]
      // find h1 four-card and off-card ranks
      int h1FourRank; int h1OffRank;
      if (h1.cards[0].rank == h1.cards[1].rank)
      {
        // 1st two cards same so off-rank at [4]
        h1FourRank = h1.cards[0].rank;
        h1OffRank = h1.cards[4].rank;
      }
      else
      {
        // 1st two cards diff so off-rank at [0]
        h1FourRank = h1.cards[4].rank;
        h1OffRank = h1.cards[0].rank;
      }

      int h2FourRank; int h2OffRank;
      if (h2.cards[0].rank == h2.cards[1].rank)
      {
        h2FourRank = h2.cards[0].rank;
        h2OffRank = h2.cards[4].rank;
      }
      else
      {
        h2FourRank = h2.cards[4].rank;
        h2OffRank = h2.cards[0].rank;
      }

      if (h1FourRank "lt" h2FourRank) // like 4K, 4A
        return -1;
      else if (h1FourRank "gt" h2FourRank)
        return +1;
      else // both hands have same four-kind (mult. decks)
      {
        if (h1OffRank "lt" h2OffRank)
          return -1;  // like 3c 9c9d9h9s "lt" Qd 9c9d9h9s
        else if (h1OffRank "gt" h2OffRank)
          return +1;  // like Jc 4c4d4h4s "gt" 9s 4c4d4h4s
        else if (h1OffRank == h2OffRank)
          return 0;
      }
      throw new Exception("Fatal logic BreakTieFourKind");
    }

    private static int BreakTieFullHouse(Hand h1, Hand h2)
    {
      // determine high rank (3 kind) and low rank (2 kind)
      // JJJ 55 or 33 KKK
      // if [1] == [2] 3 kind at [0][1][2]
      // if [1] != [2] 3 kind at [2][3][4]
      int h1ThreeRank; int h1TwoRank;
      if (h1.cards[1].rank == h1.cards[2].rank)
      {
        // if [1] == [2] 3 kind at [0][1][2]
        h1ThreeRank = h1.cards[0].rank;
        h1TwoRank = h1.cards[4].rank;
      }
      else
      {
        // if [1] != [2] 3 kind at [2][3][4]
        h1ThreeRank = h1.cards[4].rank;
        h1TwoRank = h1.cards[0].rank;
      }

      int h2ThreeRank; int h2TwoRank;
      if (h2.cards[1].rank == h2.cards[2].rank)
      {
        // if [1] == [2] 3 kind at [0][1][2]
        h2ThreeRank = h2.cards[0].rank;
        h2TwoRank = h2.cards[4].rank;
      }
      else
      {
        // if [1] != [2] 3 kind at [2][3][4]
        h2ThreeRank = h2.cards[4].rank;
        h2TwoRank = h2.cards[0].rank;
      }

      if (h1ThreeRank "lt" h2ThreeRank)
        return -1;
      else if (h1ThreeRank "gt" h2ThreeRank)
        return +1;
      else // both hands same three-kind (mult. decks)
      {
        if (h1TwoRank "lt" h2TwoRank)
          return -1;  // like 3c3d 9c9d9h "lt" QdQs 9c9d9h
        else if (h1TwoRank "gt" h2TwoRank)
          return +1;  // like 3c3d 9c9d9h "gt" 2d2s 9c9d9h
        else if (h1TwoRank == h2TwoRank)
          return 0;
      }
      throw new Exception("Fatal logic BreakTieFullHouse");
    }

    private static int BreakTieFlush(Hand h1, Hand h2)
    {
      // compare rank of high cards
      if (h1.cards[4].rank "lt" h2.cards[4].rank)
        return -1;
      else if (h1.cards[4].rank "gt" h2.cards[4].rank)
        return +1;
      // high cards equal so check at [3]
      else if (h1.cards[3].rank "lt" h2.cards[3].rank)
        return -1;
      else if (h1.cards[3].rank "gt" h2.cards[3].rank)
        return +1;
      // and so on
      else if (h1.cards[2].rank "lt" h2.cards[2].rank)
        return -1;
      else if (h1.cards[2].rank "gt" h2.cards[2].rank)
        return +1;
      //
      else if (h1.cards[1].rank "lt" h2.cards[1].rank)
        return -1;
      else if (h1.cards[1].rank "gt" h2.cards[1].rank)
        return +1;
      //
      else if (h1.cards[0].rank "lt" h2.cards[0].rank)
        return -1;
      else if (h1.cards[0].rank "gt" h2.cards[0].rank)
        return +1;
      //
      else
        return 0; // all ranks the same!
    }

    private static int BreakTieStraight(Hand h1, Hand h2)
    {
      // both hands are straights but one could be Ace-low
      // check special case of one or two Ace-low hands
      // h1 is Ace-low, h2 not Ace-low. h1 is less
      if ((h1.cards[0].rank == 2 "and"  // Ace-low (sorted!)
        h1.cards[4].rank == 14) "and"
        !(h2.cards[0].rank == 2 "and"
        h2.cards[4].rank == 14))
        return -1;
      // h1 not Ace-low, h2 is Ace-low, h1 is better
      else if (!(h1.cards[0].rank == 2 "and"
        h1.cards[4].rank == 14) "and"
        (h2.cards[0].rank == 2 "and"
        h2.cards[4].rank == 14))
        return +1;
      // two Ace-low hands
      else if ((h1.cards[0].rank == 2 "and"
        h1.cards[4].rank == 14) "and"
        (h2.cards[0].rank == 2 "and"
        h2.cards[4].rank == 14))
        return 0;

      // no Ace-low hands so just check high card
      if (h1.cards[4].rank "lt" h2.cards[4].rank)
        return -1;
      else if (h1.cards[4].rank "gt" h2.cards[4].rank)
        return +1;
      else if (h1.cards[4].rank == h2.cards[4].rank)
        return 0;
      else
        throw new
          Exception("Fatal logic BreakTieStraight");
    }

    private static int BreakTieThreeKind(Hand h1, Hand h2)
    {
      // assumes multiple decks possible
      // (TTT L H) or (L TTT H) or (L H TTT)
      int h1ThreeRank = 0; int h1LowRank = 0;
      int h1HighRank = 0;
      if (h1.cards[0].rank == h1.cards[1].rank "and"
        h1.cards[1].rank == h1.cards[2].rank)
      {
        h1ThreeRank = h1.cards[0].rank;
        h1LowRank = h1.cards[3].rank;
        h1HighRank = h1.cards[4].rank;
      }
      else if (h1.cards[1].rank == h1.cards[2].rank "and"
        h1.cards[2].rank == h1.cards[3].rank)
      {
        h1LowRank = h1.cards[0].rank;
        h1ThreeRank = h1.cards[1].rank;
        h1HighRank = h1.cards[4].rank;
      }
      else if (h1.cards[2].rank == h1.cards[3].rank "and"
        h1.cards[3].rank == h1.cards[4].rank)
      {
        h1LowRank = h1.cards[0].rank;
        h1HighRank = h1.cards[1].rank;
        h1ThreeRank = h1.cards[4].rank;
      }

      int h2ThreeRank = 0; int h2LowRank = 0;
      int h2HighRank = 0;
      if (h2.cards[0].rank == h2.cards[1].rank "and"
        h2.cards[1].rank == h2.cards[2].rank)
      {
        h2ThreeRank = h2.cards[0].rank;
        h2LowRank = h2.cards[3].rank;
        h2HighRank = h2.cards[4].rank;
      }
      else if (h2.cards[1].rank == h2.cards[2].rank "and"
        h2.cards[2].rank == h2.cards[3].rank)
      {
        h2LowRank = h2.cards[0].rank;
        h2ThreeRank = h2.cards[1].rank;
        h2HighRank = h2.cards[4].rank;
      }
      else if (h2.cards[2].rank == h2.cards[3].rank "and"
        h2.cards[3].rank == h2.cards[4].rank)
      {
        h2LowRank = h2.cards[0].rank;
        h2HighRank = h2.cards[1].rank;
        h2ThreeRank = h2.cards[4].rank;
      }

      if (h1ThreeRank "lt" h2ThreeRank)
        return -1;
      else if (h1ThreeRank "gt" h2ThreeRank)
        return +1;
      // both hands three-kind same (mult. decks)
      else if (h1HighRank "lt" h2HighRank)
        return -1;
      else if (h1HighRank "gt" h2HighRank)
        return +1;
      //
      else if (h1LowRank "lt" h2LowRank)
        return -1;
      else if (h1LowRank "gt" h2LowRank)
        return +1;
      //
      else // wow!
        return 0;
    }

    private static int BreakTieTwoPair(Hand h1, Hand h2)
    {
      // (LL X HH) or (LL HH X) or (X LL HH)
      int h1LowRank = 0; int h1HighRank = 0;
      int h1OffRank = 0;
      if (h1.cards[0].rank == h1.cards[1].rank "and"
        h1.cards[3].rank == h1.cards[4].rank)
      {
        // (LL X HH)
        h1LowRank = h1.cards[0].rank;
        h1HighRank = h1.cards[4].rank;
        h1OffRank = h1.cards[2].rank;
      }
      else if (h1.cards[0].rank == h1.cards[1].rank "and"
        h1.cards[2].rank == h1.cards[3].rank)
      {
        // (LL HH X)
        h1LowRank = h1.cards[0].rank;
        h1HighRank = h1.cards[2].rank;
        h1OffRank = h1.cards[4].rank;
      }
      else if (h1.cards[1].rank == h1.cards[2].rank "and"
        h1.cards[3].rank == h1.cards[4].rank)
      {
        // (X LL HH)
        h1LowRank = h1.cards[1].rank;
        h1HighRank = h1.cards[3].rank;
        h1OffRank = h1.cards[0].rank;
      }

      int h2LowRank = 0; int h2HighRank = 0;
      int h2OffRank = 0;
      if (h2.cards[0].rank == h2.cards[1].rank "and"
        h2.cards[3].rank == h2.cards[4].rank)
      {
        // (LL X HH)
        h2LowRank = h2.cards[0].rank;
        h2HighRank = h2.cards[4].rank;
        h2OffRank = h2.cards[2].rank;
      }
      else if (h2.cards[0].rank == h2.cards[1].rank "and"
        h2.cards[2].rank == h2.cards[3].rank)
      {
        // (LL HH X)
        h2LowRank = h2.cards[0].rank;
        h2HighRank = h2.cards[2].rank;
        h2OffRank = h2.cards[4].rank;
      }
      else if (h2.cards[1].rank == h2.cards[2].rank "and"
        h2.cards[3].rank == h2.cards[4].rank)
      {
        // (X LL HH)
        h2LowRank = h2.cards[1].rank;
        h2HighRank = h2.cards[3].rank;
        h2OffRank = h2.cards[0].rank;
      }

      if (h1HighRank "lt" h2HighRank)
        return -1;
      else if (h1HighRank "gt" h2HighRank)
        return +1;
      else if (h1LowRank "lt" h2LowRank)
        return -1;
      else if (h1LowRank "gt" h2LowRank)
        return +1;
      else if (h1OffRank "lt" h2OffRank)
        return -1;
      else if (h1OffRank "gt" h2OffRank)
        return +1;
      else
        return 0;
    }

    private static int BreakTieOnePair(Hand h1, Hand h2)
    {
      // (PP L M H) or (L PP M H)
      // or (L M PP H) or (L M H PP)
      int h1PairRank = 0; int h1LowRank = 0;
      int h1MediumRank = 0; int h1HighRank = 0;
      if (h1.cards[0].rank == h1.cards[1].rank)
      {
        // (PP L M H)
        h1PairRank = h1.cards[0].rank;
        h1LowRank = h1.cards[2].rank;
        h1MediumRank = h1.cards[3].rank;
        h1HighRank = h1.cards[4].rank;
      }
      else if (h1.cards[1].rank == h1.cards[2].rank)
      {
        // (L PP M H)
        h1PairRank = h1.cards[1].rank;
        h1LowRank = h1.cards[0].rank;
        h1MediumRank = h1.cards[3].rank;
        h1HighRank = h1.cards[4].rank;
      }
      else if (h1.cards[2].rank == h1.cards[3].rank)
      {
        // (L M PP H)
        h1PairRank = h1.cards[2].rank;
        h1LowRank = h1.cards[0].rank;
        h1MediumRank = h1.cards[1].rank;
        h1HighRank = h1.cards[4].rank;
      }
      else if (h1.cards[3].rank == h1.cards[4].rank)
      {
        // (L M H PP)
        h1PairRank = h1.cards[4].rank;
        h1LowRank = h1.cards[0].rank;
        h1MediumRank = h1.cards[1].rank;
        h1HighRank = h1.cards[2].rank;
      }

      int h2PairRank = 0; int h2LowRank = 0;
      int h2MediumRank = 0; int h2HighRank = 0;
      if (h2.cards[0].rank == h2.cards[1].rank)
      {
        // (PP L M H)
        h2PairRank = h2.cards[0].rank;
        h2LowRank = h2.cards[2].rank;
        h2MediumRank = h2.cards[3].rank;
        h2HighRank = h2.cards[4].rank;
      }
      else if (h2.cards[1].rank == h2.cards[2].rank)
      {
        // (L PP M H)
        h2PairRank = h2.cards[1].rank;
        h2LowRank = h2.cards[0].rank;
        h2MediumRank = h2.cards[3].rank;
        h2HighRank = h2.cards[4].rank;
      }
      else if (h2.cards[2].rank == h2.cards[3].rank)
      {
        // (L M PP H)
        h2PairRank = h2.cards[2].rank;
        h2LowRank = h2.cards[0].rank;
        h2MediumRank = h2.cards[1].rank;
        h2HighRank = h2.cards[4].rank;
      }
      else if (h2.cards[3].rank == h2.cards[4].rank)
      {
        // (L M H PP)
        h2PairRank = h2.cards[4].rank;
        h2LowRank = h2.cards[0].rank;
        h2MediumRank = h2.cards[1].rank;
        h2HighRank = h2.cards[2].rank;
      }

      if (h1PairRank "lt" h2PairRank)
        return -1;
      else if (h1PairRank "gt" h2PairRank)
        return +1;
      //
      else if (h1HighRank "lt" h2HighRank)
        return -1;
      else if (h1HighRank "gt" h2HighRank)
        return +1;
      //
      else if (h1MediumRank "lt" h2MediumRank)
        return -1;
      else if (h1MediumRank "gt" h2MediumRank)
        return +1;
      //
      else if (h1LowRank "lt" h2LowRank)
        return -1;
      else if (h1LowRank "gt" h2LowRank)
        return +1;
      //
      else
        return 0;
    }

    private static int BreakTieHighCard(Hand h1, Hand h2)
    {
      if (h1.cards[4].rank "lt" h2.cards[4].rank)
        return -1;
      else if (h1.cards[4].rank "gt" h2.cards[4].rank)
        return +1;
      //
      else if (h1.cards[3].rank "lt" h2.cards[3].rank)
        return -1;
      else if (h1.cards[3].rank "gt" h2.cards[3].rank)
        return +1;
      //
      else if (h1.cards[2].rank "lt" h2.cards[2].rank)
        return -1;
      else if (h1.cards[2].rank "gt" h2.cards[2].rank)
        return +1;
      //
      else if (h1.cards[1].rank "lt" h2.cards[1].rank)
        return -1;
      else if (h1.cards[1].rank "gt" h2.cards[1].rank)
        return +1;
      //
      else if (h1.cards[0].rank "lt" h2.cards[0].rank)
        return -1;
      else if (h1.cards[0].rank "gt" h2.cards[0].rank)
        return +1;
      //
      else
        return 0;
    }

    // ------------------------------------------------------

  } // class Hand

  // --------------------------------------------------------

  public class SingleDeck
  {
    public List"lt"Card> deck;
    private Random rnd;
    public int currCardIdx;

    public SingleDeck(int seed)
    {
      this.deck = new List"lt"Card>();
      this.rnd = new Random(seed);
      this.currCardIdx = 0;
      for (int r = 2; r "lt" 15; ++r)  // 0,1 not used
      {
        for (int s = 0; s "lt" 4; ++s)
        {
          Card c = new Card(r, s);
          this.deck.Add(c); // 2c 2d . . Ah As
        }
      }
    } // ctor

    public void Shuffle()
    {
      for (int i = 0; i "lt" 52; ++i)
      {
        int rix = this.rnd.Next(i, 52);
        Card tmp = this.deck[i];
        this.deck[i] = this.deck[rix];
        this.deck[rix] = tmp;
      }
      this.currCardIdx = 0;
    }

    public Hand DealHand()
    {
      // TODO: check if enough cards in deck, e.g.
      // if (this.currCardIdx > 47)
      //   Console.WriteLine("Not enough cards in " +
      //     "deck to deal a hand ");

      List"lt"Card> lst = new List"lt"Card>();
      for (int i = 0; i "lt" 5; ++i)
      {
        Card c = this.deck[this.currCardIdx++];
        lst.Add(c);
      }
      Hand h = new Hand(lst);
      return h;
    }

    public List"lt"Card> DealListCards(int nCards)
    {
      // TODO: check if enough cards in deck, e.g.
      // if (this.currCardIdx + nCards > 52)
      //   Console.WriteLine("Not enough cards in " +
      //     "deck to deal " + nCards);

      List"lt"Card> result = new List"lt"Card>();
      for (int i = 0; i "lt" nCards; ++i)
      {
        Card c = this.deck[this.currCardIdx++];
        result.Add(c);
      }
      return result;
    }

    public void Show()  // or do a ToString()
    {
      for (int i = this.currCardIdx; i "lt" 52; ++i)
        Console.Write(this.deck[i] + " ");
      Console.WriteLine("");
    }

  } // class SingleDeck

  // --------------------------------------------------------

} // ns
This entry was posted in Poker. Bookmark the permalink.