确定最小极限井尖的正确位置

时间:2015-12-18 00:50:03

标签: c++ tic-tac-toe minimax

我尝试使用minimax算法在C ++中编写简单版本的tic-tac-toe,但在尝试确定得分最佳的位置时遇到了问题。 minEval(最小值的返回分数),maxEval(返回最大分数)和playMove(确定要播放的位置然后播放移动)功能如下所示。

int maxEval(int board[9]) {
    if (checkDraw(board)) {
        return 0;
    }
    else if (checkWin(board)) {
        return -1000;
    }
    int finalScore = -1000;
    for (int i = 0; i < 9; i++) {
        if (board[i] == 0) {
            board[i] = 1;
            int score = minEval(board);
            if (score > finalScore) {
                finalScore = score;
            }
            board[i] = 0;
        }
    }
    return finalScore;
}

int minEval(int board[9]) {
    if (checkDraw(board)) {
        return 0;
    }
    else if (checkWin(board)) {
        return 1000;
    }
    int finalScore = 1000;
    for (int i = 0; i < 9; i++) {
        if (board[i] == 0) {
            board[i] = -1;
            int score = maxEval(board);
            if (score < finalScore) {
                finalScore = score;
            }
            board[i] = 0;
        }
    }
    return finalScore;
}

void playMove(int board[9], int player) {
    int finalScore = player * -1000;
    int position;
    for (int i = 0; i < 9; i++) {
        if (board[i] == 0) {
            board[i] = player;
            int score;
            if (player == 1) {
                score = maxEval(board);
            }
            else {
                score = minEval(board);
            }
            if (player == 1 && score >= finalScore) {
                finalScore = score;
                position = i;
            }
            else if (player == -1 && score <= finalScore) {
                finalScore = score;
                position = i;
            }
            board[i] = 0;
        }
    }

    board[position] = player;
}

当我测试不同位置以查看minEval和maxEval是否正确评估位置时,函数会返回正确的分数(最大胜利为1000,最小胜利为-1000,平局为0)。但是,当我使用playMove功能进行AI播放时,它会播放非常可疑的动作,并且几乎总是会进行“不正确”的动作。 这是我制作节目游戏的一个例子(自己):

A game with itself by repeatedly calling the playMove function in a loop

我怀疑我设置位置的方式有问题,但我试图做出改变无济于事。关于评估函数有什么问题的任何建议?感谢。

以下是整个代码的链接:http://ideone.com/6791d4

2 个答案:

答案 0 :(得分:0)

我会检查发现的变化而不仅仅是分数。你是在找到任何获胜的变种,还是对手最好的变种?

e.g。修改您的最小/最大Eval代码,以便将选择的移动添加到数组中。

顺便说一句,如果将最小/最大Eval例程合并为一个,可能更容易看到发生了什么。

警告未经审查的代码

int minmaxEval(int board[9], int player, int moves[9], int move) {
    if (checkDraw(board)) {
        return 0;
    }
    int finalScore = player * -1000;
    if (checkWin(board)) {
        return finalScore;
    }
    for (int i = 0; i < 9; i++) {
        if (board[i] == 0) {
            board[i] = player;
            int score = minmaxEval(board, -player, moves, move+1);
            if ( (player > 0 && score > finalScore) ||
                (player < 0 && score < finalScore) ) {
                  finalScore = score;
                  moves[move] = i;
            }
            board[i] = 0;
        }
    }
    return finalScore;
}

如果你在你的顶级常规中打印出移动[],你应该看到给出该分数的变化。不匹配会告知您对算法的理解,例如:当它找到胜利时它会停止。

一般来说,重要的是要有一种方法来仔细检查你的代码正在做你期望的。研究单元测试和测试驱动开发。

答案 1 :(得分:0)

感谢您的见解,我解决了这个问题。 playMove函数中存在一个错误,其中我使maxEval和minEval不匹配,这导致AI无法进行获胜或平局。因此,更正的代码是:

void playMove(int board[9], int player) {
    int finalScore = player * -1000;
    int position;
    for (int i = 0; i < 9; i++) {
        if (board[i] == 0) {
            board[i] = player;
            int score;
            if (player == 1) {
                score = minEval(board);  //Previously Mismatched
            }
            else {
                score = maxEval(board);  //Previously Mismatched
            }
            if (player == 1 && score >= finalScore) {
                finalScore = score;
                position = i;
            }
            else if (player == -1 && score <= finalScore) {
                finalScore = score;
                position = i;
            }
            board[i] = 0;
        }
    }

    board[position] = player;
}