patterncsharpModerate
Ultimate Tic-Tac-Toe data model
Viewed 0 times
toetictacultimatedatamodel
Problem
This is another entry for The Ultimate Tic-Tac-Toe review.
My design criteria were:
Here's the DLL code:
```
using System;
using System.Collections.Generic;
namespace UltimateTicTacToe.Model
{
// Cell only contains its state, not its own location
// true -> "O"
// false -> "X"
// null -> (not played yet)
// Immutable because it's a struct.
public struct Cell
{
readonly bool? state;
public bool? State { get { return state; } }
public Cell(bool state) { this.state = state; }
}
// A trivial struct with fly-weight static instances
// Immutable because it's a struct.
// Short, constant-length names like 'L00' so that they line up well.
public struct Location
{
readonly int row;
readonly int column;
public int Row { get { return row; } }
public int Column { get { return column; } }
public Location(int row, int column)
{
this.row = row;
this.column = column;
}
public static Location L00 = new Location(0, 0);
public static Location L01 = new Location(0, 1);
public static Location L02 = new Location(0, 2);
public static Location L10 = new Location(1, 0);
public static Location L11 = new Location(1, 1);
public static Location L12 = new Location(1, 2);
public static Location L20 = new Location(2, 0);
public static Location L21 = new Location(2, 1);
public static Location L22 = new Location(2, 2);
internal static List All = new List()
{
L00, L01, L02,
L10, L11, L12,
L20, L21, L22
};
// Simpler than overriding Equals etc.
// http://stackoverflow.com/a/1
My design criteria were:
- A DLL which encapsulates the data, i.e. the game state
- Don't include the GUI, nor the decision-making (game-playing) logic
- Be careful not to allow corrupted state
- Make it as small (few lines of code) as possible
Here's the DLL code:
```
using System;
using System.Collections.Generic;
namespace UltimateTicTacToe.Model
{
// Cell only contains its state, not its own location
// true -> "O"
// false -> "X"
// null -> (not played yet)
// Immutable because it's a struct.
public struct Cell
{
readonly bool? state;
public bool? State { get { return state; } }
public Cell(bool state) { this.state = state; }
}
// A trivial struct with fly-weight static instances
// Immutable because it's a struct.
// Short, constant-length names like 'L00' so that they line up well.
public struct Location
{
readonly int row;
readonly int column;
public int Row { get { return row; } }
public int Column { get { return column; } }
public Location(int row, int column)
{
this.row = row;
this.column = column;
}
public static Location L00 = new Location(0, 0);
public static Location L01 = new Location(0, 1);
public static Location L02 = new Location(0, 2);
public static Location L10 = new Location(1, 0);
public static Location L11 = new Location(1, 1);
public static Location L12 = new Location(1, 2);
public static Location L20 = new Location(2, 0);
public static Location L21 = new Location(2, 1);
public static Location L22 = new Location(2, 2);
internal static List All = new List()
{
L00, L01, L02,
L10, L11, L12,
L20, L21, L22
};
// Simpler than overriding Equals etc.
// http://stackoverflow.com/a/1
Solution
Here's a bug:
Cell state is
It makes sense (code would be more readable) to replace bool with an
The
- Someone can play on an already-won quadrant (is this allowed by the rules?).
- If they play on an empty space of an already-won quadrant they can 'win again' i.e. trigger the Recalculate logic and potentially get a different Winner.
Cell state is
bool? and Player is a corresponding bool.It makes sense (code would be more readable) to replace bool with an
enum Player { X, O }, remove the struct Cell definition altogether, and use BoardT as the subclass (or member data) of Quadrant.The
bool canPlay calculation could be a internal bool CanPlay { get {...}} property of Quadrant.public bool CanPlay(Location quadrantLocation) (which depends on the PreviousPlay in Game) should be a public method of Game, because the UI will want it in order to know whether to render each quadrant as playable.Context
StackExchange Code Review Q#41078, answer score: 13
Revisions (0)
No revisions yet.