Complete game

This commit is contained in:
Andrew Cooper
2022-08-03 08:40:05 +10:00
parent aedfd73e8c
commit 572b9b3a69
8 changed files with 159 additions and 34 deletions

View File

@@ -1,36 +1,80 @@
namespace Digits
namespace Digits;
internal class GameSeries
{
internal class Game
private readonly IReadOnlyList<int> _weights = new List<int> { 0, 1, 3 }.AsReadOnly();
private readonly IReadWrite _io;
private readonly IRandom _random;
public GameSeries(IReadWrite io, IRandom random)
{
private readonly IReadWrite _io;
private readonly IRandom _random;
public Game(IReadWrite io, IRandom random)
{
_io = io;
_random = random;
}
internal void Play()
{
_io.Write(Streams.Introduction);
if (_io.ReadNumber(Prompts.ForInstructions) != 0)
{
_io.Write(Streams.Instructions);
}
do
{
PlayOne();
} while (_io.ReadNumber(Prompts.WantToTryAgain) == 1);
_io.Write(Streams.Thanks);
}
private void PlayOne()
{
}
_io = io;
_random = random;
}
}
internal void Play()
{
_io.Write(Streams.Introduction);
if (_io.ReadNumber(Prompts.ForInstructions) != 0)
{
_io.Write(Streams.Instructions);
}
do
{
new Game(_io, _random).Play();
} while (_io.ReadNumber(Prompts.WantToTryAgain) == 1);
_io.Write(Streams.Thanks);
}
}
internal class Game
{
private readonly IReadWrite _io;
private readonly Guesser _guesser;
public Game(IReadWrite io, IRandom random)
{
_io = io;
_guesser = new Guesser(random);
}
public void Play()
{
var correctGuesses = 0;
for (int round = 0; round < 3; round++)
{
var digits = _io.Read10Digits(Prompts.TenNumbers, Streams.TryAgain);
correctGuesses = GuessDigits(digits, correctGuesses);
}
_io.Write(correctGuesses switch
{
< 10 => Streams.YouWin,
10 => Streams.ItsATie,
> 10 => Streams.IWin
});
}
private int GuessDigits(IEnumerable<int> digits, int correctGuesses)
{
_io.Write(Streams.Headings);
foreach (var digit in digits)
{
var guess = _guesser.GuessNextDigit();
if (guess == digit) { correctGuesses++; }
_io.WriteLine(Formats.GuessResult, guess, digit, guess == digit ? "Right" : "Wrong", correctGuesses);
_guesser.ObserveActualDigit(digit);
}
return correctGuesses;
}
}

View File

@@ -0,0 +1,52 @@
namespace Digits;
internal class Guesser
{
private readonly IReadOnlyList<int> _weights = new List<int> { 0, 1, 3 }.AsReadOnly();
private readonly int[][,] _matrices = new[] { new int[3, 3], new int[9, 3], new int[27, 3] };
private readonly int[] _indices = new[] { 2, 8, 26 };
private readonly IRandom _random;
public Guesser(IRandom random)
{
_random = random;
for (int j = 0; j < 3; j++)
{
for (int i = 0; i < 3; i++) { _matrices[0][i, j] = 9; }
for (int i = 0; i < 9; i++) { _matrices[1][i, j] = i == 4 * j ? 2 : 3; }
for (int i = 0; i < 27; i++) { _matrices[2][i, j] = 1; }
}
}
public int GuessNextDigit()
{
var currentSum = 0;
var guess = 0;
for (int j = 0; j < 3; j++)
{
var sum = Enumerable.Range(0, 3).Aggregate((s, i) => s + GetWeightedValue(i, j));
if (sum > currentSum || _random.NextFloat() >= 0.5)
{
currentSum = sum;
guess = j;
}
}
return guess;
}
public void ObserveActualDigit(int digit)
{
for (int i = 0; i < 3; i++)
{
_matrices[i][_indices[i], digit]++;
}
_indices[2] = _indices[2] % 9 * 3 + digit;
_indices[1] = _indices[2] % 9;
_indices[0] = digit;
}
private int GetWeightedValue(int matrix, int row) => _weights[matrix] * _matrices[matrix][_indices[matrix], row];
}

View File

@@ -0,0 +1,20 @@
namespace Digits;
internal static class IOExtensions
{
internal static IEnumerable<int> Read10Digits(this IReadWrite io, string prompt, Stream retryText)
{
while (true)
{
var numbers = new float[10];
io.ReadNumbers(prompt, numbers);
if (numbers.All(n => n == 0 || n == 1 || n == 2))
{
return numbers.Select(n => (int)n);
}
io.Write(retryText);
}
}
}

View File

@@ -3,4 +3,4 @@ global using Games.Common.IO;
global using Games.Common.Randomness;
global using static Digits.Resources.Resource;
new Game(new ConsoleIO(), new RandomNumberGenerator()).Play();
new GameSeries(new ConsoleIO(), new RandomNumberGenerator()).Play();

View File

@@ -0,0 +1 @@
{0} {1} {2} {3}

View File

@@ -1 +1,3 @@
My guess Your no. Result No. right

View File

@@ -24,6 +24,11 @@ internal static class Resource
public static string WantToTryAgain => GetString();
}
internal static class Formats
{
public static string GuessResult => GetString();
}
private static string GetString([CallerMemberName] string? name = null)
{
using var stream = GetStream(name);

View File

@@ -1 +1,2 @@
Ten numbers, please