diff --git a/00_Common/dotnet/Games.Common/IO/IReadWrite.cs b/00_Common/dotnet/Games.Common/IO/IReadWrite.cs index 24529947..02ab573e 100644 --- a/00_Common/dotnet/Games.Common/IO/IReadWrite.cs +++ b/00_Common/dotnet/Games.Common/IO/IReadWrite.cs @@ -94,6 +94,13 @@ public interface IReadWrite /// The to be written. void WriteLine(object value); + /// + /// Writes a formatted string to output. + /// + /// The format to be written. + /// The values to be inserted into the format. + void WriteLine(string format, params object[] values); + /// /// Writes the contents of a to output. /// diff --git a/00_Common/dotnet/Games.Common/IO/TextIO.cs b/00_Common/dotnet/Games.Common/IO/TextIO.cs index a96935af..c2584e69 100644 --- a/00_Common/dotnet/Games.Common/IO/TextIO.cs +++ b/00_Common/dotnet/Games.Common/IO/TextIO.cs @@ -99,6 +99,8 @@ public class TextIO : IReadWrite public void WriteLine(object value) => _output.WriteLine(value.ToString()); + public void WriteLine(string format, params object[] values) => _output.WriteLine(format, values); + public void Write(Stream stream, bool keepOpen = false) { using var reader = new StreamReader(stream); diff --git a/82_Stars/csharp/Game.cs b/82_Stars/csharp/Game.cs index 9711dd82..f3944737 100644 --- a/82_Stars/csharp/Game.cs +++ b/82_Stars/csharp/Game.cs @@ -1,94 +1,105 @@ using System; +using Games.Common.IO; +using Games.Common.Randomness; +using Stars.Resources; -namespace Stars +namespace Stars; + +internal class Game { - internal class Game - { - private readonly int _maxNumber; - private readonly int _maxGuessCount; - private readonly Random _random; + private readonly TextIO _io; + private readonly IRandom _random; + private readonly int _maxNumber; + private readonly int _maxGuessCount; - public Game(int maxNumber, int maxGuessCount) + public Game(TextIO io, IRandom random, int maxNumber, int maxGuessCount) + { + _io = io; + _random = random; + _maxNumber = maxNumber; + _maxGuessCount = maxGuessCount; + } + + internal void Play(Func playAgain) + { + DisplayIntroduction(); + + do { - _maxNumber = maxNumber; - _maxGuessCount = maxGuessCount; - _random = new Random(); + Play(); + } while (playAgain.Invoke()); + } + + private void DisplayIntroduction() + { + _io.Write(Resource.Streams.Title); + + if (_io.ReadString("Do you want instructions").Equals("N", StringComparison.InvariantCultureIgnoreCase)) + { + return; } - internal void DisplayInstructions() + _io.WriteLine(Resource.Formats.Instructions, _maxNumber, _maxGuessCount); + } + + private void Play() + { + _io.WriteLine(); + _io.WriteLine(); + + var target = _random.Next(_maxNumber) + 1; + + _io.WriteLine("Ok, I am thinking of a number. Start guessing."); + + AcceptGuesses(target); + } + + private void AcceptGuesses(int target) + { + for (int guessCount = 1; guessCount <= _maxGuessCount; guessCount++) { - if (Input.GetString("Do you want instructions? ").Equals("N", StringComparison.InvariantCultureIgnoreCase)) + _io.WriteLine(); + var guess = _io.ReadNumber("Your guess"); + + if (guess == target) { + DisplayWin(guessCount); return; } - Console.WriteLine($"I am thinking of a number between 1 and {_maxNumber}."); - Console.WriteLine("Try to guess my number. After you guess, I"); - Console.WriteLine("will type one or more stars (*). The more"); - Console.WriteLine("stars I type, the close you are to my number."); - Console.WriteLine("One star (*) means far away, seven stars (*******)"); - Console.WriteLine($"means really close! You get {_maxGuessCount} guesses."); + DisplayStars(target, guess); } - internal void Play() + DisplayLoss(target); + } + + private void DisplayStars(int target, float guess) + { + var stars = Math.Abs(guess - target) switch { - Console.WriteLine(); - Console.WriteLine(); + >= 64 => "*", + >= 32 => "**", + >= 16 => "***", + >= 8 => "****", + >= 4 => "*****", + >= 2 => "******", + _ => "*******" + }; - var target = _random.Next(_maxNumber) + 1; + _io.WriteLine(stars); + } - Console.WriteLine("Ok, I am thinking of a number. Start guessing."); + private void DisplayWin(int guessCount) + { + _io.WriteLine(); + _io.WriteLine(new string('*', 79)); + _io.WriteLine(); + _io.WriteLine($"You got it in {guessCount} guesses!!! Let's play again..."); + } - AcceptGuesses(target); - } - - private void AcceptGuesses(int target) - { - for (int guessCount = 1; guessCount <= _maxGuessCount; guessCount++) - { - Console.WriteLine(); - var guess = Input.GetNumber("Your guess? "); - - if (guess == target) - { - DisplayWin(guessCount); - return; - } - - DisplayStars(target, guess); - } - - DisplayLoss(target); - } - - private static void DisplayStars(int target, float guess) - { - var stars = Math.Abs(guess - target) switch - { - >= 64 => "*", - >= 32 => "**", - >= 16 => "***", - >= 8 => "****", - >= 4 => "*****", - >= 2 => "******", - _ => "*******" - }; - - Console.WriteLine(stars); - } - - private static void DisplayWin(int guessCount) - { - Console.WriteLine(); - Console.WriteLine(new string('*', 79)); - Console.WriteLine(); - Console.WriteLine($"You got it in {guessCount} guesses!!! Let's play again..."); - } - - private void DisplayLoss(int target) - { - Console.WriteLine(); - Console.WriteLine($"Sorry, that's {_maxGuessCount} guesses. The number was {target}."); - } + private void DisplayLoss(int target) + { + _io.WriteLine(); + _io.WriteLine($"Sorry, that's {_maxGuessCount} guesses. The number was {target}."); } } diff --git a/82_Stars/csharp/Input.cs b/82_Stars/csharp/Input.cs deleted file mode 100644 index 6ba6e3a1..00000000 --- a/82_Stars/csharp/Input.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; - -namespace Stars -{ - internal static class Input - { - // Float, because that's what the BASIC input operation returns - internal static float GetNumber(string prompt) - { - Console.Write(prompt); - - while (true) - { - var response = Console.ReadLine(); - if (float.TryParse(response, out var value)) - { - return value; - } - - Console.WriteLine("!Number expected - retry input line"); - Console.Write("? "); - } - } - - internal static string GetString(string prompt) - { - Console.Write(prompt); - return Console.ReadLine(); - } - } -} diff --git a/82_Stars/csharp/Program.cs b/82_Stars/csharp/Program.cs index b072595c..cf6e9e4a 100644 --- a/82_Stars/csharp/Program.cs +++ b/82_Stars/csharp/Program.cs @@ -1,30 +1,7 @@ -using System; +using Games.Common.IO; +using Games.Common.Randomness; +using Stars; -namespace Stars -{ - class Program - { - static void Main(string[] args) - { - DisplayTitle(); +var game = new Game(new ConsoleIO(), new RandomNumberGenerator(), maxNumber: 100, maxGuessCount: 7); - var game = new Game(maxNumber: 100, maxGuessCount: 7); - - game.DisplayInstructions(); - - while (true) - { - game.Play(); - } - } - - private static void DisplayTitle() - { - Console.WriteLine(" Stars"); - Console.WriteLine(" Creative Computing Morristown, New Jersey"); - Console.WriteLine(); - Console.WriteLine(); - Console.WriteLine(); - } - } -} +game.Play(() => true); diff --git a/82_Stars/csharp/Resources/Instructions.txt b/82_Stars/csharp/Resources/Instructions.txt new file mode 100644 index 00000000..372c7809 --- /dev/null +++ b/82_Stars/csharp/Resources/Instructions.txt @@ -0,0 +1,6 @@ +I am thinking of a number between 1 and {0}. +Try to guess my number. After you guess, I +will type one or more stars (*). The more +stars I type, the closer you are to my number. +One star (*) means far away, seven stars (*******) +means really close! You get {1} guesses. \ No newline at end of file diff --git a/82_Stars/csharp/Resources/Resource.cs b/82_Stars/csharp/Resources/Resource.cs new file mode 100644 index 00000000..f3a6e47b --- /dev/null +++ b/82_Stars/csharp/Resources/Resource.cs @@ -0,0 +1,28 @@ +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace Stars.Resources; + +internal static class Resource +{ + internal static class Streams + { + public static Stream Title => GetStream(); + } + + internal static class Formats + { + public static string Instructions => GetString(); + } + + private static string GetString([CallerMemberName] string name = null) + { + using var stream = GetStream(name); + using var reader = new StreamReader(stream); + return reader.ReadToEnd(); + } + + private static Stream GetStream([CallerMemberName] string name = null) + => Assembly.GetExecutingAssembly().GetManifestResourceStream($"Stars.Resources.{name}.txt"); +} \ No newline at end of file diff --git a/82_Stars/csharp/Resources/Title.txt b/82_Stars/csharp/Resources/Title.txt new file mode 100644 index 00000000..67ccb545 --- /dev/null +++ b/82_Stars/csharp/Resources/Title.txt @@ -0,0 +1,5 @@ + Stars + Creative Computing Morristown, New Jersey + + + diff --git a/82_Stars/csharp/Stars.csproj b/82_Stars/csharp/Stars.csproj index 20827042..f8fe6e62 100644 --- a/82_Stars/csharp/Stars.csproj +++ b/82_Stars/csharp/Stars.csproj @@ -2,7 +2,15 @@ Exe - net5.0 + net6.0 + + + + + + + +