C-如何找到跨界赢家

时间:2018-07-13 16:49:35

标签: c arrays

我目前正在使用C制作井字游戏。我正在制作一个Check(字符符号)功能,每位玩家出手之后我都可以调用该功能(它将检查获胜者)。我需要帮助,因为井字游戏可以在不同尺寸的板上(3到12)进行播放。

我编写了以下代码,可用于查找3 x 3游戏的赢家:

**//For Rows**
for(i=0; i<3; i++)/***sign is the player symbol e.g. 'X'OR'O'***/
    if(board[i][0] == sign && board[i][0] == board[i][1] && board[i][1] == ` 
     board[i][2]){`
         printf("the winner is %c", sign );
         return 1;
}

**//For Columns** 
for(i=0; i<3; i++)/***sign is the player symbol e.g. 'X'OR'O'***/
    if(board[0][i] == sign && board[0][i] == board[1][i] && board[1][i] == 
        board[2][i]){
        printf("the winner is %c", sign );
        return 1;
}

**//For Diagnal 1 \**
if(board[0][0] == sign && board[0][0] == board[1][1] && board[1][1] == 
    board[2][2]){
    printf("the winner is %c", sign );
    return 1;
}

**//For Diagnal 2 /**
if(board[0][2] == sign && board[0][2] == board[1][1] && board[1][1] == 
    board[2][0]){
    printf("the winner is %c", sign );
    return 1;
}

但是,正如我提到的,我的游戏可以在不同的棋盘尺寸上玩,这是由游戏开始时的用户输入来选择的。此大小存储在可变的“ int大小”中。我将如何更改以上代码以使其与任何大小的板一起使用?

我知道我可以创建一个if语句列表,每个语句包含特定板级尺寸的代码,但这似乎是不正确且效率最低的方法。

我希望有人能提供帮助。任何帮助将不胜感激。

谢谢。

2 个答案:

答案 0 :(得分:1)

请注意,您的4种情况下的if语句都可以使用循环来编写;例如,第一个可以写为:

int win = (board[i][0] == sign); // assume a win until we find out otherwise
// loop over the pairs to compare until we find a mismatch or exhaust them all
for ( int j = 1; (win == 1) && (j < size); j++ )
    if ( board[i][j-1] != board[i][j] )
        win = 0;
if ( win ) {
     printf("the winner is %c", board[i][0] );
     return 1;
}

对于其他3种情况,分别更改要比较的board的哪两个元素和win的初始化。

答案 1 :(得分:1)

您可以具有三个函数,一个遍历行,一个遍历cols,另一个遍历对角线对。

/* If the sign player won, return 1. Else return 0. */
int rowWinnerCheck(int n, char sign, char board[n][n]){
    for(int i = 0; i < n; i++){
        int sameSign = 1;
        for(int j = 0; j < n; j++){
            char letter = board[i][j];
            if(letter != sign){
                sameSign = 0;
            }
        }
        if(sameSign == 1){
            return 1;
        }
    }
    return 0;
}

colWinnerCheckrowWinnerCheck的实现方式相似。

验证玩家是否在对角线上获胜也很相似。

/* This function checks if a player won diagonally from the top-left to bottom-right*/
int diagonalWinnerCheck(int n, char sign, char board[n][n]){
    for(int i = 0; i < n; i++){
        int sameSign = 1;
        char letter = board[i][i];
        if(letter != sign){
            return 0;
        }
    }
    return 1;
}

无循环的解决方案

这里是没有循环的一种可能的解决方案,我相信对于较大的n来说,扩展性更好。

我将把C留给您完成,而我只解释在n x n董事会上确定获胜者的概念。您提供的代码使用循环来比较板上的内容。该解决方案不依赖循环,因为它利用数学表示法来确定获胜者。

董事会代表

我们首先需要使用尺寸为n x n的整数的2D数组来表示电路板。从一开始,我们还将董事会中的所有内容都设为零。

int board[n][n];
memset(board, 0, sizeof(board[0][0]) * n * n);

我们定义使用的字母XO,并将它们分别指定为常量1-1注意:1,-1是任意选择的,但要使该解决方案有效,它们必须为整数k,-k

我们为解决方案定义了另外四个项目。两个整数数组,一个代表行,一个代表cols,两个整数代表两个对角线。

int rows[n] = {0};
int cols[n] = {0};
int leftDiag = 0;
int rightDiag = 0;

工作方式

让我们假设一个新游戏是在3x3板上开始的。我玩X,而您玩O。我继续移动位置(2,0)。程序首先检查(2,0)处的电路板位置,并查看其是否为零。如果是,请将其设置为X,否则将引发错误,因为该位置已经播放过。该程序还将X添加到rows[2]cols[0]中。

您在(1,1)处播放O。首先检查是否已经播放过board[1][1],如果尚未播放,请将其设置为O。将O添加到rows[1]cols[1]。这是一个特例。当玩家在对角线上打O时,即移动(a,b) a == ba == (n-b-1)时,请将O添加到适当的对角线变量中。由于(1,1)属于两个对角线,因此将O添加到leftDiagrightDiag中。

我们轮流转弯,直到满足以下条件之一:

  • irows这样的位置rows[i] == n * X。这意味着X 通过填充第i行获胜。行中的位置j rows[j] == n * O。这意味着O赢了
  • icols这样的位置cols[i] == n * X。这意味着X 赢得第ith列而获胜。位置j在cols中,使得 cols[j] == n * O。这意味着O赢了
  • leftDiag == n * XrightDiag == n * X,X赢了。 leftDiag == n * OrightDiag == n * O,O赢了。
  • n*n已采取行动,但先前的条件是 从没见过。这意味着游戏以平局告终。

请注意,最后,我们不需要遍历行,列或对角线来验证是否有人获胜。如果在整个游戏中一行,一列或对角线的总和为n * Character,则该角色玩家获胜。这样可以将验证获胜者的难度从O(n^2)降低到O(1)。权衡只是增加O(n)个空间。