Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ tic-tac-toe的minimax算法实现_C++_Algorithm_Minimax - Fatal编程技术网

C++ tic-tac-toe的minimax算法实现

C++ tic-tac-toe的minimax算法实现,c++,algorithm,minimax,C++,Algorithm,Minimax,我正在尝试为一个tic-tac-toe游戏实现minimax算法,在这个游戏中,两个玩家都是人类,每次计算机使用minimax算法建议一个最佳移动。但它并不是每次都给出正确的建议。例如:对于以下场景,它没有给出正确的建议: 球员X:1 球员O:2 玩家X:5。 这是我的密码: #include <stdio.h> #include <algorithm> #include <string> using namespace std; #define inf

我正在尝试为一个tic-tac-toe游戏实现minimax算法,在这个游戏中,两个玩家都是人类,每次计算机使用minimax算法建议一个最佳移动。但它并不是每次都给出正确的建议。例如:对于以下场景,它没有给出正确的建议: 球员X:1 球员O:2 玩家X:5。 这是我的密码:

#include <stdio.h>
#include <algorithm>  
#include <string>
using namespace std;

#define inf 1<<20
int posmax, posmin;
char board[15];

void print_board()
{
    int i;
    for (i = 1; i <= 9; i++)
    {   
        printf("%c ",board[i]);
        if (i % 3 == 0)
            printf("\n");
    }
    printf("\n");
}

int check_win(char board[])
{
    if ((board[1] == 'X' && board[2] == 'X' && board[3] == 'X') ||
        (board[4] == 'X' && board[5] == 'X' && board[6] == 'X') ||
        (board[7] == 'X' && board[8] == 'X' && board[9] == 'X') ||
        (board[1] == 'X' && board[4] == 'X' && board[7] == 'X') ||
        (board[2] == 'X' && board[5] == 'X' && board[8] == 'X') ||
        (board[3] == 'X' && board[6] == 'X' && board[9] == 'X') ||
        (board[1] == 'X' && board[5] == 'X' && board[9] == 'X') ||
        (board[3] == 'X' && board[5] == 'X' && board[7] == 'X'))
    {
        return 1;
    }
    else if((board[1] == 'O' && board[2] == 'O' && board[3] == 'O') ||
            (board[4] == 'O' && board[5] == 'O' && board[6] == 'O') ||
            (board[7] == 'O' && board[8] == 'O' && board[9] == 'O') ||
            (board[1] == 'O' && board[4] == 'O' && board[7] == 'O') ||
            (board[2] == 'O' && board[5] == 'O' && board[8] == 'O') ||
            (board[3] == 'O' && board[6] == 'O' && board[9] == 'O') ||
            (board[1] == 'O' && board[5] == 'O' && board[9] == 'O') ||
            (board[3] == 'O' && board[5] == 'O' && board[7] == 'O'))
    {
        return -1;
    }
    else return 0;
}

int check_draw(char board[])
{
    if ((check_win(board) == 0) && (board[1] != '_') && (board[2] != '_') &&
        (board[3] != '_') && (board[4] != '_') && (board[5] != '_') &&
        (board[6] != '_') && (board[7] != '_') && (board[8] != '_') &&
        (board[9] != '_'))
    {
        return 1;
    }
    else return 0;
}

int minimax(int player, char board[], int n)
{
    int i, res, j;

    int max = -inf;
    int min = inf;

    int chk = check_win(board);
    if (chk == 1)
        return 1;
    else if (chk == (-1))
        return -1;
    else if (chk = check_draw(board))
        return 0;

    for (i = 1; i <= 9; i++)
    {
        if(board[i] == '_')
        {
            if(player == 2)  
            {
                board[i] = 'O';
                res = minimax(1, board, n + 1);

                board[i] = '_';
                if(res < min)
                {
                    min = res;
                    if (n == 0)
                        posmin = i;
                }
            }
            else if (player == 1)
            {
                board[i] = 'X';
                res = minimax(2, board, n + 1);
                board[i] = '_';
                if (res > max)
                {
                    max = res;
                    if (n == 0)
                        posmax = i;
                }
            }
        }
    }

    if (player == 1)
        return max;
    else return min;    
}


