Функция минимакс и альфа-бета
Минимакс (Minimax) и альфа-бета отсечение (Alpha-Beta Pruning) являются алгоритмами, используемыми в игровом искусственном интеллекте для принятия решений в стратегических играх, таких как шахматы или игра в крестики-нолики.
Минимакс - это алгоритм, который предполагает, что каждый игрок принимает наилучшее (максимальное) решение, тогда как противник пытается выбрать наихудшее (минимальное) решение. Алгоритм стремится максимизировать свою выигрышную позицию, учитывая возможные ходы противника. Минимакс используется для поиска оптимального решения в дереве игры путем просмотра всех возможных ходов и их последствий.
Альфа-бета отсечение (Alpha-Beta Pruning) - это метод, который ускоряет вычисления минимакса путем игнорирования некоторых ветвей дерева, которые уже не могут принести улучшения текущему решению. При проходе через дерево игры, альфа-бета отсечение отсекает ветви, которые не могут привести к лучшему результату, поэтому они не исследуются дальше. Это позволяет существенно уменьшить количество проверок в поиске оптимального решения.
Программный код с комментариями
struct move
{
int oldX;
int oldY;
int newX;
int newY;
};
std::vector <int> CheckRoutesAI(int x, int y)
{
std::vector <int> returned_move_vec;
if (board_char[x + 1][y] == '0') // низ
{
returned_move_vec.push_back((x + 1) * 10 + y);
}
if (board_char[x + 1][y] == '2' && board_char[x + 2][y] == '0') // низ перепрыгивая шашку
{
returned_move_vec.push_back((x + 2) * 10 + y);
}
if (board_char[x][y - 1] == '0') // лево
{
returned_move_vec.push_back(x * 10 + (y - 1));
}
if (board_char[x][y - 1] == '2' && board_char[x][y - 2] == '0') // лево перепрыгивая шашку
{
returned_move_vec.push_back(x * 10 + (y - 2));
}
if (board_char[x][y + 1] == '0') // право
{
returned_move_vec.push_back(x * 10 + (y + 1));
}
if (board_char[x][y + 1] == '2' && board_char[x][y + 2] == '0') // право перепрыгивая шашку
{
returned_move_vec.push_back(x * 10 + (y + 2));
}
return returned_move_vec;
}
void move_AI(int old_x, int old_y, int new_x, int new_y) // Ход AI
{
board_char[new_x][new_y] = '1';
board_char[old_x][old_y] = '0';
++queue;
++move_count_black;
}
void StartMiniMaxFunction() // Старт минимакс
{
int best = INT_MIN;
move bestMove;
for (int i = 0; i < 8; ++i)
{
for (int j = 0; j < 8; ++j)
{
if (board_char[i][j] == '1')
{
std::vector<int> possibleMoves = CheckRoutesAI(i, j);
for (auto coord : possibleMoves)
{
char curBoard[8][8];
for (int k = 0; k < 8; ++k)
{
for (int t = 0; t < 8; ++t)
{
curBoard[k][t] = board_char[k][t];
}
}
int currentVal = minimax(curBoard, 3, INT_MIN, INT_MAX, false);
if (currentVal > best)
{
best = currentVal;
bestMove.oldX = i;
bestMove.oldY = j;
bestMove.newX = coord / 10;
bestMove.newY = coord % 10;
}
}
}
}
}
move_AI(bestMove.oldX, bestMove.oldY, bestMove.newX, bestMove.newY);
}
int minimax(char field[8][8], int depth, int alpha, int beta, bool maximizingPlayer) // Минимакс
{
if (depth == 0 || CheckWin() != '0')
return EvaluationFunction(field);
if (maximizingPlayer)
{
int max = INT_MIN;
for (int i = 0; i < 8; ++i)
{
for (int j = 0; j < 8; ++j)
{
if (max >= beta)
{
return max;
}
if (field[i][j] == '1')
{
std::vector<int> possibleMoves = CheckRoutesAI(i, j);
for (auto coord : possibleMoves)
{
char curBoard[8][8];
for (int k = 0; k < 8; ++k)
{
for (int t = 0; k < 8; ++k)
{
curBoard[k][t] = board_char[k][t];
}
}
curBoard[i][j] = '0';
curBoard[coord / 10][coord % 10] = '1';
int val = minimax(curBoard, depth - 1, alpha, beta, false);
max = std::max(max, val);
alpha = std::max(alpha, val);
}
}
}
}
return max;
}
else
{
int min = INT_MAX;
for (int i = 0; i < 8; ++i)
{
for (int j = 0; j < 8; ++j)
{
if (min <= alpha)
{
return min;
}
if (field[i][j] == '1')
{
std::vector<int> possibleMoves = CheckRoutesAI(i, j);
for (auto coord : possibleMoves)
{
char curBoard[8][8];
for (int k = 0; k < 8; ++k)
{
for (int t = 0; k < 8; ++k)
{
curBoard[k][t] = board_char[k][t];
}
}
curBoard[i][j] = '0';
curBoard[coord / 10][coord % 10] = '1';
int val = minimax(curBoard, depth - 1, alpha, beta, true);
min = std::min(min, val);
beta = std::min(beta, val);
}
}
}
}
return min;
}
}
