This below program will be further enhanced for TicTacToe
game with Human and Computer as players.
Currently this program is written for choosing best move for a given grid position.
package project2.tictactoe;
enum TicTacToe{
X, O, NULL;
@Override
public String toString(){
switch(this){
case X:
return "X";
case O:
return "O";
default:
return "NULL";
}
}
}
public class TicTacToeGame{
TicTacToe[][] twoDimArray = new TicTacToe[3][3];
TicTacToeGame(){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
this.twoDimArray[i][j] = TicTacToe.NULL;
}
}
}
private static final Boolean HUMAN_TURN = false;
private static final Boolean COMPUTER_TURN = true;
private static String bestMove = null;
boolean gameDone(){
for(int i = 0; i < 3; i++){
if(this.twoDimArray[i][0] != TicTacToe.NULL){
if(this.twoDimArray[i][0] == this.twoDimArray[i][1]){
if(this.twoDimArray[i][1] == this.twoDimArray[i][2]){
return true;
}
}
}
if(this.twoDimArray[0][i] != TicTacToe.NULL){
if(this.twoDimArray[0][i] == this.twoDimArray[1][i]){
if(this.twoDimArray[1][i] == this.twoDimArray[2][i]){
return true;
}
}
}
if(i == 1){
/* Diagnol check */
if(this.twoDimArray[i-1][0] != TicTacToe.NULL){
if(this.twoDimArray[i-1][0] == this.twoDimArray[i][i]){
if(this.twoDimArray[i][i] == this.twoDimArray[i+1][i+1]){
return true;
}
}
}
if(this.twoDimArray[i+1][0] != TicTacToe.NULL){
if(this.twoDimArray[i+1][0] == this.twoDimArray[i][i]){
if(this.twoDimArray[i][i] == this.twoDimArray[i-1][i+1]){
return true;
}
}
}
}
} /* end for-loop*/
return false;
}
byte chooseBestMove(boolean side){
byte bestScore;
if(this.gameDone()){
if( side == HUMAN_TURN){
return +1; //actually computer side won here, so +1
}else{
return -1; //actually human side won here, so -1.
}
}else{
if(side == COMPUTER_TURN){
bestScore = -2; // this is little mathematics to maintain best score
}else{
bestScore = +2;
}
for(int i=0; i<9; ++i)
if(this.twoDimArray[i/3][i%3] == TicTacToe.NULL)
{
/*Make a new possible move and modify the array on heap*/
if(side == TicTacToeGame.COMPUTER_TURN){
this.twoDimArray[i/3][i%3] = TicTacToe.O;
}else{
this.twoDimArray[i/3][i%3] = TicTacToe.X;
}
byte score = chooseBestMove(!side);
if(side == TicTacToeGame.COMPUTER_TURN){
if(score > bestScore){
bestScore = score;
bestMove = "Place \"" + TicTacToe.O + "\" at position [" + i/3 + "][" + i%3 + "]";
}
}
if(side == TicTacToeGame.HUMAN_TURN){
if(score < bestScore){
bestScore = score;
bestMove = "Place \"" + TicTacToe.X + "\" at position [" + i/3 + "][" + i%3 + "]";
}
}
/* Undo the possible move */
if(side == TicTacToeGame.COMPUTER_TURN){
this.twoDimArray[i/3][i%3] = TicTacToe.NULL;
}else{
this.twoDimArray[i/3][i%3] = TicTacToe.NULL;
}
}
}
return bestScore;
}
void printElements(){
for(int i = 0; i < 3; i++){
System.out.println(" " + twoDimArray[i][0] + " | " + twoDimArray[i][1] + " | " + twoDimArray[i][2]);
if(i != 2)
System.out.println("------------------");
}
}
public static void main(String[] args){
TicTacToeGame objRef = new TicTacToeGame();
boolean side = true; //first move is computer move
/* For any Grid scenario set below*/
objRef.twoDimArray[0][0] = TicTacToe.NULL;
objRef.twoDimArray[0][1] = TicTacToe.NULL;
objRef.twoDimArray[0][2] = TicTacToe.NULL;
objRef.twoDimArray[1][0] = TicTacToe.NULL;
objRef.twoDimArray[1][1] = TicTacToe.NULL;
objRef.twoDimArray[1][2] = TicTacToe.NULL;
objRef.twoDimArray[2][0] = TicTacToe.NULL;
objRef.twoDimArray[2][1] = TicTacToe.NULL;
objRef.twoDimArray[2][2] = TicTacToe.NULL;
/* Choose best move */
byte score = objRef.chooseBestMove(side);
System.out.println(TicTacToeGame.bestMove);
}
}
Does this program follow the elements of OOPs paradigm, abstraction and encapsulation?
I would require comments to refine this programming style to fit into OOP paradigm.