// TT4DBoad.java /** * * @author Sean Bridges * @version 1.0.1 * * The TT4D Board represents the game logic for a game of 4d Tic Tac Toe. */ import java.util.*; public class TT4DBoard implements Board { //----------------------------------------------------- //class variables public static final int NULL_PLAYER_NUMBER = -1; public static final int X_PLAYER_NUMBER = 0; public static final int O_PLAYER_NUMBER = 1; public static final String NULL_PLAYER_STRING = " "; public static final String X_PLAYER_STRING = "X"; public static final String O_PLAYER_STRING = "O"; private static final int NUMBER_OF_SQUARES = 81; //----------------------------------------------------- //instance variables private TT4DSquare[] squares = new TT4DSquare[NUMBER_OF_SQUARES]; private TT4DStats stats = new TT4DStats(); private Vector rows = new Vector(); private int[] moves = new int[NUMBER_OF_SQUARES]; //1 move possible for each square private int moveIndex = 0; //points after the last move. //----------------------------------------------------- //constructor /** Creates new TT4DBoad */ public TT4DBoard() { initSquares(); }//end constructor //------------------------------------------------- //instance methods //------------------------------------------------- //initializing /** * Create the squares and organize them into rows. */ private void initSquares() { //create the squares for(int i = 0; i < NUMBER_OF_SQUARES; i++) { squares[i] = new TT4DSquare( new TT4DPoint(i) ); } //create the rows /* * The task is to find all possible lines in the board. * Counting each line only once. * * A line consists of three points, one degree of freedom between points. * * a line can be thought of as <a,b,c,d> * s.t. a,b,c,d exist in the set {0,1,2,x,-x} and at * least one of a,b,c,d = x or -x. * 0,1,2 represent constant terms, while x and -x represent * the variable portion. * to construct the three points. x is substituted for 0,1,2 * and -x is substititued for 2,1,0 * For example <x,-x,1,2> is the line composed of the points * <0,2,1,2>, <1,1,1,2> and <2,0,1,2> * * The task is to find all possible lines in the board. * Counting each line once. To do this get each combination * of 0,1,2,x,-x. * To get the unique lines, we select each combination with at least * one x, and with any -x's occuring after the first x. * * x is represented as 3, -x as 4. */ int x, y, z, w, count; count = 0; for(x = 0; x <= 4; x++) { for(y = 0; y <= 4; y ++) { for(z = 0; z <= 4; z ++) { for(w = 0; w <= 4; w++) { //if we have at least 1 x if( (w == 3) | (z == 3) | (y == 3) | (x == 3) ) { //if all -x's occur after at least 1 x if( (x == 3) || ((y == 3) & (x != 4)) || ((z == 3) & (x != 4) & (y != 4) ) || ((w == 3) & (x != 4) & (y != 4) & (z != 4) ) ) { //we have a valid line. count++; TT4DRow r = createRow(x,y,z,w); rows.addElement(r); }//end if }//end if }//end for w }//end for z }//end for y } //end for x //System.out.println(count); } //------------------------------------------------- //row construction /** * Creates and returns a new TT4D row from the given line. * x,y,z,w exist in 0,1,2,3,4 * 3 represents x, 4 represents -x */ private TT4DRow createRow(int x, int y, int z, int w) { return new TT4DRow( getSquare(x,y,z,w, 0), getSquare(x,y,z,w, 1), getSquare(x,y,z,w, 2), stats ); } /** * Find the square for the given point on the line. * x,y,z,w represent the line. * 0,1,2 representing constants * 3 representing x, and 4 representing -x. * * The key argument determines which point on the line is returned. * 0,1,2 return the first second and third points on the line respectively. */ private TT4DSquare getSquare(int x, int y, int z, int w, int key) { if (x == 3) {x = key;} if (x == 4) {x = 2 - key;} if (y == 3) {y = key;} if (y == 4) {y = 2 - key;} if (z == 3) {z = key;} if (z == 4) {z = 2 - key;} if (w == 3) {w = key;} if (w == 4) {w = 2 - key;} return squareAt(x + (y * 3) + (z * 9) + (w * 27)); } //--------------------------------------------------- //accessing private TT4DSquare squareAt(int position) { return squares[position]; } public TT4DSquare squareAt(TT4DPoint point) { return squareAt(point.toInt() ); } //--------------------------------------------------- //clone /** * Create a copy of myself. * The copy is totally independent, ie a deep copy. */ public synchronized Object clone() { TT4DBoard copy = null; try { copy = (TT4DBoard) super.clone(); } catch(CloneNotSupportedException e) { //should never get here System.err.println(e); } copy.squares = (TT4DSquare[]) this.squares.clone(); copy.moves = (int[]) this.moves.clone(); copy.stats = new TT4DStats(); copy.initSquares(); for(int i = 0; i < NUMBER_OF_SQUARES; i++ ) { if(squares[i].getContents() != NULL_PLAYER_STRING) { copy.squares[i].setContents( this.squares[i].getContents() ); } copy.moves[i] = this.moves[i]; } copy.moveIndex = this.moveIndex; return copy; } //----------------------------------------------------- //Board Methods /** * Return an object which can be interrogated to discover the current * state of the game */ public BoardStats getBoardStats() { return stats; } /** * Try and make a move. * Returns wether or not the move attempt was successful. */ public boolean move(Move m) { if( squareAt(m.toInt()).getContents() == NULL_PLAYER_STRING ) { squareAt(m.toInt()).setContents(m.maker().getName()); moves[moveIndex] = m.toInt(); moveIndex ++; return true; } else { return false; } } /** Undo the last move made. */ public void undoLastMove() { moveIndex--; squareAt(moves[moveIndex]).setContents(NULL_PLAYER_STRING); } /** * Get the list of moves that are possible for the given * player */ public Move[] getPossibleMoves(Player aPlayer) { Move[] possible = new Move[NUMBER_OF_SQUARES - moveIndex]; int current = 0; for(int i = 0; i < NUMBER_OF_SQUARES; i++) { if(squares[i].getContents() == NULL_PLAYER_STRING) { possible[current] = new TT4DMove(aPlayer, squares[i].getPosition()); current++; } } return possible; } /** Whether or not the game is over. */ public boolean isGameOver() { //we are over if there are no more empty squares boolean over = true; for(int i = 0; i < NUMBER_OF_SQUARES; i++) { if(squares[i].getContents().equals(NULL_PLAYER_STRING) ) { over = false; break; } } return over; } /** Called by the game master when the game is started. */ public void gameStarted() { clearBoard(); } /** Called by the game master when the game is restarted. */ public void gameRestarted() { clearBoard(); } /** Called by the game master when the game is stopped. */ public void gameStoped() { clearBoard(); } /** * Clear all the squares on the board. */ private void clearBoard() { //clear the squares for(int i = 0; i < NUMBER_OF_SQUARES; i++) { squares[i].setContents(NULL_PLAYER_STRING); } moveIndex = 0; } public String toString() { StringBuffer buf = new StringBuffer(); for(int x = 0; x < 3; x++) { buf.append("\n"); for(int y = 0; y < 3; y++) { buf.append("\n"); for(int z = 0; z < 3; z++) { buf.append(" "); for(int w = 0; w < 3; w++) { int v = x + (y * 3) + (z * 9) + (w * 27); buf.append("|"); buf.append(squareAt(v).getContents() ); }//end for w }//end for z }//end for y }//end for x return buf.toString(); }//end toString }//end class TT4DBoard