diff --git a/71_Poker/csharp/Cards/Hand.cs b/71_Poker/csharp/Cards/Hand.cs index d697853a..34c14ac4 100644 --- a/71_Poker/csharp/Cards/Hand.cs +++ b/71_Poker/csharp/Cards/Hand.cs @@ -1,5 +1,5 @@ using System.Text; - +using static Poker.Cards.HandRank; namespace Poker.Cards; internal class Hand @@ -7,15 +7,11 @@ internal class Hand public static readonly Hand Empty = new Hand(); private readonly Card[] _cards; - private readonly string _name1; - private readonly string _name2; private Hand() { _cards = Array.Empty(); - _name1 = ""; - _name2 = ""; - Name = ""; + Rank = None; } public Hand(IEnumerable cards) @@ -26,16 +22,15 @@ internal class Hand private Hand(IEnumerable cards, bool isAfterDraw) { _cards = cards.ToArray(); - (Rank, _name1, _name2, HighCard, KeepMask) = Analyze(); - Name = GetHandName(); + (Rank, HighCard, KeepMask) = Analyze(); - IsWeak = Rank < 10 - || Rank == 10 && isAfterDraw - || Rank <= 12 && HighCard.Rank <= 6; + IsWeak = Rank < PartialStraight + || Rank == PartialStraight && isAfterDraw + || Rank <= TwoPair && HighCard.Rank <= 6; } - public string Name { get; } - public int Rank { get; } + public string Name => Rank.ToString(HighCard); + public HandRank Rank { get; } public Card HighCard { get; } public int KeepMask { get; set; } public bool IsWeak { get; } @@ -48,7 +43,7 @@ internal class Hand return new Hand(_cards, isAfterDraw: true); } - private (int, string, string, Card, int) Analyze() + private (HandRank, Card, int) Analyze() { var suitMatchCount = 0; for (var i = 0; i < _cards.Length; i++) @@ -60,31 +55,31 @@ internal class Hand } if (suitMatchCount == 4) { - return (15, "A Flus", "h in", _cards[0], 0b11111); + return (Flush, _cards[0], 0b11111); } var sortedCards = _cards.OrderBy(c => c.Rank).ToArray(); - var handRank = 0; + var handRank = Schmaltz; var keepMask = 0; Card highCard = default; - var handName1 = ""; - var handName2 = ""; for (var i = 0; i < sortedCards.Length - 1; i++) { - if (sortedCards[i].Rank == sortedCards[i+1].Rank) + var matchesNextCard = sortedCards[i].Rank == sortedCards[i+1].Rank; + var matchesPreviousCard = i > 0 && sortedCards[i].Rank == sortedCards[i - 1].Rank; + + if (matchesNextCard) { keepMask |= 0b11 << i; highCard = sortedCards[i]; - (handRank, handName1, handName2) = - (handRank, i > 0 && sortedCards[i].Rank == sortedCards[i - 1].Rank) switch - { - (<11, _) => (11, "A Pair", " of "), - (11, true) => (13, "Three", " "), - (11, _) => (12, "Two P", "air, "), - (12, _) => (16, "Full H", "ouse, "), - (_, true) => (17, "Four", " "), - _ => (16, "Full H", "ouse, ") - }; + handRank = matchesPreviousCard switch + { + _ when handRank < Pair => Pair, + true when handRank == Pair => Three, + _ when handRank == Pair => TwoPair, + _ when handRank == TwoPair => FullHouse, + true => Four, + _ => FullHouse + }; } } if (keepMask == 0) @@ -92,36 +87,21 @@ internal class Hand if (sortedCards[3] - sortedCards[0] == 3) { keepMask=0b1111; - handRank=10; + handRank=PartialStraight; } if (sortedCards[4] - sortedCards[1] == 3) { - if (handRank == 10) + if (handRank == PartialStraight) { - return (14, "Straig", "ht", sortedCards[4], 0b11111); + return (Straight, sortedCards[4], 0b11111); } - handRank=10; + handRank=PartialStraight; keepMask=0b11110; } } - return handRank < 10 - ? (9, "Schmal", "tz, ", sortedCards[4], 0b11000) - : (handRank, handName1, handName2, highCard, keepMask); - } - - private string GetHandName() - { - var sb = new StringBuilder(_name1).Append(_name2); - if (_name1 == "A Flus") - { - sb.Append(HighCard.Suit).AppendLine(); - } - else - { - sb.Append(HighCard.Rank) - .AppendLine(_name1 == "Schmal" || _name1 == "Straig" ? " High" : "'s"); - } - return sb.ToString(); + return handRank < PartialStraight + ? (Schmaltz, sortedCards[4], 0b11000) + : (handRank, highCard, keepMask); } public override string ToString() diff --git a/71_Poker/csharp/Cards/HandRank.cs b/71_Poker/csharp/Cards/HandRank.cs new file mode 100644 index 00000000..878746ee --- /dev/null +++ b/71_Poker/csharp/Cards/HandRank.cs @@ -0,0 +1,34 @@ +namespace Poker.Cards; + +internal class HandRank +{ + public static HandRank None = new(0, ""); + public static HandRank Schmaltz = new(1, "schmaltz, ", c => $"{c.Rank} high"); + public static HandRank PartialStraight = new(2, ""); // The original code does not assign a display string here + public static HandRank Pair = new(3, "a pair of ", c => $"{c.Rank}'s"); + public static HandRank TwoPair = new(4, "two pair, ", c => $"{c.Rank}'s"); + public static HandRank Three = new(5, "three ", c => $"{c.Rank}'s"); + public static HandRank Straight = new(6, "straight", c => $"{c.Rank} high"); + public static HandRank Flush = new(7, "a flush in ", c => c.Suit.ToString()); + public static HandRank FullHouse = new(8, "full house, ", c => $"{c.Rank}'s"); + public static HandRank Four = new(9, "four ", c => $"{c.Rank}'s"); + // The original code does not detect a straight flush or royal flush + + private readonly int _value; + private readonly string _displayName; + private readonly Func _suffixSelector; + + private HandRank(int value, string displayName, Func? suffixSelector = null) + { + _value = value; + _displayName = displayName; + _suffixSelector = suffixSelector ?? (_ => ""); + } + + public string ToString(Card highCard) => $"{_displayName}{_suffixSelector.Invoke(highCard)}"; + + public static bool operator >(HandRank x, HandRank y) => x._value > y._value; + public static bool operator <(HandRank x, HandRank y) => x._value < y._value; + public static bool operator >=(HandRank x, HandRank y) => x._value >= y._value; + public static bool operator <=(HandRank x, HandRank y) => x._value <= y._value; +} diff --git a/71_Poker/csharp/Game.cs b/71_Poker/csharp/Game.cs index 1f6c639f..d99a4baa 100644 --- a/71_Poker/csharp/Game.cs +++ b/71_Poker/csharp/Game.cs @@ -59,12 +59,12 @@ internal class Game Z = table.Computer.Hand.Rank switch { _ when table.Computer.Hand.IsWeak => - table.Computer.BluffIf(Get0To9() > 7, 0b11100) ?? - table.Computer.BluffIf(Get0To9() > 7, 0b11110) ?? + table.Computer.BluffIf(Get0To9() < 2, 0b11100) ?? + table.Computer.BluffIf(Get0To9() < 2, 0b11110) ?? table.Computer.BluffIf(Get0To9() < 1, 0b11111) ?? 1, - < 13 => table.Computer.BluffIf(Get0To9() < 2) ?? 0, - <= 16 => 35, + _ when table.Computer.Hand.Rank < HandRank.Three => table.Computer.BluffIf(Get0To9() < 2) ?? 0, + _ when table.Computer.Hand.Rank < HandRank.FullHouse => 35, _ when Get0To9() < 1 => 35, _ => 2 }; @@ -90,8 +90,8 @@ internal class Game { _ when table.Computer.IsBluffing => 28, _ when table.Computer.Hand.IsWeak => 1, - < 13 => Get0To9() == 0 ? 19 : 2, - < 16 => Get0To9() == 8 ? 11 : 19, + _ when table.Computer.Hand.Rank < HandRank.Three => Get0To9() == 0 ? 19 : 2, + _ when table.Computer.Hand.Rank < HandRank.FullHouse => Get0To9() == 0 ? 11 : 19, _ => 2 };