mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2026-07-03 11:24:52 -07:00
Merge pull request #787 from drewjcooper/csharp-67-one-check
C# 67 one check
This commit is contained in:
@@ -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"))));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -6,4 +6,12 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources/*.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\00_Common\dotnet\Games.Common\Games.Common.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
global using Games.Common.IO;
|
||||
global using static OneCheck.Resources.Resource;
|
||||
using OneCheck;
|
||||
|
||||
new Game(new ConsoleIO()).Play();
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
O.K. Hope you had fun!!
|
||||
@@ -0,0 +1 @@
|
||||
Jump from
|
||||
@@ -0,0 +1 @@
|
||||
Illegal move. Try again...
|
||||
@@ -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.
|
||||
|
||||
@@ -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}'.");
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
You made {0} jumps and had {1} pieces
|
||||
remaining on the board.
|
||||
@@ -0,0 +1 @@
|
||||
to
|
||||
@@ -0,0 +1 @@
|
||||
Try again
|
||||
@@ -0,0 +1 @@
|
||||
Please answer 'Yes' or 'No'.
|
||||
Reference in New Issue
Block a user