C++ 4连续AlphaBeta算法不是很聪明
C++ 4 In a row AlphaBeta algorithm is not very smart
我正在为学校项目制作 AI 控制的 alpha-beta 算法,但我的算法非常不一致。有时它成功地阻止了我所有的动作,有时它只是忽略了我的连续 3 个动作,如 here 所示。怎么会发生这种情况,我该如何解决这个问题?
int alphaBeta(const State board, int alpha, int beta, const Player player, int depth)
{
//Max player = Player::O
//Min player = Player::X
std::vector<Move> possibleMoves = getMoves(board);
if(eval(board)==Player::X){return 9999-depth;} //Player X wins
else if(eval(board)==Player::O){return -9999+depth;} //Player O wins
else if(possibleMoves.size()==0){return 0;} //Tie
else{ //Zoek verder
depth++;
State nextBoard = board;
int result;
if(player==Player::O){
for (Move move: possibleMoves) {
nextBoard = doMove(nextBoard, move);
result = alphaBeta(nextBoard, alpha, beta, Player::X, depth);
if (result > alpha){
alpha = result;
if (depth == 1){
choice = move; //The actual move he will do
}
}
else if (alpha >= beta){
return alpha;
}
}
return alpha;
}
else{
for (Move move: possibleMoves) {
nextBoard = doMove(nextBoard, move);
result = alphaBeta(nextBoard, alpha, beta, Player::O, depth);
if (result < beta){
beta = result;
if (depth == 1){
choice = move;
}
}
else if (beta <= alpha){
return beta;
}
}
return beta;
}
}
}
您重复修改 nextBoard
,向其添加(可能是非法的)移动:
nextBoard = doMove(nextBoard, move);
但你应该在原来的棋盘上依次尝试每一步:
State nextBoard = doMove(board, move);
(免责声明:可能还有其他问题。)
1) 不要评估递归调用中的每个节点,那样会花费太多时间。仅评估叶节点。
2) 在minimax递归调用中使用边界条件,如果深度超过一定值则终止;每个分支都不会导致获胜,并且搜索太大,程序可能会挂起。
3) 考虑在顶级分支上使用 multi-thread 以加快搜索速度。
int alphaBeta(const State board, int alpha, int beta, const Player player, int depth)
{
std::vector<Move> possibleMoves = getMoves(board);
if(CheckForWinX(board))
{
return 9999;
}
else
if(CheckForWinO(board))
{
return -9999;
}
else
if(possibleMoves.size()==0)
{
return 0;
}
else
if( depth >= 5) // without this boundary condition, the search tree will too big
{
return eval(board); // evaluate ( which is more time expensive than CheckForWin() ) only the leaf node, not every nodes
}
else{
depth++;
State nextBoard = board;
int result;
if(player==Player::O){
/**/
return alpha;
}
else{
/**/
return beta;
}
}
}
我正在为学校项目制作 AI 控制的 alpha-beta 算法,但我的算法非常不一致。有时它成功地阻止了我所有的动作,有时它只是忽略了我的连续 3 个动作,如 here 所示。怎么会发生这种情况,我该如何解决这个问题?
int alphaBeta(const State board, int alpha, int beta, const Player player, int depth)
{
//Max player = Player::O
//Min player = Player::X
std::vector<Move> possibleMoves = getMoves(board);
if(eval(board)==Player::X){return 9999-depth;} //Player X wins
else if(eval(board)==Player::O){return -9999+depth;} //Player O wins
else if(possibleMoves.size()==0){return 0;} //Tie
else{ //Zoek verder
depth++;
State nextBoard = board;
int result;
if(player==Player::O){
for (Move move: possibleMoves) {
nextBoard = doMove(nextBoard, move);
result = alphaBeta(nextBoard, alpha, beta, Player::X, depth);
if (result > alpha){
alpha = result;
if (depth == 1){
choice = move; //The actual move he will do
}
}
else if (alpha >= beta){
return alpha;
}
}
return alpha;
}
else{
for (Move move: possibleMoves) {
nextBoard = doMove(nextBoard, move);
result = alphaBeta(nextBoard, alpha, beta, Player::O, depth);
if (result < beta){
beta = result;
if (depth == 1){
choice = move;
}
}
else if (beta <= alpha){
return beta;
}
}
return beta;
}
}
}
您重复修改 nextBoard
,向其添加(可能是非法的)移动:
nextBoard = doMove(nextBoard, move);
但你应该在原来的棋盘上依次尝试每一步:
State nextBoard = doMove(board, move);
(免责声明:可能还有其他问题。)
1) 不要评估递归调用中的每个节点,那样会花费太多时间。仅评估叶节点。
2) 在minimax递归调用中使用边界条件,如果深度超过一定值则终止;每个分支都不会导致获胜,并且搜索太大,程序可能会挂起。
3) 考虑在顶级分支上使用 multi-thread 以加快搜索速度。
int alphaBeta(const State board, int alpha, int beta, const Player player, int depth)
{
std::vector<Move> possibleMoves = getMoves(board);
if(CheckForWinX(board))
{
return 9999;
}
else
if(CheckForWinO(board))
{
return -9999;
}
else
if(possibleMoves.size()==0)
{
return 0;
}
else
if( depth >= 5) // without this boundary condition, the search tree will too big
{
return eval(board); // evaluate ( which is more time expensive than CheckForWin() ) only the leaf node, not every nodes
}
else{
depth++;
State nextBoard = board;
int result;
if(player==Player::O){
/**/
return alpha;
}
else{
/**/
return beta;
}
}
}