I’m trying to create a game of checkers and play for the computer using minimax, but somehow I can’t find an error that causes the player to be favored over the computer when calculating minimax, and in main in the variable val I get more values if the computer is not doing well, somehow I can’t find it cause. Thank you for all the comments
minimax function
int CGame::minimax(CGame& game, int depth, int alpha, int beta, bool isMaximizingPlayer, Color playerColor)
{
if(game.isFinished() || depth == 0)
return evaluateBoard(game.m_Board, playerColor);
if (isMaximizingPlayer)
{
int maxEval = std::numeric_limits<int>::min();
for (const auto& [from, to] : game.m_Computer_Playable_Positions)
{
CGame newGame = game;
if(to.size() == 1 && isMove(from.first, from.second, to[0].first, to[0].second))
{
newGame.m_Board.makeMove(from.first, from.second, to[0].first, to[0].second, playerColor);
}
else
{
for (const auto& [toI, toJ] : to)
{
newGame.m_Board.makeAttack(from.first, from.second, toI, toJ, playerColor);
}
}
int eval = minimax(newGame, depth - 1, alpha, beta, false, m_Player);
maxEval = std::max(maxEval, eval);
alpha = std::max(alpha, maxEval);
if(beta <= alpha)
break;
}
return maxEval;
}
else
{
int minEval = std::numeric_limits<int>::max();
for (const auto& [from, to] : game.m_Player_Playable_Positions)
{
CGame newGame = game;
if (to.size() == 1 && isMove(from.first, from.second, to[0].first, to[0].second))
{
newGame.m_Board.makeMove(from.first, from.second, to[0].first, to[0].second, playerColor);
}
else
{
for (const auto& [toI, toJ] : to)
{
newGame.m_Board.makeAttack(from.first, from.second, toI, toJ, playerColor);
}
}
int eval = minimax(newGame, depth - 1, alpha, beta, true, m_Computer);
minEval = std::min(minEval, eval);
beta = std::min(beta, minEval);
if (beta <= alpha)
break; // Pruning
}
return minEval;
}
}
int main()
{
// BLACK- player , WHITE - computer
CGame game(8, Color::BLACK, Color::WHITE);
bool playerOnMove = 0;
while(!game.isFinished())
{
if(playerOnMove)
{
// player .. - manul from terminal
}
else
{
int bestMoveValue = std::numeric_limits<int>::min();
pair<long int, long int> bestMoveFrom;
vector<pair<long int, long int>> bestMoveTo;
for(const auto& [from, to] : game.m_Computer_Playable_Positions)
{
int depth = 7;
CGame gameCopy = game;
if(to.size() == 1 && isMove(from.first, from.second, to[0].first, to[0].second))
{
gameCopy.m_Board.makeMove(from.first, from.second, to[0].first, to[0].second, gameCopy.m_Computer);
}
else
{
for(const auto &[toI, toJ] : to)
{
gameCopy.m_Board.makeAttack(from.first, from.second, toI, toJ, gameCopy.m_Computer);
}
}
int val = gameCopy.minimax(gameCopy, depth, std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), true, gameCopy.m_Computer);
if (val > bestMoveValue)
{
bestMoveValue = val;
bestMoveFrom = from;
bestMoveTo = {to};
}
}
game.makeComputerMove(bestMoveFrom.first, bestMoveFrom.second, bestMoveTo);
}
playerOnMove = !playerOnMove;
}
Eval function
int CGame::evaluateBoard(const CBoard& board, Color player)
{
int score = 0;
for(long int i=0; i<board.getSize(); i++)
{
for(long int j=0; j<board.getSize(); j++)
{
if(board[i][j].getType() == Type::STONE)
{
if(board[i][j].getColor() == player)
score += 10;
else
score -= 10;
if(i > m_Board.getSize()/2 && (board[i][j].getType() == Type::STONE || board[i][j].getType() == Type::QUEEN) && board[i][j].getColor() == Color::WHITE)
{
if(player == Color::WHITE)
score += 3;
else
score -= 3;
}
else if(i < m_Board.getSize()/2 && (board[i][j].getType() == Type::STONE || board[i][j].getType() == Type::QUEEN) && board[i][j].getColor() == Color::BLACK)
{
if(player == Color::BLACK)
score += 3;
else
score -= 3;
}
}
else if(board[i][j].getType() == Type::QUEEN)
{
if(board[i][j].getColor() == player)
score += 30;
else
score -= 30;
}
}
}
int gameStatus = isFinished();
if (gameStatus != 0)
{
if((gameStatus == 1 && player == m_Player) || (gameStatus == 2 && player == m_Computer))
score += 1000;
else
score -= 1000;
}
return score;
}
Checkers game c++ minimax
New contributor
user24995323 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.