在Tic Tac Toe中实现MiniMax算法

时间:2014-08-29 01:18:06

标签: c algorithm minimax

我试图为一个tic tac toe游戏创造一个无与伦比的AI,就像http://perfecttictactoe.herokuapp.com/那样。但是,因为我还在学习C,所以它更简单,因为用户总是先行,而且没有GUI,而ASCII艺术则用于图形。我已经查看了MiniMax算法的各种实现,因为它似乎是解决问题的最佳方法,根据该网站以及许多其他网站。我有一点问题,因为算法似乎不起作用。相反,它从方形(1,1)(数组中的[0,0])开始从左向右稳定移动,并在到达行尾时向下移动到下一行。我已经尝试了很多东西,从精心梳理我的代码到重写它,但似乎没有任何工作。我希望这里的精彩社区可以帮助我!

提前致谢!

代码:

#include <stdio.h>
#include "simpio.h"
#include "stdlib.h"

void print(char board[3][3]);
char didwin(char board[3][3]);
void AImove(char board[3][3], int *rows, int *columns);
int MinMax(char board[3][3], int player);

int main(void)
{
    int i, i2, player, rows=0,columns=0;
    char board[3][3], tempboard[3][3], winner;
    string name;
    printf("The computer will now play tic-tac-tow with you.\n");
    printf("The computer will use \"O\" and you will use \"X\".\n");
    printf("You will go first. To begin, please enter your name: ");
    name=GetLine();
    while(true) 
    {
        for(i=0;i<3;i++) 
        {
            for(i2=0;i2<3;i2++) 
            {
                board[i][i2]='\0';
            }
        }
        print(board);
        for(i=0;i<9&&winner==0;i++)
        { 
            printf("\n");
            player=i%2+1;
            if(player==1)
            {
                printf("\n%s, what row is your square in?\t", name);
                rows=GetInteger()-1;
                printf("\n%s, what column is your square in?\t", name);
                columns=GetInteger()-1;
            }
            else if(player==2)
            {
                printf("\nThe computer will move now.\n");
                for(i=0;i<3;i++)
                {
                    for(i2=0;i2<3;i2++)
                    {
                        tempboard[i][i2]=board[i][i2];
                    }
                }
                AImove(tempboard, &rows, &columns);
            }
            if(rows<0||rows>3||columns<0||columns>3||board[rows][columns]=='X'||board[rows][columns]=='O')
            {
                if(player==1)
                {
                    printf("The space is already taken or out of bounds, please try again");    
                }
                i--;
            }
            else 
            {
                if(player==1) board[rows][columns]='X';
                else board[rows][columns]='O';
                print(board);
            }
            winner = didwin(board);
        }
        if(winner!='\0') 
        {
            if(winner=='X') printf("\n\nYou won!");
            else printf("\n\nThe computer won! Try harder next time.");
            break;

        }
        else
        {
            printf("No winner this round. Try again.");
            break;
        }
    }
}

void print(char board[3][3])
{
    int i,i2;
    printf("\n");
    for(i=0;i<3;i++)
    {
        for(i2=0;i2<3;i2++)
        {
            if(board[i][i2]=='\0')
            {
                printf("   ");
            }   
            else
            {
                printf(" %c ", board[i][i2]);
            }
            if(i2<2) printf("|"); 
        }
        if(i<2)
        {
            printf("\n-----------\n");
        }
    }
}

char didwin(char board[3][3])
{
    int i,i2;
    char temp;
    char winner = '\0';

    for(i=0;i<3;i++) 
    {
        temp=board[i][0];
        for(i2=0;i2<3;i2++) 
        {
            if(board[i][i2]!=temp)
            {
                temp='\0';
            }
        }
        if(temp!='\0') 
        {
            winner=temp;
        }
    }

    for(i=0;i<3;i++)
    {
        temp=board[0][i];
        for(i2=0;i2<3;i2++) 
        {
            if(board[i2][i]!=temp) 
            {
                temp='\0';
            }       
        }
        if(temp!='\0') 
        {
            winner=temp;
        }
    }

    temp=board[0][0];
    for(i=0;i<3;i++) 
    {
        if(board[i][i]!=temp) 
        {
            temp='\0';
        }
    }
    if(temp!='\0') 
    {
        winner=temp;
    }

    temp=board[0][2];
    for(i=0;i<3;i++) 
    {
        if(board[i][2-i]!= temp) 
        {
            temp='\0';
        }
    }
    if(temp!='\0') 
    {
        winner=temp;
    }
    return winner;
}

void AImove(char tempboard[3][3], int *rows,  int *columns)
{
    int points=-1, temppoints, i, i2;

    for(i=0;i<3;i++)
    {
        for(i2=0;i2<3;i2++)
        {
            if(tempboard[i][i2]=='\0')
            {
                tempboard[i][i2]='O';
                temppoints=MinMax(tempboard, 1);
                if(temppoints>points)
                {
                    points=temppoints;
                    *rows=i;
                    *columns=i2;
                }
                tempboard[i][i2]='\0';
            }
        }
    }
}

int MinMax(char tempboard[3][3], int player)
{
    int winner, points, temppoints, i, i2;
    winner=didwin(tempboard);
    if(winner=='X') return(0);
    else if (winner=='O') return(999);
    else
    {
        for(i=0;i<3;i++)
        {
            for(i2=0;i2<3;i2++)
            {
                if(tempboard[i][i2]='\0')
                {
                    if (player==1)
                    {
                        tempboard[i][i2]='X';
                    }
                    else
                    {
                        tempboard[i][i2]='O';
                    }
                    if (player==1)
                    {
                        temppoints=MinMax(tempboard, 2);
                    }
                    else
                    {
                        temppoints=MinMax(tempboard, 1);
                    }
                    if(temppoints>points)
                    {
                        points=temppoints;
                    }
                    tempboard[i][i2]='\0';
                }
            }
        }
    }
    return(points);
}

2 个答案:

答案 0 :(得分:1)

代码在MinMax()中进行分配而不是比较。 points没有初始化并返回,只有UB。

int points
...
// if(tempboard[i][i2]='\0') { // never true
if (tempboard[i][i2] == '\0') { 
  points == ...
...
return points;

BTW:建议明确返回main()

的值

答案 1 :(得分:0)

您的代码的关键错误是算法&#34; MinMax&#34;没有正确实施。请注意,根据您的评估,player1是Min玩家,他试图让他的积分尽可能低,而player2是试图让他的积分尽可能高的Max玩家。所以你应该分别讨论这两种情况:

if (player==1)
{
    temppoints=MinMax(tempboard, 2);
}
else
{
    temppoints=MinMax(tempboard, 1);
}
if(player==1 && temppoints<points) //HERE
{
    points=temppoints;
}
else if(player==2 && temppoints>points) //HERE
{                                       //HERE
    points=temppoints;                  //HERE
}                                       //HERE

除了上述错误之外,您还可能会注意一些无意的错误,例如在MinMax函数中将if(tempboard[i][i2]='\0')更改为if(tempboard[i][i2]=='\0')