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

Recursive and flexible approach to Tic-Tac-Toe

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

Problem

Description

This is my code for the Weekend Challenge Reboot - Tic Tac Toe Ultimate.

The game can be played here: http://www.zomis.net/ttt (along with some other variations that are also use the same code base, but with other 'controllers').

This question contains the game model and a 'controller' for the TicTacToe Ultimate game.

The classic TTT is 33. TTT Ultimate is a 33 grid of classic TTTs, so 33 33. As usual I wanted this code to be flexible, so technically it should be possible to extend it to a TTTUltimatePlus which would be a 33 grid of TTTUltimate games, or 33 33 3*3. I have not done a controller for TTTUltimatePlus yet, but the TTBase system would support it. When I started this project, I did not expect myself to make it work with Reversi (a.k.a. Othello), or Quantum Tic-Tac-Toe but well... when I realized how I could structure this I thought "Why not?".

My first code, having a TTUltimateGame, TTBoard and a TTField class had a lot of code duplication which I wanted to avoid. This made me want to make this code. The TTBase class is the most important one, to support any number of recursiveness (by making a TTTUltimatePlus for example) I made it as a recursive class. Each clickable field is a TTBase, each area containing the fields is a TTBase, and the outermost game itself is a TTBase.

Class Summary (695 lines in 12 files, making a total of 18218 bytes)

  • HasSub.java: Interface indicating that a class contains smaller parts, 'subs' (a small field is a sub to a 3x3 area for example).



  • TicFactory.java: Interface for creating TTBase objects.



  • TicUtils.java: Utility methods, including code to create the Win Conditions for a TTBase.



  • TTBase.java: Class that can contain more TTBases in a rectangular grid. Can be won and played by players.



  • TTController.java: Abstract class for determining which TTBases that can be played and for playing at them.



  • TTFactories.java: Code to instanciate variations of TTBases.



  • TTMNKParamete

Solution

There is not much to criticize in your code.... and there is a lot of code to go though.

Mostly really neat, and, it takes a while to 'grok' it, but it comes together OK.

Here's a laundry-list of small items (there are no big Items I can see):

-
In TTUtils:

  • getWinCondsWith is a method that is never called from anywhere



  • getAllSmallestFields should be called getAllSmallestSubs to match other methods.



-
In TTBase:

-
Unmodifiable in constructor:

this.winConditions = Collections.unmodifiableList(TicUtils.setupWins(this));


I would expect the unmodifiable constraint to be set in setupWins(), in other words it should return an unmodifyable list rather than having that imposed outside the call.

-
in setPlayedBy() you have:

if (playedBy == null && this.hasSubs() && parent != null)
     new Exception().printStackTrace();


No Braces is against Java code-style

You are printing a stack trace, but continuing to set the value null anyway.

This would be a good location for an assert.

-
TTFactories

  • all the private-static-final fields should be ALL_UPPERCASE per the Java Guidelines



-
TTPlayer

-
un-braced 1-liner if statements again:

-
or - if this==NONE and other == null, then why return null instead of NONE?

public TTPlayer or(TTPlayer other) {
        if (this == NONE || other == null)
            return other;
        if (other == NONE)
            return this;
        if (this == XO)
            return this;
        if (this != other)
            return XO;
        return this;
    }

Code Snippets

this.winConditions = Collections.unmodifiableList(TicUtils.setupWins(this));
if (playedBy == null && this.hasSubs() && parent != null)
     new Exception().printStackTrace();
public TTPlayer or(TTPlayer other) {
        if (this == NONE || other == null)
            return other;
        if (other == NONE)
            return this;
        if (this == XO)
            return this;
        if (this != other)
            return XO;
        return this;
    }

Context

StackExchange Code Review Q#45086, answer score: 12

Revisions (0)

No revisions yet.