Initial commit: terminal Minesweeper in C# for .NET 10
A playable console Minesweeper (arrow keys, chording, flags, question marks, pause, difficulty presets) plus a deduction-and-guess solver that can play the game headlessly. Game logic lives in src/Minesweeper/Game and has no console dependencies, so it is covered by 65 unit tests. Includes publishing helpers for self-contained, trimmed single-file binaries (publish.sh) and an .editorconfig that the sources conform to: UTF-8 BOM and 4-space indents for C#, 2-space indents for project files, LF endings and 2-space indents for shell scripts, System-first usings, no redundant `this.`, and s_/ _ prefixed private static and instance fields.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
using Minesweeper.Cli;
|
||||
using Minesweeper.Game;
|
||||
using Xunit;
|
||||
|
||||
namespace Minesweeper.Tests;
|
||||
|
||||
public class CommandLineTests
|
||||
{
|
||||
[Fact]
|
||||
public void DefaultsAreBeginner()
|
||||
{
|
||||
Assert.True(CommandLine.TryParse([], out var options, out var errors, out var help));
|
||||
Assert.Empty(errors);
|
||||
Assert.False(help);
|
||||
Assert.Equal(DifficultyProfile.Beginner, options.Difficulty);
|
||||
Assert.True(options.ReserveSafeZone);
|
||||
Assert.True(options.QuestionMarks);
|
||||
Assert.False(options.Auto);
|
||||
Assert.Null(options.Seed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PresetAndCustomSizesCombine()
|
||||
{
|
||||
Assert.True(CommandLine.TryParse(["-d", "expert"], out var options, out _, out _));
|
||||
Assert.Equal(30, options.Difficulty.Width);
|
||||
Assert.Equal(99, options.Difficulty.Mines);
|
||||
|
||||
Assert.True(CommandLine.TryParse(["--size", "12x8", "--mines", "5"], out options, out _, out _));
|
||||
Assert.Equal((12, 8, 5), (options.Difficulty.Width, options.Difficulty.Height, options.Difficulty.Mines));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SwitchesAreHonoured()
|
||||
{
|
||||
Assert.True(CommandLine.TryParse(
|
||||
["--auto-trace", "--seed", "42", "--no-safe-zone", "--no-question-marks", "--compact", "--ascii", "--no-color"],
|
||||
out var options, out var errors, out _));
|
||||
|
||||
Assert.Empty(errors);
|
||||
Assert.True(options.Auto);
|
||||
Assert.True(options.AutoTrace);
|
||||
Assert.Equal(42, options.Seed);
|
||||
Assert.False(options.ReserveSafeZone);
|
||||
Assert.False(options.QuestionMarks);
|
||||
Assert.True(options.Compact);
|
||||
Assert.True(options.Ascii);
|
||||
Assert.False(options.Color);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HelpShortCircuitsEverythingElse()
|
||||
{
|
||||
Assert.True(CommandLine.TryParse(["--help"], out _, out var errors, out var help));
|
||||
Assert.True(help);
|
||||
Assert.Empty(errors);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new[] { "--nope" }, "Unknown option")]
|
||||
[InlineData(new[] { "--seed" }, "needs a value")]
|
||||
[InlineData(new[] { "--seed", "abc" }, "expects a whole number")]
|
||||
[InlineData(new[] { "-d", "impossible" }, "Unknown difficulty")]
|
||||
[InlineData(new[] { "--size", "9x9", "--mines", "900" }, "do not leave a safe square")]
|
||||
[InlineData(new[] { "--auto-max-steps", "0" }, "expects a positive number")]
|
||||
public void MistakesAreReported(string[] args, string expectedFragment)
|
||||
{
|
||||
Assert.False(CommandLine.TryParse(args, out _, out var errors, out _));
|
||||
Assert.Contains(errors, error => error.Contains(expectedFragment, StringComparison.Ordinal));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user