6

I've implemented a Texas Hold'em game using C#.
I wrote classes like Card, Deck, Player, Table etc...
For example:

    Player player1 = new Player("player1");
    player1.Card1 = new Card(4, Symbol.Clubs, true);
    player1.Card2 = new Card(5, Symbol.Clubs, true);

    Card card1 = new Card(4, Symbol.Clubs, true);
    Card card2 = new Card(7, Symbol.Hearts, true);
    Card card3 = new Card(2, Symbol.Spades, true);
    Card card4 = new Card(4, Symbol.Diamonds, true);
    Card card5 = new Card(4, Symbol.Clubs, true);
    Card[] tableCards = {card1, card2, card3, card4, card5};

I've also wrote some methods for evaluate cards array, like IsFlush, IsStraight, IsPair and so on.
My question is how should I pick the best hand combination if I got 7 cards(2 hand, 5 from the table).
In this code example it's {4,4,4,4,7}.

Adir
  • 1,423
  • 3
  • 19
  • 32
  • 2
    What have you tried so far? How do you think that you should start to find the correct hand? – jgauffin May 03 '11 at 18:55
  • Similar question [here](http://stackoverflow.com/questions/5293405/algorithm-to-determine-the-winner-of-a-texas-holdem-hand) for python, but top answer has link to generic algorithm. – CodeNaked May 03 '11 at 18:59
  • This is not a good approach for ranking hands. What are you planning to do with this code ? – Alexandre C. May 03 '11 at 19:03
  • 2
    As random aside you could really improve the readability of your code using optional parameters `new Card(value: 7, suit: Symbol.Clubs, idontknowwhatthis: true)` – Chris Marisic May 03 '11 at 19:04

5 Answers5

3

Don't write your code against 5-card hands. Instead, write it in general. So,

ContainsStraightFlush
ContainsFourOfAKind
ContainsFullHouse

etc. would eat a collection of cards and return true if some subset of those cards is a straight flush, four of a kind, etc. respectively.

Then runs backwards from highest ranking hand to lowest. If one of these methods returns true, then you can easily pick off the best hand that satisfies that condition. For example on

2h Kh Qh Jh Th 9h 6c

ContainsStraightFlush would return true, and then you can pick off 9h Th Jh Qh Kh as the best hand.

jason
  • 236,483
  • 35
  • 423
  • 525
2

Start by sorting the cards, it will make doing your search for the best hand that much easier, then you just have to compare adjacent elements for multiples of the same number, or straights. then you just have a special case to look for a flush

Dan F
  • 17,654
  • 5
  • 72
  • 110
2

Don't do it like this, it is awfully slow and actually rather cumbersome to write (the logic is quite hairy). Also, for Monte Carlo simulations where you'll need to run hundred of millions of hands, such an approach simply cannot stand.

See this link for a survey of available techniques. Actually, using table-based comparison algorithms is much simpler to code than using a truckload of if statements.

Most of the routines presented in the above article are available in already-bundled C# libraries that you can plug your code into.

[The first high-performance original idea is there, and uses lookup tables, perfect hashes and a nice trick of multiplying prime numbers to evaluate a hand at a glance.]

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
  • 1
    I suspect that the OP is more interested in understanding the simple way of doing it, rather than squeezing the ultimate performance from a poker hand identifier. – Jim Mischel May 03 '11 at 19:07
  • @Jim: the resulting code is way more simple, and there are C# libraries available all over the place. Writing the logic as OP wants to do is a matter of a few hundreds of lines. Writing table based evaluators is a matter of a few dozens. – Alexandre C. May 03 '11 at 19:19
  • Interesting post! No idea why the idea that other people have thought about the problem caused your post to get down-voted. Your survey link is dead. But it's been archived here: https://web.archive.org/web/20140625212722/http://codingthewheel.com/archives/poker-hand-evaluator-roundup/ – dcaswell Jan 06 '15 at 16:21
2

The easiest way to do it is make every collection of 5 cards possible and grab the hand value. Remember the best hand. There are only 21 combinations for the 7 card situation, so it's not good in terms of optimality, but it's not terrible either unless you are using this for research.

foreach (possible 5 card combination in allCards)
    bestHand = Max(bestHand, GetValue(possible));

Alternatively you could create an array that has 1 entry for each card, and each index is a pointer to new array which has all 2 card combinations, and each index in that is an array for all 3 card combinations, etc. If you work it out with all suit and rank abstractions possible, the total size of the data structure is about 128 MB in memory. There is a reference implementation in c++ on the 2+2 forums.

Nick Larsen
  • 18,631
  • 6
  • 67
  • 96
  • 1
    The link to the 2+2 thread is there, among other valuable resource : http://www.codingthewheel.com/archives/poker-hand-evaluator-roundup Also, using Cactus-Kev 5-card evaluator with enumeration of the possible 5-card hands turned out to perform well enough for Omaha Monte-Carlo computations (where you have 9 cards + constraints). For Texas Hold-em, 2+2 implementation is just perfect. – Alexandre C. May 03 '11 at 19:31
  • @AlexandreC.: I agree with you on all counts except being perfect. It runs faster when dealing out hands by changing 1 card at a time, but for random hand groupings the Pokersource evaluator is faster. The decision needs to be made based on what type of evaluation you'll be making most often. – Nick Larsen May 03 '11 at 20:31
-1

create an array of cards, and add the first 5 cards. Then, foreach additional card, find the lowest in the card hand, and see if the extra card is larger, if so, switch them. Keeping in mind that you need to find pairs, straights, and full houses and such

Keerigan
  • 1,182
  • 1
  • 9
  • 17