-2

三目並べのゲームをCでコーディングしています。ロジックは次のとおりです。ユーザーが最初に移動し、スロットを選択します。スロットの位置は、簡単な式を使用して計算されます。次に、選択したスロットが埋められます。次に、コンピュータはランダムにスロットを選択します。このために、stdlib.hのrand()関数を使用しました。最初は、3x3マトリックスのすべての要素が0に設定されています。私の問題は、他のすべての要素が0であり、ユーザーがスロット5またはスロット9を選択した場合でも、ユーザーが勝つことです。コンプも同じです。これが私のコードです-

#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でTicTacToeを実装する必要があり、MiniMaxアルゴリズムに似たものを使用することになりました。これは、githubで見つけることができます。

TicTacToeゲームでは、9つあります。(362880)ゲームの可能な状態。各状態は、ボード内のXとOの特定の組み合わせを表します。これらの状態は、「無効な状態」(つまり、プレイしてもその状態に到達することはできません)、「引き分け」、「X勝ち」、または「O勝ち」を表すことができます。

可能な状態は比較的少ないので、可能な各移動をプレイすることで、それらすべての可能な状態を計算できます(これは、ゲームの初期化時に行う作業が少なく、パフォーマンスを気にしないためです)、そして、最初の動きをそれらの可能な次の動きと関連付けます。

これにより、最初の動きが与えられると、引き分け、勝ち、または負けのシナリオにつながるツリーが得られます(もちろん、誰がXで誰がOかによって異なります)。その状態に達すると、この結果を最初の動きまで伝播できます。

その結果、人間のプレーヤーが動きをするとき、コンピューターはこの可能な動きのツリーをたどり、常に「勝ち」または「引き分け」の結果をもたらすものを再生しますが、「負け」は決してしません。移動するたびに状態が変化するのは、単なるステートマシンです。人間はプレイすることで状態を変更し、コンピューターは、ゲームを最終的な勝利の状態(コンピューターの観点から)または勝てない場合は引き分けにリダイレクトする動きをプレイすることによって、次の状態を選択します。

つまり、本質的に、これは「完璧な三目並べプレーヤー」です。あなたはそれを打ち負かすことはできません。完璧にプレーすれば、試合を引き分けることはできますが、勝つことはできません。

于 2012-05-09T14:42:28.387 に答える