因此,我的井字游戏的AI出现了一些问题。 AI纯粹是防御性的,因此它将始终阻止您。通常在我的第一种情况下就可以正常工作,因此例如,如果我演奏左上角,然后演奏中上角,则它将始终占据右上角。其他情况,例如如果我打两条对角线,可能会冻结游戏,或者让我再转一圈。这些问题只有在我实施了错误的智能AI之后才出现。最初,该程序具有一个“哑AI”,可以选择随机点,如代码底部所示。而且,我认为问题在于某些阻塞条件可能彼此冲突并引起问题。我怎样才能解决这个问题?相关代码如下:
坐标基于井字格网,其中左上角为(0,0),右下角为(2,2)

void Game::AIGetNextMoveRand()
{
    //top row
    if(GetSquareState(0,0) == O && GetSquareState(1,0) == O)
    {
        do
        {
            AIMoveX = 2;
            AIMoveY = 0;
        }
            while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);

    }
    else if(GetSquareState(2,0) == O && GetSquareState(1,0) == O)
    {

        do
        {
            AIMoveX = 0;
            AIMoveY = 0;
        }
            while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    //middle row
    else if(GetSquareState(0,1) == O && GetSquareState(1,1) == O)
    {
        do
        {
        AIMoveX = 2;
        AIMoveY = 1;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    else if(GetSquareState(2,1) == O && GetSquareState(1,1) == O)
    {
        do
        {
        AIMoveX = 0;
        AIMoveY = 1;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    // bottom row
    else if(GetSquareState(0,2) == O && GetSquareState(1,2) == O)
    {
        do
        {
            AIMoveX = 2;
            AIMoveY = 2;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    else if(GetSquareState(2,2) == O && GetSquareState(1,2) == O)
    {
        do
        {
        AIMoveX = 0;
        AIMoveY = 2;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    // vert 0
    else if(GetSquareState(0,0) == O && GetSquareState(0,1) == O)
    {
        do
        {
        AIMoveX = 0;
        AIMoveY = 2;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    else if(GetSquareState(0,2) == O && GetSquareState(0,1) == O)
    {
        do
        {
            AIMoveX = 0;
            AIMoveY = 0;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    // vert 1
    else if(GetSquareState(1,0) == O && GetSquareState(1,1) == O)
    {

        do
        {
            AIMoveX = 1;
            AIMoveY = 2;
        }
            while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    else if(GetSquareState(1,2) == O && GetSquareState(1,1) == O)
    {
        do
        {
            AIMoveX = 1;
            AIMoveY = 0;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    //vert 2
    else if(GetSquareState(2,2) == O && GetSquareState(2,1) == O)
    {
        do
        {
            AIMoveX  = 2;
            AIMoveY = 0;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    else if(GetSquareState(2,0) == O && GetSquareState(2,1) == O)
    {
        do
        {
            AIMoveX = 2;
            AIMoveY = 2;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    // diagonal 1
    else if(GetSquareState(0,0) == O && GetSquareState(1,1) == O)
    {

        do
        {
            AIMoveX = 2;
            AIMoveY = 2;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    else if(GetSquareState(2,2) == O && GetSquareState(1,1) == O)
    {

        do
        {
            AIMoveX = 0;
            AIMoveY = 0;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    //diagonal 2
    else if(GetSquareState(0,2) == O && GetSquareState(1,1) == O)
    {
        do
        {
            AIMoveX = 0;
            AIMoveY = 2;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    else if(GetSquareState(0,2) == O && GetSquareState(1,1) == O)
    {
        do
        {
            AIMoveX = 2;
            AIMoveY = 0;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    // mid 0
    else if(GetSquareState(0,0) == O && GetSquareState(2,0) == O)
    {

        do
        {
            AIMoveX = 1;
            AIMoveY = 0;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    //mid 1
    else if(GetSquareState(1,0) == O && GetSquareState(2,1) == O)
    {
        do
        {
            AIMoveX = 1;
            AIMoveY = 1;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    // mid 2
    else if(GetSquareState(0,2) == O && GetSquareState(2,2) == O)
    {
        do
        {
            AIMoveX = 1;
            AIMoveY = 2;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    //diag 1
    else if(GetSquareState(0,0) == O && GetSquareState(2,2) == O)
    {
        do
        {
            AIMoveX = 1;
            AIMoveY = 1;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }
    //diag 2
    else if(GetSquareState(2,0) == O && GetSquareState(0,2) == O)
    {

        do
        {
            AIMoveX = 1;
            AIMoveY = 1;
        }
        while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
    }

    else
    {
    do
    {
        AIMoveX = rand() % 3;
        AIMoveY = rand() % 3;
    }while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);

    }
    }

void Game::DoAITurnRand()
{
    AIGetNextMoveRand();
    SetSquareState(AIMoveX,AIMoveY,activePlayer);
    EndTurn();
}

最佳答案

do while循环是垃圾。考虑一下您的规则是否做出了错误的选择(即尝试在实心方块上进行游戏),然后再次做出相同的错误选择将无济于事。实际上,这就是为什么您获得“冻结”的原因。您需要重新组织代码的逻辑。我建议,如果您的AI选择了一个非法的正方形,那么您应该退回到您的随机选择代码,那么至少您会得到合法的举动。

像这样

// no move selected yet
AIMoveX = -1;
AIMoveY = -1;

// AI rules
if(GetSquareState(0,0) == O && GetSquareState(1,0) == O)
{
    AIMoveX = 2;
    AIMoveY = 0;
}
else if(GetSquareState(2,0) == O && GetSquareState(1,0) == O)
{
    AIMoveX = 0;
    AIMoveY = 0;
}
// lots more rules
...

// check for fallback to random move
if ((AIMoveX == -1 && AIMoveY == -1)             // if no rules applied
    || GetSquareState(AIMoveX,AIMoveY) != EMPTY) // or if the square is not empty
{
    // pick a random square
    do
    {
        AIMoveX = rand() % 3;
        AIMoveY = rand() % 3;
    }
    while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}


我最初将AIMoveX和AIMoveY设置为-1,以指示尚未选择任何规则。如果在通过所有规则后它们仍然为-1,那么我知道没有选择任何规则,因此我必须做出随机选择。如果确实选择了一条规则,但它选择了一个非空的正方形,那么我也会做出随机选择。我在代码末尾测试了这两个条件。

您必须仔细考虑所编写的代码的实际作用。仅将do while循环放在一个地方,因为它在另一个地方工作是不正确的。

关于c++ - C++井字游戏的AI问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15858844/

10-13 07:04