【问题标题】:The right way to use != in a While loop ?...Or ..?在 While 循环中使用 != 的正确方法?...或 ..?
【发布时间】:2015-07-23 00:02:55
【问题描述】:

我只是 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;
}

【问题讨论】:

标签: c++ while-loop inequality


【解决方案1】:

这里的问题是你的测试条件。如果您输入 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

如果您在逻辑上将这些“与”在一起(就像您使用 &amp;&amp; 一样),则计算结果为 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' &amp;&amp; table[1][1] == 'X' &amp;&amp; table[2][2] == 'X')
    这会检查用户是否连续没有 3 个
  • table[0][0] != 'X' || table[1][1] != 'X' || table[2][2] != 'X'
    这将检查用户是否没有'X' 任何所需职位。从逻辑上讲,如果用户在这些位置之一中缺少'X',则用户不能连续拥有 3 个。这只是De Morgan's laws 对前面逻辑语句的应用。

【讨论】:

    【解决方案2】:

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

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2012-11-04
      • 1970-01-01
      • 2021-07-18
      • 1970-01-01
      • 2021-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-01
      相关资源
      最近更新 更多