152 lines
4.5 KiB
Java
152 lines
4.5 KiB
Java
package com.game.tictacteo.engine;
|
|
|
|
import android.util.Log;
|
|
|
|
public class GameAI {
|
|
|
|
static final byte player = 2;
|
|
static final byte opponent = 1;
|
|
|
|
private static Boolean isMovesLeft(byte board[][]) {
|
|
for (int i = 0; i < board.length; i++)
|
|
for (int j = 0; j < board[i].length; j++)
|
|
if (board[i][j] == 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
private static int evaluate(byte[][] board) {
|
|
// Checking for Rows is player or opponent victory.
|
|
for (int row = 0; row < board.length; row++) {
|
|
if (board[row][0] == board[row][1] &&
|
|
board[row][1] == board[row][2]) {
|
|
if (board[row][0] == player)
|
|
return +10;
|
|
else if (board[row][0] == opponent)
|
|
return -10;
|
|
}
|
|
}
|
|
|
|
|
|
for (int col = 0; col < board[0].length; col++) {
|
|
if (board[0][col] == board[1][col] &&
|
|
board[1][col] == board[2][col]) {
|
|
if (board[0][col] == player)
|
|
return +10;
|
|
|
|
else if (board[0][col] == opponent)
|
|
return -10;
|
|
}
|
|
}
|
|
|
|
if (board[0][0] == board[1][1] && board[1][1] == board[2][2]) {
|
|
if (board[0][0] == player)
|
|
return +10;
|
|
else if (board[0][0] == opponent)
|
|
return -10;
|
|
}
|
|
|
|
if (board[0][2] == board[1][1] && board[1][1] == board[2][0]) {
|
|
if (board[0][2] == player)
|
|
return +10;
|
|
else if (board[0][2] == opponent)
|
|
return -10;
|
|
}
|
|
|
|
// Else if none of them have won then return 0
|
|
return 0;
|
|
}
|
|
|
|
private static int minimax(byte board[][], int depth, Boolean isMax) {
|
|
int score = evaluate(board);
|
|
|
|
// Evaluated score if Maximizer has won the game
|
|
if (score == 10)
|
|
return score;
|
|
|
|
if (score == -10)
|
|
return score;
|
|
|
|
// no winner then it is a tie if false
|
|
if (isMovesLeft(board) == false)
|
|
return 0;
|
|
|
|
if (isMax) {
|
|
int best = -1000;
|
|
|
|
// Traverse all cells
|
|
for (int i = 0; i < board.length; i++) {
|
|
for (int j = 0; j < board[i].length; j++) {
|
|
// Check cell is empty
|
|
if (board[i][j] == 0) {
|
|
// Make the move
|
|
board[i][j] = player;
|
|
|
|
// calculate minimax recursively and choose
|
|
best = Math.max(best, minimax(board, depth + 1, !isMax));
|
|
|
|
// Undo move
|
|
board[i][j] = 0;
|
|
}
|
|
}
|
|
}
|
|
return best;
|
|
}else {
|
|
int best = 1000;
|
|
|
|
// Traverse all cells
|
|
for (int i = 0; i < board.length; i++) {
|
|
for (int j = 0; j < board[i].length; j++) {
|
|
// Check cell is empty
|
|
if (board[i][j] == 0) {
|
|
// Make the move
|
|
board[i][j] = opponent;
|
|
|
|
// calculate minimax recursively and choose
|
|
best = Math.min(best, minimax(board,
|
|
depth + 1, !isMax));
|
|
|
|
// Undo move
|
|
board[i][j] = 0;
|
|
}
|
|
}
|
|
}
|
|
return best;
|
|
}
|
|
}
|
|
|
|
public static int[] findBestMove(byte board[][]) {
|
|
int bestVal = -1000;
|
|
int[] bestMove = new int[2];
|
|
bestMove[0] = -1;
|
|
bestMove[1] = -1;
|
|
|
|
// evaluate minimax func
|
|
for (int i = 0; i < board.length; i++) {
|
|
for (int j = 0; j < board[i].length; j++) {
|
|
// Check cell is empty
|
|
if (board[i][j] == 0) {
|
|
// Make the move
|
|
board[i][j] = player;
|
|
|
|
// compute evaluation function
|
|
int moveVal = minimax(board, 0, false);
|
|
|
|
// Undo the move
|
|
board[i][j] = 0;
|
|
|
|
// If the value of the current move is higher then best value, then update
|
|
if (moveVal > bestVal) {
|
|
bestMove[0] = i;
|
|
bestMove[1] = j;
|
|
bestVal = moveVal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return bestMove;
|
|
}
|
|
|
|
}
|