diff --git a/67_One_Check/csharp/Board.cs b/67_One_Check/csharp/Board.cs
new file mode 100644
index 00000000..2e68072d
--- /dev/null
+++ b/67_One_Check/csharp/Board.cs
@@ -0,0 +1,64 @@
+namespace OneCheck;
+
+internal class Board
+{
+ private readonly bool[][] _checkers;
+ private int _pieceCount;
+ private int _moveCount;
+
+ public Board()
+ {
+ _checkers =
+ Enumerable.Range(0, 8)
+ .Select(r => Enumerable.Range(0, 8)
+ .Select(c => r <= 1 || r >= 6 || c <= 1 || c >= 6).ToArray())
+ .ToArray();
+ _pieceCount = 48;
+ }
+
+ private bool this[int index]
+ {
+ get => _checkers[index / 8][index % 8];
+ set => _checkers[index / 8][index % 8] = value;
+ }
+
+ public bool PlayMove(IReadWrite io)
+ {
+ while (true)
+ {
+ var from = (int)io.ReadNumber(Prompts.From);
+ if (from == 0) { return false; }
+
+ var move = new Move { From = from - 1, To = (int)io.ReadNumber(Prompts.To) - 1 };
+
+ if (TryMove(move))
+ {
+ _moveCount++;
+ return true;
+ }
+
+ io.Write(Streams.IllegalMove);
+ }
+ }
+
+ public bool TryMove(Move move)
+ {
+ if (move.IsInRange && move.IsTwoSpacesDiagonally && IsPieceJumpingPieceToEmptySpace(move))
+ {
+ this[move.From] = false;
+ this[move.Jumped] = false;
+ this[move.To] = true;
+ _pieceCount--;
+ return true;
+ }
+
+ return false;
+ }
+
+ private bool IsPieceJumpingPieceToEmptySpace(Move move) => this[move.From] && this[move.Jumped] && !this[move.To];
+
+ public string GetReport() => string.Format(Formats.Results, _moveCount, _pieceCount);
+
+ public override string ToString() =>
+ string.Join(Environment.NewLine, _checkers.Select(r => string.Join(" ", r.Select(c => c ? " 1" : " 0"))));
+}
diff --git a/67_One_Check/csharp/Game.cs b/67_One_Check/csharp/Game.cs
new file mode 100644
index 00000000..d9e64e26
--- /dev/null
+++ b/67_One_Check/csharp/Game.cs
@@ -0,0 +1,45 @@
+namespace OneCheck;
+
+internal class Game
+{
+ private readonly IReadWrite _io;
+
+ public Game(IReadWrite io)
+ {
+ _io = io;
+ }
+
+ public void Play()
+ {
+ _io.Write(Streams.Introduction);
+
+ do
+ {
+ var board = new Board();
+ do
+ {
+ _io.WriteLine(board);
+ _io.WriteLine();
+ } while (board.PlayMove(_io));
+
+ _io.WriteLine(board.GetReport());
+ } while (_io.ReadYesNo(Prompts.TryAgain) == "yes");
+
+ _io.Write(Streams.Bye);
+ }
+}
+
+internal static class IOExtensions
+{
+ internal static string ReadYesNo(this IReadWrite io, string prompt)
+ {
+ while (true)
+ {
+ var response = io.ReadString(prompt).ToLower();
+
+ if (response == "yes" || response == "no") { return response; }
+
+ io.Write(Streams.YesOrNo);
+ }
+ }
+}
diff --git a/67_One_Check/csharp/Move.cs b/67_One_Check/csharp/Move.cs
new file mode 100644
index 00000000..0b48659e
--- /dev/null
+++ b/67_One_Check/csharp/Move.cs
@@ -0,0 +1,13 @@
+namespace OneCheck;
+
+internal class Move
+{
+ public int From { get; init; }
+ public int To { get; init; }
+ public int Jumped => (From + To) / 2;
+
+ public bool IsInRange => From >= 0 && From <= 63 && To >= 0 && To <= 63;
+ public bool IsTwoSpacesDiagonally => RowDelta == 2 && ColumnDelta == 2;
+ private int RowDelta => Math.Abs(From / 8 - To / 8);
+ private int ColumnDelta => Math.Abs(From % 8 - To % 8);
+}
\ No newline at end of file
diff --git a/67_One_Check/csharp/OneCheck.csproj b/67_One_Check/csharp/OneCheck.csproj
index d3fe4757..3870320c 100644
--- a/67_One_Check/csharp/OneCheck.csproj
+++ b/67_One_Check/csharp/OneCheck.csproj
@@ -6,4 +6,12 @@
enable
enable
+
+
+
+
+
+
+
+
diff --git a/67_One_Check/csharp/Program.cs b/67_One_Check/csharp/Program.cs
new file mode 100644
index 00000000..4a3ab83b
--- /dev/null
+++ b/67_One_Check/csharp/Program.cs
@@ -0,0 +1,5 @@
+global using Games.Common.IO;
+global using static OneCheck.Resources.Resource;
+using OneCheck;
+
+new Game(new ConsoleIO()).Play();
diff --git a/67_One_Check/csharp/Resources/Bye.txt b/67_One_Check/csharp/Resources/Bye.txt
new file mode 100644
index 00000000..ee4ddab1
--- /dev/null
+++ b/67_One_Check/csharp/Resources/Bye.txt
@@ -0,0 +1,2 @@
+
+O.K. Hope you had fun!!
\ No newline at end of file
diff --git a/67_One_Check/csharp/Resources/From.txt b/67_One_Check/csharp/Resources/From.txt
new file mode 100644
index 00000000..bb4c7a2d
--- /dev/null
+++ b/67_One_Check/csharp/Resources/From.txt
@@ -0,0 +1 @@
+Jump from
\ No newline at end of file
diff --git a/67_One_Check/csharp/Resources/IllegalMove.txt b/67_One_Check/csharp/Resources/IllegalMove.txt
new file mode 100644
index 00000000..a96b6e81
--- /dev/null
+++ b/67_One_Check/csharp/Resources/IllegalMove.txt
@@ -0,0 +1 @@
+Illegal move. Try again...
\ No newline at end of file
diff --git a/67_One_Check/csharp/Resources/Introduction.txt b/67_One_Check/csharp/Resources/Introduction.txt
new file mode 100644
index 00000000..409f6b37
--- /dev/null
+++ b/67_One_Check/csharp/Resources/Introduction.txt
@@ -0,0 +1,30 @@
+ One Check
+ Creative Computing Morristown, New Jersey
+
+
+
+Solitaire checker puzzle by David Ahl
+
+48 checkers and placed on the 2 outside spaces of a
+standard 64-square checkerboard. The object is to
+remove as many checkers as possible by diagonal jumps
+(as in standard checkers). Use the numbered board to
+indicate the square you wish to jump from and to. On
+the board printed out on each turn '1' indicates a
+checker and '0' an empty square. When you have no
+possible jumps remaining, input a '0' in response to
+question 'Jump from ?'
+
+Here is the numerical board:
+
+ 1 2 3 4 5 6 7 8
+ 9 10 11 12 13 14 15 16
+ 17 18 19 20 21 22 23 24
+ 25 26 27 28 29 30 31 32
+ 33 34 35 36 37 38 39 40
+ 41 42 43 44 45 46 47 48
+ 49 50 51 52 53 54 55 56
+ 57 58 59 60 61 62 63 64
+
+And here is the opening position of the checkers.
+
diff --git a/67_One_Check/csharp/Resources/Resource.cs b/67_One_Check/csharp/Resources/Resource.cs
new file mode 100644
index 00000000..7095d7ec
--- /dev/null
+++ b/67_One_Check/csharp/Resources/Resource.cs
@@ -0,0 +1,45 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+namespace OneCheck.Resources;
+
+internal static class Resource
+{
+ internal static class Streams
+ {
+ public static Stream Introduction => GetStream();
+ public static Stream IllegalMove => GetStream();
+ public static Stream YesOrNo => GetStream();
+ public static Stream Bye => GetStream();
+ }
+
+ internal static class Formats
+ {
+ public static string Results => GetString();
+ }
+
+ internal static class Prompts
+ {
+ public static string From => GetString();
+ public static string To => GetString();
+ public static string TryAgain => GetString();
+ }
+
+ internal static class Strings
+ {
+ public static string TooManyColumns => GetString();
+ public static string TooManyRows => 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/67_One_Check/csharp/Resources/Results.txt b/67_One_Check/csharp/Resources/Results.txt
new file mode 100644
index 00000000..a8771b6b
--- /dev/null
+++ b/67_One_Check/csharp/Resources/Results.txt
@@ -0,0 +1,3 @@
+
+You made {0} jumps and had {1} pieces
+remaining on the board.
diff --git a/67_One_Check/csharp/Resources/To.txt b/67_One_Check/csharp/Resources/To.txt
new file mode 100644
index 00000000..788636ff
--- /dev/null
+++ b/67_One_Check/csharp/Resources/To.txt
@@ -0,0 +1 @@
+to
\ No newline at end of file
diff --git a/67_One_Check/csharp/Resources/TryAgain.txt b/67_One_Check/csharp/Resources/TryAgain.txt
new file mode 100644
index 00000000..c65e51fc
--- /dev/null
+++ b/67_One_Check/csharp/Resources/TryAgain.txt
@@ -0,0 +1 @@
+Try again
\ No newline at end of file
diff --git a/67_One_Check/csharp/Resources/YesOrNo.txt b/67_One_Check/csharp/Resources/YesOrNo.txt
new file mode 100644
index 00000000..703d4ad6
--- /dev/null
+++ b/67_One_Check/csharp/Resources/YesOrNo.txt
@@ -0,0 +1 @@
+Please answer 'Yes' or 'No'.
\ No newline at end of file