// 1 is X, 2 is O
int main()
{
    int i, j, input, opt;

    for(i = 1; i <= 9; i++)
        board[i] = '_';

    printf("Board:\n");
    print_board();

    for(i = 1; i <= 9; i++)
    {
        if (i % 2 == 0)
            printf("Player O give input:\n");
        else 
            printf("Player X give input:\n");

        scanf("%d", &input);
        if (i % 2 != 0)
            board[input] = 'X';
        else
            board[input] = 'O';

        printf("Board:\n");
        print_board();

        int chk = check_win(board);
        if (chk == 1)
        {
            printf("Player X wins!\n");
            break;
        }
        else if (chk == -1)
        {
            printf("Player O wins!\n");
            break;
        }
        else if ((chk == 0) && (i != 9))
        {
            posmax = -1;
            posmin = -1;
            if(i % 2 == 0)
            {
                opt = minimax(1, board, 0);
                printf("Optimal move for player X is %d\n", posmax);
            }
            else 
            {
            opt = minimax(2, board, 0);
            printf("Optimal move for player O is %d\n", posmin);
            }
        }
        else 
            printf("The game is tied!\n");
    }
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
#定义inf 1除非我把main()读错了,否则在宣布它为平局之前,只能填充8个方块。这可能不是您要查找的bug,但这只是一个开始。

我认为这(尽管编码效率低下)是正确的。如果没有,请给出你认为程序错误的移动顺序

它并没有给出最短的移动顺序,这可能是你所追求的。然后,您应该重构它以返回移动序列最短(如果获胜)或最长(如果失败)。

替换
printf(“玩家X的最佳移动是%d%d\n”,posmax)
具有
printf(“玩家X的最佳移动是%d\n”,posmax)

printf(“玩家O的最佳移动是%d%d\n”,posmin)
具有
printf(“玩家O的最佳移动是%d\n”,posmin)


其他一切似乎都是正确的,尽管它并不总是打印最快的胜利(如果胜利存在)。

在我看来,您的程序不会给出错误的建议。如果两个玩家都处于最佳状态,Minimax计算移动的分数。在你的情况下,分数可以是+1、-1和0,因此,如果一场比赛(例如)不可避免地输掉,那么输掉的深度没有区别。给定以下游戏状态

X O _
X _ _
_ _ _
和玩家X的最佳游戏,玩家O在哪里移动并不重要(在任何情况下他都会输):

  • O玩7,X玩5,O玩6,X玩8-->X赢
  • O播放3后,X播放7-->X获胜
玩家X获胜。第七步的得分与第三步和所有其他可玩的动作相同。如果你想让你的算法给出这个例子的移动建议7,你必须将游戏深度包含在你的评估函数中。可以通过将函数的返回值更改为以下值来完成此操作:

int chk = check_win(board);
if (chk == 1)
    return (10 - n);
else if (chk == (-1))
    return -(10 - n);
else if (chk = check_draw(board))
    return 0;

“唯一的赢家是不玩。”——约书亚(又名沃普)你把问题缩小到什么程度了?你做过任何调试吗?“else if(chk=check_draw(board))”很奇怪。这是非常好的代码,没有明显的错误。对于你给出的场景,你认为算法应该建议什么动作?在任何情况下,玩家O的游戏都会失败。建议的移动3与预期的移动9的分数相同,它们(不考虑深度)相同。它没有给出正确的移动顺序答案:玩家X:1,玩家O:2,玩家X:5。@user1563286在前两个移动后,它知道玩家X赢了。无论球员O采取什么行动,每一个行动都是失败的。因此,返回任意移动似乎并不正确。试着在前两步后不要以O的身份输球。