在tic tac toe match中找到胜利者

时间:2014-03-18 18:35:30

标签: c arrays char

我知道人们之前会问这个,但我不明白答案。

假设您在函数中有char board[3][3]作为参数 如果X赢了,你需要返回1,如果O赢了,你需要返回-1;如果没有赢,你需要返回0或者如果它是平局,则需要返回0。

int checkforwin(char board[3][3]);

该功能的声明。

对于其中一个对手获胜的非原始测试有什么想法吗?

4 个答案:

答案 0 :(得分:2)

我可能会做类似以下的事情。您可以使用不带for循环的if语句,但这会减小源代码的大小。

// board[3][3]:
//    [0][0] | [1][0] | [2][0]
//    -------+--------+-------
//    [0][1] | [1][1] | [2][1]
//    -------+--------+-------
//    [0][2] | [1][2] | [2][2]
//
int checkforwin(char board[3][3])
{
    int x;

    for(x = 0; x < 3; x++)
    {
      // check vertical lines
      if ((board[x][0] != '\0') && 
          (board[x][0] == board[x][1]) && 
          (board[x][0] == board[x][2]))
         return(board[x][0] == 'O' ? -1 : 1);

      // check horizontal lines
      if ((board[0][x] != '\0') &&
          (board[0][x] == board[1][x]) && 
          (board[0][x] == board[2][x]))
         return(board[0][x] == 'O' ? -1 : 1);
    };

    // check top left to bottom right diagonal line
    if ((board[0][0] != '\0') && 
       (board[0][0] == board[1][1]) && 
       (board[0][0] == board[2][2]))
      return(board[0][0] == 'O' ? -1 : 1);

    // check bottom left to top right diagonal line
    if ((board[2][0] != '\0') && 
       (board[2][0] == board[1][1]) &&
       (board[0][0] == board[0][2]))
      return(board[2][0] == 'O' ? -1 : 1);

    // no winner
    return 0;
}

答案 1 :(得分:2)

这个对每行/列/对角线进行计数。

如果计数达到3,则表示一行中有三个X 同样,-3表示一行中有三个O 任何其他值表示没有赢家。

代码中有4个块:

  • 检查行
  • 检查列
  • 检查一个对角线
  • 检查另一个对角线。

这有很多重复的代码,违反了良好代码的DRY原则 但这很容易理解。

int CheckTicTacToe(char board[3][3])
{
    int count = 0;
    int row, col;

    // Check each of 3 rows:
    for(row = 0; row < 3; ++row)
    {
        count = 0;
        for(col=0; col < 3; ++col)
        {
            count += (board[row][col] == 'X')?  1 :
                     (board[row][col] == 'O')? -1 : 0;
        }
        if (count == 3 || count == -3)
        {
            return count / abs(count); // Return either 1 or -1
        }
    }

    // Check each of 3 columns.
    for(col = 0; col < 3; ++col)
    {
        count = 0;
        for(row=0; row < 3; ++row)
        {
            count += (board[row][col] == 'X')?  1 :
                     (board[row][col] == 'O')? -1 : 0;
        }
        if (count == 3 || count == -3)
        {
            return count / abs(count); // Return either 1 or -1
        }
    }

    // Check Left-to-Right downward Diagonal:
    count = 0;
    for(col = 0; col < 3; ++col)
    {
        count += (board[col][col] == 'X')?  1 :
                 (board[col][col] == 'O')? -1 : 0;
    }
    if (count == 3 || count == -3)
    {
        return count / abs(count); // Return either 1 or -1
    }

    // Check Left-to-Right upward Diagonal
    count = 0;
    for(col = 0; col < 3; ++col)
    {
        count += (board[col][2-col] == 'X')?  1 :
                 (board[col][2-col] == 'O')? -1 : 0;
    }
    if (count == 3 || count == -3)
    {
        return count / abs(count); // Return either 1 or -1
    }

    return 0;
}

答案 2 :(得分:2)

有三种方法可以解决在井字游戏中检测获胜者的问题。有蛮力方法,算法方法和数据驱动方法。

蛮力方法由一系列if语句组成。由于只有8种方式可以赢得井字游戏,因此只需要8个if语句来确定获胜者。因此,强力方法与其他方法相比较,因为它具有相对少量的代码行,简单,易于读取的代码,相对小的可执行大小和快速的执行速度。蛮力方法是最好的方法,因为井字游戏是微不足道的。像Connect Four这样稍微复杂的游戏可能需要更高级的编码技术,但是使用简单的if语句可以最好地解决井字游戏问题。

算法方法已在对此问题的其他回答中得到证明。 David Syzdek的算法是迄今为止最好的算法,但在某种程度上是混合解决方案,因为它通过使用{{1}将八个if语句减少到四个if语句循环。请注意,他的算法仍然在整个代码中分散了硬编码索引。

数据驱动方法使用初始化数据集来抽象问题,以便代码完全通用,并且所有混乱都被收集到数据集中。以下是使用数据驱动解决方案的代码。

for

请注意,我并未提倡针对此特定问题的数据驱动解决方案,因为问题本身太过微不足以保证数据驱动的解决方案。

答案 3 :(得分:0)

if语句是采用这种数据结构的方法。您可以使用位掩码,但在给定数据结构的情况下使用字符串元素('X' 'O'),位掩​​码将非常难看并且只会使事情变得不必要地复杂。使用If语句进行测试的最短和最清晰的方法。

如果您使用了不同的数据结构,则可能会使事情变得更简单。例如,如果电路板存储为位数组“011011001”,则位掩码更清晰。