我在C#中开发了一个tic tac toe游戏,并为胜利条件设置了一个函数,但我似乎无法弄清楚当网格已满时如何设置条件。当我尝试输入时,领带会随机出现。我想知道是不是我如何设置or和and运算符。这就是我尝试过的。
public bool Ended()
{
if (grid[0, 0] == 'X' && grid[0, 1] == 'X' && grid[0, 2] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
if (grid[1, 0] == 'X' && grid[1, 1] == 'X' && grid[1, 2] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
if (grid[2, 0] == 'X' && grid[2, 1] == 'X' && grid[2, 2] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
if (grid[0, 0] == 'X' && grid[1, 0] == 'X' && grid[2, 0] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
if (grid[0, 1] == 'X' && grid[1, 1] == 'X' && grid[2, 1] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
if (grid[0, 2] == 'X' && grid[1, 2] == 'X' && grid[2, 2] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
if (grid[0, 0] == 'X' && grid[1, 1] == 'X' && grid[2, 2] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
if (grid[0, 2] == 'X' && grid[1, 1] == 'X' && grid[2, 0] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
if (grid[0, 0] == 'O' && grid[0, 1] == 'O' && grid[0, 2] == 'O') { Console.WriteLine("PLayer 2 Wins"); return true; }
if (grid[1, 0] == 'O' && grid[1, 1] == 'O' && grid[1, 2] == 'O') { Console.WriteLine("PLayer 2 Wins"); return true; }
if (grid[2, 0] == 'O' && grid[2, 1] == 'O' && grid[2, 2] == 'O') { Console.WriteLine("PLayer 2 Wins"); return true; }
if (grid[0, 0] == 'O' && grid[1, 0] == 'O' && grid[2, 0] == 'O') { Console.WriteLine("PLayer 2 Wins"); return true; }
if (grid[0, 1] == 'O' && grid[1, 1] == 'O' && grid[2, 1] == 'O') { Console.WriteLine("PLayer 2 Wins"); return true; }
if (grid[0, 2] == 'O' && grid[1, 2] == 'O' && grid[2, 2] == 'O') { Console.WriteLine("PLayer 2 Wins"); return true; }
if (grid[0, 0] == 'O' && grid[1, 1] == 'O' && grid[2, 2] == 'O') { Console.WriteLine("PLayer 2 Wins"); return true; }
if (grid[0, 2] == 'O' && grid[1, 1] == 'O' && grid[2, 0] == 'O') { Console.WriteLine("PLayer 2 Wins"); return true; }
else if (grid[0, 0] == 'X' || grid[0, 0] == 'O' &&
grid[0, 1] == 'X' || grid[0, 1] == 'O' &&
grid[0, 2] == 'X' || grid[0, 2] == 'O' &&
grid[1, 0] == 'X' || grid[1, 0] == 'O' &&
grid[1, 1] == 'X' || grid[1, 1] == 'O' &&
grid[1, 2] == 'X' || grid[1, 2] == 'O' &&
grid[2, 0] == 'X' || grid[2, 0] == 'O' &&
grid[2, 1] == 'X' || grid[2, 1] == 'O' &&
grid[2, 2] == 'X' || grid[2, 2] == 'O')
{ Console.WriteLine("It's a Tie"); return true; }
return false;
}
答案 0 :(得分:14)
根本问题在于程序的缩进与其含义不符。假设我写道:
int x =
2 + 3 *
4 + 5;
很容易认为这应该是5 x 9 = 45,但事实上它是2 + 12 + 5 = 19.
你做了同样的事情。
if (a || b &&
c || d)
装置
if (a || (b && c) || d)
不是你想要它的意思,这是
if ((a || b) && (c || d))
您可能已经记住乘法优先于加法。您可以记住AND高于OR,因为AND与乘法相同!
true && true == true
true && false == false
false && true == false
false && false == false
如果我们将true替换为1,将false替换为0,将&&
替换为*
,那么我们会得到真实的陈述:
1 * 1 == 1
1 * 0 == 0
0 * 1 == 0
0 * 0 == 0
现在让我们解决你的程序中的其他问题。
每当您发现两次或两次以上编写相同代码时,请考虑制作方法。切割和粘贴是代码中的坏习惯。
if (grid[0, 0] == 'X' && grid[0, 1] == 'X' && grid[0, 2] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
if (grid[1, 0] == 'X' && grid[1, 1] == 'X' && grid[1, 2] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
if (grid[2, 0] == 'X' && grid[2, 1] == 'X' && grid[2, 2] == 'X') { Console.WriteLine("PLayer 1 Wins"); return true; }
我注意到你剪了一个错字!只是另外一个原因让它如此糟糕。
如果您发现正在切割和粘贴,请制定方法:
private bool HasRow(char player, int row)
{
return grid[row,0] == player && grid[row,1] == player && grid[row,2] == player;
}
现在您可以用
替换该代码if (HasRow('X', 0) || HasRow('X', 1) || HasRow('X', 2)) { ... }
...
if (HasRow('O', 0) || HasRow('O', 1) || HasRow('O', 2)) { ... }
但是等等,我们再次剪切并粘贴代码。所以解决这个问题!
private bool HasAnyRow(char player)
{
return HasRow(player, 0) || HasRow(player, 1) || HasRow(player, 2);
}
现在您的代码变为
if (HasAnyRow('X')) { ... }
...
if (HasAnyRow('O')) { ... }
...
对列和对角线执行相同操作,最后使用
if (HasAnyRow('X') || HasAnyColumn('X') || HasAnyDiagonal('X')) { ... }
if (HasAnyRow('O') || HasAnyColumn('O') || HasAnyDiagonal('O')) { ... }
但是等等,这是仍然过多的复制粘贴。
private bool HasWin(char player)
{
return HasAnyRow(player) || HasAnyColumn(player) || HasAnyDiagonal(player);
}
现在代码是:
if (HasWin('X')) { ... }
if (HasWin('O')) { ... }
您的代码将变得更好 - 更容易编写,更易于阅读,更易于调试,更有可能在第一次更正 - 如果您:
答案 1 :(得分:1)
||
运算符的优先级低于&&
。将or
条件放在括号中:
if ((grid[0, 0] == 'X' || grid[0, 0] == 'O') &&
(grid[0, 1] == 'X' || grid[0, 1] == 'O') &&
(grid[0, 2] == 'X' || grid[0, 2] == 'O') &&
(grid[1, 0] == 'X' || grid[1, 0] == 'O') &&
(grid[1, 1] == 'X' || grid[1, 1] == 'O') &&
(grid[1, 2] == 'X' || grid[1, 2] == 'O') &&
(grid[2, 0] == 'X' || grid[2, 0] == 'O') &&
(grid[2, 1] == 'X' || grid[2, 1] == 'O') &&
(grid[2, 2] == 'X' || grid[2, 2] == 'O'))
{
Console.WriteLine("It's a Tie");
return true;
}
答案 2 :(得分:0)
检查网格变量是否不包含''(或用于空的任何内容)
答案 3 :(得分:0)
此解决方案通过完全删除错误代码并使用基于for循环的方法进行最后检查来解决您的问题。它还避免了冗余并使(imho)更容易遵循:
private const char PLAYER_1_SYMBOL = 'X';
private const char PLAYER_2_SYMBOL = 'O';
private readonly char[,] grid = new char[3,3];
public bool Ended()
{
if (CheckPlayerVictory(PLAYER_1_SYMBOL))
{
Console.WriteLine("Player 1 Wins");
return true;
}
else if (CheckPlayerVictory(PLAYER_2_SYMBOL))
{
Console.WriteLine("Player 2 Wins");
return true;
}
else if (CheckNoMovesRemaining())
{
Console.WriteLine("It's a Tie");
return true;
}
return false;
}
// true, if a match for the given symbol was found in the grid.
private bool CheckPlayerVictory(char symbol)
{
return (grid[0, 0] == symbol && grid[0, 1] == symbol && grid[0, 2] == symbol)
|| (grid[1, 0] == symbol && grid[1, 1] == symbol && grid[1, 2] == symbol)
|| (grid[2, 0] == symbol && grid[2, 1] == symbol && grid[2, 2] == symbol)
|| (grid[0, 0] == symbol && grid[1, 0] == symbol && grid[2, 0] == symbol)
|| (grid[0, 1] == symbol && grid[1, 1] == symbol && grid[2, 1] == symbol)
|| (grid[0, 2] == symbol && grid[1, 2] == symbol && grid[2, 2] == symbol)
|| (grid[0, 0] == symbol && grid[1, 1] == symbol && grid[2, 2] == symbol)
|| (grid[0, 2] == symbol && grid[1, 1] == symbol && grid[2, 0] == symbol);
}
// true, if no free grid cell is left.
private bool CheckNoMovesRemaining()
{
int numFreeSpaces = 9;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (grid[i,j] == PLAYER_1_SYMBOL || grid[i,j] == PLAYER_2_SYMBOL)
{
numFreeSpaces--;
}
}
}
return numFreeSpaces <= 0;
}
答案 4 :(得分:0)
这是一种检查方法。首先创建网格的所有8个切片:
var slices =
Enumerable
.Range(0, 3)
.SelectMany(i => new []
{
Enumerable.Range(0, 3).Select(j => grid[i, j]),
Enumerable.Range(0, 3).Select(j => grid[j, i])
})
.Concat(new [] { Enumerable.Range(0, 3).SelectMany(i => new [] { grid[i, i] }) })
.Concat(new [] { Enumerable.Range(0, 3).SelectMany(i => new [] { grid[i, 2 - i] }) })
.Select(z => String.Join("", z))
.ToArray();
从此输入开始:
char[,] grid = new char[3, 3]
{
{ 'X', 'O', 'X' },
{ 'O', 'X', 'X' },
{ 'X', 'X', 'O' },
};
那会给你:
现在很容易看出谁赢了:
bool xWins = slices.Any(z => z == "XXX") && slices.All(z => z != "OOO");
bool oWins = slices.Any(z => z == "OOO") && slices.All(z => z != "XXX");
看看董事会是否是抽奖检查,两者都是假的,如果有空位(假设_
为空):
bool draw = !xWins && !oWins && slices.All(z => !z.Contains("_"));