我目前正在使用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语句列表,每个语句包含特定板级尺寸的代码,但这似乎是不正确且效率最低的方法。
我希望有人能提供帮助。任何帮助将不胜感激。
谢谢。
答案 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;
}
colWinnerCheck
与rowWinnerCheck
的实现方式相似。
验证玩家是否在对角线上获胜也很相似。
/* 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);
我们定义使用的字母X
和O
,并将它们分别指定为常量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 == b
或a == (n-b-1)
时,请将O
添加到适当的对角线变量中。由于(1,1)属于两个对角线,因此将O
添加到leftDiag
和rightDiag
中。
我们轮流转弯,直到满足以下条件之一:
i
中rows
这样的位置rows[i] == n * X
。这意味着X
通过填充第i行获胜。行中的位置j
rows[j] == n * O
。这意味着O赢了i
中cols
这样的位置cols[i] == n * X
。这意味着X
赢得第ith列而获胜。位置j
在cols中,使得
cols[j] == n * O
。这意味着O赢了leftDiag == n * X
或rightDiag == n * X
,X赢了。 leftDiag == n * O
或rightDiag == n * O
,O赢了。n*n
已采取行动,但先前的条件是
从没见过。这意味着游戏以平局告终。请注意,最后,我们不需要遍历行,列或对角线来验证是否有人获胜。如果在整个游戏中一行,一列或对角线的总和为n * Character
,则该角色玩家获胜。这样可以将验证获胜者的难度从O(n^2)
降低到O(1)
。权衡只是增加O(n)
个空间。