Eat.随 发表于 2023-11-9 15:18:06

井字棋

我的程序测试的时候和电脑下的时候一直都无法出现平局的情况(电脑总是下着下着就让我赢了),请问哪位大佬可以用AI帮我测试一下,感谢大佬!
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

void printArray(char arr)
{
    int i,j;
    for (i=0; i<3; i++)
    {
      for (j=0; j<3; j++)
      {
            printf("%c ", arr);
      }
      printf("\n");
    }
}

bool humanwin(char arr)
{
    for (int i = 0; i < 3; i++)
    {
      if (arr[ i] == 'X' && arr[ i] == 'X' && arr[ i] == 'X')
      {
            return true;
      }
    }
    for (int j = 0; j < 3; j++)
    {
      if (arr == 'X' && arr == 'X' && arr == 'X')
      {
            return true;
      }
      
    }
    if (arr == 'X' && arr == 'X' && arr == 'X')
    {
      return true;
    }
    if (arr == 'X' && arr == 'X' && arr == 'X')
    {
      return true;
    }
    return false;
}

bool computerwin(char arr)
{
    for (int i = 0; i < 3; i++)
    {
      if (arr[ i] == 'O' && arr[ i] == 'O' && arr[ i] == 'O')
      {
            return true;
      }
    }
    for (int j = 0; j < 3; j++)
    {
      if (arr == 'O' && arr == 'O' && arr == 'O')
      {
            return true;
      }
      
    }
    if (arr == 'O' && arr == 'O' && arr == 'O')
    {
      return true;
    }
    if (arr == 'O' && arr == 'O' && arr == 'O')
    {
      return true;
    }
    return false;
}

bool nowin(char arr)
{
    if (arr != '.' && arr != '.' && arr != '.' && arr != '.' && arr != '.' && arr != '.' && arr != '.' && arr != '.' && arr != '.')
    {
      return true;
    }
    else
    {
      return false;
    }
}
   

void calculateRowAndCol(int x, int* row, int* col)
{
    *row = 2 - ((x-1) / 3);
    *col = (x-1) % 3;
}


int main()
{
    char board_now = {{'.','.','.'},{'.','.','.'},{'.','.','.'}};
    int i,x,y,row,col;
    for (i=0;i<9;i++)
    {
      for (i=0;i<5;i++)
      {
            printArray(board_now);
            printf("human input:");
            scanf("%i",&x);
            calculateRowAndCol(x, &row, &col);
            if (board_now == '.')
            {
                board_now = 'X';
                printf("\033[2J\033[H");
                break;
            }
            else
            {
                printf("\033[2J\033[H");
                printf("you have done this.please input again.\n");
                i = i-1;
            }   
      }
      if (humanwin(board_now))
      {
            printArray(board_now);
            printf("human win.\n");
            break;
      }
      for (i=0;i<4;i++)
      {
            srand(time(NULL));
            y = rand()%(9+1);
            calculateRowAndCol(y, &row, &col);
            if (board_now == '.')
            {
                board_now = 'O';
                printf("\033[2J\033[H");
                break;
            }
            else
            {
                i = i-1;
                if (nowin(board_now))
                {
                  printf("nobady win.");
                  break;
                }
            }
      }
      if (computerwin(board_now))
      {
            printArray(board_now);
            printf("computer win.\n");
            break;
      }
    }
    return 0;   
}

isdkz 发表于 2023-11-9 15:21:00

这个程序的问题在于计算机的移动是随机的,没有使用任何AI算法来进行决策。为了实现一个可以与玩家下井字棋并且可以出现平局的AI,你可以使用一个简单的算法,例如最小最大算法(Minimax algorithm)。

最小最大算法是一种用于决策的算法,它可以找到最佳的移动来最大化自己的得分或最小化对手的得分。在井字棋中,你可以将计算机的角色定义为最小化得分的一方,玩家的角色定义为最大化得分的一方。

下面是一个使用最小最大算法的示例代码:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

#define SIZE 3

void printArray(char arr)
{
    for (int i=0; i<SIZE; i++)
    {
      for (int j=0; j<SIZE; j++)
      {
            printf("%c ", arr[ i]);
      }
      printf("\n");
    }
}

