Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在井字游戏比赛中找到赢家_C_Arrays_Char - Fatal编程技术网

C 在井字游戏比赛中找到赢家

C 在井字游戏比赛中找到赢家,c,arrays,char,C,Arrays,Char,我知道以前有人问过这个问题,但我不明白答案 假设函数中有一个字符板[3][3]作为参数 如果X赢了,则需要返回1;如果O赢了,则需要返回1;如果还没有人赢了,或如果是平局,则需要返回0 int checkforwin(char board[3][3]); 这是函数的声明 有没有想过通过非原始测试来让对手获胜?If语句就是这种数据结构的一种方式。您可以使用位掩码,但对于具有字符串元素的给定数据结构('X''O'),位掩码将非常难看,只会使事情变得不必要的复杂。进行测试的最短和最清晰的方法是使用I

我知道以前有人问过这个问题,但我不明白答案

假设函数中有一个
字符板[3][3]
作为参数 如果X赢了,则需要返回1;如果O赢了,则需要返回1;如果还没有人赢了,或如果是平局,则需要返回0

int checkforwin(char board[3][3]);
这是函数的声明


有没有想过通过非原始测试来让对手获胜?

If语句就是这种数据结构的一种方式。您可以使用位掩码,但对于具有字符串元素的给定数据结构(
'X''O'
),位掩码将非常难看,只会使事情变得不必要的复杂。进行测试的最短和最清晰的方法是使用If语句


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

我可能会执行以下操作。您可以使用不带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;
}
//板[3][3]:
//    [0][0] | [1][0] | [2][0]
//    -------+--------+-------
//    [0][1] | [1][1] | [2][1]
//    -------+--------+-------
//    [0][2] | [1][2] | [2][2]
//
int checkforwin(字符板[3][3])
{
int x;
对于(x=0;x<3;x++)
{
//检查垂直线
如果((板[x][0]!='\0')&&
(董事会[x][0]==董事会[x][1])&
(单板[x][0]==单板[x][2]))
返回(板[x][0]='O'?-1:1);
//检查水平线
如果((板[0][x]!='\0')&&
(董事会[0][x]==董事会[1][x])&
(单板[0][x]==单板[2][x]))
返回(单板[0][x]='O'?-1:1);
};
//检查左上至右下对角线
如果((板[0][0]!='\0')&&
(董事会[0][0]==董事会[1][1])&
(单板[0][0]==单板[2][2]))
返回(单板[0][0]='O'?-1:1);
//检查左下角到右上角的对角线
如果((电路板[2][0]!='\0')&&
(董事会[2][0]==董事会[1][1])&&
(单板[0][0]==单板[0][2]))
返回(单板[2][0]='O'?-1:1);
//没有赢家
返回0;
}

这一项在每行/每列/每对角线上保留一个计数

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

代码中有4个块:

  • 检查行
  • 检查列
  • 检查一条对角线
  • 检查另一条对角线
这有很多重复代码,违反了良好代码的原则。
但这很容易理解

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;
}
int CheckTicTacToe(字符板[3][3])
{
整数计数=0;
int row,col;
//检查三行中的每一行:
用于(行=0;行<3;++行)
{
计数=0;
用于(列=0;列<3;++
{
计数+=(板[行][列]='X')?1:
(板[行][col]='O')?-1:0;
}
如果(计数=3 | |计数=3)
{
返回计数/abs(count);//返回1或-1
}
}
//检查3列中的每一列。
用于(列=0;列<3;++
{
计数=0;
用于(行=0;行<3;++行)
{
计数+=(板[行][列]='X')?1:
(板[行][col]='O')?-1:0;
}
如果(计数=3 | |计数=3)
{
返回计数/abs(count);//返回1或-1
}
}
//检查从左到右向下的对角线:
计数=0;
用于(列=0;列<3;++
{
计数+=(板[col][col]='X')?1:
(board[col][col]='O')?-1:0;
}
如果(计数=3 | |计数=3)
{
返回计数/abs(count);//返回1或-1
}
//检查从左到右向上的对角线
计数=0;
用于(列=0;列<3;++
{
计数+=(电路板[col][2-col]=='X')?1:
(电路板[col][2-col]=='O')?-1:0;
}
如果(计数=3 | |计数=3)
{
返回计数/abs(count);//返回1或-1
}
返回0;
}

有三种方法可以解决在井字游戏中发现赢家的问题。有蛮力法、算法法和数据驱动法

蛮力方法由一系列
if
语句组成。因为只有8种方法可以赢得一场井字游戏,所以只有8种
if
语句才能确定胜利者。因此,蛮力方法与其他方法相比比较好,因为它具有相对较少的代码行数、简单易读的代码、相对较小的可执行文件大小和较快的执行速度。蛮力法是最好的方法,因为tic tac toe的游戏很简单。一个稍微复杂一点的游戏,比如Connect Four,可能需要更高级的编码技术,但是tic tac toe最好用简单的
if
语句来解决

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

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

typedef struct
{
    int valid;
    int rowA, colA;
    int rowB, colB;
    int rowC, colC;
}
    stPath;

static stPath paths[] =
{
    { TRUE,   0, 0,   0, 1,   0, 2 },   // top row
    { TRUE,   1, 0,   1, 1,   1, 2 },   // middle row
    { TRUE,   2, 0,   2, 1,   2, 2 },   // bottom row

    { TRUE,   0, 0,   1, 0,   2, 0 },   // left column
    { TRUE,   0, 1,   1, 1,   2, 1 },   // middle column
    { TRUE,   0, 2,   1, 2,   2, 2 },   // right column

    { TRUE,   0, 0,   1, 1,   2, 2 },   // TL to BR diagonal
    { TRUE,   0, 2,   1, 1,   2, 0 },   // TR to BL diagonal

    { FALSE,  0, 0,   0, 0,   0, 0 }    // end of list
};

int checkforwin( char board[3][3] )
{
    int a, b, c;
    stPath *pptr;

    // assumes that board array uses 'X' 'O' and <sp> to mark each position

    for ( pptr = paths; pptr->valid; pptr++ )
    {
        a = board[pptr->rowA][pptr->colA];
        b = board[pptr->rowB][pptr->colB];
        c = board[pptr->rowC][pptr->colC];

        if ( a == b && b == c && a != ' ' )
            return( (a == 'X') ? 1 : -1 );
    }

    return( 0 );    // no winner yet
}
typedef结构
{
int有效;
内罗瓦,可乐;
内罗布,科尔布;
int rowC,colC;
}
stPath;
静态stPath路径[]=
{
{TRUE,0,0,0,1,0,2},//顶行
{TRUE,1,0,1,1,1,2},//中间行