package de.tims.tictactoe.ai; import de.tims.tictactoe.GameLogic; public class AIHard implements TicTacToeAI { private static final char AI_CHAR = 'o'; private static final char EMPTY_CHAR = '-'; private static final char PLAYER_CHAR = 'x'; private static final int BOARD_SIZE = 3; private GameLogic gl; public AIHard(GameLogic gl) throws IllegalArgumentException { if (gl.getBoard().length != BOARD_SIZE) { throw new IllegalArgumentException("Hard AI only supports 3x3 boards!"); } this.gl = gl; } @Override public void calculateNextMove() { char[][] board = gl.getBoard(); int row; int col; int charsInRow = 0; int charsInCol = 0; int charsInDiag = 0; char actualChar; for (int i = 0; i < 2; i++) { actualChar = (i == 0) ? AI_CHAR : PLAYER_CHAR; for (int j = 0; j < BOARD_SIZE; j++) { charsInRow = countCharsInRow(j, actualChar); charsInCol = countCharsInCol(j, actualChar); if (j < 2) { charsInDiag = countCharsInDiag(j, actualChar); if (charsInDiag == BOARD_SIZE - 1) { for (int k = 0; k < BOARD_SIZE; k++) { row = k; col = (j == 0) ? k : BOARD_SIZE - 1 - k; if (board[row][col] == EMPTY_CHAR) { gl.setField(row, col, AI_CHAR); return; } } } } if (charsInRow == BOARD_SIZE - 1 || charsInCol == BOARD_SIZE - 1) { for (int k = 0; k < BOARD_SIZE; k++) { if (charsInRow == BOARD_SIZE - 1) { row = j; col = k; if (board[row][col] == EMPTY_CHAR) { gl.setField(row, col, AI_CHAR); return; } } if (charsInCol == BOARD_SIZE - 1) { row = k; col = j; if (board[row][col] == EMPTY_CHAR) { gl.setField(row, col, AI_CHAR); return; } } } } } } if (board[BOARD_SIZE / 2][BOARD_SIZE / 2] == EMPTY_CHAR) { gl.setField(BOARD_SIZE / 2, BOARD_SIZE / 2, AI_CHAR); return; } else if (board[BOARD_SIZE / 2][BOARD_SIZE / 2] == AI_CHAR && (board[0][0] == AI_CHAR || board[0][BOARD_SIZE - 1] == AI_CHAR || board[BOARD_SIZE - 1][0] == AI_CHAR || board[BOARD_SIZE - 1][BOARD_SIZE - 1] == AI_CHAR)) { int onwCharsInRow = 0; int ownCharsInCol = 0; int emptyCharsInRow = 0; int emptyCharsInCol = 0; for (int i = BOARD_SIZE - 2; i > 0; i--) { for (int j = 0; j < BOARD_SIZE; j += BOARD_SIZE - 1) { for (int k = 1; k < BOARD_SIZE - 1; k++) { for (int l = 0; l < 2; l++) { row = (l == 0) ? j : k; col = (l == 0) ? k : j; onwCharsInRow = countCharsInRow(row, AI_CHAR); ownCharsInCol = countCharsInCol(col, AI_CHAR); emptyCharsInRow = countCharsInRow(row, EMPTY_CHAR); emptyCharsInCol = countCharsInCol(col, EMPTY_CHAR); if (onwCharsInRow >= i && ownCharsInCol >= i && emptyCharsInRow >= BOARD_SIZE - onwCharsInRow && emptyCharsInCol == BOARD_SIZE - ownCharsInCol) { gl.setField(row, col, AI_CHAR); return; } } } } } } else { boolean emptyEdgeFound = false; row = -1; col = -1; int prioRow = -1; int prioCol = -1; for (int i = 0; i < BOARD_SIZE; i = i + BOARD_SIZE - 1) { for (int j = 0; j < BOARD_SIZE; j = j + BOARD_SIZE - 1) { if (board[i][j] == EMPTY_CHAR) { row = (row == -1) ? i : row; col = (col == -1) ? j : col; if (countCharsInRow(i, PLAYER_CHAR) != 0 || countCharsInCol(j, PLAYER_CHAR) != 0) { prioRow = i; prioCol = j; emptyEdgeFound = true; break; } } } if (emptyEdgeFound) { break; } } if (row != -1 && col != -1) { row = (prioRow != -1) ? prioRow : row; col = (prioCol != -1) ? prioCol : col; gl.setField(row, col, AI_CHAR); return; } } for (row = 0; row < BOARD_SIZE; row++) { for (col = 0; col < BOARD_SIZE; col++) { if (board[row][col] == EMPTY_CHAR) { gl.setField(row, col, AI_CHAR); return; } } } } public int countCharsInRow(int index, char charToCount) { int count = 0; char[][] board = gl.getBoard(); for (int i = 0; i < BOARD_SIZE; i++) { count += (board[index][i] == charToCount) ? 1 : 0; } return count; } public int countCharsInCol(int index, char charToCount) { int count = 0; char[][] board = gl.getBoard(); for (int i = 0; i < BOARD_SIZE; i++) { count += (board[i][index] == charToCount) ? 1 : 0; } return count; } public int countCharsInDiag(int index, char charToCount) throws IndexOutOfBoundsException { if (index < 0 || index > 1) { throw new IndexOutOfBoundsException("Only 0 and 1 are allowed values for index!"); } int count = 0; char[][] board = gl.getBoard(); for (int i = 0; i < BOARD_SIZE; i++) { count += (board[i][(index == 0) ? i : BOARD_SIZE - 1 - i] == charToCount) ? 1 : 0; } return count; } }