0

我只是 C++ 的初学者,在编写创建井字游戏的代码时,我陷入了 while 语句,该语句将推动游戏继续运行,直到满足获胜条件:

 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;
}
4

2 回答 2

3

这里的问题是您的测试条件。如果您输入 2、3、4、6、7 或 8,您的循环将重复。只要您输入 1、5 或 9,循环就会退出。如果输入 1、5 或 9,则对角线值之一设置为'X'while条件为真时循环。一旦条件评估为假,它就会退出。当您输入 1、5 或 9 时,会导致条件为假。

想象一下,即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

如果您在逻辑上将这些 AND 在一起(就像您使用 一样&&),则计算结果为false(这是有道理的:false AND true应该计算为false;只true AND true应该计算为true)。

那么你的测试条件应该是什么?

您真正想要做的是仅当用户连续没有 3 个时才循环。也就是说,检查用户是否连续有 3 个;如果他没有连续 3 个,则继续。

我们可以将该逻辑语句构造为:

// 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')
    这会检查用户是否连续没有 3 个
  • table[0][0] != 'X' || table[1][1] != 'X' || table[2][2] != 'X'
    这将检查用户是否没有'X'任何所需的职位。从逻辑上讲,如果用户'X'在这些位置之一中缺少一个,则用户不能连续拥有 3 个。这只是将德摩根定律应用于前面的逻辑陈述。
于 2015-07-22T15:25:10.510 回答
1

学习编程的一个关键部分是学习避免在源代码中一遍又一遍地做类似的事情。您需要抽象出相似的行为,以便它们可以共享一段代码。所以计算机做了所有的工作,但是在编写源代码时,你并没有做所有的工作。

你试图建立一个巨大的游戏状态布尔表达式是如何不编程的一个极端例子。这是一个常见的初学者错误(并且远非代码中该初学者错误的唯一示例)。修复那个巨大的布尔表达式是可能的,但在你学习编程的道路上,这将是非常适得其反的。相反,您应该以此为例来学习如何组合和抽象工作:

首先了解游戏概念:游戏状态是 wonX、wonY、draw、inProgress 之一。您可以为这些可能性定义一个枚举。通过棋盘的 8 条线中的每条线都具有相同的四种可能状态,其中游戏状态为 wonX 或 wonY(如果任何一条线具有该状态),游戏状态为 inProgress 是没有线是 wonX 或 wonY 并且某些线是 inProgress。

因为 draw 以与 wonX 或 wonY 相反的方式从单个 rline 到 board 级别进行组合,所以组合操作在高级别上会很棘手,并且在也确定行状态的代码中更容易。

所以我建议编写一个函数,将一行的三个值作为输入,同时将游戏状态累加器作为输入,并返回一个更新的游戏状态。在每一轮中,您将开始计算游戏状态为平局,然后为 8 行中的每一行调用函数来更新它。如果这条线是 X 或 Y 的胜利,那么状态将无条件地变为该状态。如果该线处于进行中,则状态将更改为仅当状态为绘制时。如果这条线是平局,那不会改变状态(处于平局状态的一条线没有说明游戏状态)。

好的设计会进一步抽象和组合代码的更多方面,但是由于未能抽象和组合而造成的最大问题是,正如我指出的那样,查看一行并计算其对代码状态的影响的步骤全板。

通常,您会发现用于抽象和组合工作的最强大工具是将那部分工作移动到一个函数中(如上所述)。试图做太多而不是拆分成单独的功能是初学者的一个主要错误。

于 2015-07-22T16:02:55.697 回答