diff --git a/07_Basketball/csharp/Game.cs b/07_Basketball/csharp/Game.cs index b44278d3..4f405c38 100644 --- a/07_Basketball/csharp/Game.cs +++ b/07_Basketball/csharp/Game.cs @@ -21,35 +21,39 @@ internal class Game var defense = _io.ReadDefense("Your starting defense will be"); + var homeTeam = new Team("Dartmouth"); + _io.WriteLine(); - var opponent = _io.ReadString("Choose your opponent"); + var visitingTeam = new Team(_io.ReadString("Choose your opponent")); + _io.WriteLine("Center jump"); - var offense = _random.NextFloat() > 0.6 ? "Dartmouth" : opponent; + var offense = _random.NextFloat() > 0.6 ? homeTeam : visitingTeam; _io.WriteLine($"{offense} controls the tap."); var time = 0; - var score = new Dictionary { ["Dartmouth"] = 0, [opponent] = 0 }; + var scoreboard = new Scoreboard(homeTeam, visitingTeam, _io); + scoreboard.Offense = offense; _io.WriteLine(); - if (offense == "Dartmouth") + if (offense == homeTeam) { var shot = _io.ReadShot("Your shot"); if (_random.NextFloat() >= 0.5 && time >= 100) { _io.WriteLine(); - if (score["Dartmouth"] == score[opponent]) + if (scoreboard.ScoresAreEqual) { - _io.WriteScore(Resource.Formats.EndOfSecondHalf, opponent, score); + scoreboard.Display(Resource.Formats.EndOfSecondHalf); time = 93; // Loop back to center jump } else { - _io.WriteScore(Resource.Formats.EndOfGame, opponent, score); + scoreboard.Display(Resource.Formats.EndOfGame); return; } } @@ -66,7 +70,7 @@ internal class Game time++; if (time == 50) { - _io.WriteScore(Resource.Formats.EndOfFirstHalf, opponent, score); + scoreboard.Display(Resource.Formats.EndOfFirstHalf); // Loop back to center jump; } if (time == 92) @@ -76,9 +80,7 @@ internal class Game _io.WriteLine("Jump shot"); if (_random.NextFloat() <= 0.341 * defense / 8) { - _io.WriteLine("Shot is good"); - score["Dartmouth"] += 2; - _io.WriteScore(Resource.Formats.Score, opponent, score); + scoreboard.AddBasket("Shot is good"); // over to opponent } else if (_random.NextFloat() <= 0.682 * defense / 8) @@ -86,7 +88,8 @@ internal class Game _io.WriteLine("Shot is off target"); if (defense / 6 * _random.NextFloat() > 0.45) { - _io.WriteLine($"Rebound to {opponent}"); + _io.WriteLine($"Rebound to {visitingTeam}"); + scoreboard.Turnover(); // over to opponent } else @@ -102,9 +105,8 @@ internal class Game { if (_random.NextFloat() > 0.6) { - _io.WriteLine($"Pass stolen be {opponent} easy layup."); - score[opponent] += 2; - _io.WriteScore(Resource.Formats.Score, opponent, score); + scoreboard.Turnover(); + scoreboard.AddBasket($"Pass stolen by {visitingTeam} easy layup."); _io.WriteLine(); } } @@ -115,19 +117,21 @@ internal class Game } else if (_random.NextFloat() <= 0.782 * defense / 8) { - offense = _random.NextFloat() <= 0.5 ? "Dartmouth" : opponent; + offense = _random.NextFloat() <= 0.5 ? homeTeam : visitingTeam; + scoreboard.Offense = offense; _io.WriteLine($"Shot is blocked. Ball controlled by {offense}."); // go to next shot } else if (_random.NextFloat() <= 0.843 * defense / 8) { _io.WriteLine("Shooter is fouled. Two shots."); - FreeShots(); + FreeThrows(); // over to opponent } else { _io.WriteLine("Charging foul. Dartmouth loses ball."); + scoreboard.Turnover(); // over to opponent } } @@ -135,7 +139,7 @@ internal class Game time++; if (time == 50) { - _io.WriteScore(Resource.Formats.EndOfFirstHalf, opponent, score); + scoreboard.Display(Resource.Formats.EndOfFirstHalf); // Loop back to center jump; } if (time == 92) @@ -147,9 +151,7 @@ internal class Game if (7 / defense * _random.NextFloat() <= 0.4) { - _io.WriteLine("Shot is good. Two points."); - score["Dartmouth"] += 2; - _io.WriteScore(Resource.Formats.Score, opponent, score); + scoreboard.AddBasket("Shot is good. Two points."); // over to opponent } else if (7 / defense * _random.NextFloat() <= 0.7) @@ -157,7 +159,8 @@ internal class Game _io.WriteLine("Shot is off the rim."); if (_random.NextFloat() <= 2 / 3f) { - _io.WriteLine($"{opponent} controls the rebound."); + _io.WriteLine($"{visitingTeam} controls the rebound."); + scoreboard.Turnover(); // over to opponent } else @@ -177,17 +180,19 @@ internal class Game else if (7 / defense * _random.NextFloat() <= 0.875) { _io.WriteLine("Shooter fouled. Two shots."); - FreeShots(); + FreeThrows(); // over to opponent } else if (7 / defense * _random.NextFloat() <= 0.925) { - _io.WriteLine($"Shot blocked. {opponent}'s ball."); + _io.WriteLine($"Shot blocked. {visitingTeam}'s ball."); + scoreboard.Turnover(); // over to opponent } else { _io.WriteLine("Charging foul. Dartmouth loses ball."); + scoreboard.Turnover(); // over to opponent } } @@ -197,7 +202,7 @@ internal class Game time++; if (time == 50) { - _io.WriteScore(Resource.Formats.EndOfFirstHalf, opponent, score); + scoreboard.Display(Resource.Formats.EndOfFirstHalf); // Loop back to center jump; } if (time == 92) @@ -213,9 +218,7 @@ internal class Game if (8 / defense * _random.NextFloat() <= 0.35) { - _io.WriteLine("Shot is good."); - score[opponent] += 2; - _io.WriteScore(Resource.Formats.Score, opponent, score); + scoreboard.AddBasket("Shot is good."); // over to Dartmouth } else if (8 / defense * _random.NextFloat() <= 0.75) @@ -224,25 +227,25 @@ internal class Game if (defense / 6 * _random.NextFloat() <= 0.5) { _io.WriteLine("Dartmouth controls the rebound."); + scoreboard.Turnover(); // over to Dartmouth } else { - _io.WriteLine($"{opponent} controls the rebound."); + _io.WriteLine($"{visitingTeam} controls the rebound."); if (defense == 6) { if (_random.NextFloat() > 0.75) { - _io.WriteLine("Ball stolen. Easy lay up for Dartmouth."); - score["Dartmouth"] += 2; - _io.WriteScore(Resource.Formats.Score, opponent, score); + scoreboard.Turnover(); + scoreboard.AddBasket("Ball stolen. Easy lay up for Dartmouth."); _io.WriteLine(); // next opponent shot } } if (_random.NextFloat() <= 0.5) { - _io.WriteLine($"Pass back to {opponent} guard."); + _io.WriteLine($"Pass back to {visitingTeam} guard."); // next opponent shot } // goto 3500 @@ -251,7 +254,7 @@ internal class Game else if (8 / defense * _random.NextFloat() <= 0.9) { _io.WriteLine("Player fouled. Two shots."); - FreeShots(); + FreeThrows(); // next Dartmouth shot } else @@ -266,9 +269,7 @@ internal class Game if (7 / defense * _random.NextFloat() <= 0.413) { - _io.WriteLine("Shot is good."); - score[opponent] += 2; - _io.WriteScore(Resource.Formats.Score, opponent, score); + scoreboard.AddBasket("Shot is good."); // over to Dartmouth } else @@ -277,25 +278,25 @@ internal class Game if (defense / 6 * _random.NextFloat() <= 0.5) { _io.WriteLine("Dartmouth controls the rebound."); + scoreboard.Turnover(); // over to Dartmouth } else { - _io.WriteLine($"{opponent} controls the rebound."); + _io.WriteLine($"{visitingTeam} controls the rebound."); if (defense == 6) { if (_random.NextFloat() > 0.75) { - _io.WriteLine("Ball stolen. Easy lay up for Dartmouth."); - score["Dartmouth"] += 2; - _io.WriteScore(Resource.Formats.Score, opponent, score); + scoreboard.Turnover(); + scoreboard.AddBasket("Ball stolen. Easy lay up for Dartmouth."); _io.WriteLine(); // next opponent shot } } if (_random.NextFloat() <= 0.5) { - _io.WriteLine($"Pass back to {opponent} guard."); + _io.WriteLine($"Pass back to {visitingTeam} guard."); // next opponent shot } // goto 3500 @@ -303,50 +304,20 @@ internal class Game } } - void FreeShots() + void FreeThrows() { if (_random.NextFloat() <= 0.49) { - _io.WriteLine("Shooter makes both shots."); - score[offense] += 2; + scoreboard.AddFreeThrows(2, "Shooter makes both shots."); } else if (_random.NextFloat() <= 0.75) { - _io.WriteLine("Shooter makes one shot and misses one."); - score[offense] += 1; + scoreboard.AddFreeThrows(1, "Shooter makes one shot and misses one."); } else { - _io.WriteLine("Both shots missed."); + scoreboard.AddFreeThrows(0, "Both shots missed."); } - _io.WriteScore(Resource.Formats.Score, opponent, score); } } } - -internal record Team(string Name); - -internal static class IReadWriteExtensions -{ - public static float ReadDefense(this IReadWrite io, string prompt) - { - while (true) - { - var defense = io.ReadNumber(prompt); - if (defense >= 6) { return defense; } - } - } - - public static int ReadShot(this IReadWrite io, string prompt) - { - while (true) - { - var shot = io.ReadNumber(prompt); - if ((int)shot == shot && shot >= 0 && shot <= 4) { return (int)shot; } - io.Write("Incorrect answer. Retype it. "); - } - } - - public static void WriteScore(this IReadWrite io, string format, string opponent, Dictionary score) => - io.WriteLine(format, "Dartmouth", score["Dartmouth"], opponent, score[opponent]); -} \ No newline at end of file diff --git a/07_Basketball/csharp/IReadWriteExtensions.cs b/07_Basketball/csharp/IReadWriteExtensions.cs new file mode 100644 index 00000000..7b510a50 --- /dev/null +++ b/07_Basketball/csharp/IReadWriteExtensions.cs @@ -0,0 +1,28 @@ +using Games.Common.IO; + +namespace Basketball; + +internal static class IReadWriteExtensions +{ + public static float ReadDefense(this IReadWrite io, string prompt) + { + while (true) + { + var defense = io.ReadNumber(prompt); + if (defense >= 6) { return defense; } + } + } + + public static int ReadShot(this IReadWrite io, string prompt) + { + while (true) + { + var shot = io.ReadNumber(prompt); + if ((int)shot == shot && shot >= 0 && shot <= 4) { return (int)shot; } + io.Write("Incorrect answer. Retype it. "); + } + } + + public static void WriteScore(this IReadWrite io, string format, string opponent, Dictionary score) => + io.WriteLine(format, "Dartmouth", score["Dartmouth"], opponent, score[opponent]); +} \ No newline at end of file diff --git a/07_Basketball/csharp/Scoreboard.cs b/07_Basketball/csharp/Scoreboard.cs new file mode 100644 index 00000000..fc94b432 --- /dev/null +++ b/07_Basketball/csharp/Scoreboard.cs @@ -0,0 +1,43 @@ +using Basketball.Resources; +using Games.Common.IO; + +namespace Basketball; + +internal class Scoreboard +{ + private readonly Dictionary _scores; + private readonly IReadWrite _io; + + private Team _home; + private Team _visitors; + private Team _offense; + + public Scoreboard(Team home, Team visitors, IReadWrite io) + { + _scores = new() { [home] = 0, [visitors] = 0 }; + _home = home; + _visitors = visitors; + _offense = home; + _io = io; + } + + public bool ScoresAreEqual => _scores[_home] == _scores[_visitors]; + public Team Offense { set => _offense = value; } + + public void AddBasket(string message) => AddScore(2, message); + + public void AddFreeThrows(uint count, string message) => AddScore(count, message); + + private void AddScore(uint score, string message) + { + _io.WriteLine(message); + _scores[_offense] += score; + Turnover(); + Display(); + } + + public void Turnover() => _offense = _offense == _home ? _visitors : _home; + + public void Display(string? format = null) => + _io.WriteLine(format ?? Resource.Formats.Score, _home, _scores[_home], _visitors, _scores[_visitors]); +} diff --git a/07_Basketball/csharp/Team.cs b/07_Basketball/csharp/Team.cs new file mode 100644 index 00000000..91181588 --- /dev/null +++ b/07_Basketball/csharp/Team.cs @@ -0,0 +1,6 @@ +namespace Basketball; + +internal record Team(string Name) +{ + public override string ToString() => Name; +}