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
+
+
+
+
+
+
+
+