正确的使用方式!=在While循环中?或者

The right way to use != in a While loop ?...Or ..?

本文关键字:While 循环 或者 方式      更新时间:2023-10-16

我只是C++的初学者,在编写创建TicTacToe游戏的代码时,我被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;
}

这里的问题是您的测试条件。如果输入2、3、4、6、7或8,循环将重复。一旦输入1、5或9,循环就会退出。如果输入1、5或9,则其中一个对角线值将设置为'X'。当条件为true时,while循环。一旦条件计算结果为false,它就会退出。当您输入1、5或9时,会导致条件为false。

想象一下,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应计算结果为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个。这只是德摩根定律对先前逻辑陈述的应用

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

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

首先理解游戏概念:游戏状态是wonX、wonY、draw、inProgress中的一种。你可以为这些可能性定义一个枚举。通过棋盘的八条线中的每一条都有相同的四种可能状态,其中游戏状态为wonX或wonY,如果任何一条线具有该状态,则游戏状态为进行中。

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

因此,我建议编写一个函数,将一行的三个值作为输入,同时将游戏状态累加器作为输入,并返回更新的游戏状态。在每一轮中,你都会开始将游戏状态计算为平局,然后为8条线中的每一条调用函数来更新它。如果这条线是X或Y的胜利,那么状态将无条件地更改为平局。如果线处于进行中,则只有在绘制状态时,状态才会更改为进行中。如果这条线是平局的,那不会改变状态(平局状态下的一条线对游戏状态没有任何影响(。

好的设计会进一步抽象和组合代码的几个方面,但由于未能抽象和组合,最大的问题是,正如我所指出的,查看一行并计算其对整个板状态的影响的步骤。

一般来说,您会发现用于抽象和组合工作的最强大的工具是将工作的大块移动到一个函数中(正如我在上面描述的(。尝试做太多而不将其拆分为单独的函数是初学者的一个主要错误。