C++编写五子棋AI
编写五子棋AI可以使用极大极小算法(MinMax Algorithm)和Alpha-Beta剪枝(Alpha-Beta Pruning)来优化算法效率。以下是一个简单的示例代码:
#include <iostream>
#include <vector>
#include <climits>
const int SIZE = 15; // 棋盘大小
enum class Player {
NONE,
BLACK,
WHITE
};
struct Move {
int row;
int col;
};
// 判断棋盘上某位置是否合法
bool isValidMove(int row, int col) {
return row >= 0 && row < SIZE && col >= 0 && col < SIZE;
}
// 判断游戏是否结束
bool isGameOver(const std::vector<std::vector<Player>>& board, Player& winner) {
int directions[4][2] = {{1, 0}, {0, 1}, {1, 1}, {-1, 1}}; // 四个方向:横、竖、斜、反斜
for (int row = 0; row < SIZE; ++row) {
for (int col = 0; col < SIZE; ++col) {
if (board[row][col] == Player::NONE) {
continue;
}
Player currPlayer = board[row][col];
for (const auto& direction : directions) {
int dx = direction[0];
int dy = direction[1];
int count = 1;
for (int i = 1; i < 5; ++i) {
int newRow = row + dx * i;
int newCol = col + dy * i;
if (isValidMove(newRow, newCol) && board[newRow][newCol] == currPlayer) {
++count;
} else {
break;
}
}
if (count == 5) {
winner = currPlayer;
return true;
}
}
}
}
return false;
}
// 评估当前局面分数
int evaluate(const std::vector<std::vector<Player>>& board) {
int score = 0;
int directions[4][2] = {{1, 0}, {0, 1}, {1, 1}, {-1, 1}};
for (int row = 0; row < SIZE; ++row) {
for (int col = 0; col < SIZE; ++col) {
if (board[row][col] == Player::NONE) {
continue;
}
Player currPlayer = board[row][col];
for (const auto& direction : directions) {
int dx = direction[0];
int dy = direction[1];
int count = 1;
int emptyCount = 0;
for (int i = 1; i < 5; ++i) {
int newRow = row + dx * i;
int newCol = col + dy * i;
if (isValidMove(newRow, newCol) && board[newRow][newCol] == currPlayer) {
++count;
} else if (isValidMove(newRow, newCol) && board[newRow][newCol] == Player::NONE) {
++emptyCount;
} else {
break;
}
}
score += (count * count * count * count) * (currPlayer == Player::BLACK ? 1 : -1);
score += (emptyCount * emptyCount * emptyCount * emptyCount) * (currPlayer == Player::BLACK ? 1 : -1);
}
}
}
return score;
}
// 极大极小算法
int minimax(std::vector<std::vector<Player>> board, int depth, bool isMaximizingPlayer) {
Player winner = Player::NONE;
if (isGameOver(board, winner)) {
if (winner == Player::BLACK) {
return INT_MAX;
} else if (winner == Player::WHITE) {
return INT_MIN;
} else {
return 0;
}
}
if (depth == 0) {
return evaluate(board);
}
if (isMaximizingPlayer) {
int maxEval = INT_MIN;
for (int row = 0; row < SIZE; ++row) {
for (int col = 0; col < SIZE; ++col) {
if (board[row][col] == Player::NONE) {
board[row][col] = Player::BLACK;
int eval = minimax(board, depth - 1, false);
board[row][col] = Player::NONE;
maxEval = std::max(maxEval, eval);
}
}
}
return maxEval;
} else {
int minEval = INT_MAX;
for (int row = 0; row < SIZE; ++row) {
for (int col = 0; col < SIZE; ++col) {
if (board[row][col] == Player::NONE) {
board[row][col] = Player::WHITE;
int eval = minimax(board, depth - 1, true);
board[row][col] = Player::NONE;
minEval = std::min(minEval, eval);
}
}
}
return minEval;
}
}
// Alpha-Beta剪枝
int alphabeta(std::vector<std::vector<Player>> board, int depth, int alpha, int beta, bool isMaximizingPlayer) {
Player winner = Player::NONE;
if (isGameOver(board, winner)) {
if (winner == Player::BLACK) {
return INT_MAX;
} else if (winner == Player::WHITE) {
return INT_MIN;
} else {
return 0;
}
}
if (depth == 0) {
return evaluate(board);
}
if (isMaximizingPlayer) {
int maxEval = INT_MIN;
for (int row = 0; row < SIZE; ++row) {
for (int col = 0; col < SIZE; ++col) {
if (board[row][col] == Player::NONE) {
board[row][col] = Player::BLACK;
int eval = alphabeta(board, depth - 1, alpha, beta, false);
board[row][col] = Player::NONE;
maxEval = std::max(maxEval, eval);
alpha = std::max(alpha, eval);
if (beta <= alpha) {
break;
}
}
}
}
return maxEval;
} else {
int minEval = INT_MAX;
for (int row = 0; row < SIZE; ++row) {
for (int col = 0; col < SIZE; ++col) {
if (board[row][col] == Player::NONE) {
board[row][col] = Player::WHITE;
int eval = alphabeta(board, depth - 1, alpha, beta, true);
board[row][col] = Player::NONE;
minEval = std::min(minEval, eval);
beta = std::min(beta, eval);
if (beta <= alpha) {
break;
}
}
}
}
return minEval;
}
}
// 获取AI的下一步落子位置
Move getNextMove(const std::vector<std::vector<Player>>& board, int depth, bool useAlphaBeta) {
Move bestMove;
int bestScore = INT_MIN;
Player currPlayer = Player::BLACK; // AI执黑棋
if (!useAlphaBeta) {
for (int row = 0; row < SIZE; ++row) {
for (int col = 0; col < SIZE; ++col) {
if (board[row][col] == Player::NONE) {
std::vector<std::vector<Player>> newBoard = board;
newBoard[row][col] = currPlayer;
int score = minimax(newBoard, depth, false);
if (score > bestScore) {
bestScore = score;
bestMove.row = row;
bestMove.col = col;
}
}
}
}
} else {
int alpha = INT_MIN;
int beta = INT_MAX;
for (int row = 0; row < SIZE; ++row) {
for (int col = 0; col < SIZE; ++col) {
if (board[row][col] == Player::NONE) {
std::vector<std::vector<Player>> newBoard = board;
newBoard[row][col] = currPlayer;
int score = alphabeta(newBoard, depth, alpha, beta, false);
if (score > bestScore) {
bestScore = score;
bestMove.row = row;
bestMove.col = col;
}
alpha = std::max(alpha, score);
}
}
}
}
return bestMove;
}
int main() {
std::vector<std::vector<Player>> board(SIZE, std::vector<Player>(SIZE, Player::NONE));
// AI执黑棋,玩家执白棋
Player currPlayer = Player::BLACK;
Player winner = Player::NONE;
while (!isGameOver(board, winner)) {
// 玩家输入下一步落子位置
int row, col;
std::cin >> row >> col;
if (isValidMove(row, col) && board[row][col] == Player::NONE) {
board[row][col] = Player::WHITE;
} else {
std::cout << "Invalid move. Please try again." << std::endl;
continue;
}
// AI计算下一步落子位置
Move nextMove = getNextMove(board, 4, true);
board[nextMove.row][nextMove.col] = Player::BLACK;
// 打印棋盘
for (int row = 0; row < SIZE; ++row) {
for (int col = 0; col < SIZE; ++col) {
switch (board[row][col]) {
case Player::NONE:
std::cout << ".";
break;
case Player::BLACK:
std::cout << "X";
break;
case Player::WHITE:
std::cout << "O";
break;
}
}
std::cout << std::endl;
}
}
if (winner == Player::BLACK) {
std::cout << "AI wins!" << std::endl;
} else if (winner == Player::WHITE) {
std::cout << "Player wins!" << std::endl;
} else {
std::cout << "It's a draw!" << std::endl;
}
return 0;
}
这个示例代码实现了一个简单的五子棋AI,通过极大极小算法和Alpha-Beta剪枝来搜索最优解。其中,isValidMove函数用于判断落子位置是否合法,isGameOver函数用于判断游戏是否结束,evaluate函数用于评估当前局面分数,minimax函数用于执行极大极小算法,alphabeta函数用于执行Alpha-Beta剪枝,getNextMove函数用于获取AI的下一步落子位置。
在main函数中,先由玩家输入下一步落子位置,然后AI计算下一步落子位置,并将落子位置打印到控制台。
需要注意的是,这只是一个简单的示例,实际的五子棋AI可能需要更复杂的算法和策略来提高性能和游戏水平
原文地址: https://www.cveoy.top/t/topic/h6QJ 著作权归作者所有。请勿转载和采集!