HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Ultimate Tic-Tac-Toe data model

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
toetictacultimatedatamodel

Problem

This is another entry for The Ultimate Tic-Tac-Toe review.

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:

  • 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.