using Game.TicTacToe;
using OECS;
using System.Text;
namespace Game.TicTacToe.Tests;
internal static class TestHelpers
{
///
/// Creates a fresh TicTacToe world with 9 empty cells, GameState singleton, and WinCheckSystem.
///
public static (World World, SystemGroup Group) SetupGame()
{
var world = new World();
var group = new SystemGroup(world);
group.Add(new WinCheckSystem());
for (int r = 0; r < 3; r++)
for (int c = 0; c < 3; c++)
world.AddComponent(world.CreateEntity(), new Cell { Row = r, Col = c });
world.SetSingleton(new GameState
{
CurrentPlayer = Player.X,
Status = GameStatus.Playing,
MoveCount = 0
});
world.PostChanges();
return (world, group);
}
///
/// Enqueues and runs a sequence of moves.
///
public static void PlayMoves(World world, SystemGroup group, params (int Row, int Col)[] moves)
{
foreach (var (row, col) in moves)
{
world.Commands.Enqueue(new PlaceMarkCommand { Row = row, Col = col });
group.RunLogical();
}
}
///
/// Returns a human-readable textual snapshot of the world state.
///
public static string SnapshotWorld(World world)
{
var sb = new StringBuilder();
var state = world.ReadSingleton();
var statusText = state.Status switch
{
GameStatus.Playing => $"{(state.CurrentPlayer == Player.X ? 'X' : 'O')}'s turn, {state.MoveCount} moves",
GameStatus.XWon => "XWon",
GameStatus.OWon => "OWon",
GameStatus.Draw => "Draw",
_ => "Unknown"
};
sb.AppendLine($"GameState: {statusText}");
var grid = new char?[3, 3];
foreach (var it in world.Select())
grid[it.Val1.Row, it.Val1.Col] =
it.Val2.Player == Player.X ? 'X' : 'O';
int totalCells = 0;
int markedCells = 0;
for (int r = 0; r < 3; r++)
{
for (int c = 0; c < 3; c++)
{
totalCells++;
var mark = grid[r, c];
if (mark.HasValue)
{
markedCells++;
sb.AppendLine($" ({r},{c}): {mark.Value}");
}
else
{
sb.AppendLine($" ({r},{c}): .");
}
}
}
sb.AppendLine($"Cells: {totalCells} total, {markedCells} marked");
return sb.ToString().TrimEnd();
}
///
/// Returns the (Row, Col) of all empty cells.
///
public static List<(int Row, int Col)> GetEmptyCells(World world)
{
var empty = new List<(int, int)>();
foreach (var it in world.Select(new Query().Without()))
empty.Add((it.Val1.Row, it.Val1.Col));
return empty;
}
///
/// Checks whether placing a mark at (row, col) for the given player would win the game.
///
public static bool WouldWin(World world, int row, int col, Player player)
{
var grid = new Player[3, 3];
foreach (var it in world.Select| ())
grid[it.Val1.Row, it.Val1.Col] = it.Val2.Player;
grid[row, col] = player;
for (int r = 0; r < 3; r++)
if (grid[r, 0] == player && grid[r, 1] == player && grid[r, 2] == player)
return true;
for (int c = 0; c < 3; c++)
if (grid[0, c] == player && grid[1, c] == player && grid[2, c] == player)
return true;
if (grid[0, 0] == player && grid[1, 1] == player && grid[2, 2] == player)
return true;
if (grid[0, 2] == player && grid[1, 1] == player && grid[2, 0] == player)
return true;
return false;
}
} | | |