2026-07-18 20:43:13 +08:00
|
|
|
|
using OECS;
|
|
|
|
|
|
|
|
|
|
|
|
namespace TicTacToe;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// After each move, checks whether the game has been won or drawn.
|
|
|
|
|
|
/// Updates the GameState singleton accordingly.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class WinCheckSystem : ISystem
|
|
|
|
|
|
{
|
|
|
|
|
|
public void Run(World world)
|
|
|
|
|
|
{
|
|
|
|
|
|
ref var state = ref world.GetSingleton<GameState>();
|
|
|
|
|
|
|
|
|
|
|
|
if (state.Status != GameStatus.Playing)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2026-07-18 21:22:23 +08:00
|
|
|
|
// Build a 3×3 grid of marks using the iterator API.
|
2026-07-18 20:43:13 +08:00
|
|
|
|
var grid = new Player[3, 3];
|
|
|
|
|
|
|
2026-07-18 22:27:14 +08:00
|
|
|
|
using var iter = world.Select<Cell, Mark>();
|
2026-07-18 21:22:23 +08:00
|
|
|
|
while (iter.MoveNext())
|
2026-07-18 20:43:13 +08:00
|
|
|
|
{
|
2026-07-18 21:22:23 +08:00
|
|
|
|
grid[iter.Current1.Row, iter.Current1.Col] = iter.Current2.Player;
|
|
|
|
|
|
}
|
2026-07-18 20:43:13 +08:00
|
|
|
|
|
|
|
|
|
|
// Check rows.
|
|
|
|
|
|
for (int r = 0; r < 3; r++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (TryGetWinner(grid[r, 0], grid[r, 1], grid[r, 2], out var winner))
|
|
|
|
|
|
{
|
|
|
|
|
|
SetWinner(world, ref state, winner);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check columns.
|
|
|
|
|
|
for (int c = 0; c < 3; c++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (TryGetWinner(grid[0, c], grid[1, c], grid[2, c], out var winner))
|
|
|
|
|
|
{
|
|
|
|
|
|
SetWinner(world, ref state, winner);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check diagonals.
|
|
|
|
|
|
if (TryGetWinner(grid[0, 0], grid[1, 1], grid[2, 2], out var diag1))
|
|
|
|
|
|
{
|
|
|
|
|
|
SetWinner(world, ref state, diag1);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (TryGetWinner(grid[0, 2], grid[1, 1], grid[2, 0], out var diag2))
|
|
|
|
|
|
{
|
|
|
|
|
|
SetWinner(world, ref state, diag2);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check draw.
|
|
|
|
|
|
if (state.MoveCount >= 9)
|
|
|
|
|
|
{
|
|
|
|
|
|
state.Status = GameStatus.Draw;
|
|
|
|
|
|
world.MarkModified<GameState>(World.SingletonEntity);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static bool TryGetWinner(Player a, Player b, Player c, out Player winner)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (a != Player.None && a == b && b == c)
|
|
|
|
|
|
{
|
|
|
|
|
|
winner = a;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
winner = Player.None;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void SetWinner(World world, ref GameState state, Player winner)
|
|
|
|
|
|
{
|
|
|
|
|
|
state.Status = winner == Player.X ? GameStatus.XWon : GameStatus.OWon;
|
|
|
|
|
|
world.MarkModified<GameState>(World.SingletonEntity);
|
|
|
|
|
|
}
|
2026-07-18 22:22:52 +08:00
|
|
|
|
}
|