I am currently trying to implement a simple tic tac toe game in flutter. I am using a minimax function to calculate the AI player moves. For the simplest 3×3 list array, the minimax function works perfectly. But when i try to use the same minimax function for 4×4,5×5, 6×6 list array(to make the game a little bit more complex and interesting), the minimax function seems to run endlessly without returning a move, no matter what i do(i added alpha-beta pruning to no avail). What am i doing wrong. Any help will be appreciated. The following are the main functions i am using:
int minimax(List<List<String>> board, bool isMaximizing, BuildContext context, int alpha, int beta) {
// Check for terminal states
if (checkWin(board, 'O', context)) {
return 1;
} else if (checkWin(board, 'X', context)) {
return -1;
} else if (checkDraw(board)) {
return 0;
}
// Recursively explore the game tree
if (isMaximizing) {
int bestScore = -1000;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (board[i][j].isEmpty) {
board[i][j] = 'O';
int score = minimax(board, false, context, alpha, beta);
board[i][j] = '';
bestScore = max(score, bestScore);
alpha = max(alpha, score);
if (beta <= alpha) {
break; // Prune the subtree
}
}
}
}
return bestScore;
} else {
int bestScore = 1000;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (board[i][j].isEmpty) {
board[i][j] = 'X';
int score = minimax(board, true, context, alpha, beta,);
board[i][j] = '';
bestScore = min(score, bestScore);
beta = min(beta, score);
if (beta <= alpha) {
break; // Prune the subtree
}
}
}
}
return bestScore;
}
}
bool checkWin(List<List<String>> board, String player, BuildContext context) {
for (int i = 0; i < 4; i++) {
if ((board[i][0] == player &&
board[i][1] == player && board[i][2] == player && board[i][3] == player) || (board[0][i] == player &&
board[1][i] == player && board[2][i] == player && board[3][i] == player)) {
//Testing for winning cells so as to add colors
if(context.read<SharedPrefProvider>().hardLevel % 2 != 0) {
checkWinColors(board, player, i, context);
}
return true;
}
}
if ((board[0][0] == player && board[1][1] == player && board[2][2] == player && board[3][3] == player) ||
(board[0][3] == player && board[1][2] == player && board[2][1] == player && board[3][0] == player)) {
//Testing for winning cells so as to add colors
if(context.read<SharedPrefProvider>().hardLevel % 2 != 0) {
checkWinColors(board, player, 0, context);
}
return true;
}
return false;
}
bool checkDraw(List<List<String>> board) {
// Check if every row has every cell filled
for (var row in board) {
for (var cell in row) {
if (cell.isEmpty) {
return false; // If any cell is empty, the game is not a draw
}
}
}
// If all cells are filled, the game is a draw
return true;
}
The following function calls the minimax function to get the index of the best AI move on the board
void makeAIMove(board) {
int bestScore = -1000;
int bestMoveRow = -1;
int bestMoveCol = -1;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (board[i][j].isEmpty) {
board[i][j] = 'O';
int score = minimax(board, false, context, -1000, 1000);
board[i][j] = '';
if (score > bestScore) {
bestScore = score;
bestMoveRow = i;
bestMoveCol = j;
}else{
}
}
}
}
//Returns index of the next move on the board
if (bestMoveRow != -1 && bestMoveCol != -1) {
setState(() {
board[bestMoveRow][bestMoveCol] = "O";
});
}
}