bool humanwin(char arr)
{
    for (int i = 0; i < SIZE; i++)
    {
      if (arr[ i] == 'X' && arr[ i] == 'X' && arr[ i] == 'X')
      {
            return true;
      }
    }
    for (int j = 0; j < SIZE; j++)
    {
      if (arr == 'X' && arr == 'X' && arr == 'X')
      {
            return true;
      }
    }
    if (arr == 'X' && arr == 'X' && arr == 'X')
    {
      return true;
    }
    if (arr == 'X' && arr == 'X' && arr == 'X')
    {
      return true;
    }
    return false;
}

bool computerwin(char arr)
{
    for (int i = 0; i < SIZE; i++)
    {
      if (arr[ i] == 'O' && arr[ i] == 'O' && arr[ i] == 'O')
      {
            return true;
      }
    }
    for (int j = 0; j < SIZE; j++)
    {
      if (arr == 'O' && arr == 'O' && arr == 'O')
      {
            return true;
      }
    }
    if (arr == 'O' && arr == 'O' && arr == 'O')
    {
      return true;
    }
    if (arr == 'O' && arr == 'O' && arr == 'O')
    {
      return true;
    }
    return false;
}

bool nowin(char arr)
{
    for (int i = 0; i < SIZE; i++)
    {
      for (int j = 0; j < SIZE; j++)
      {
            if (arr[ i] == '.')
            {
                return false;
            }
      }
    }
    return true;
}

int evaluate(char arr)
{
    if (humanwin(arr))
    {
      return -1;
    }
    else if (computerwin(arr))
    {
      return 1;
    }
    else
    {
      return 0;
    }
}

int minimax(char arr, int depth, bool isMaximizer)
{
    int score = evaluate(arr);

    if (score == 1)
    {
      return score;
    }
    if (score == -1)
    {
      return score;
    }
    if (nowin(arr))
    {
      return 0;
    }

    if (isMaximizer)
    {
      int best = -1000;

      for (int i = 0; i < SIZE; i++)
      {
            for (int j = 0; j < SIZE; j++)
            {
                if (arr[ i] == '.')
                {
                  arr[ i] = 'O';
                  best = max(best, minimax(arr, depth + 1, !isMaximizer));
                  arr[ i] = '.';
                }
            }
      }

      return best;
    }
    else
    {
      int best = 1000;

      for (int i = 0; i < SIZE; i++)
      {
            for (int j = 0; j < SIZE; j++)
            {
                if (arr[ i] == '.')
                {
                  arr[ i] = 'X';
                  best = min(best, minimax(arr, depth + 1, !isMaximizer));
                  arr[ i] = '.';
                }
            }
      }

      return best;
    }
}

void findBestMove(char arr)
{
    int bestVal = -1000;
    int bestRow = -1;
    int bestCol = -1;

    for (int i = 0; i < SIZE; i++)
    {
      for (int j = 0; j < SIZE; j++)
      {
            if (arr[ i] == '.')
            {
                arr[ i] = 'O';
                int moveVal = minimax(arr, 0, false);
                arr[ i] = '.';

                if (moveVal > bestVal)
                {
                  bestRow = i;
                  bestCol = j;
                  bestVal = moveVal;
                }
            }
      }
    }

    arr = 'O';
}

int main()
{
    char board_now = {{'.','.','.'},{'.','.','.'},{'.','.','.'}};
    int x, row, col;

    while (!nowin(board_now))
    {
      printArray(board_now);
      printf("human input:");
      scanf("%i", &x);
      calculateRowAndCol(x, &row, &col);

      if (board_now == '.')
      {
            board_now = 'X';
            printf("\033[2J\033[H");
      }
      else
      {
            printf("\033[2J\033[H");
            printf("you have done this.please input again.\n");
            continue;
      }

      if (humanwin(board_now))
      {
            printArray(board_now);
            printf("human win.\n");
            break;
      }

      findBestMove(board_now);

      if (computerwin(board_now))
      {
            printArray(board_now);
            printf("computer win.\n");
            break;
      }
    }

    if (nowin(board_now))
    {
      printArray(board_now);
      printf("nobady win.\n");
    }

    return 0;
}


这个代码使用了递归的最小最大算法来决策计算机的下一步棋。它会遍历所有可能的下一步棋,并计算出每个可能的得分,然后选择得分最高的一步作为计算机的下一步棋。

希望这个代码可以帮助你解决问题!

Eat.随 发表于 2023-11-9 15:29:14

isdkz 发表于 2023-11-9 15:21
这个程序的问题在于计算机的移动是随机的,没有使用任何AI算法来进行决策。为了实现一个可以与玩家下井字棋 ...

额,并没有解决我的问题,不过算了自己手动运行测试吧
页: [1]
查看完整版本: 井字棋