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},//中间行