refactor: update iterator access and simplify loops
Refactor code to use `Val1` and `Val2` instead of `Item1` and `Item2` for iterator access. Simplify `PlaceMarkCommand` and `WinCheckSystem` by replacing `while` loops with `foreach` and removing redundant comments.
This commit is contained in:
parent
52e1e8fdc9
commit
4cdfe9c957
|
|
@ -31,9 +31,9 @@ public class GameFlowTests
|
||||||
foreach (var it in world.Select<Cell, Mark>())
|
foreach (var it in world.Select<Cell, Mark>())
|
||||||
{
|
{
|
||||||
markedCount++;
|
markedCount++;
|
||||||
it.Item1.Row.Should().Be(0);
|
it.Val1.Row.Should().Be(0);
|
||||||
it.Item1.Col.Should().Be(0);
|
it.Val1.Col.Should().Be(0);
|
||||||
it.Item2.Player.Should().Be(Player.X);
|
it.Val2.Player.Should().Be(Player.X);
|
||||||
}
|
}
|
||||||
|
|
||||||
markedCount.Should().Be(1);
|
markedCount.Should().Be(1);
|
||||||
|
|
@ -66,7 +66,7 @@ public class GameFlowTests
|
||||||
// Only one mark should exist at (0,0), and it should still be X.
|
// Only one mark should exist at (0,0), and it should still be X.
|
||||||
var marks = new List<(int Row, int Col, Player Player)>();
|
var marks = new List<(int Row, int Col, Player Player)>();
|
||||||
foreach (var it in world.Select<Cell, Mark>())
|
foreach (var it in world.Select<Cell, Mark>())
|
||||||
marks.Add((it.Item1.Row, it.Item1.Col, it.Item2.Player));
|
marks.Add((it.Val1.Row, it.Val1.Col, it.Val2.Player));
|
||||||
|
|
||||||
marks.Should().ContainSingle()
|
marks.Should().ContainSingle()
|
||||||
.Which.Should().Be((0, 0, Player.X));
|
.Which.Should().Be((0, 0, Player.X));
|
||||||
|
|
@ -166,7 +166,7 @@ public class GameFlowTests
|
||||||
|
|
||||||
var marks = new List<(int Row, int Col, Player Player)>();
|
var marks = new List<(int Row, int Col, Player Player)>();
|
||||||
foreach (var it in world2.Select<Cell, Mark>())
|
foreach (var it in world2.Select<Cell, Mark>())
|
||||||
marks.Add((it.Item1.Row, it.Item1.Col, it.Item2.Player));
|
marks.Add((it.Val1.Row, it.Val1.Col, it.Val2.Player));
|
||||||
|
|
||||||
marks.Should().BeEquivalentTo([(0, 0, Player.X), (1, 0, Player.O)]);
|
marks.Should().BeEquivalentTo([(0, 0, Player.X), (1, 0, Player.O)]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -161,8 +161,8 @@ public class PlayTests
|
||||||
var sb = new System.Text.StringBuilder();
|
var sb = new System.Text.StringBuilder();
|
||||||
var grid = new char?[3, 3];
|
var grid = new char?[3, 3];
|
||||||
foreach (var it in world.Select<Cell, Mark>())
|
foreach (var it in world.Select<Cell, Mark>())
|
||||||
grid[it.Item1.Row, it.Item1.Col] =
|
grid[it.Val1.Row, it.Val1.Col] =
|
||||||
it.Item2.Player == Player.X ? 'X' : 'O';
|
it.Val2.Player == Player.X ? 'X' : 'O';
|
||||||
|
|
||||||
for (int r = 0; r < 3; r++)
|
for (int r = 0; r < 3; r++)
|
||||||
{
|
{
|
||||||
|
|
@ -251,7 +251,7 @@ public class PlayTests
|
||||||
{
|
{
|
||||||
var empty = new List<(int, int)>();
|
var empty = new List<(int, int)>();
|
||||||
foreach (var it in world.Select(new Query<Cell>().Without<Mark>()))
|
foreach (var it in world.Select(new Query<Cell>().Without<Mark>()))
|
||||||
empty.Add((it.Item1.Row, it.Item1.Col));
|
empty.Add((it.Val1.Row, it.Val1.Col));
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -259,7 +259,7 @@ public class PlayTests
|
||||||
{
|
{
|
||||||
var grid = new Player[3, 3];
|
var grid = new Player[3, 3];
|
||||||
foreach (var it in world.Select<Cell, Mark>())
|
foreach (var it in world.Select<Cell, Mark>())
|
||||||
grid[it.Item1.Row, it.Item1.Col] = it.Item2.Player;
|
grid[it.Val1.Row, it.Val1.Col] = it.Val2.Player;
|
||||||
grid[row, col] = player;
|
grid[row, col] = player;
|
||||||
|
|
||||||
for (int r = 0; r < 3; r++)
|
for (int r = 0; r < 3; r++)
|
||||||
|
|
|
||||||
|
|
@ -209,8 +209,8 @@ public class SnapshotTests
|
||||||
// Board: build a 3x3 grid.
|
// Board: build a 3x3 grid.
|
||||||
var grid = new char?[3, 3];
|
var grid = new char?[3, 3];
|
||||||
foreach (var it in world.Select<Cell, Mark>())
|
foreach (var it in world.Select<Cell, Mark>())
|
||||||
grid[it.Item1.Row, it.Item1.Col] =
|
grid[it.Val1.Row, it.Val1.Col] =
|
||||||
it.Item2.Player == Player.X ? 'X' : 'O';
|
it.Val2.Player == Player.X ? 'X' : 'O';
|
||||||
|
|
||||||
int totalCells = 0;
|
int totalCells = 0;
|
||||||
int markedCells = 0;
|
int markedCells = 0;
|
||||||
|
|
|
||||||
|
|
@ -15,34 +15,24 @@ public struct PlaceMarkCommand : ICommand
|
||||||
|
|
||||||
public void Execute(World world)
|
public void Execute(World world)
|
||||||
{
|
{
|
||||||
// Read-only check before iteration — never auto-marks.
|
|
||||||
if (world.ReadSingleton<GameState>().Status != GameStatus.Playing)
|
if (world.ReadSingleton<GameState>().Status != GameStatus.Playing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Find the cell entity at (Row, Col) that has no Mark.
|
// Find the cell entity at (Row, Col) that has no Mark.
|
||||||
var query = new Query<Cell>().Without<Mark>();
|
|
||||||
Entity? target = null;
|
Entity? target = null;
|
||||||
|
|
||||||
// Fetch singleton ref inside iteration so mutations are auto-marked.
|
|
||||||
using var iter = world.Select(query);
|
|
||||||
ref var state = ref world.GetSingleton<GameState>();
|
ref var state = ref world.GetSingleton<GameState>();
|
||||||
|
foreach(var iter in world.Select(new Query<Cell>().Without<Mark>())){
|
||||||
while (iter.MoveNext())
|
if (iter.Val1.Row != Row || iter.Val1.Col != Col) continue;
|
||||||
{
|
target = iter.Entity;
|
||||||
if (iter.Item1.Row == Row && iter.Item1.Col == Col)
|
break;
|
||||||
{
|
|
||||||
target = iter.Entity;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target == null)
|
if (target == null)
|
||||||
return; // Cell already occupied or invalid position.
|
return;
|
||||||
|
|
||||||
// Place the mark.
|
|
||||||
world.AddComponent(target.Value, new Mark { Player = state.CurrentPlayer });
|
world.AddComponent(target.Value, new Mark { Player = state.CurrentPlayer });
|
||||||
|
|
||||||
// Advance turn. Mutations auto-marked via EndIteration — no MarkModified needed.
|
|
||||||
state.MoveCount++;
|
state.MoveCount++;
|
||||||
state.CurrentPlayer = state.CurrentPlayer == Player.X ? Player.O : Player.X;
|
state.CurrentPlayer = state.CurrentPlayer == Player.X ? Player.O : Player.X;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,24 +8,18 @@ namespace Game.TicTacToe;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WinCheckSystem : ISystem
|
public class WinCheckSystem : ISystem
|
||||||
{
|
{
|
||||||
public void Run(World world)
|
public void RunImpl(World world)
|
||||||
{
|
{
|
||||||
// Check game status before doing any work. Use ReadSingleton
|
|
||||||
// to avoid auto-marking GameState as modified when we bail early.
|
|
||||||
if (world.ReadSingleton<GameState>().Status != GameStatus.Playing)
|
if (world.ReadSingleton<GameState>().Status != GameStatus.Playing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get singleton ref inside iteration so all mutations are auto-marked
|
|
||||||
// by EndIteration — no MarkModified calls needed.
|
|
||||||
using var iter = world.Select<Cell, Mark>();
|
|
||||||
ref var state = ref world.GetSingleton<GameState>();
|
ref var state = ref world.GetSingleton<GameState>();
|
||||||
|
|
||||||
// Build a 3×3 grid of marks.
|
// Build a 3×3 grid of marks.
|
||||||
var grid = new Player[3, 3];
|
var grid = new Player[3, 3];
|
||||||
|
foreach (var iter in world.Select<Cell, Mark>())
|
||||||
while (iter.MoveNext())
|
|
||||||
{
|
{
|
||||||
grid[iter.Item1.Row, iter.Item1.Col] = iter.Item2.Player;
|
grid[iter.Val1.Row, iter.Val1.Col] = iter.Val2.Player;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check rows.
|
// Check rows.
|
||||||
|
|
@ -62,9 +56,7 @@ public class WinCheckSystem : ISystem
|
||||||
|
|
||||||
// Check draw.
|
// Check draw.
|
||||||
if (state.MoveCount >= 9)
|
if (state.MoveCount >= 9)
|
||||||
{
|
|
||||||
state.Status = GameStatus.Draw;
|
state.Status = GameStatus.Draw;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryGetWinner(Player a, Player b, Player c, out Player winner)
|
private static bool TryGetWinner(Player a, Player b, Player c, out Player winner)
|
||||||
|
|
@ -82,4 +74,4 @@ public class WinCheckSystem : ISystem
|
||||||
{
|
{
|
||||||
state.Status = winner == Player.X ? GameStatus.XWon : GameStatus.OWon;
|
state.Status = winner == Player.X ? GameStatus.XWon : GameStatus.OWon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue