Untitled
unknown
java
2 years ago
8.1 kB
1
Indexable
import java.awt.*; import java.util.ArrayList; import java.util.Collections; import static java.lang.Math.max; import static java.lang.Math.min; /** * This is the class that we will have to implement for the assignment */ public class StudentPlayer extends Player{ // Some constants for the code private final int AI = 2; private final int HUMAN = 1; private final int TIE = 0; // constructor, do not touch public StudentPlayer(int playerIndex, int[] boardSize, int nToConnect) { super(playerIndex, boardSize, nToConnect); } /** * @param board - the board that the players are using * @return - an int that represents how good a move is */ @Override public int step(Board board) { int best_score = Integer.MIN_VALUE; int best_move = board.getValidSteps().get(0); for (int move : board.getValidSteps()) { Board new_board = new Board(board); new_board.step(this.AI, move); int score = this.minimax(new_board, 5, false, Integer.MIN_VALUE, Integer.MAX_VALUE); System.out.println(score); if (score > best_score) { best_score = score; best_move = move; } } return best_move; } /** * @param board - the board the players are using * @param move - the move that one of the players will make * @param player_index - the index of the player that makes the move * @return - returns true, if the player wins the game with the move */ private boolean is_winner_move(Board board, int move, int player_index) { Board new_board = new Board(board); new_board.step(player_index, move); return new_board.gameEnded(); } /** * @param board - the board the players are using * @param max_depth - the maximum depth the algorithm will look at * @param is_maximizing - bool flag, signals which player is currently making the move * @param alpha - constant for alpha-beta pruning, initizalize it as -INF * @param beta - constant for alpha-beta pruning, initialize it as +INF * @return - the score of the the last move */ private int minimax(Board board, int max_depth, boolean is_maximizing, int alpha, int beta) { if (--max_depth == 0) { return is_maximizing ? this.getPositionValue(board) : -this.getPositionValue(board); } if (board.gameEnded() && board.getWinner() == 0) { return 0; } if (is_maximizing) { // If we win with one of the next moves, return +INF for (int move : board.getValidSteps()) { if (is_winner_move(board, move, this.AI)) { return 20 + max_depth; } } int best_score = Integer.MIN_VALUE; for (int move : board.getValidSteps()) { Board new_board = new Board(board); new_board.step(this.AI, move); int score = minimax(new_board, max_depth, false, alpha, beta); best_score = Math.max(score, best_score); // alpha beta pruning alpha = Math.max(alpha, score); if (beta <= alpha) break; } return best_score; } // MINIMIZING PLAYER else { // If we win with one of the next moves, return -INF for (int move : board.getValidSteps()) { if (is_winner_move(board, move, this.HUMAN)) { return -20 - max_depth; } } int best_score = Integer.MAX_VALUE; // Check what future moves will look like for (int move : board.getValidSteps()) { Board new_board = new Board(board); new_board.step(this.HUMAN, move); int score = minimax(new_board, max_depth, true, alpha, beta); best_score = Math.min(score, best_score); // alpha beta pruning beta = Math.min(beta, score); if (beta <= alpha) break; } return best_score; } } // -------------------------- THESE FUNCTIONS SHOULD BE IN THE BOARD CLASS --------------------------------------- private int getPositionValue(Board board) { int value = 0; for (int i = 1; i <= 4; i++) { if (this.countInARow(board, i)) value += i; else if (this.countInACol(board, i)) value += i; else if (this.countNDiagonally(board, i)) value += i; else if (this.countNSkewDiagonally(board, i)) value += i; } return value; } private boolean countInARow(Board board, int n_to_connect) { int row = board.getLastPlayerRow(); int col = board.getLastPlayerColumn(); int player_index = board.getLastPlayerIndex(); int n_in_a_row = 0; int startCol = max(0, col - n_to_connect + 1); int endCol = min(boardSize[1], col + n_to_connect); for (int c = startCol; c < endCol; c++) { if (board.getState()[row][c] == player_index) { n_in_a_row++; if (n_in_a_row == n_to_connect) { return true; } } else n_in_a_row = 0; } return false; } private boolean countInACol(Board board, int n_to_connect) { int row = board.getLastPlayerRow(); int col = board.getLastPlayerColumn(); int player_index = board.getLastPlayerIndex(); int n_in_a_col = 0; int startRow = max(0, row - n_to_connect + 1); int endRow = min(boardSize[0], row + n_to_connect); for (int r = startRow; r < endRow; r++) { if (board.getState()[r][col] == player_index) { n_in_a_col++; if (n_in_a_col == n_to_connect) { return true; } } else n_in_a_col = 0; } return false; } private boolean countNDiagonally(Board board, int n_to_connect) { int row = board.getLastPlayerRow(); int col = board.getLastPlayerColumn(); int player_index = board.getLastPlayerIndex(); int n_in_a_diagonal = 0; int stepLeftUp = min(n_to_connect - 1, min(row, col)); int stepRightDown = min(n_to_connect, min(boardSize[0] - row, boardSize[1] - col)); if ((stepLeftUp + stepRightDown) < n_to_connect) return false; for (int diagonalStep = -stepLeftUp; diagonalStep < stepRightDown; diagonalStep++) { if (board.getState()[row + diagonalStep][col + diagonalStep] == player_index) { n_in_a_diagonal++; if (n_in_a_diagonal == n_to_connect) { return true; } } else { n_in_a_diagonal = 0; } } return false; } private boolean countNSkewDiagonally(Board board, int n_to_connect) { int row = board.getLastPlayerRow(); int col = board.getLastPlayerColumn(); int player_index = board.getLastPlayerIndex(); int n_in_a_skew_diagonal = 0; int stepLeftDown = min(n_to_connect - 1, min(boardSize[0] - row - 1, col)); int stepRightUp = min(n_to_connect, min(row + 1, boardSize[1] - col)); if ((stepRightUp + stepLeftDown) < n_to_connect) return false; for (int skewDiagonalStep = -stepLeftDown; skewDiagonalStep < stepRightUp; skewDiagonalStep++) { if (board.getState()[row - skewDiagonalStep][col + skewDiagonalStep] == player_index) { n_in_a_skew_diagonal++; if (n_in_a_skew_diagonal == n_to_connect) { return true; } } else n_in_a_skew_diagonal = 0; } return false; } }
Editor is loading...