package players; import TicTac.*; import java.util.*; /** * Sample skeleton for a smart player that knows how to make the next * move based on the min-max evaluation strategy. */ public class SmartPlayer extends TTPlayer { public SmartPlayer(char mark) { _mark = mark; } /** * Randomizes the moves array. */ private final void randomize(Vector moves) { // see the code in DumbPlayer } /** * Computes and returns the value of the board for the player whose * symbol is playerMark. * @param board the current board configuration. * @param playerMark the character used by a player to mark the board. * @return the min-max value of the current board configuration. */ private final int eval(char[][] board, char playerMark) { // if leaf node then return payoff value: if (playerWins (board, _mark)) { return 1; } else if (playerWins (board, TTEngine.GetOpponentMark(_mark))) { return -1; } else if (getNumEmptyCell (board) == 0) { return 0; } // else recur to compute min-max: int min_max = (_mark == playerMark ? Integer.MIN_VALUE: Integer.MAX_VALUE); Vector moves = GetLegalMoves (playerMark, board); for (int i = 0; i < moves.size(); i++) { // Make the i-th move. // Compute the min-max of this i-th move and update the // current min-max. If it's this SmartPlayer's turn then // compute the max else compute the min. // Undo the i-th move. } return min_max; } /** * Computes the next move based on the current board status. * @param board_status * @return the next best move. */ public TTMove NextMove (char[][] board_status) { System.out.println ("I'm thinking..."); int best = eval (board_status, _mark); Vector moves = GetLegalMoves (_mark, board_status); randomize (moves); for (int i = 0; i < moves.size(); i++) { TTMove move = (TTMove)moves.elementAt(i); MakeMove (_mark, move, board_status); int temp = eval(board_status, TTEngine.GetOpponentMark(_mark)); if (temp == best) { undoMove (move, board_status); System.out.println ("OK..."); return move; } undoMove (move, board_status); } return null; // should never get here! } private final boolean playerWins(char[][] board_status, char playerMark) { return (someRowHasAll(board_status, playerMark) || someColHasAll(board_status, playerMark) || someDiagHasAll(board_status, playerMark)); } private final boolean someRowHasAll(char[][] board_status, char mark) { return ((board_status[0][0] == mark && board_status[0][1] == mark && board_status[0][2] == mark) || (board_status[1][0] == mark && board_status[1][1] == mark && board_status[1][2] == mark) || (board_status[2][0] == mark && board_status[2][1] == mark && board_status[2][2] == mark)); } private final boolean someDiagHasAll(char[][] board_status, char mark) { return ((board_status[0][0] == mark && board_status[1][1] == mark && board_status[2][2] == mark) || (board_status[2][0] == mark && board_status[1][1] == mark && board_status[0][2] == mark)); } private final boolean someColHasAll(char[][] board_status, char mark) { return ((board_status[0][0] == mark && board_status[1][0] == mark && board_status[2][0] == mark) || (board_status[0][1] == mark && board_status[1][1] == mark && board_status[2][1] == mark) || (board_status[0][2] == mark && board_status[1][2] == mark && board_status[2][2] == mark)); } private final int getNumEmptyCell(char[][] board_status) { int cell_total = 0; int i, j; for (i=0; i