带有 for 循环的 goto() 函数

Posted

技术标签:

【中文标题】带有 for 循环的 goto() 函数【英文标题】:goto() function with for loops 【发布时间】:2020-09-12 11:01:28 【问题描述】:

我正在制作一个简单的猜谜游戏,用户必须猜测隐藏地图(数组)中的一个关键位置,并且他有 12 次尝试进行猜测 我几乎成功了,但唯一的问题是计数器没有改变我希望TryCounter 在用户不猜测密钥位置时实际计算尝试次数 这是我的代码:

#include <iostream> 
using namespace std;

int main()

    bool w;
    int x;
    int y;
    
    int array1[6][6] = 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0;
    cout << "game is starting ... " << endl;
    cout << "You have 12 try to find one of the hidden keys " << endl;
    loop: for (int TryCounter = 1; TryCounter <= 12; TryCounter++)
    
        cout << " guess  " << TryCounter << "  - x and -y coordiants : " << endl;
        cin >> x;
        cin >> y;
         if (TryCounter == 12)
        
            cout << "You have used your chances" << endl;
            if (w == false)
            
                cout << "You lost" << endl;
                for (int i = 0; i < 6; i++)//Drawing the hidden array
                
                    cout << "   " << endl;
                    for (int j = 0; j < 6; j++)
                    
                        cout << array1[i][j];
                        cout << "   ";  
                    
                break;
            break;
    
        for (int i = 0; i < 6; i++)//checking the input
        
            for (int j = 0; j < 6; j++)
            
                if (array1[x][y] == 1)
                
                    cout << "" << endl;
                    cout << "--- Nice Shot ! ---" << endl;
                    w = true;
                    cout << "You Won" << endl;
                    for (int i = 0; i < 6; i++) //drwaing the hidden map
                    
                        cout << "   " << endl;
                        for (int j = 0; j < 6; j++)
                        
                            cout << array1[i][j];
                            cout << "   ";
                        
                    return 0;
                
                else if (array1[x][y] == 0) //wrong guess
                
                    w = false;
                    cout << "--- You missed ---" << endl;
                    goto loop ;
                
            
         
    


 

【问题讨论】:

TryCounter 在 goto 标签之后被初始化。将int TryCounter = 1 移动到loop: 之前。 C++ 中没有“goto 函数”。 goto 是语言关键字,在 goto 语句中使用。 那我应该把它放在哪里呢?我尝试了几个位置,但都没有工作@i486 @Peter 对不起,我不知道我正在自学编程 不要投反对票。这是一个合理的问题,恕我直言。答案是,您可以删除循环标签和 goto。就如此容易。然后,让 for 循环包含带有检查的块。并删除if (TryCounter == 12) 检查。 for 循环已经为您做到了。 【参考方案1】:

通常人们会在没有 goto 的情况下进行编程。但有时确实有用……所以这里不做判断。

int main(...) 
   // the variable and array stuff...
   for(int attemptCounter = 0; attemptCounter < 12; ++attemptCounter) 
      // the user input stuff...
      // the checking if user guessed right
      if( userGuessedCorrectly ) goto Success;
   
   std::cout << "better luck next time, pal - you did not guess right." << std::endl;
   return 0;
Success:
   std::cout << "Congratulations you made it!" << std::endl;
   return 0;


当然,在没有 goto 的情况下编写此代码会稍微困难一些。不过既然你想用,我就答应了。

【讨论】:

在没有goto 的情况下编写这个更容易goto 的使用混淆了这里实际发生的事情。使用goto 通常被认为是有害的,就像使用原始拥有指针被认为是有害的一样。这不是“不判断”的情况,好像这是个人选择。我们可以批评不良纪律而不“评判”一个人。在 C 中使用 goto 来清理代码有一些很好的论据;在 C++ 中使用 goto 没有什么好的理由。 @cdhowie 这取决于您应用的指标。在这种情况下如果没有 goto,当然我同意没有人会认真使用 goto,您需要将 for 循环的第一项移到外部,然后添加一个 if(attemptCounter &lt; 12) ... else ...,如果您应用“cyclometric复杂性”指标比 goto 更复杂。只是说...不是每个 goto 都是黑色的,也不是所有其他的都是白色的。 ;) 什么?您可以在示例代码中将goto Success; 替换为 std::cout &lt;&lt; "Congratulations you made it!" &lt;&lt; std::endl; return 0; 。您代码中的goto 实际上混淆了正在发生的事情。【参考方案2】:

查看您的代码,它看起来很复杂。 我试图通过重构来理解它,我希望你已经遇到了一些错误。

我的建议是从这段代码中提取一些函数。 我已经确定了一些重复的代码来将数组打印到 std::cout。 这将最深点上的循环嵌套减少了 2 个。

第二个功能是检查功能,您可以在其中检查镜头是否正常。 在这里,我注意到在循环中,您很可能错误地索引数组,因为您的循环使用 i 和 j(在循环中未使用),而您使用 x 和 y 进行索引。

提取后,您最终会得到一个 for 循环,您可以使用相同名称的关键字继续/中断该循环。 (这是我如何理解您的代码应该如何工作的想法https://compiler-explorer.com/z/TKqGMh)

我的经验法则是,如果你需要记住你的 for 循环的状态,这些应该被放入函数中。

【讨论】:

感谢您的重播,与您的代码相比,我的代码真是一团糟。 @JVApen 编辑:我运行了你的代码,看起来 else if (array1[x][y] == 0) // wrong guess w = false; cout &lt;&lt; "--- You missed ---" &lt;&lt; endl; 不起作用,这总是一个胜利的局面。 就像我说的,我必须改变一些东西,因为我假设你有一个错误。但是,我认为总体要点很明确:在一个函数中放入一些东西以降低另一个函数的复杂性,从而使最终结果更易于维护【参考方案3】:

计数器不会因为您使用goto 而改变。计数器在循环结束时更改(右大括号)。你的执行指针永远不会到达右大括号,因为goto 将它提前隧道到循环的开头。

【讨论】:

以上是关于带有 for 循环的 goto() 函数的主要内容,如果未能解决你的问题,请参考以下文章

Oracle循环的几种写法(GOTO 、FOR 、 WHILE 、LOOP)

Linux C 编程学习第四天_循环语句_while_do/while_for_goto

Java中For循环中的GoTo Next迭代

C语言基础:循环结构(循环类型(while,do...while,for,嵌套循环),循环控制语句(break,continue,goto),无线循环(死循环))

在实现无限循环时,使用 while(1) 与 for(;;) 与 goto (在 C 中)有区别吗?

条件循环函数定义 练习