在基本的Tic-Tac-Toe游戏中保存数据

时间:2012-01-11 19:28:17

标签: c

我对C.相对较新。在Kochan的“C语言编程”中,我目前正在使用if-else语句。我正在尝试编写一个基本的tic-tac-toe游戏,但我遇到了一些困难。一旦玩家放置了x或o,我不确定如何保存棋盘。这是我到目前为止的代码:

#include <stdio.h>

int main (void)
{
    int board = "_|_|_\n
                 _|_|_\n
                  | | \n";
    int player1, player2;

    printf ("Print %i", board)

    printf("Player 1, it's your move:")
    scanf("%i", player1)

    if(player1 == "upLeft")
        printf("x|_|_\n
                _|_|_\n
                _|_|_\n
etc.

我是否仍然太过初学者才能实现此功能?

5 个答案:

答案 0 :(得分:6)

首先,这没有意义:

int board = "_|_|_\n
             _|_|_\n
              | | \n";

int不是字符串,您不能将字符串分配给int。在C中,字符串是字符数组:

char board[] = "_|_|_\n_|_|_\n | | \n";

这更有意义。但它真的不是存储tic tac toe board状态的好方法。你应该做的是为板上的每个位置存储一些值。不要担心电路板的实际格式,您可以在显示时按照您的喜好对其进行格式化。所以以这种方式存储你的电路板:

char board[9] = "---------";

其中“ - ”表示空格为空。当玩家移动时,您可以使用“X”或“O”(或1和2,或任何其他适合您的值)替换阵列中相应位置的角色。当您从用户那里获得一些输入时,您将只更改电路板阵列中的相应值。例如,如果您从左上角开始对位置0-8进行编号,则中间行的最右侧位置将是位置5。 (请记住,C数组是从零开始的,因此第一个索引是0.)因此,如果用户想要在该位置放置X,您可以说:

board[5] = 'X';

接下来,您可能想要编写一个打印电路板的功能。 是你要插入任何你喜欢的字符来画板的地方。

最后,您将要使用某种循环来重复读取用户的输入,修改电路板的状态,打印电路板,并显示提示。

答案 1 :(得分:3)

首先,你不能存储

"_|_|_\n
 _|_|_\n
  | | \n";

在整数变量中。您需要其他类型的变量(例如char *char a[][]等)。

OTOH,伪代码如下。请尝试按照此操作自行编写C程序。

Let row = 3 and column = 3
Declare an array[row][column] and fill it all with 0
Let 1 represent the input of user-1 and 2 represent the input of user-2 (in the array)
i.e. if a[2][2] = 1 means, user-1 marked that location.
while ( ! all_locations_filled() ) {
    take input from user-1
    if user-1 chooses a valid_location(location) to mark, then mark_location(user-1, location)
    check if user-1 won_the_game(user-1), if so break and congratulate user-1! 

    take input from user-2
    if user-2 chooses a valid_location(location) to mark, then mark_location(user-2, location)
    check if user-2 won_the_game(user-2), if so break and congratulate user-2! 

}

valid_location(location l)
{
    return array[l.row][l.column] == 0;
}

mark_location(user u, location l)
{
    array[l.row][l.column] = (u==user-1) ? 1 : 2;
}

display_board()
{
    for i=0 to row
       for j=0 to col
           if array[i][j] == 0 print "" 
           else print array[i][j]
    /* print blank when that location is not yet marked */
}

all_locations_filled()
{
    for i=0 to row
       for j=0 to col
           if array[i][j] == 0
               return false    
    return true
}

won_the_game(user u)
{
    /* You need to write the logic here */
    :P
}

答案 2 :(得分:1)

您可以使用2d数组来表示电路板,也可以使用一些小的int,其中0表示无效,1表示X,2表示0。

你不能保存那样的

 int board = "X|_|_\n
              _|_|_\n
               | | \n";

你可以拥有像[0] [0] = 1;

这样的东西

然后你可以迭代那个数组,如果它的1打印X。

答案 3 :(得分:1)

这是一个初学者问题,但你是初学者,所以没关系!让我们来看一些主要问题:

所以,你说你想要保存董事会状态。你想要保存什么?在程序的任何一点,你想要查找什么?这些举动的历史?董事会是什么样的?每个角落包含什么?当您从用户那里获得一些输入时,其中每一个都提示了 更改变量 的不同方式。

正如其他人所说,你不能用int类型做所有这些事情,即使你可以,这个程序仍然太难和令人沮丧,直到你的工具箱中有更多的工具。第7章是Arrays,它将非常有用,第10章是Character Strings,它将向您展示如何在C中以正确的方式处理所有这些字符串。所以我给你的建议是经过本书的几个章节。大局将开始变得更有意义。快乐的黑客!

答案 4 :(得分:0)

这是一个小模板,就像我在GetBestMove()函数中为计算机移动编写自己的逻辑(如果你正在构建AI),或者在StartGame函数中用GetMove函数替换GetBestMove的调用

#include<stdio.h>
#define HUMAN_WIN 1
#define DRAW 0
#define HUMAN_LOSE -1
#define HUMAN_COIN 'X'
#define COMP_COIN 'O'
#define DEFAULT 0xFFF

int main(void)
{
   StartGame();
}

enum turnOf{ Human = 0, Computer};
enum gameEndState{Lose = -1, Draw, Win};
int humanMove = 1;
int computerMove = 1;
char _board[3][3] = {'-', '-', '-', '-', '-', '-', '-', '-', '-'};

void StartGame()
{
   enum turnOf turn = 0;
   enum gameEndState state = -2;

   while(1)
   {
      turn = 1 - turn;
      if(turn == Human)
      {
         GetMove();
         UpdateBoard(humanMove, turn);
      }
      else if(turn == Computer)
      {
         GetBestMove(turn);
         UpdateBoard(computerMove, turn, _board);
      }
      state = win(_board);
      switch(state)
      {
         case Win:
            NotifyUser("You win.");exit(0);
         case Draw:
            NotifyUser("Match draw.");exit(0);
         case Lose:
            NotifyUser("You Lose.");exit(0);
      }
   }
}

int depth = 0;
int GetBestMove(enum turnOf turn, int *x, int *y)
{
   depth++;
   int i, j, MOV = -10, BESTMOVx, BESTMOVy;
   enum turnOf now = turn;
   char pebble = (now == Human) ? HUMAN_COIN : COMP_COIN;

   for(i=0; i<3; i++)
   {
      for(j=0; j<3; j++)
      {
         if(_board[i][j] == '-')
         {
            _board[i][j] = pebble;
            now = 1 - now;

            int condition = win(_board);

            if(condition != DRAW || condition != DEFAULT)
            {
               return (condition == HUMAN_LOSE) ? (depth - 10) : (10 - depth);
            }
            else
            {
               int state = GetBestMove(now, BESTMOVx, BESTMOVy);
               if(state > MOV)
               {
                  MOV = state;
               }
            }
         }
      }
   }
}

int win(char a[3][3])
{
   char pebble = HUMAN_COIN;
   int i, j, p = 0;

   i=0;
   for(j = 0; j < 3; j++)
      if(a[i][j] == pebble && a[i+1][j] == pebble && a[i+2][j] == pebble) return HUMAN_WIN;
   j=0;
   for(i = 0; i < 3; i++)
      if(a[i][j] == pebble && a[i][j+1] == pebble && a[i][j+2] == pebble) return HUMAN_WIN;
   if(a[0][0] == pebble && a[1][1] == pebble && a[2][2] == pebble) return HUMAN_WIN;
   else if(a[0][2] == pebble && a[1][1] == pebble && a[2][0] == pebble) return HUMAN_WIN;

   /// Recheck for lose
   pebble = COMP_COIN;
   i=0;
   for(j = 0; j < 3; j++)
      if(a[i][j] == pebble && a[i+1][j] == pebble && a[i+2][j] == pebble) return HUMAN_LOSE;
   j=0;
   for(i = 0; i < 3; i++)
      if(a[i][j] == pebble && a[i][j+1] == pebble && a[i][j+2] == pebble) return HUMAN_LOSE;
   if(a[0][0] == pebble && a[1][1] == pebble && a[2][2] == pebble) return HUMAN_LOSE;
   else if(a[0][2] == pebble && a[1][1] == pebble && a[2][0] == pebble) return HUMAN_LOSE;

   for(i = 0; i < 3; i++)
      for(j = 0; j < 3; j++)
         if(a[i][j] == '-') p++;

   if(p == 0) return DRAW;

   return DEFAULT;
}

void GetMove()
{
   int x, y;
   LoadFrame(_board);
   printf("\nEnter your move : ");
   humanMove = getche() - 48;

   if(!(humanMove > 0 && humanMove < 10))
   {
      NotifyUser("Enter a valid location.");
      GetMove();
   }
   GetCordinates(&x, &y, humanMove);

   if(_board[x][y] != '-')
   {
      NotifyUser("The place is nonEmpty.");
      GetMove();
   }
}


void UpdateBoard(int move, enum turnOf player, char board[3][3])
{
   int x, y;
   char pebble = (player == Human) ? HUMAN_COIN : COMP_COIN;

   GetCordinates(&x, &y, move);

   board[x][y] = pebble;
   LoadFrame(board);
}

void LoadFrame(char board[3][3])
{
   int x, y;
   system("cls");
   for(x = 0; x < 3; x++)
   {
      printf("\n\t  ");
      for(y = 0; y < 3; y++)
      {
         printf(" %c ", board[x][y]);
      }
   }
}

void GetCordinates(int *x, int *y, int move)
{
   switch(move)
   {
      case 1: *x = 0; *y = 0; break;
      case 2: *x = 0; *y = 1; break;
      case 3: *x = 0; *y = 2; break;
      case 4: *x = 1; *y = 0; break;
      case 5: *x = 1; *y = 1; break;
      case 6: *x = 1; *y = 2; break;
      case 7: *x = 2; *y = 0; break;
      case 8: *x = 2; *y = 1; break;
      case 9: *x = 2; *y = 2; break;
   }
}

void NotifyUser(const char* message)
{
   printf("\n\n%s\a", message);
   getch();
   system("cls");
   LoadFrame(_board);
}