// 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