Poker hand evaluation

Hello people,

I’m doing a Texas Hold’em implementation of Poker. I’ve been studying the game and it’s great.

Texas Hold’em is just like regular poker, except that only 2 cards are dealt to each player, and then 5 “community” cards that are available to all players to use to make the best 5 card hand, that is they can use any of their 2 cards and any of the 5 cards on the table to create the best 5 card poker hand.

My main problems I need to solve are the following:

  1. Since the player has 7 cards, I need to figure out what combination of 5 cards out of 7 cards makes up the best possible hand.

  2. Compare all best possible hands of each player, to figure out the winner.

  3. Tell the player what kind of a hand he has, some don’t know the rules and I want to print somewhere on the screen “You have a pair of aces”, or “You have a flush, king high.”. So I need to create a textual description of the hand.

Since Texas Hold’em is a iterative game, that is; you start with 2 cards, then 3 cards are dealt to the table, then 1 more card, and then the final 1 card. So you have to create a textual description of the hand 4 times (when you have 2 cards, 5 cards, 6 cards and then 7 cards.)

I hope this makes any sense. Anything will help me:

  • Articles
  • Tutorials
  • Code
  • Papers
  • Best: a Java library that takes care of it all for me =)

1 and 2 are pretty much the same task, basically comparing possible hands. I wouldn’t over think this one, just try all 8 possible combinations of hands for each person and evaluate them against themselves (not n*n by the way). Worry about a sophisticated algorithm for not trying all possibilities when you’ve finished, or if you stumble across it - even on a slow machine it’s low cost.

One way of doing it is by creating a simple scoring system that could give each type of hand a defined score, such that a straight is one score, and the highest card in the straight adds to it. A flush is one score and the value of the cards then contributes to the score in a way that you can define, for example if you order the cards by number and then create the score of the flush by storing the highest card number, multiply by 13, add the next, multiply by 12, then add the next - the largest number is 240240. It’s a really simple system and makes it really easy to score hands and pick the highest one :slight_smile: If I communicated it badly let me know.

3 doesn’t sound like much of a problem, the hands ranking system doesn’t require much logic, except additional descriptions when more detail is needed over a win. An example (taken from the wikipedia article) would be when an AK-high flush beats an ace high flush; but it’s a simple special case, just list the highest cards of winning significance.

Read how we learned to cheat at online poker: details what number generators and shuffling algorithms not to use and why they make cheating very easy. I would give you more links depending on what exactly you want to know; for example there are tables on poker strategy, etc. Having said that I’ve just looked on wikipedia and it looks like people have ruined the good pages with ‘silly’ merges and removal of good sections. I have no idea what happened to my poker links either, I had loads of good relevant links; although I was researching with the intention of creating poker AI.

So you have two levels of hand comparabilty,

  • one, the type of hand - a flush is better than a straight is better than a pair
  • two, between two hands of the same type - a pair of aces is better than a pair fives, a king high straight is better than a 7 high straight.

How about this as a stab at some of the main entities. The idea is that you would write a subclass of AbstractHandType for each type of hand (flush, straight, straight flush etc…) give them appropriate ordinals and implement the toHumanReadable and compareIntraHand methods. I implemented HighCard as an example.


public interface HandType<T extends HandType> extends Comparable<HandType>
{
	int getOrdinal();

	String toHumanReadable();
}

public abstract class AbstractHandType<T extends HandType> implements HandType<T>
{
	private final int	ordinal;

	public AbstractHandType(int ordinal)
	{
		this.ordinal = ordinal;
	}

	@Override
	public int getOrdinal()
	{
		return ordinal;
	}

	@Override
	public int compareTo(HandType other)
	{
		int comparison;
		int ordinalComparison = Double.compare(getOrdinal(), other.getOrdinal());
		if (ordinalComparison == 0)
		{
			comparison = compareIntraHand((T) other);
		}
		else
		{
			comparison = ordinalComparison;
		}
		return comparison;
	}

