我只是C ++的初学者,在制作代码来创建TicTacToe游戏时,我遇到了一段时间的声明,它将推动游戏继续前进,直到获胜条件得以实现:
while(((table[0][0]!='X')&&(table[1][1]!='X')&&(table[2][2]!='X')))
这只是对角条件(把所有条件都给你眼睛......)。 问题是,即使满足条件,这也不起作用(我确定因为我最后使用了一个cout),但是当我改变&&与||条件工作! 我想也许是因为!=会影响一切?
编辑:最小示例(我删除了浮点数!):
#include <iostream>
using namespace std;
int main()
{
int tailleX(3),tailleY(3); //The Size of the table.
char table[tailleX][tailleY]; //TictacToe table.
table[0][0]='N';
table[0][1]='N';
table[0][2]='N';
table[1][0]='N';
table[1][1]='N'; //Randomly filling the array to avoid an error
table[1][2]='N';
table[2][0]='N';
table[2][1]='N';
table[2][2]='N';
int coorP1; //The Coordinate of the square (Exp: x=1 , y=2 will be 1.2)
while(((table[0][0]!='X')&&(table[1][1]!='X')&&(table[2][2]!='X'))) //For the minimal example I made just the diagonal condition
{
cout<<"PLAYER1: Enter the coordination to score: (Exemple: 1, 2, 3..) "<<endl;
cin>>coorP1;
switch(coorP1) //Filling the square depending on the coordinates.//I used If because Switch does not work.
{
case 1:
table[0][0]='X';
break;
case 2:
table[0][1]='X';
break;
case 3:
table[0][2]='X';
break;
case 4:
table[1][0]='X';
break;
case 5:
table[1][1]='X';
break;
case 6:
table[1][2]='X';
break;
case 7:
table[2][0]='X';
break;
case 8:
table[2][1]='X';
break;
case 9:
table[2][2]='X';
break;
}
}
cout<<"You won"<<endl;
return 0;
}
答案 0 :(得分:3)
这里的问题是你的测试条件。如果输入2,3,4,6,7或8,则循环重复。一旦输入1,5或9,循环就会退出。如果输入1,5或9,则其中一个对角线值设置为internal
。条件为真时'X'
循环。一旦条件评估为假,它就会退出。输入1,5或9时,会导致条件为假。
想象一下,while
为table[0][0]
,'X'
为table[1][1]
,'N'
为table[2][2]
。换句话说,董事会看起来像这样:
'N'
然后你的测试条件是:
X | N | N
--+---+---
N | N | N
--+---+---
N | N | N
如果你在逻辑上和这些一起(与table[0][0] != 'X' && table[1][1] != 'X' && table[2][2] != 'X'
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
false true true
一样),则评估为&&
(这是有道理的:false
应评估为false AND true
;仅{ {1}}应评估为false
)。
那么你的测试条件应该是什么?
如果用户没有连续3个,那么你真正想做的就是循环。换句话说,检查用户是否连续3个;如果他没有连续3,那么继续。
我们可以将该逻辑语句构造为:
true AND true
因此,你的循环条件应该是(它们都是等价的;选择对你更有意义的那个):
true
// This checks if the user has 3 in a row
table[0][0] == 'X' && table[1][1] == 'X' && table[2][2] == 'X'
// We want to check if the user does NOT have 3 in a row,
// so we can negate the above with !
!(table[0][0] == 'X' && table[1][1] == 'X' && table[2][2] == 'X')
// With De Morgan's laws, we can simplify this to:
table[0][0] != 'X' || table[1][1] != 'X' || table[2][2] != 'X'
!(table[0][0] == 'X' && table[1][1] == 'X' && table[2][2] == 'X')
任何一个所需位置。从逻辑上讲,如果用户在其中一个位置缺少table[0][0] != 'X' || table[1][1] != 'X' || table[2][2] != 'X'
,则用户不能连续3个。这只是De Morgan's laws对前一个逻辑语句的应用。答案 1 :(得分:1)
学习编程的关键部分是学习避免在源代码中反复做类似的事情。您需要抽象相似的行为,以便他们可以共享一个代码块。因此,计算机可以完成所有这些工作,但在编写源代码时,您无法完成所有工作。
你试图建立游戏状态的巨型布尔表达式是一个如何不编程的极端例子。这是一个常见的初学者错误(远远不是代码中初学者错误的唯一例子)。修复这个巨大的布尔表达式是可能的,但是在你学习编程的过程中它会非常适得其反。相反,你应该以此为例来学习如何组合和抽象工作:
首先要了解游戏概念:游戏状态是wonX,wonY,draw,inProgress之一。您可以为这些可能性定义枚举。通过棋盘的八条线中的每条线都具有相同的四种可能状态,其中如果任何线具有该状态,则游戏状态为wonX或wonY,并且游戏状态是inProgress是没有线获胜或者是胜利且一些线是inProgress。 / p>
因为绘制从单独的rline到板级结合,与wonX或wonY相反,所以组合操作在高级别上会变得棘手,并且在代码中也更容易确定行状态。
所以我建议编写一个函数,它将一行的三个值作为输入,并将游戏状态累加器作为输入,并返回更新的游戏状态。在每一轮中,您将开始计算游戏状态为draw,然后为8行中的每一行调用该函数来更新它。如果该行是X或Y的胜利,那么状态将无条件地改变为该。如果该行是inProgress,只有当状态为draw时,状态才会变为该状态。如果该线是绘制的,那么这不会改变状态(绘制状态中的一行说明游戏状态)。
好的设计会进一步抽象和组合你的代码的几个方面,但是那个是你未能抽象和组合的大问题,就像我指出了一行看一行并计算其对整个董事会的状态。
一般来说,你会发现你最强大的抽象和组合工具是将工作的一部分转移到一个函数中(如上所述)。试图做太多而不分成单独的功能是一个重大的初学者错误。