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.