oecs-sharp/Game.TicTacToe/Systems/WinCheckSystem.cs

78 lines
2.0 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using OECS;
namespace Game.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 RunImpl(World world)
{
if (world.ReadSingleton<GameState>().Status != GameStatus.Playing)
return;
ref var state = ref world.GetSingleton<GameState>();
// Build a 3×3 grid of marks.
var grid = new Player[3, 3];
foreach (var iter in world.Select<Cell, Mark>())
{
grid[iter.Val1.Row, iter.Val1.Col] = iter.Val2.Player;
}
// Check rows.
for (int r = 0; r < 3; r++)
{
if (TryGetWinner(grid[r, 0], grid[r, 1], grid[r, 2], out var winner))
{
SetWinner(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(ref state, winner);
return;
}
}
// Check diagonals.
if (TryGetWinner(grid[0, 0], grid[1, 1], grid[2, 2], out var diag1))
{
SetWinner(ref state, diag1);
return;
}
if (TryGetWinner(grid[0, 2], grid[1, 1], grid[2, 0], out var diag2))
{
SetWinner(ref state, diag2);
return;
}
// Check draw.
if (state.MoveCount >= 9)
state.Status = GameStatus.Draw;
}
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(ref GameState state, Player winner)
{
state.Status = winner == Player.X ? GameStatus.XWon : GameStatus.OWon;
}
}