mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2026-02-04 11:07:59 -08:00
Update 62_Mugwump
This commit is contained in:
@@ -2,7 +2,11 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\00_Common\dotnet\Games.Common\Games.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
13
62_Mugwump/csharp/Distance.cs
Normal file
13
62_Mugwump/csharp/Distance.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Mugwump;
|
||||
|
||||
internal struct Distance
|
||||
{
|
||||
private readonly float _value;
|
||||
|
||||
public Distance(float deltaX, float deltaY)
|
||||
{
|
||||
_value = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
}
|
||||
|
||||
public override string ToString() => _value.ToString("0.0");
|
||||
}
|
||||
@@ -1,36 +1,55 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Mugwump
|
||||
namespace Mugwump;
|
||||
|
||||
internal class Game
|
||||
{
|
||||
internal class Game
|
||||
private readonly TextIO _io;
|
||||
private readonly IRandom _random;
|
||||
|
||||
internal Game(TextIO io, IRandom random)
|
||||
{
|
||||
private readonly Grid _grid;
|
||||
_io = io;
|
||||
_random = random;
|
||||
}
|
||||
|
||||
private Game(Random random)
|
||||
internal void Play(Func<bool> playAgain = null)
|
||||
{
|
||||
DisplayIntro();
|
||||
|
||||
while (playAgain?.Invoke() ?? true)
|
||||
{
|
||||
_grid = new Grid(Enumerable.Range(1, 4).Select(id => new Mugwump(id, random.Next(10), random.Next(10))));
|
||||
}
|
||||
Play(new Grid(_io, _random));
|
||||
|
||||
public static void Play(Random random) => new Game(random).Play();
|
||||
|
||||
private void Play()
|
||||
{
|
||||
for (int turn = 1; turn <= 10; turn++)
|
||||
{
|
||||
var guess = Input.ReadGuess($"Turn no. {turn} -- what is your guess");
|
||||
|
||||
if (_grid.Check(guess))
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"You got them all in {turn} turns!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Sorry, that's 10 tries. Here is where they're hiding:");
|
||||
_grid.Reveal();
|
||||
_io.WriteLine();
|
||||
_io.WriteLine("That was fun! Let's play again.......");
|
||||
_io.WriteLine("Four more mugwumps are now in hiding.");
|
||||
}
|
||||
}
|
||||
|
||||
private void DisplayIntro()
|
||||
{
|
||||
using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Mugwump.Strings.Intro.txt");
|
||||
|
||||
_io.Write(stream);
|
||||
}
|
||||
|
||||
private void Play(Grid grid)
|
||||
{
|
||||
for (int turn = 1; turn <= 10; turn++)
|
||||
{
|
||||
var guess = _io.ReadGuess($"Turn no. {turn} -- what is your guess");
|
||||
|
||||
if (grid.Check(guess))
|
||||
{
|
||||
_io.WriteLine();
|
||||
_io.WriteLine($"You got them all in {turn} turns!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_io.WriteLine();
|
||||
_io.WriteLine("Sorry, that's 10 tries. Here is where they're hiding:");
|
||||
grid.Reveal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Mugwump
|
||||
namespace Mugwump;
|
||||
|
||||
internal class Grid
|
||||
{
|
||||
internal class Grid
|
||||
private readonly TextIO _io;
|
||||
private readonly List<Mugwump> _mugwumps;
|
||||
|
||||
public Grid(TextIO io, IRandom random)
|
||||
{
|
||||
private readonly List<Mugwump> _mugwumps;
|
||||
_io = io;
|
||||
_mugwumps = Enumerable.Range(1, 4).Select(id => new Mugwump(id, random.NextPosition(10, 10))).ToList();
|
||||
}
|
||||
|
||||
public Grid(IEnumerable<Mugwump> mugwumps)
|
||||
public bool Check(Position guess)
|
||||
{
|
||||
foreach (var mugwump in _mugwumps.ToList())
|
||||
{
|
||||
_mugwumps = mugwumps.ToList();
|
||||
var (found, distance) = mugwump.FindFrom(guess);
|
||||
|
||||
_io.WriteLine(found ? $"You have found {mugwump}" : $"You are {distance} units from {mugwump}");
|
||||
if (found)
|
||||
{
|
||||
_mugwumps.Remove(mugwump);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Check(Position guess)
|
||||
return _mugwumps.Count == 0;
|
||||
}
|
||||
|
||||
public void Reveal()
|
||||
{
|
||||
foreach (var mugwump in _mugwumps)
|
||||
{
|
||||
foreach (var mugwump in _mugwumps.ToList())
|
||||
{
|
||||
var (found, distance) = mugwump.FindFrom(guess);
|
||||
|
||||
Console.WriteLine(found ? $"You have found {mugwump}" : $"You are {distance} units from {mugwump}");
|
||||
if (found)
|
||||
{
|
||||
_mugwumps.Remove(mugwump);
|
||||
}
|
||||
}
|
||||
|
||||
return _mugwumps.Count == 0;
|
||||
}
|
||||
|
||||
public void Reveal()
|
||||
{
|
||||
foreach (var mugwump in _mugwumps.ToList())
|
||||
{
|
||||
Console.WriteLine(mugwump.Reveal());
|
||||
}
|
||||
_io.WriteLine(mugwump.Reveal());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
7
62_Mugwump/csharp/IRandomExtensions.cs
Normal file
7
62_Mugwump/csharp/IRandomExtensions.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Mugwump;
|
||||
|
||||
internal static class IRandomExtensions
|
||||
{
|
||||
internal static Position NextPosition(this IRandom random, int maxX, int maxY) =>
|
||||
new(random.Next(maxX), random.Next(maxY));
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mugwump
|
||||
{
|
||||
// Provides input methods which emulate the BASIC interpreter's keyboard input routines
|
||||
internal static class Input
|
||||
{
|
||||
internal static Position ReadGuess(string prompt)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
var input = ReadNumbers(prompt, 2);
|
||||
return new Position(input[0], input[1]);
|
||||
}
|
||||
|
||||
private static void Prompt(string text = "") => Console.Write($"{text}? ");
|
||||
|
||||
private static List<float> ReadNumbers(string prompt, int requiredCount)
|
||||
{
|
||||
var numbers = new List<float>();
|
||||
|
||||
while (!TryReadNumbers(prompt, requiredCount, numbers))
|
||||
{
|
||||
prompt = "";
|
||||
}
|
||||
|
||||
return numbers;
|
||||
}
|
||||
|
||||
private static bool TryReadNumbers(string prompt, int requiredCount, List<float> numbers)
|
||||
{
|
||||
Prompt(prompt);
|
||||
var inputValues = ReadStrings();
|
||||
|
||||
foreach (var value in inputValues)
|
||||
{
|
||||
if (numbers.Count == requiredCount)
|
||||
{
|
||||
Console.WriteLine("!Extra input ingored");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!TryParseNumber(value, out var number))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
numbers.Add(number);
|
||||
}
|
||||
|
||||
return numbers.Count == requiredCount || TryReadNumbers("?", requiredCount, numbers);
|
||||
}
|
||||
|
||||
private static string[] ReadStrings() => Console.ReadLine().Split(',', StringSplitOptions.TrimEntries);
|
||||
|
||||
private static bool TryParseNumber(string text, out float number)
|
||||
{
|
||||
if (float.TryParse(text, out number)) { return true; }
|
||||
|
||||
Console.WriteLine("!Number expected - retry input line");
|
||||
number = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,19 @@
|
||||
namespace Mugwump
|
||||
namespace Mugwump;
|
||||
|
||||
internal class Mugwump
|
||||
{
|
||||
internal class Mugwump
|
||||
private readonly int _id;
|
||||
private readonly Position _position;
|
||||
|
||||
public Mugwump(int id, Position position)
|
||||
{
|
||||
private readonly int _id;
|
||||
private readonly Position _position;
|
||||
|
||||
public Mugwump(int id, int x, int y)
|
||||
{
|
||||
_id = id;
|
||||
_position = new Position(x, y);
|
||||
}
|
||||
|
||||
public (bool, Distance) FindFrom(Position guess) => (guess == _position, guess - _position);
|
||||
|
||||
public string Reveal() => $"{this} is at {_position}";
|
||||
|
||||
public override string ToString() => $"Mugwump {_id}";
|
||||
_id = id;
|
||||
_position = position;
|
||||
}
|
||||
|
||||
public (bool, Distance) FindFrom(Position guess) => (guess == _position, guess - _position);
|
||||
|
||||
public string Reveal() => $"{this} is at {_position}";
|
||||
|
||||
public override string ToString() => $"Mugwump {_id}";
|
||||
}
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Strings\Intro.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\00_Common\dotnet\Games.Common\Games.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Mugwump
|
||||
{
|
||||
internal class Distance
|
||||
{
|
||||
private readonly float _value;
|
||||
|
||||
public Distance(float deltaX, float deltaY)
|
||||
{
|
||||
_value = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
}
|
||||
|
||||
public override string ToString() => $"{_value:0.0}";
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace Mugwump
|
||||
{
|
||||
internal record Position(float X, float Y)
|
||||
{
|
||||
public override string ToString() => $"( {X} , {Y} )";
|
||||
namespace Mugwump;
|
||||
|
||||
public static Distance operator -(Position p1, Position p2) => new(p1.X - p2.X, p1.Y - p2.Y);
|
||||
}
|
||||
internal record struct Position(float X, float Y)
|
||||
{
|
||||
public override string ToString() => $"( {X} , {Y} )";
|
||||
|
||||
public static Distance operator -(Position p1, Position p2) => new(p1.X - p2.X, p1.Y - p2.Y);
|
||||
}
|
||||
|
||||
@@ -1,33 +1,12 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
global using System;
|
||||
global using Games.Common.IO;
|
||||
global using Games.Common.Randomness;
|
||||
|
||||
namespace Mugwump
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
DisplayIntro();
|
||||
using Mugwump;
|
||||
|
||||
var random = new Random();
|
||||
var random = new RandomNumberGenerator();
|
||||
var io = new ConsoleIO();
|
||||
|
||||
while (true)
|
||||
{
|
||||
Game.Play(random);
|
||||
var game = new Game(io, random);
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("That was fun! Let's play again.......");
|
||||
Console.WriteLine("Four more mugwumps are now in hiding.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void DisplayIntro()
|
||||
{
|
||||
using var stream = Assembly.GetExecutingAssembly()
|
||||
.GetManifestResourceStream("Mugwump.Strings.Intro.txt");
|
||||
using var stdout = Console.OpenStandardOutput();
|
||||
|
||||
stream.CopyTo(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
game.Play();
|
||||
|
||||
13
62_Mugwump/csharp/TextIOExtensions.cs
Normal file
13
62_Mugwump/csharp/TextIOExtensions.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Mugwump;
|
||||
|
||||
// Provides input methods which emulate the BASIC interpreter's keyboard input routines
|
||||
internal static class TextIOExtensions
|
||||
{
|
||||
internal static Position ReadGuess(this TextIO io, string prompt)
|
||||
{
|
||||
io.WriteLine();
|
||||
io.WriteLine();
|
||||
var (x, y) = io.Read2Numbers(prompt);
|
||||
return new Position(x, y);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user