diff --git a/71_Poker/csharp/Card.cs b/71_Poker/csharp/Cards/Card.cs similarity index 93% rename from 71_Poker/csharp/Card.cs rename to 71_Poker/csharp/Cards/Card.cs index 95721142..d3176213 100644 --- a/71_Poker/csharp/Card.cs +++ b/71_Poker/csharp/Cards/Card.cs @@ -1,4 +1,4 @@ -namespace Poker; +namespace Poker.Cards; internal record struct Card (Rank Rank, Suit Suit) { diff --git a/71_Poker/csharp/Deck.cs b/71_Poker/csharp/Cards/Deck.cs similarity index 91% rename from 71_Poker/csharp/Deck.cs rename to 71_Poker/csharp/Cards/Deck.cs index 38a72244..d3a101b4 100644 --- a/71_Poker/csharp/Deck.cs +++ b/71_Poker/csharp/Cards/Deck.cs @@ -1,6 +1,6 @@ -using static Poker.Rank; +using static Poker.Cards.Rank; -namespace Poker; +namespace Poker.Cards; internal class Deck { diff --git a/71_Poker/csharp/Hand.cs b/71_Poker/csharp/Cards/Hand.cs similarity index 99% rename from 71_Poker/csharp/Hand.cs rename to 71_Poker/csharp/Cards/Hand.cs index 6e078089..d697853a 100644 --- a/71_Poker/csharp/Hand.cs +++ b/71_Poker/csharp/Cards/Hand.cs @@ -1,6 +1,6 @@ using System.Text; -namespace Poker; +namespace Poker.Cards; internal class Hand { diff --git a/71_Poker/csharp/Rank.cs b/71_Poker/csharp/Cards/Rank.cs similarity index 90% rename from 71_Poker/csharp/Rank.cs rename to 71_Poker/csharp/Cards/Rank.cs index ab642cd4..cd44922a 100644 --- a/71_Poker/csharp/Rank.cs +++ b/71_Poker/csharp/Cards/Rank.cs @@ -1,4 +1,4 @@ -namespace Poker; +namespace Poker.Cards; internal struct Rank : IComparable { @@ -43,4 +43,8 @@ internal struct Rank : IComparable public static bool operator <=(Rank rank, int value) => rank._value <= value; public static bool operator >=(Rank rank, int value) => rank._value >= value; + + public override bool Equals(object? obj) => obj is Rank other && this == other; + + public override int GetHashCode() => _value.GetHashCode(); } diff --git a/71_Poker/csharp/Suit.cs b/71_Poker/csharp/Cards/Suit.cs similarity index 75% rename from 71_Poker/csharp/Suit.cs rename to 71_Poker/csharp/Cards/Suit.cs index 616febb3..0a246999 100644 --- a/71_Poker/csharp/Suit.cs +++ b/71_Poker/csharp/Cards/Suit.cs @@ -1,4 +1,4 @@ -namespace Poker; +namespace Poker.Cards; internal enum Suit { diff --git a/71_Poker/csharp/Games.cs b/71_Poker/csharp/Game.cs similarity index 51% rename from 71_Poker/csharp/Games.cs rename to 71_Poker/csharp/Game.cs index 099690d0..1f6c639f 100644 --- a/71_Poker/csharp/Games.cs +++ b/71_Poker/csharp/Game.cs @@ -1,5 +1,6 @@ +using Poker.Cards; +using Poker.Players; using Poker.Resources; -using static System.StringComparison; namespace Poker; @@ -239,284 +240,3 @@ internal record Bet (int Amount) : IAction { } } - -internal abstract class Player -{ - private Table? _table; - private bool _hasFolded; - - protected Player(int bank) - { - Hand = Hand.Empty; - Balance = bank; - } - - public Hand Hand { get; set; } - public int Balance { get; set; } - public int Bet { get; private set; } - public bool HasFolded => _hasFolded; - - protected Table Table => - _table ?? throw new InvalidOperationException("The player must be sitting at the table."); - - public void Sit(Table table) => _table = table; - - public virtual void NewHand(Hand hand) - { - Hand = hand; - _hasFolded = false; - } - - public void Pay(int amount) - { - Balance -= amount; - } - - public virtual void TakeWinnings() - { - Balance += Table.Pot; - Table.Pot = 0; - } - - public void Fold() - { - _hasFolded = true; - } -} - -internal class Human : Player -{ - private readonly IReadWrite _io; - - public Human(int bank, IReadWrite io) - : base(bank) - { - HasWatch = true; - _io = io; - } - - public bool HasWatch { get; set; } - - public void DrawCards(Deck deck) - { - var count = _io.ReadNumber("How many cards do you want", 3, "You can't draw more than three cards."); - if (count == 0) { return; } - - _io.WriteLine("What are their numbers:"); - for (var i = 1; i <= count; i++) - { - Hand = Hand.Replace((int)_io.ReadNumber(), deck.DealCard()); - } - - _io.WriteLine("Your new hand:"); - _io.Write(Hand); - } - - public bool IsBroke() - { - _io.WriteLine(); - _io.WriteLine("You can't bet with what you haven't got."); - - if (Table.Computer.TryBuyWatch(this)) { return false; } - - // The original program had some code about selling a tie tack, but due to a fault - // in the logic the code was unreachable. I've omitted it in this port. - - _io.WriteLine("Your wad is shot. So long, sucker!"); - return true; - } - - public void ReceiveWatch() - { - // In the original code the player does not pay any money to receive the watch back. - HasWatch = true; - } - - public void SellWatch(int amount) - { - HasWatch = false; - Balance += amount; - } - - public override void TakeWinnings() - { - _io.WriteLine("You win."); - base.TakeWinnings(); - } -} - -internal class Computer : Player -{ - private readonly IReadWrite _io; - private readonly IRandom _random; - private bool _isBluffing; - - public Computer(int bank, IReadWrite io, IRandom random) - : base(bank) - { - _io = io; - _random = random; - } - - public bool IsBluffing => _isBluffing; - - public override void NewHand(Hand hand) - { - base.NewHand(hand); - _isBluffing = false; - } - - public int? BluffIf(bool shouldBluff, int? keepMask = null) - { - if (!shouldBluff) { return null; } - - _isBluffing = true; - Hand.KeepMask = keepMask ?? Hand.KeepMask; - return 23; - } - - public void DrawCards(Deck deck) - { - var keepMask = Hand.KeepMask; - var count = 0; - for (var i = 1; i <= 5; i++) - { - if ((keepMask & (1 << (i - 1))) == 0) - { - Hand = Hand.Replace(i, deck.DealCard()); - count++; - } - } - - _io.WriteLine(); - _io.Write($"I am taking {count} card"); - if (count != 1) - { - _io.WriteLine("s"); - } - } - - public bool TryBuyWatch(Human human) - { - if (!human.HasWatch) { return false; } - - var response = _io.ReadString("Would you like to sell your watch"); - if (response.StartsWith("N", InvariantCultureIgnoreCase)) { return false; } - - var (value, message) = (_random.Next(10) < 7) switch - { - true => (75, "I'll give you $75 for it."), - false => (25, "That's a pretty crummy watch - I'll give you $25.") - }; - - _io.WriteLine(message); - human.SellWatch(value); - // The original code does not have the computer part with any money - - return true; - } - - public bool TrySellWatch(Human human) - { - if (human.HasWatch) { return false; } - - var response = _io.ReadString("Would you like to buy back your watch for $50"); - if (response.StartsWith("N", InvariantCultureIgnoreCase)) { return false; } - - // The original code does not deduct $50 from the player - Balance += 50; - human.ReceiveWatch(); - return true; - } - - public override void TakeWinnings() - { - _io.WriteLine("I win."); - base.TakeWinnings(); - } -} - -internal class Table -{ - private IReadWrite _io; - public int Pot; - private Deck _deck; - - public Table(IReadWrite io, Deck deck, Human human, Computer computer) - { - _io = io; - _deck = deck; - Human = human; - Computer = computer; - - human.Sit(this); - computer.Sit(this); - } - - public Human Human { get; } - public Computer Computer { get; } - - public void Deal() - { - Pot = 10; - Human.Pay(5); - Computer.Pay(5); - - Human.NewHand(_deck.DealHand()); - Computer.NewHand(_deck.DealHand()); - - _io.WriteLine("Your hand:"); - _io.Write(Human.Hand); - } - - public void Draw() - { - _io.WriteLine(); - _io.Write("Now we draw -- "); - Human.DrawCards(_deck); - Computer.DrawCards(_deck); - _io.WriteLine(); - } - - public void AcceptBets() - { - - } - - public bool SomeoneHasFolded() - { - if (Human.HasFolded) - { - _io.WriteLine(); - Computer.TakeWinnings(); - } - else if (Computer.HasFolded) - { - _io.WriteLine(); - Human.TakeWinnings(); - } - else - { - return false; - } - - Pot = 0; - return true; - } - - public Player? GetWinner() - { - _io.WriteLine(); - _io.WriteLine("Now we compare hands:"); - _io.WriteLine("My hand:"); - _io.Write(Computer.Hand); - _io.WriteLine(); - _io.Write($"You have {Human.Hand.Name}"); - _io.Write($"and I have {Computer.Hand.Name}"); - if (Computer.Hand > Human.Hand) { return Computer; } - if (Human.Hand > Computer.Hand) { return Human; } - _io.WriteLine("The hand is drawn."); - _io.WriteLine($"All $ {Pot} remains in the pot."); - return null; - } -} \ No newline at end of file diff --git a/71_Poker/csharp/Players/Computer.cs b/71_Poker/csharp/Players/Computer.cs new file mode 100644 index 00000000..350e9785 --- /dev/null +++ b/71_Poker/csharp/Players/Computer.cs @@ -0,0 +1,95 @@ +using Poker.Cards; +using static System.StringComparison; + +namespace Poker.Players; + +internal class Computer : Player +{ + private readonly IReadWrite _io; + private readonly IRandom _random; + private bool _isBluffing; + + public Computer(int bank, IReadWrite io, IRandom random) + : base(bank) + { + _io = io; + _random = random; + } + + public bool IsBluffing => _isBluffing; + + public override void NewHand(Hand hand) + { + base.NewHand(hand); + _isBluffing = false; + } + + public int? BluffIf(bool shouldBluff, int? keepMask = null) + { + if (!shouldBluff) { return null; } + + _isBluffing = true; + Hand.KeepMask = keepMask ?? Hand.KeepMask; + return 23; + } + + public void DrawCards(Deck deck) + { + var keepMask = Hand.KeepMask; + var count = 0; + for (var i = 1; i <= 5; i++) + { + if ((keepMask & (1 << (i - 1))) == 0) + { + Hand = Hand.Replace(i, deck.DealCard()); + count++; + } + } + + _io.WriteLine(); + _io.Write($"I am taking {count} card"); + if (count != 1) + { + _io.WriteLine("s"); + } + } + + public bool TryBuyWatch(Human human) + { + if (!human.HasWatch) { return false; } + + var response = _io.ReadString("Would you like to sell your watch"); + if (response.StartsWith("N", InvariantCultureIgnoreCase)) { return false; } + + var (value, message) = (_random.Next(10) < 7) switch + { + true => (75, "I'll give you $75 for it."), + false => (25, "That's a pretty crummy watch - I'll give you $25.") + }; + + _io.WriteLine(message); + human.SellWatch(value); + // The original code does not have the computer part with any money + + return true; + } + + public bool TrySellWatch(Human human) + { + if (human.HasWatch) { return false; } + + var response = _io.ReadString("Would you like to buy back your watch for $50"); + if (response.StartsWith("N", InvariantCultureIgnoreCase)) { return false; } + + // The original code does not deduct $50 from the player + Balance += 50; + human.ReceiveWatch(); + return true; + } + + public override void TakeWinnings() + { + _io.WriteLine("I win."); + base.TakeWinnings(); + } +} diff --git a/71_Poker/csharp/Players/Human.cs b/71_Poker/csharp/Players/Human.cs new file mode 100644 index 00000000..ac3674bd --- /dev/null +++ b/71_Poker/csharp/Players/Human.cs @@ -0,0 +1,64 @@ +using Poker.Cards; + +namespace Poker.Players; + +internal class Human : Player +{ + private readonly IReadWrite _io; + + public Human(int bank, IReadWrite io) + : base(bank) + { + HasWatch = true; + _io = io; + } + + public bool HasWatch { get; set; } + + public void DrawCards(Deck deck) + { + var count = _io.ReadNumber("How many cards do you want", 3, "You can't draw more than three cards."); + if (count == 0) { return; } + + _io.WriteLine("What are their numbers:"); + for (var i = 1; i <= count; i++) + { + Hand = Hand.Replace((int)_io.ReadNumber(), deck.DealCard()); + } + + _io.WriteLine("Your new hand:"); + _io.Write(Hand); + } + + public bool IsBroke() + { + _io.WriteLine(); + _io.WriteLine("You can't bet with what you haven't got."); + + if (Table.Computer.TryBuyWatch(this)) { return false; } + + // The original program had some code about selling a tie tack, but due to a fault + // in the logic the code was unreachable. I've omitted it in this port. + + _io.WriteLine("Your wad is shot. So long, sucker!"); + return true; + } + + public void ReceiveWatch() + { + // In the original code the player does not pay any money to receive the watch back. + HasWatch = true; + } + + public void SellWatch(int amount) + { + HasWatch = false; + Balance += amount; + } + + public override void TakeWinnings() + { + _io.WriteLine("You win."); + base.TakeWinnings(); + } +} diff --git a/71_Poker/csharp/Players/Player.cs b/71_Poker/csharp/Players/Player.cs new file mode 100644 index 00000000..d12e92c1 --- /dev/null +++ b/71_Poker/csharp/Players/Player.cs @@ -0,0 +1,47 @@ +using Poker.Cards; + +namespace Poker.Players; + +internal abstract class Player +{ + private Table? _table; + private bool _hasFolded; + + protected Player(int bank) + { + Hand = Hand.Empty; + Balance = bank; + } + + public Hand Hand { get; set; } + public int Balance { get; set; } + public int Bet { get; private set; } + public bool HasFolded => _hasFolded; + + protected Table Table => + _table ?? throw new InvalidOperationException("The player must be sitting at the table."); + + public void Sit(Table table) => _table = table; + + public virtual void NewHand(Hand hand) + { + Hand = hand; + _hasFolded = false; + } + + public void Pay(int amount) + { + Balance -= amount; + } + + public virtual void TakeWinnings() + { + Balance += Table.Pot; + Table.Pot = 0; + } + + public void Fold() + { + _hasFolded = true; + } +} diff --git a/71_Poker/csharp/Table.cs b/71_Poker/csharp/Table.cs new file mode 100644 index 00000000..7b7524bc --- /dev/null +++ b/71_Poker/csharp/Table.cs @@ -0,0 +1,89 @@ +using Poker.Cards; +using Poker.Players; + +namespace Poker; + +internal class Table +{ + private IReadWrite _io; + public int Pot; + private Deck _deck; + + public Table(IReadWrite io, Deck deck, Human human, Computer computer) + { + _io = io; + _deck = deck; + Human = human; + Computer = computer; + + human.Sit(this); + computer.Sit(this); + } + + public Human Human { get; } + public Computer Computer { get; } + + public void Deal() + { + Pot = 10; + Human.Pay(5); + Computer.Pay(5); + + Human.NewHand(_deck.DealHand()); + Computer.NewHand(_deck.DealHand()); + + _io.WriteLine("Your hand:"); + _io.Write(Human.Hand); + } + + public void Draw() + { + _io.WriteLine(); + _io.Write("Now we draw -- "); + Human.DrawCards(_deck); + Computer.DrawCards(_deck); + _io.WriteLine(); + } + + public void AcceptBets() + { + + } + + public bool SomeoneHasFolded() + { + if (Human.HasFolded) + { + _io.WriteLine(); + Computer.TakeWinnings(); + } + else if (Computer.HasFolded) + { + _io.WriteLine(); + Human.TakeWinnings(); + } + else + { + return false; + } + + Pot = 0; + return true; + } + + public Player? GetWinner() + { + _io.WriteLine(); + _io.WriteLine("Now we compare hands:"); + _io.WriteLine("My hand:"); + _io.Write(Computer.Hand); + _io.WriteLine(); + _io.Write($"You have {Human.Hand.Name}"); + _io.Write($"and I have {Computer.Hand.Name}"); + if (Computer.Hand > Human.Hand) { return Computer; } + if (Human.Hand > Computer.Hand) { return Human; } + _io.WriteLine("The hand is drawn."); + _io.WriteLine($"All $ {Pot} remains in the pot."); + return null; + } +} \ No newline at end of file