TicTacToe Minimax算法始终返回最低值

时间:2017-04-18 06:51:18

标签: c# algorithm debugging unity3d minimax

我正在尝试使用minimax算法实现TicTacToe AI。

当轮到AI播放时,我会调用ComputerTurn(它接收电路板状态,一组跟踪方形是X,O还是空的整数)。然后ComputerTurn调用minimax(minimax算法)和win(连续检查3)。

当我运行脚本时,算法总是决定返回最低合法游戏。 IE,只要左上方(方块0)可用,它将始终首先返回它。如果采用该方格,它将返回顶部中间(图块1)等。

我不确定这里发生了什么,我的传统调试技术(Debug.Log或print)导致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;
}

2 个答案:

答案 0 :(得分:1)

它并不总是返回第一个空单元格。例如,尝试用[0,0,0,-1,0,-1,1,0,1]位置提供它:它不会返回0,而是选择4。您的实现不包含任何错误。

问题在于算法。由于你的体重函数只能得到1,0或-1,你的程序只能看到是否有可能在该回合中获胜,但是看不到强烈动作(高胜利输出)和弱动作之间的任何差异(获胜是可能的,但不太可能)。它可以过滤掉松动的动作,如您所提供的示例所示。

答案 1 :(得分:0)

编辑:如何将其标记为已解决

我发现了发生了什么。

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

我的球员转身方式也出现了错误。感谢任何看过我问题的人。