public int CompareHands(IHand firstHand, IHand secondHand) { // "null is smaller than a non-null object by definition" if (firstHand == null) { if (secondHand == null) return 0; return -1; } if (secondHand == null) { return 1; } if (!IsValidHand(firstHand)) { if (!IsValidHand(secondHand)) return 0; return -1; } if (!IsValidHand(secondHand)) { return 1; } // we could also map each hand type to an integer foreach (var predicate in this.PredicatesList) { var isFirst = predicate(firstHand); var isSecond = predicate(secondHand); if (isFirst && isSecond) { if (predicate == this.IsStraightFlush || predicate == this.IsStraight || predicate == this.IsFlush || predicate == this.IsHighCard) { return firstHand.HighestCard().Face.CompareTo( secondHand.HighestCard().Face); } // x of kind var x = 0; if (predicate == this.IsFourOfAKind) x = 4; if (predicate == this.IsThreeOfAKind) x = 3; if (predicate == this.IsTwoPair || predicate == this.IsOnePair) x = 2; var seq1 = firstHand.GetXOfKind(x).OrderByDescending(g => g.Key).SelectMany(g => g); var seq2 = secondHand.GetXOfKind(x).OrderByDescending(g => g.Key).SelectMany(g => g); return Utils.CompareSequences(seq1, seq2, c => (int)c.Suit); } if (isFirst) { return 1; } if (isSecond) { return -1; } } Debug.Assert(false, "should not happen"); throw new ApplicationException("assertion failed"); }