我的minimax算法对tictactoe有什么问题

时间:2015-07-24 18:33:56

标签: c algorithm tic-tac-toe minimax

我正在构建一个tic tac toe游戏,以获得有趣的学习体验。我已经构建了一个minimax算法来返回计算机的最佳移动,但不知怎的,我出错并得到像这样的奇怪输出

TIC TAC TOE V1.0
---
---
---
Enter row, column of your move
1,1
---
-X-
---
...
0, 0: -1038
0, 1: -1470
0, 2: -1038
1, 0: -1470
1, 2: -1470
2, 0: -1038
2, 1: -1470
2, 2: -1038
O--
-X-
---
Enter row, column of your move
1,2
O--
-XX
---
...
0, 1: -15
0, 2: -9
1, 0: -10
2, 0: -1
2, 1: -29
2, 2: -41
O--
-XX
O--
Enter row, column of your move
1,0
O--
XXX
O--
WINNER: PLAYER

您可以看到计算机选择左下角而不是切断播放器。我的代码尝试通过所有可能的游戏状态递归地翻转翻转,总结转弯可能导致的每次赢或输的得分,然后以最高得分返回移动。打印输出是每个回合之前的得分(你可以看到它选择最高),那么我为什么不切断玩家呢?我怎样才能解决这个问题?这是我的代码。

int compMoveScoreRecursive(state_t **board, int dimension, int row, int col, state_t turn) {
    board[row][col] = turn;
    state_t winner = checkWinner(board, dimension);
    if (winner == COMPUTER) {
        return 1;
    } else if (winner == PLAYER) {
        return -1;
    } else {
        int score = 0;
        state_t nextTurn = turn == COMPUTER ? PLAYER : COMPUTER;
        for (int i = 0; i < dimension; i++) {
            for (int j = 0; j < dimension; j++) {
                if (board[i][j] == NIL) {
                    state_t **boardCopy = copyBoard(board, dimension);
                    score += compMoveScoreRecursive(boardCopy, dimension, i, j, nextTurn);
                    destroyBoard(boardCopy, dimension);
                }
            }
        }
        return score;
    }
}

move_t optimalCompMove(state_t **board, int dimension) {
    move_t optMove;
    int optScore = INT_MIN;
    for (int row = 0; row < dimension; row++) {
        for (int col = 0; col < dimension; col++) {
            if (board[row][col] == NIL) {
                state_t **boardCopy = copyBoard(board, dimension);
                int score = compMoveScoreRecursive(boardCopy, dimension, row, col, COMPUTER);
                printf("%d, %d: %d\n", row, col, score);
                if (score > optScore) {
                    optMove.row = row;
                    optMove.col = col;
                    optScore = score;
                }
                destroyBoard(boardCopy, dimension);
            }
        }
    }
    return optMove;
}

3 个答案:

答案 0 :(得分:4)

minmax算法的概念是“最大限度地减少最大损失”(Wikipedia),因此算法的第一件事就是你的总和。

对于游戏的任何状态S,以及针对当前玩家的任何移动M(假设玩家1 P1),minmax (S + M, P2)的值为如果P2播放P1M最大可能输出。因此,如果P1想要最大化获胜机会,他应该尽可能地减少P2的最大输出,即他必须找到输出的最小。 / p>

tictactoe minmax 中,可以测试整个游戏(最多9次移动),这意味着如果PX获胜(1),你现在总是丢失(-1)或者平局(0)。因此minmax (state, PX)只返回这三个值中的一个。

在许多游戏中,您无法玩整个游戏(例如草稿),因此返回的值是状态的指示,例如-oo如果您输了,{{ 1}}如果你赢了,请将你的选票数量和对手之间的差异另外说明。

答案 1 :(得分:2)

根据我的理解,在compMoveScoreRecursive的实现中,通过

添加递归计算的分数
score += compMoveScoreRecursive(boardCopy, dimension, i, j, nextTurn);

而不是最大化或最小化该值。但是,要返回的值应最小化,最小化,具体取决于参数turn,这也是该方法被称为MinMax的原因。

答案 2 :(得分:0)

您的算法背后的概念似乎存在缺陷。根据你所描述的方式,你要考虑每一个游戏线,而不是假设对手要做出正确的动作。因此,对手可以通过下一步动作获胜的事实很少,因为你也考虑了其他4个动作提供的所有选项(尽管事实上这些选项显然永远不会被制造)。您必须将算法优化为适当的最小 - 最大值,而不是搜索整组电路板状态