// Overview: This class captures the state of the board at a given // time. It has idea about the position of different pieces on the // board, legality of different moves. Any move instantiated by the // user changes the state of the object. import java.util.*; public class CheckersBoard { // Attributes // representation of different public static final int EMPTY = 0, RED = 1, RED_KING = 2, BLACK = 3, BLACK_KING = 4; private Piece[][] board; // board[r][c] is the contents of row r, column c. public CheckersBoard() { // Constructor. Create the board and set it up for a new game. board = new Piece[8][8]; setUpGame(); } // end CheckersBoard() // An accessor that returns the Board public Piece[][] getBoard() { return board; } // end getBoard() public void setUpGame() { // Does the initial setup the board with pieces in position. At the start of the // game, all such squares in the first three rows contain black squares // and all such squares in the last three rows contain red squares. int blackNo=0; // The variable is used to assign the ID to each of the pieces belonging to the BLACK player int redNo=0; // The variable is used to assign the ID to each of the pieces belonging to the RED player // Assign the Piece object to the squares for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { if ( row % 2 == col % 2 ) { if (row < 3) { board[row][col] = new Piece(blackNo,row,col,BLACK,BLACK); blackNo++; } else if (row > 4) { board[row][col] = new Piece(redNo,row,col,RED,RED); redNo++; } else { board[row][col] = new Piece(12,row,col,EMPTY,10); } } else { board[row][col] = new Piece (12,row,col,EMPTY,10); } } } } // end setUpGame() public void displayBoard(){ // The method used to create a visual representation of the board at a given time. // System.out.println("\n 0 1 2 3 4 5 6 7\n"); for (int row = 0; row < 8; row++) { System.out.print(Integer.toString(row)+"| "); for (int col = 0; col < 8; col++) { String id2Print=" "; String player=""; if (board[row][col].getPlayer()==BLACK) { player="B"; if (board[row][col].getpieceID()<10){ id2Print=player+"("+board[row][col].getpieceID()+") "; } else { id2Print=player+"("+board[row][col].getpieceID()+")"; } } else if (board[row][col].getPlayer()==RED){ player="R"; if (board[row][col].getpieceID()<10){ id2Print=player+"("+board[row][col].getpieceID()+") "; } else { id2Print=player+"("+board[row][col].getpieceID()+")"; } } System.out.print(id2Print+"|"); } System.out.println("\n"); } } //end DisplayBoard public Piece pieceAt(int row, int col) { // Return the contents of the square in the specified row and column. return board[row][col]; } public void setPieceAt(int row, int col, Piece piece) { // Set the contents of the square in the specified row and column. // piece must be one of the constants EMPTY, RED, BLACK, RED_KING, // BLACK_KING. board[row][col] = piece; } public void makeMove(CheckersMove move) { // Accept a move from the caller and Make the specified move. // It is assumed that move is legal. makeMove(move.getfromRow(), move.getfromCol(), move.gettoRow(), move.gettoCol()); } public void makeMove(int fromRow, int fromCol, int toRow, int toCol) { // Make the move from (fromRow,fromCol) to (toRow,toCol). As mentioned, // it is assumed that the move is legal. There could be three types of moves: // i. A regular move where the pieces moves forward by one position. // ii. A jump where the piece move two positions. Also in case of a // jump, the jumped piece is removed from the board. // iii. If a piece movee the last row on the opponent's side of the board, the // piece becomes a king. // An empty piece has the ID=12 and playertype=10 board[toRow][toCol] = board[fromRow][fromCol]; // Assign the piece to it's new position board[fromRow][fromCol] = new Piece(12,fromRow,fromCol,EMPTY,10); // make the previous position empty if (fromRow - toRow == 2 || fromRow - toRow == -2) { // The move is a jump. Remove the jumped piece from the board. int jumpRow = (fromRow + toRow) / 2; // Row of the jumped piece. int jumpCol = (fromCol + toCol) / 2; // Column of the jumped piece. board[jumpRow][jumpCol] = new Piece(12,fromRow,fromCol,EMPTY,10); } // The piece becomes a 'king' if (toRow == 0 && board[toRow][toCol].getColor() == RED) board[toRow][toCol] = new Piece (board[toRow][toCol].getpieceID(),toRow,toCol,RED_KING,RED); if (toRow == 7 && board[toRow][toCol].getColor() == BLACK) board[toRow][toCol] = new Piece(board[toRow][toCol].getpieceID(),toRow,toCol,BLACK_KING,BLACK); } public CheckersMove[] getLegalMoves(int player) { // An array containing all the legal CheckersMoves for the // specfied player on the current board. A null is returned // the player has no legal moves. For a non-null array, it // consists entirely of jump or regular moves. if (player != RED && player != BLACK) return null; int playerKing; // The constant representing a King belonging to player. if (player == RED) playerKing = RED_KING; else playerKing = BLACK_KING; Vector moves = new Vector(); // Moves will be stored in this list. /* For each of the pieces of the player (either regular or king), it looks for the possible jumps in each of the four directions from it's position. Any legal jump is added to the vector. */ for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { if (board[row][col].getColor() == player || board[row][col].getColor() == playerKing) { if (canJump(player, row, col, row+1, col+1, row+2, col+2)) moves.addElement(new CheckersMove(row, col, row+2, col+2)); if (canJump(player, row, col, row-1, col+1, row-2, col+2)) moves.addElement(new CheckersMove(row, col, row-2, col+2)); if (canJump(player, row, col, row+1, col-1, row+2, col-2)) moves.addElement(new CheckersMove(row, col, row+2, col-2)); if (canJump(player, row, col, row-1, col-1, row-2, col-2)) moves.addElement(new CheckersMove(row, col, row-2, col-2)); } } } /* This version of the game assumes that jumps are mandatory. So, if the above vector is not empty, no need to add any regular moves. However, if no jumps were found, check for any legal regualar moves. The process is very similar to the above, only differene is the distance the piece can travel (1 in this case). Any legal move is addded to the vectors. */ if (moves.size() == 0) { for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { if (board[row][col].getColor() == player || board[row][col].getColor() == playerKing) { if (canMove(player,row,col,row+1,col+1)) // for the regular piece moves.addElement(new CheckersMove(row,col,row+1,col+1)); if (canMove(player,row,col,row-1,col+1)) // for the king moves.addElement(new CheckersMove(row,col,row-1,col+1)); if (canMove(player,row,col,row+1,col-1)) // for the king moves.addElement(new CheckersMove(row,col,row+1,col-1)); if (canMove(player,row,col,row-1,col-1)) // for the king moves.addElement(new CheckersMove(row,col,row-1,col-1)); } } } } /* Create an array holding the the legal moves, copy the legal moves from the ArrayList into the array, and return the array. */ if (moves.size() == 0) return null; else { CheckersMove[] moveArray = new CheckersMove[moves.size()+1]; for (int i = 0; i < moves.size(); i++) moveArray[i] = (CheckersMove)moves.get(i); return moveArray; } } // end getLegalMoves public CheckersMove[] getLegalJumpsFrom(int player, int row, int col) { // An array containing all the legal jumps for the // specfied player on the current board. A null is returned // the player has no jump. if (player != RED && player != BLACK) return null; int playerKing; // The constant representing a King belonging to player. if (player == RED) playerKing = RED_KING; else playerKing = BLACK_KING; // ArrayList moves = new ArrayList(); // The legal jumps will be stored in this list. Vector moves = new Vector(); if (board[row][col].getColor() == player || board[row][col].getColor() == playerKing) { if (canJump(player, row, col, row+1, col+1, row+2, col+2)) // for the regular piece moves.addElement(new CheckersMove(row, col, row+2, col+2)); if (canJump(player, row, col, row-1, col+1, row-2, col+2)) // for the king moves.addElement(new CheckersMove(row, col, row-2, col+2)); if (canJump(player, row, col, row+1, col-1, row+2, col-2)) // for the king moves.addElement(new CheckersMove(row, col, row+2, col-2)); if (canJump(player, row, col, row-1, col-1, row-2, col-2)) // for the king moves.addElement(new CheckersMove(row, col, row-2, col-2)); } if (moves.size() == 0) return null; else { CheckersMove[] moveArray = new CheckersMove[moves.size()+1]; for (int i = 0; i < moves.size(); i++) moveArray[i] = (CheckersMove)moves.get(i); return moveArray; } } // end getLegalMovesFrom() private boolean canJump(int player, int r1, int c1, int r2, int c2, int r3, int c3) { // The method is used by the two previous methods to check whether the // player can legally jump from a square to another. if (r3 < 0 || r3 >= 8 || c3 < 0 || c3 >= 8) return false; // (r3,c3) is not within the board. if (board[r3][c3].getpieceID() != 12) return false; // (r3,c3) already contains a piece. if (player == RED) { if (board[r1][c1].getColor() == RED && r3 > r1) return false; // Regular red piece can only move up. if (board[r2][c2].getColor() != BLACK && board[r2][c2].getColor() != BLACK_KING) return false; // There is no black piece to jump. return true; // The jump is legal. } else { if (board[r1][c1].getColor() == BLACK && r3 < r1) return false; // Regular black piece can only move downn. if (board[r2][c2].getColor() != RED && board[r2][c2].getColor() != RED_KING) return false; // There is no red piece to jump. return true; // The jump is legal. } } // end canJump() private boolean canMove(int player, int r1, int c1, int r2, int c2) { // This is used by the getLegalMoves() method to determine whether // the player can legally move from one position to another. The logic // is very similar to the above method. if (r2 < 0 || r2 >= 8 || c2 < 0 || c2 >= 8) return false; // (r2,c2) is not within the board. if (board[r2][c2].getpieceID() != 12) return false; // (r2,c2) already contains a piece. if (player == RED) { if (board[r1][c1].getColor() == RED && r2 > r1) return false; // Regualr red piece can only move down. return true; // The move is legal. } else { if (board[r1][c1].getColor() == BLACK && r2 < r1) return false; // Regular black piece can only move up. return true; // The move is legal. } } // end canMove() } // end class CheckersBoard