diff --git a/41_Guess/csharp/Game.cs b/41_Guess/csharp/Game.cs
new file mode 100644
index 00000000..57ae071a
--- /dev/null
+++ b/41_Guess/csharp/Game.cs
@@ -0,0 +1,78 @@
+namespace Guess;
+
+internal class Game
+{
+ private readonly IReadWrite _io;
+ private readonly IRandom _random;
+
+ public Game(IReadWrite io, IRandom random)
+ {
+ _io = io;
+ _random = random;
+ }
+
+ public void Play()
+ {
+ while (true)
+ {
+ _io.Write(Streams.Introduction);
+
+ var limit = _io.ReadNumber(Prompts.Limit);
+ _io.WriteLine();
+
+ // There's a bug here that exists in the original code.
+ // If the limit entered is <= 0 then the program will crash.
+ var targetGuessCount = checked((int)Math.Log2(limit) + 1);
+
+ PlayGuessingRounds(limit, targetGuessCount);
+
+ _io.Write(Streams.BlankLines);
+ }
+ }
+
+ private void PlayGuessingRounds(float limit, int targetGuessCount)
+ {
+ while (true)
+ {
+ _io.WriteLine(Formats.Thinking, limit);
+
+ // There's a bug here that exists in the original code. If a non-integer is entered as the limit
+ // then it's possible for the secret number to be the next integer greater than the limit.
+ var secretNumber = (int)_random.NextFloat(limit) + 1;
+
+ var guessCount = 0;
+
+ while (true)
+ {
+ var guess = _io.ReadNumber("");
+ if (guess <= 0) { return; }
+ guessCount++;
+ if (IsGuessCorrect(guess, secretNumber)) { break; }
+ }
+
+ ReportResult(guessCount, targetGuessCount);
+
+ _io.Write(Streams.BlankLines);
+ }
+ }
+
+ private bool IsGuessCorrect(float guess, int secretNumber)
+ {
+ if (guess < secretNumber) { _io.Write(Streams.TooLow); }
+ if (guess > secretNumber) { _io.Write(Streams.TooHigh); }
+
+ return guess == secretNumber;
+ }
+
+ private void ReportResult(int guessCount, int targetGuessCount)
+ {
+ _io.WriteLine(Formats.ThatsIt, guessCount);
+ _io.WriteLine(
+ (guessCount - targetGuessCount) switch
+ {
+ < 0 => Strings.VeryGood,
+ 0 => Strings.Good,
+ > 0 => string.Format(Formats.ShouldHave, targetGuessCount)
+ });
+ }
+}
\ No newline at end of file
diff --git a/41_Guess/csharp/Guess.csproj b/41_Guess/csharp/Guess.csproj
index d3fe4757..3870320c 100644
--- a/41_Guess/csharp/Guess.csproj
+++ b/41_Guess/csharp/Guess.csproj
@@ -6,4 +6,12 @@
enable
enable
+
+
+
+
+
+
+
+
diff --git a/41_Guess/csharp/Program.cs b/41_Guess/csharp/Program.cs
new file mode 100644
index 00000000..73ab09dd
--- /dev/null
+++ b/41_Guess/csharp/Program.cs
@@ -0,0 +1,7 @@
+global using Games.Common.IO;
+global using Games.Common.Randomness;
+global using static Guess.Resources.Resource;
+
+using Guess;
+
+new Game(new ConsoleIO(), new RandomNumberGenerator()).Play();
diff --git a/41_Guess/csharp/Resources/BlankLines.txt b/41_Guess/csharp/Resources/BlankLines.txt
new file mode 100644
index 00000000..3f2ff2d6
--- /dev/null
+++ b/41_Guess/csharp/Resources/BlankLines.txt
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/41_Guess/csharp/Resources/Good.txt b/41_Guess/csharp/Resources/Good.txt
new file mode 100644
index 00000000..989dfa38
--- /dev/null
+++ b/41_Guess/csharp/Resources/Good.txt
@@ -0,0 +1 @@
+Good.
\ No newline at end of file
diff --git a/41_Guess/csharp/Resources/Introduction.txt b/41_Guess/csharp/Resources/Introduction.txt
new file mode 100644
index 00000000..ed679492
--- /dev/null
+++ b/41_Guess/csharp/Resources/Introduction.txt
@@ -0,0 +1,9 @@
+ Guess
+ Creative Computing Morristown, New Jersey
+
+
+
+This is a number guessing game. I'll think
+of a number between 1 and any limit you want.
+The you have to guess what it is.
+
diff --git a/41_Guess/csharp/Resources/Limit.txt b/41_Guess/csharp/Resources/Limit.txt
new file mode 100644
index 00000000..62e698a6
--- /dev/null
+++ b/41_Guess/csharp/Resources/Limit.txt
@@ -0,0 +1 @@
+What limit do you want
\ No newline at end of file
diff --git a/41_Guess/csharp/Resources/Resource.cs b/41_Guess/csharp/Resources/Resource.cs
new file mode 100644
index 00000000..d42477e2
--- /dev/null
+++ b/41_Guess/csharp/Resources/Resource.cs
@@ -0,0 +1,44 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+namespace Guess.Resources;
+
+internal static class Resource
+{
+ internal static class Streams
+ {
+ public static Stream Introduction => GetStream();
+ public static Stream TooLow => GetStream();
+ public static Stream TooHigh => GetStream();
+ public static Stream BlankLines => GetStream();
+ }
+
+ internal static class Formats
+ {
+ public static string Thinking => GetString();
+ public static string ThatsIt => GetString();
+ public static string ShouldHave => GetString();
+ }
+
+ internal static class Prompts
+ {
+ public static string Limit => GetString();
+ }
+
+ internal static class Strings
+ {
+ public static string Good => GetString();
+ public static string VeryGood => 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($"{typeof(Resource).Namespace}.{name}.txt")
+ ?? throw new Exception($"Could not find embedded resource stream '{name}'.");
+}
\ No newline at end of file
diff --git a/41_Guess/csharp/Resources/ShouldHave.txt b/41_Guess/csharp/Resources/ShouldHave.txt
new file mode 100644
index 00000000..84803588
--- /dev/null
+++ b/41_Guess/csharp/Resources/ShouldHave.txt
@@ -0,0 +1 @@
+You should have been able to get it in only {0}
\ No newline at end of file
diff --git a/41_Guess/csharp/Resources/ThatsIt.txt b/41_Guess/csharp/Resources/ThatsIt.txt
new file mode 100644
index 00000000..61f78c43
--- /dev/null
+++ b/41_Guess/csharp/Resources/ThatsIt.txt
@@ -0,0 +1 @@
+That's it! You got it in {0} tries.
\ No newline at end of file
diff --git a/41_Guess/csharp/Resources/Thinking.txt b/41_Guess/csharp/Resources/Thinking.txt
new file mode 100644
index 00000000..8f1bbac7
--- /dev/null
+++ b/41_Guess/csharp/Resources/Thinking.txt
@@ -0,0 +1,2 @@
+I'm thinking of a number between 1 and {0}
+Now you try to guess what it is.
\ No newline at end of file
diff --git a/41_Guess/csharp/Resources/TooHigh.txt b/41_Guess/csharp/Resources/TooHigh.txt
new file mode 100644
index 00000000..bb4ee4ed
--- /dev/null
+++ b/41_Guess/csharp/Resources/TooHigh.txt
@@ -0,0 +1 @@
+Too high. Try a smaller answer.
\ No newline at end of file
diff --git a/41_Guess/csharp/Resources/TooLow.txt b/41_Guess/csharp/Resources/TooLow.txt
new file mode 100644
index 00000000..4bc1776f
--- /dev/null
+++ b/41_Guess/csharp/Resources/TooLow.txt
@@ -0,0 +1 @@
+Too low. Try a bigger answer.
\ No newline at end of file
diff --git a/41_Guess/csharp/Resources/VeryGood.txt b/41_Guess/csharp/Resources/VeryGood.txt
new file mode 100644
index 00000000..606150c7
--- /dev/null
+++ b/41_Guess/csharp/Resources/VeryGood.txt
@@ -0,0 +1 @@
+Very good.
\ No newline at end of file