TicTacToe Minimax 算法总是 Returns 最低值
TicTacToe Minimax Algorithm Always Returns Lowest Value
我正在尝试使用 minimax 算法实现 TicTacToe AI。
轮到 AI 下棋时,我调用 ComputerTurn(它接收棋盘状态,一个整数数组,用于跟踪正方形是 X、O 还是空)。 ComputerTurn 然后调用 minimax(minimax 算法)和 win(连续检查 3 个)。
当我运行脚本时,算法总是决定return最低的合法播放。 IE,只要左上角的方块(tile 0)可用,它总是先 return 它。如果该方块被占用,它将 return 顶部中间(图块 1)等
我不确定这里发生了什么,我的传统调试技术(Debug.Log 或打印)导致 Unity 在我想查看的许多地方崩溃。
void ComputerTurn(int[] board)
{
int move = -1;
int score = -2;
int i;
for (i = 0; i < 9; ++i)
{
if (board[i] == 0)
{
board[i] = 1;
int tempScore = -minimax(board, -1);
board[i] = 0;
if (tempScore > score)
{
score = tempScore;
move = i;
}
}
}
board[move] = 1;
if (PlayerTurn == 1)
{
//Draw an O
Board[move] = -1;
}
else
{
//Draw an X
Board[move] = 1;
}
//Changes to player's turn
}
int minimax(int[] board, int player)
{
int winner = win(board);
if (winner != 0) return winner * player;
int move = -1;
int score = -2;//Losing moves are preferred to no move
int i;
for (i = 0; i < 9; ++i)
{//For all moves,
if (board[i] == 0)
{//If legal,
board[i] = player;//Try the move
int thisScore = -minimax(board, player * -1);
if (thisScore > score)
{
score = thisScore;
move = i;
}//Pick the one that's worst for the opponent
board[i] = 0;//Reset board after try
}
}
if (move == -1) return 0;
return score;
}
int win(int[] board)
{
//determines if a player has won, returns 0 otherwise.
int[,] wins = new int[8, 3] { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, { 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 }, { 0, 4, 8 }, { 2, 4, 6 } };
int i;
for (i = 0; i< 8; ++i)
{
if (board[wins[i, 0]] != 0 &&
board[wins[i, 0]] == board[wins[i, 1]] &&
board[wins[i, 0]] == board[wins[i, 2]])
{
return board[wins[i, 2]];
}
}
return 0;
}
它并不总是 return 第一个空单元格。例如,尝试用 [0, 0, 0, -1, 0, -1, 1, 0, 1] 位置喂它:它不会 return 0,它会选择 4。您的实施不包含任何错误。
问题出在算法上。由于您的权重函数只能导致 1、0 或 -1,您的程序只能查看是否有可能在该回合获胜,但看不到强步(胜利输出高)和弱步之间的任何区别(有可能获胜,但可能性不大)。它过滤掉了松动的动作,正如您从提供的示例中看到的那样。
编辑:如何将其标记为已解决
我知道发生了什么事。
board[move] = 1;
if (PlayerTurn == 1)
{
//Draw an O
Board[move] = -1;
}
else
{
//Draw an X
Board[move] = 1;
}
//Changes to player's turn
实际上应该是
Board[move] = 1;
if (PlayerTurn == 1)
{
//Draw a Y
}
else
{
//Draw an X
}
//Change turn
我的玩家回合也有错误。感谢所有看过我问题的人。
我正在尝试使用 minimax 算法实现 TicTacToe AI。
轮到 AI 下棋时,我调用 ComputerTurn(它接收棋盘状态,一个整数数组,用于跟踪正方形是 X、O 还是空)。 ComputerTurn 然后调用 minimax(minimax 算法)和 win(连续检查 3 个)。
当我运行脚本时,算法总是决定return最低的合法播放。 IE,只要左上角的方块(tile 0)可用,它总是先 return 它。如果该方块被占用,它将 return 顶部中间(图块 1)等
我不确定这里发生了什么,我的传统调试技术(Debug.Log 或打印)导致 Unity 在我想查看的许多地方崩溃。
void ComputerTurn(int[] board)
{
int move = -1;
int score = -2;
int i;
for (i = 0; i < 9; ++i)
{
if (board[i] == 0)
{
board[i] = 1;
int tempScore = -minimax(board, -1);
board[i] = 0;
if (tempScore > score)
{
score = tempScore;
move = i;
}
}
}
board[move] = 1;
if (PlayerTurn == 1)
{
//Draw an O
Board[move] = -1;
}
else
{
//Draw an X
Board[move] = 1;
}
//Changes to player's turn
}
int minimax(int[] board, int player)
{
int winner = win(board);
if (winner != 0) return winner * player;
int move = -1;
int score = -2;//Losing moves are preferred to no move
int i;
for (i = 0; i < 9; ++i)
{//For all moves,
if (board[i] == 0)
{//If legal,
board[i] = player;//Try the move
int thisScore = -minimax(board, player * -1);
if (thisScore > score)
{
score = thisScore;
move = i;
}//Pick the one that's worst for the opponent
board[i] = 0;//Reset board after try
}
}
if (move == -1) return 0;
return score;
}
int win(int[] board)
{
//determines if a player has won, returns 0 otherwise.
int[,] wins = new int[8, 3] { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, { 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 }, { 0, 4, 8 }, { 2, 4, 6 } };
int i;
for (i = 0; i< 8; ++i)
{
if (board[wins[i, 0]] != 0 &&
board[wins[i, 0]] == board[wins[i, 1]] &&
board[wins[i, 0]] == board[wins[i, 2]])
{
return board[wins[i, 2]];
}
}
return 0;
}
它并不总是 return 第一个空单元格。例如,尝试用 [0, 0, 0, -1, 0, -1, 1, 0, 1] 位置喂它:它不会 return 0,它会选择 4。您的实施不包含任何错误。
问题出在算法上。由于您的权重函数只能导致 1、0 或 -1,您的程序只能查看是否有可能在该回合获胜,但看不到强步(胜利输出高)和弱步之间的任何区别(有可能获胜,但可能性不大)。它过滤掉了松动的动作,正如您从提供的示例中看到的那样。
编辑:如何将其标记为已解决
我知道发生了什么事。
board[move] = 1;
if (PlayerTurn == 1)
{
//Draw an O
Board[move] = -1;
}
else
{
//Draw an X
Board[move] = 1;
}
//Changes to player's turn
实际上应该是
Board[move] = 1;
if (PlayerTurn == 1)
{
//Draw a Y
}
else
{
//Draw an X
}
//Change turn
我的玩家回合也有错误。感谢所有看过我问题的人。