	public abstract int compareIntraHand(T other);

}

public class HighCard extends AbstractHandType<HighCard>
{

	private final Card	highCard;
	private final Card	kicker;

	public HighCard(Card highCard, Card kicker)
	{
		super(1);
		this.highCard = highCard;
		this.kicker = kicker;
	}

	@Override
	public int compareIntraHand(HighCard other)
	{
		int compare;
		int compareHighCard = getHighCard().compareTo(other.getHighCard());
		if (compareHighCard == 0)
		{
			compare = getKicker().compareTo(other.getKicker());
		}
		else
		{
			compare = compareHighCard;
		}
		return compare;
	}

	public Card getHighCard()
	{
		return highCard;
	}

	public Card getKicker()
	{
		return kicker;
	}

	@Override
	public String toHumanReadable()
	{
		return "High card " + getHighCard() + " with a " + getKicker() + " kicker";
	}

}

/**
 * This is a set of cards, possibly more than 5 like in Texas hold 'em
 */
public class Hand implements Comparable<Hand>
{

	private Set<Card>	cards;

	@Override
	public int compareTo(Hand other)
	{
		return getBestHand().compareTo(other.getBestHand());
	}

	private HandType getBestHand()
	{
		// TODO....
		return null;
	}

}

public final class Card implements Comparable<Card>
{
	private final Suit	suit;
	private final Rank	rank;

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

	public Suit getSuit()
	{
		return suit;
	}

	public Rank getRank()
	{
		return rank;
	}

	/**
	 * Generated by eclipse.
	 */
	@Override
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result + ((rank == null) ? 0 : rank.hashCode());
		result = prime * result + ((suit == null) ? 0 : suit.hashCode());
		return result;
	}

	/**
	 * Generated by eclipse.
	 */
	@Override
	public boolean equals(Object obj)
	{
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final Card other = (Card) obj;
		if (rank == null)
		{
			if (other.rank != null)
				return false;
		}
		else if (!rank.equals(other.rank))
			return false;
		if (suit == null)
		{
			if (other.suit != null)
				return false;
		}
		else if (!suit.equals(other.suit))
			return false;
		return true;
	}

	@Override
	public int compareTo(Card other)
	{
		return rank.compareTo(other.getRank());
	}

	@Override
	public String toString()
	{
		return rank + " of " + suit;
	}

}

public enum Rank
{
	TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE
}
public enum Suit
{
	HEARTS, CLUBS, SPADES, DIAMONDS
}


Hope that makes sense,
D.

Hmm, good direction; you could go the way of implementing a factory class to generate hands that are directly comparable. You can have the general hand type ranking as a variable, and if the hands are of the same rank it can compare itself within the class. I like that approach over the whole ‘single score’ idea, simply because it looks more ‘sophisticated’. Although generating a numerical score is deceptively easy in Texas Hold’em.

http://spaz.ca/poker/ is a nice link i recon, but you have to install a postscript reader to read the thesis.

I’ve recently started on something similar, and what i did on hand evaluation was to create an array of the cards in the hand combined with the cards on the board. You can than easily find out what kind of best possible hand you’ve got. Basicly the checks are;

Pair - if two ranks match
Two pair - if two times two ranks match
Three of a kind - if you have three of the same rank
Straight - if a minimum of 5 ranks are concecutive
Flush - if the suits are the same
Full House - if you have a Pair and a Three of a Kind
Four of a kind - if you have four of the same rank
Straight Flush - has to be a straight and a flush
Royal Flush - same as straight, but last card in the straight has to be an ace

To make it easier you can sort the array by rank; that way you can determine if you got the straight or not quite fast. The only thing you have to take into account is that the Ace can be low or high in a straight: A-2-3-4-5 aswel as T-J-Q-K-A.

Yes, thank you. This seems to be the way to do it.