-2

我正在用 C 编写一个井字游戏。这是逻辑。用户先走,选择一个插槽。使用简单的公式计算槽的位置。然后填充选定的插槽。接下来,计算机随机选择一个插槽。为此,我在 stdlib.h 中使用了 rand() 函数。最初,3x3 矩阵的所有元素都设置为 0。我的问题是,即使所有其他元素都是 0,并且用户选择插槽 5 或插槽 9,用户也会获胜。comp 也一样。这是我的代码-

#include<stdio.h>
#include<stdlib.h>
int check(int[][3]);
void print(int[][3]);
main()
{
 int i,j,match[3][3]={0},posx,posy,comp_posx,comp_posy,fill=0,slot,user_score=0,comp_score=0;
 char ch;
 srand(time(NULL));
 do
 {
  while(fill<9)
  {
   printf("\nEnter the slot you want to fill.\n");
   scanf("%d",&slot);
   if (slot > 9)
   {
    printf("Error!\nSlot value cannot exceed 9.\n");
    continue;
   }
   else if( slot >= 1&&slot <=3)
   {
    posx=0;
    posy=slot-1;
   }
   else if (slot >= 4 && slot <= 6)
   {
    posx=1;
    posy=slot-4;
   }
   else
   {
    posx=2;
    posy=slot-7;
   }
   if (match[posx][posy] == 0)
   {
    match[posx][posy]=1;
    fill++;
    check(match);
    if(check(match)==1)
    {
     printf("The user wins!\n");
     user_score++;
     print(match);
     break;
    }
    else if(check(match)==-1)
    {
     printf("The computer wins!\n");
     comp_score++;
     print(match);
    }
    else
    {
     if(fill==9)
     {
      printf("It's a draw!\n");
      print(match);
      break;
     }
     else
     {
      printf(" ");
     }
    }
   }
   else
   {
    printf("Sorry! This slot is already filled.\nPlease pick another slot.\n");
    continue;
   }
   label:
   comp_posx=rand()%3;
   comp_posy=rand()%3;
   if(match[comp_posx][comp_posy]==0)
   {
    match[comp_posx][comp_posy]=-1;
    fill++;
    check(match);
    if (check(match)==1)
    {
     printf("The user wins!\n");
     user_score++;
     print(match);
     break;
    }
    else if(check(match)==-1)
    {
     printf("The computer wins!\n");
     comp_score++;
     print(match);
     break;
    }
    else
    {
     if (fill==9)
     {
      printf("It's a draw!\n");
      print(match);
      break;
     }
     else
     {
      printf(" ");
     }
    }
   }
   else
   goto label;
   for(i=0;i<3;i++)
   {
    printf("\n");
    for(j=0;j<3;j++)
    {
    printf("%d\t",match[i][j]);
    }
   }
  }
  for(i=0;i<3;i++)
  {
   for(j=0;j<3;j++)
   {
    match[i][j]=0;
   }
  }
  printf("Continue? Y/N\n");
  scanf("%c %c",&ch,&ch);
 }
 while(ch=='y'||ch=='Y');
 printf("FINAL SCORES>>\nUser=%d\nComputer=%d\n",user_score,comp_score);
}
int check(int match[][3])
{
 int i,j;
 if( match[2][0]==match[1][1] && match[1][1]==match[0][2] )
 {
  if (match[0][2]==1)
  return 1;
  else if (match[0][2]==-1)
  return -1;
  else
  printf(" ");
 }
 for(i=0;i<3;i++)
 {
  if (match[i][0]==match[i][1]&&match[i][1]==match[i][2])
  {
   if(match[i][1]==1)
   return 1;
   else if(match[i][1]==-1)
   return -1;
   else
   continue;
  }
 }
 for(j=0;j<3;j++)
 {
  if(match[0][j]==match[1][j]&&match[0][j]==match[2][j])
  {
   if (match[0][j]==1)
   return 1;
   else if(match[0][j]==-1)
   return -1;
   else
   continue;
  }
 }
 for (i=0;i<1;i++)
 {
  if(match[i][i]==match[i+1][i+1]&&match[i][i]==match[i+2][i+2])
  {
   if (match[i][i]==1)
   return 1;
   else if (match[i][i]==-1)       return -1;
  else continue;
  }
 }
}
 void print(int match[][3])
 {
  int i,j;
  for(i=0;i<3;i++)
  {
   printf("\n");
   for(j=0;j<3;j++)
   {
    printf("%d\t",match[i][j]);
   }
  }
 }

您能否建议更改代码,以便我不会遇到这些问题?

4

2 回答 2

1

check这段代码有很多混乱,但问题的原因是如果没有人获胜,您不会返回值(或者换句话说,返回垃圾值) 。return 0;在末尾添加行check

于 2012-05-09T14:34:33.233 回答
1

我不能为您的代码提出解决方案,而是在实施中提出解决方案。我曾经不得不在 C 中实现井字游戏,最后我使用了类似于MiniMax 算法的东西,你可以在 github上找到它。

在井字游戏中,您有 9 个!(362880) 游戏的可能状态。每个状态代表棋盘中 X 和 O 的给定组合。这些状态可以表示“无效状态”(也就是说,您永远无法通过玩游戏达到该状态)、“平局”、“X 胜”或“O 胜”。

由于您的可能状态数量相对较少,您可以通过玩每个可能的移动来计算所有可能的状态(我在游戏初始化时这样做,因为它需要做的工作量很小并且不关心性能),并将初始动作与他们可能的下一步动作联系起来。

这将给你一棵树,给定一个初始移动,它将引导你进入平局、胜利或失败的情况(当然取决于谁是 X,谁是 O)。一旦达到该状态,您就可以将此结果传播到第一步。

结果,当人类玩家下棋时,计算机只会跟随这棵可能走棋的树,总是玩给出“赢”或“平”的结果,但绝不会是“输”。它只是一个状态机,每次移动都会改变状态。人类通过下棋来改变状态,计算机通过下棋来选择下一个状态,这会将游戏重定向到获胜的最终状态(从计算机的角度来看),如果不可能获胜,则为平局。

所以本质上,这是一个“完美的井字游戏”。你将无法击败它。如果你打得无懈可击,你可以打平比赛,但永远不会赢。

于 2012-05-09T14:42:28.387 回答