我正在为我的AI课程开展项目,我们需要实施深度限制的极小极大搜索,然后在Ultimate Tic-Tac-Toe或Tic-Tac-Toe-游戏中添加alpha-beta修剪Ception。这个版本的tic-tac-toe是3x3游戏板,由3x3游戏板组成。当您在smallBoards上的空间中进行游戏时,您刚刚玩过的移动对应于对手将要玩的下一个smallBoard。我已经能够找到常规tic tac toe的结果,但由于游戏规则它们并不适用。
如果您在左上角的中央进行游戏,下一位玩家将在bigBoard的中心板上玩牌。提供了这两个动作的图片。红色是第一个球员。
Here's the picture of the first two moves
我们的麻烦在于我们的alpha-beta实现。
关于我们的深度极限极小极大搜索
我们的minimax实现似乎正常工作。当我们尝试实现alpha-beta时,我们的AI代理正确地停止了功能。
我们的minimax实现代码如下:
function evaluateMove(outerX2, outerY2, innerX2, innerY2, depth, isAI, tempBoard)
{
var currentBoard = JSON.parse( JSON.stringify( tempBoard ));
var score = 0;
var bestScore = 0;
var playerZZ;
if (isAI) {
playerZZ = 2;
}
else {
playerZZ = 1;
}
if(checkForWin(2, JSON.parse( JSON.stringify( currentBoard )), outerX2, outerY2, innerX2, innerY2))
{
//AI wins
return 10;
}
if(checkForWin(1, JSON.parse( JSON.stringify( currentBoard )), outerX2, outerY2, innerX2, innerY2))
{
//Human wins
return -10;
}
else if (depth == 2) {
return 0;
}
if (checkForBoardWin(innerX2, innerY2, 1) || checkForBoardWin(innerX2, innerY2, 2))
{
if (isAI)
{
bestScore = -100;
for (var X = 0; X < 3; X++)
{
for (var Y = 0; Y < 3; Y++)
{
for (var x = 0; x < 3; x++)
{
for (var y = 0; y < 3; y++)
{
if(currentBoard[X][Y][x][y] == 0 && !(checkForBoardWin(X, Y, 1) || checkForBoardWin(X, Y, 2)))
{
//JAKE: Broken here?
currentBoard[X][Y][x][y] = 2
score = evaluateMove(X, Y, x, y, depth + 1, false, currentBoard);
//var bestScore = -100;
if (score > bestScore)
{
console.log("Line 105: Score = ", score);
return score;
}
else
{
return bestScore;
}
}
}
}
}
}
}
else
{
bestScore = 100;
for (var X = 0; X < 3; X++)
{
for (var Y = 0; Y < 3; Y++)
{
for (var x = 0; x < 3; x++)
{
for (var y = 0; y < 3; y++)
{
if(currentBoard[X][Y][x][y] == 0)
{
currentBoard[X][Y][x][y] = 1
score = evaluateMove(X, Y, x, y, depth + 1, false, currentBoard);
//bestScore = 100;
if (score < bestScore)
{
console.log("Line 137: Score = ", score);
return score;
}
else
{
return bestScore;
}
}
}
}
}
}
}
}
else
{
bestScore = -100;
if (isAI)
{
for(var x = 0; x < 3; x++)
{
for (var y = 0; y < 3; y++)
{
if(currentBoard[innerX2][innerY2][x][y] == 0)
{
//JAKE: Broken here?
currentBoard[innerX2][innerY2][x][y] = 2
score = evaluateMove(innerX2, innerY2, x, y, depth + 1, false, currentBoard);
//bestScore = -100;
if (score > bestScore)
{
console.log("Line 169: Score = ", score);
return score;
}
else
{
return bestScore;
}
}
}
}
}
else
{
bestScore = 100;
for(var x = 0; x < 3; x++)
{
for (var y = 0; y < 3; y++)
{
if(currentBoard[innerX2][innerY2][x][y] == 0)
{
currentBoard[innerX2][innerY2][x][y] = 1
score = evaluateMove(innerX2, innerY2, x, y, depth + 1, true, currentBoard);
bestScore = 100;
if (score < bestScore)
{
console.log("Line 195: Score = ", score);
return score;
}
else
{
return bestScore;
}
}
}
}
}
}
return 0;
}
关于我们的Alpha-Beta修剪实施:
我们的评估移动函数包含一些变量,X2和Y2组成了我们正在评估的bigBoard中移动的四维数组坐标。我们遵循this wikipedia page的伪代码。不幸的是我们的人工智能在左上角播放,直到它没有更多的选择这样做,在这种情况下它会在电路板的左侧播放。在过去的几天里,我和我的小组一直在梳理头发。
代码如下。
function evaluateMove(outerX2, outerY2, innerX2, innerY2, depth, isAI, tempBoard)
{
var currentBoard = JSON.parse( JSON.stringify( tempBoard ));
var score = 0;
var bestScore = 0;
var playerZZ;
if (isAI) {
playerZZ = 2;
}
else {
playerZZ = 1;
}
if(checkForWin(2, JSON.parse( JSON.stringify( currentBoard )), outerX2, outerY2, innerX2, innerY2))
{
//AI wins
return 10;
}
if(checkForWin(1, JSON.parse( JSON.stringify( currentBoard )), outerX2, outerY2, innerX2, innerY2))
{
//Human wins
return -10;
}
else if (depth == 2) {
return 0;
}
if (checkForBoardWin(innerX2, innerY2, 1) || checkForBoardWin(innerX2, innerY2, 2))
{
if (isAI)
{
bestScore = -100;
for (var X = 0; X < 3; X++)
{
for (var Y = 0; Y < 3; Y++)
{
for (var x = 0; x < 3; x++)
{
for (var y = 0; y < 3; y++)
{
if(currentBoard[X][Y][x][y] == 0 && !(checkForBoardWin(X, Y, 1) || checkForBoardWin(X, Y, 2)))
{
//JAKE: Broken here?
currentBoard[X][Y][x][y] = 2
score = evaluateMove(X, Y, x, y, depth + 1, false, currentBoard);
//var bestScore = -100;
if (score > bestScore)
{
console.log("Line 105: Score = ", score);
return score;
}
else
{
return bestScore;
}
}
}
}
}
}
}
else
{
bestScore = 100;
for (var X = 0; X < 3; X++)
{
for (var Y = 0; Y < 3; Y++)
{
for (var x = 0; x < 3; x++)
{
for (var y = 0; y < 3; y++)
{
if(currentBoard[X][Y][x][y] == 0)
{
currentBoard[X][Y][x][y] = 1
score = evaluateMove(X, Y, x, y, depth + 1, false, currentBoard);
//bestScore = 100;
if (score < bestScore)
{
console.log("Line 137: Score = ", score);
return score;
}
else
{
return bestScore;
}
}
}
}
}
}
}
}
else
{
bestScore = -100;
if (isAI)
{
for(var x = 0; x < 3; x++)
{
for (var y = 0; y < 3; y++)
{
if(currentBoard[innerX2][innerY2][x][y] == 0)
{
//JAKE: Broken here?
currentBoard[innerX2][innerY2][x][y] = 2
score = evaluateMove(innerX2, innerY2, x, y, depth + 1, false, currentBoard);
//bestScore = -100;
if (score > bestScore)
{
console.log("Line 169: Score = ", score);
return score;
}
else
{
return bestScore;
}
}
}
}
}
else
{
bestScore = 100;
for(var x = 0; x < 3; x++)
{
for (var y = 0; y < 3; y++)
{
if(currentBoard[innerX2][innerY2][x][y] == 0)
{
currentBoard[innerX2][innerY2][x][y] = 1
score = evaluateMove(innerX2, innerY2, x, y, depth + 1, true, currentBoard);
bestScore = 100;
if (score < bestScore)
{
console.log("Line 195: Score = ", score);
return score;
}
else
{
return bestScore;
}
}
}
}
}
}
return 0;
}
谢谢。