// OthelloBoard Class. This class handles the board state and updating the board // when Moves take place. import java.io.*; import java.util.*; public class OthelloBoard implements Cloneable { static final int NOWHERE = -1; static final int BLACK = 2; static final int WHITE = 1; static final int EMPTY = 0; static final int OKMOVE = 3; static final int PLAYER1 = BLACK; static final int PLAYER2 = WHITE; static final int CHANGED = 16; // the zero column is not used, board is 8x8 Vector paintPieces; int board[][] = new int[9][9]; int weight[][] = new int[9][9]; // NEW ADDITION int GameTime = 0; // has to be three since USER is 2, COMPUTER is 1 int score[] = new int[3]; int fit_inc[] = new int[3]; int gameTurn; boolean gameIsOver; //Board Statistics int num_white; int num_black; int num_white_edges; int num_black_edges; int num_white_corners; int num_black_corners; int num_white_near_corners; int num_black_near_corners; /** * Set up the board, load everything in so it's speedy */ public OthelloBoard copy() { weight[1][1] = 100; weight[1][2] = -20; weight[1][3] = 20; weight[1][4] = 3; //3 weight[2][1] = -20; weight[2][2] = -20; weight[2][3] = 20; weight[2][4] = 3; //3 weight[3][1] = 20; weight[3][2] = 20; weight[3][3] = 20; weight[3][4] = 3; // 3.. weight[4][1] = 3; weight[4][2] = 3; weight[4][3] = 3; weight[4][4] = 3; // .. 3 for(int count1=1; count1<=4; count1++) { for(int count2=1; count2<=4;count2++) { weight[9 - count1][count2] = weight[count1][count2]; weight[9 - count1][9 - count2] = weight[count1][count2]; weight[count1][9-count2] = weight[count1][count2]; } } for(int i=0;i<9;i++) { weight[0][i] = 0; weight[i][0] = 0; } OthelloBoard newBoard = new OthelloBoard(); for (int i=0; i<9; i++) { for (int j=0; j<9; j++) { newBoard.board[i][j]=board[i][j]; } } for (int k=0; k<3; k++) { newBoard.score[k]=score[k]; newBoard.fit_inc[k]=fit_inc[k]; } newBoard.GameTime = GameTime; newBoard.gameTurn = gameTurn; newBoard.gameIsOver = gameIsOver; return newBoard; } OthelloBoard() { // clear the board for (int row = 1; row < 9; row++) for (int col = 1; col < 9; col++) board[col][row] = EMPTY; // put the first pieces on the board board[4][4] = BLACK; board[4][5] = WHITE; board[5][4] = WHITE; board[5][5] = BLACK; score[PLAYER1] = 2; score[PLAYER2] = 2; fit_inc[PLAYER1] = 0; fit_inc[PLAYER2] = 0; gameIsOver = false; gameTurn = BLACK; GameTime = 0; paintPieces = new Vector(10); } public boolean gameOver() { return gameIsOver; } // The folowing function returns a string containing // all of the board statistics. They are the number white, // the number black, the number white edges, the number black edges, // the number white corners and the number black corners. public void updateBoardStatistics() { num_white = 0; num_black = 0; num_white_edges = 0; num_black_edges = 0; num_white_corners = 0; num_black_corners = 0; num_white_near_corners = 0; num_black_near_corners = 0; for (int row = 1; row < 9; row++) { for (int col = 1; col <9; col++) { if ((board[col][row] == WHITE) || (board[col][row] == WHITE + CHANGED)){ num_white++; if ((col==1) || (col==8) || (row==1) || (row==8)) { num_white_edges++; } if (((col==1) || (col==8)) && ((row==1) || (row==8))) { num_white_corners++; } if (((col==1) && ((row == 2) || (row == 7))) || ((col == 2) && ((row == 1) || (row == 2) || (row == 7) || (row==8))) || ((col == 7) && ((row == 1) || (row == 2) || (row == 7) || (row ==8))) || ((col == 8) && ((row == 2) || (row == 7)))) { num_white_near_corners++; } } if ((board[col][row] == BLACK) || (board[col][row] == BLACK + CHANGED)){ num_black++; if ((col==1) || (col==8) || (row==1) || (row==8)) { num_black_edges++; } if (((col==1) || (col==8)) && ((row==1) || (row==8))) { num_black_corners++; } if (((col==1) && ((row == 2) || (row == 7))) || ((col == 2) && ((row == 1) || (row == 2) || (row == 7) || (row==8))) || ((col == 7) && ((row == 1) || (row == 2) || (row == 7) || (row ==8))) || ((col == 8) && ((row == 2) || (row == 7)))) { num_black_near_corners++; } } } } } public String printBoardStatistics() { updateBoardStatistics(); return "" + num_white + " " + num_black + " " + num_white_edges + " " + num_black_edges + " " + num_white_corners + " " + num_black_corners + " " + num_white_near_corners + " " + num_black_near_corners; } public Vector possibleMoves(int color) { Vector moves = new Vector(8); Move tempMove; for (int col=1; col < 9; col++) { for (int row=1; row <9; row++) { if (isLegalMove(color, col, row)) { tempMove = new Move(col,row); moves.addElement(tempMove); } } } return moves; } int numPossibleMoves(int color) { Vector moves = possibleMoves(color); int numMoves = moves.size(); return numMoves; } Move getnthMove(int nthMove, int color) { Vector possibleMoves = possibleMoves(color); Move move; move = (Move)possibleMoves.elementAt(nthMove); return move; } void PrintBoard() { Vector moves; if (gameTurn==BLACK) moves = possibleMoves(BLACK); else moves = possibleMoves(WHITE); String output = "\n"; for (int row=1; row < 9; row++) { for (int col=1; col < 9; col++) { if ((board[col][row] == BLACK) || (board[col][row] == BLACK+CHANGED)) output = output + "o"; else if ((board[col][row] == WHITE) || (board[col][row] == WHITE+CHANGED)) output = output + "O"; else output = output + "."; } if (row == 1) { output = output + " Moves for "; if (gameTurn==BLACK) output = output + "BLACK"; else output = output + "WHITE"; } if (row == 2) { output = output + " "; for (int i=0; i0) { gameTurn = WHITE; } else if (numPossibleMoves(BLACK)>0) { gameTurn=BLACK; } else { gameIsOver=true; } else if (numPossibleMoves(BLACK)>0) { gameTurn = BLACK; } else if (numPossibleMoves(WHITE)>0) { gameTurn = WHITE; } else { gameIsOver=true; } } /** * make an actual move, put the new piece on the board * flip the rest of the pieces */ void FakemakeMove (int color, int col, int row) { score[color] += 1; fit_inc[color] += weight[col][row]; board[col][row] = color; for (int colinc = -1; colinc < 2; colinc++) { for (int rowinc = -1; rowinc < 2; rowinc++) { flipRow(color, col, row, colinc, rowinc, true, false); } } } /** * try and flip a row in a particular direction * if really_flipping, then go ahead and flip 'em * return number of pieces flipped */ int flipRow (int color, int col, int row, int colinc, int rowinc, boolean really_flipping, boolean really_painting) { int newcol = col + colinc; int newrow = row + rowinc; int opponent = BLACK + WHITE - color; int count = 0; // if not incrementing (moving in a direction), then forget it if ((colinc == 0) && (rowinc == 0)) return 0; if (newcol == 0 || newcol > 8 || newrow == 0 || newrow > 8) return 0; // if we aren't flipping an opponent, then forget it // have to include the CHANGED in case the screen update // has not happened yet (grr.. this is annoying about java..) if ((board[newcol][newrow] != opponent) && (board[newcol][newrow] != opponent+CHANGED)) return 0; // try to flip as many as possible while ((board[newcol][newrow] == opponent) || (board[newcol][newrow] == opponent+CHANGED)) { newcol += colinc; newrow += rowinc; count++; if (newcol == 0 || newcol > 8 || newrow == 0 || newrow > 8) return 0; } // is there a matching piece on the other end? if ((board[newcol][newrow] != color) && (board[newcol][newrow] != color + CHANGED)) return 0; // if we're really flipping them now, then do it.. if (really_flipping) { while ((col != newcol) || (row != newrow)) { if (board[col][row] != color) board[col][row] = color + CHANGED; if (really_painting) { Move tempMove = new Move(col, row); paintPieces.addElement(tempMove); } col += colinc; row += rowinc; score[color] += 1; score[opponent] -= 1; } // ok, so we got a little over-excited score[color] -= 1; score[opponent] += 1; } return count; } // can you even move there? boolean isLegalMove (int color, int col, int row) { if ((board[col][row] != EMPTY) && (board[col][row] != OKMOVE)) { return false; } for (int colinc = -1; colinc < 2; colinc++) { for (int rowinc = -1; rowinc < 2; rowinc++) { if (flipRow(color, col, row, colinc, rowinc, false, false) > 0) { return true; } } } return false; } /** * does this color have anywhere to go? */ boolean hasMove (int color) { for ( int col = 1; col < 9; col++ ) { for ( int row = 1; row < 9; row++) { if (numPossibleMoves(color) > 0) { return true; } } } return false; } // This can get overwritten if we want to do something at the end of a game. void endGame () { } } // This class defines a move record. class Move { // The column and row of a move. private int col; private int row; // the value of a move. ie the value of the board possition once it is done. // this is initially set to 0 and later change. private double value; Move(int col, int row) { this.row = row; this.col = col; value = 0; } public int col() { return col; } public int row() { return row; } public double value() { return value; } public void setValue(double val) { value = val; } public String toString() { String output = "(" + row + "," + col + ") "; return output; } }