do-while循环存在问题

3
请注意,我对Java比较熟悉,但并不是非常出色,也不知道所有的行话。因此,请在回答中使用尽可能少的编程术语,用尽可能通俗易懂的普通英语解释,或在使用术语后解释这些术语的含义。另外,这是我第一次使用Stackoverflow,请告诉我这是否是一个不错的问题,并给我一些提示。
我正在我的高中上AP计算机科学课程,我们使用Java。最近我们学习了do-while循环,并且我刚完成了使用do-while循环的“实验室”,但是出现了一个问题。
首先,让我解释一下这个“实验室”。程序生成一个1-10之间的随机整数,用户必须猜测该数(使用扫描仪将猜测存储为int类型),有一些整数值用于跟踪猜测的数量,有多少猜测大于计算机生成的整数,有多少猜测太低。当您查看我的代码时,您会注意到我有一个System.out.println(compGen);//compGen是计算机生成的整数。目的是为了测试代码。
问题在于if语句比较userGen(用户猜测)和compGen。
if(userGen==compGen)
{
//do a lot of stuff
}

在这个if语句中,如果用户猜测超过一次,则不会打印我编写的正确SOP。然而,我没有将这个写进程序中,它似乎是自己做的。我使用了我早先提到的compGen int被打印的SOP,并将其作为我的第一个猜测输入,它完美地工作了。if语句块中的所有内容都执行得很好并正确打印了一切。但是,当我把它作为我的第二个、第三个或任何不是第一个的猜测时,什么都没有打印出来。请看下面的代码并运行它。我不认为这应该有任何影响,但我使用的IDE是Eclipse,因此有包语句。请帮忙。
    package Chapter_3.Lab03_Chapter3;
    import java.util.*;

public class Guess 
{
    public static void main(String[] args) 
    {   
    Scanner userInput = new Scanner(System.in);//Scanner
    int compGen = (int)(Math.random()* 10 + 1);//compGen is computer number
    System.out.println(compGen); //USED TO VERIFY FAILURE. VALUE WAS ENTERED TO TEST CODE
    int guessTrack = 0;//tracks number of guesses
    int tooHighTrack = 0;//CREATING INTS TO TRACK STUFF
    int tooLowTrack = 0;
    System.out.println("Welcome to the integer guessing game that everyoone loves!");//PROMPT 
    System.out.println("Please enter your guess for the integer. Remeber, it is between one and ten.");//GREETING
    int userGen = userInput.nextInt();//USER GUESS  

    do
    {
        guessTrack++;//Increase guess value
        if(userGen > compGen)//checks user value in relation to computer generated int
        {
            System.out.println("Try again! Your guess was too high!");//inform user of bad guess
            userGen = userInput.nextInt();//new guess
            tooHighTrack++;//if guess is too high, this int tracker increases
        }
        else if(userGen < compGen)//checks user value in relation to computer generated int
        {
            System.out.println("Try again! Your guess was too low!");//inform user of guess
            userGen = userInput.nextInt();//new guess
            tooLowTrack++;//increases if user guess is too low
        }
        else if(userGen==compGen)//if both values are equivalent, execute THIS IS THE PROBLEM STATEMENT!!
        {
            System.out.println("Great job! You guessed the right number!");//congratulate
            if(guessTrack>1)
            {
                System.out.println("It took you: "+guessTrack+" guess to get the right answer.");//print guess tracked int
            }
            else
            {
                System.out.println("It took you: "+guessTrack+" guesses to get the right answer.");//print guess tracked int
            }               
            System.out.println(tooHighTrack +" guesses were too high and "+ tooLowTrack+ " were too low.");//print how many guess were too big or too low
            System.out.println("HELLO"); //Used to verify failure of code
            userInput.close();//close scanner object
        }
    }
    while (userGen != compGen);//condition to be ultimately checked         
}
}

我一直没能弄清楚哪里出了问题。有一次我删除了整个if语句并重新输入(我知道这不会有任何作用,但我必须尝试一下)。这个问题对我来说毫无意义。没有错误或任何弹出的东西,控制台也没有任何提示,这让我有点害怕。提前感谢。

5个回答

5
首先,您在此处输入了很多文本。作为建议,下次尝试将问题最小化,以减少文本量;) 否则一切都很好。
关于您的问题。让我简化您的代码,然后向您解释发生了什么。 1. 代码
int val = scanner.nextInt();
do {
    if (val < 5) {
        // too low
        val = scanner.nextInt();
    } else if (val > 5) {
        // too high
        val = scanner.nextInt();
    } else {
        // correct
        // THIS CODE DOESN'T RUN?!
    }
} while (val != 5);

2. 你的代码是做什么的?

在循环之前,你读取了第一个数字,这是可以的。然后,你进入了一个if-elseif-else语句。请注意,一旦进入其中一个块,其他块就不会被执行。现在的问题是,在if-elseif内部读取了下一个用户输入!程序读取了下一个值并离开整个if-elseif-else。由于循环在下一次迭代之前结束,因此正确的用户输入根本没有通过if-elseif-else进行处理。

3. 解决方案

删除所有nextInt()读取,并将其作为循环中的第一件事:内部

int val;
do {
    val = scanner.nextInt();
    if (val < 5) {
        // too low
    } else if (val > 5) {
        // too high
    } else {
        // correct
        // THIS CODE RUNS NOW!
    }
} while (val != 5);

这种需要在检查循环条件之前至少执行一次某些操作的结构,通常使用do while循环而不是while循环来实现。


谢谢您关于缩短问题的建议。这是我的第一篇帖子,我想让它清楚地表明我对这个网站没有经验。现在回到您的答案,我很感激按点分组,这确实有所帮助。下面的用户指出,如果提交了正确的答案,do-while将终止,因为while条件将为false。您给出的答案不会有同样的问题吗?即使nextInt()在块的顶部? - Ungeheuer
1
不行,因为在 if-elseif-else 进入之前用户输入已经被读取。因此输入总是在同一次迭代中通过它,然后结束。 - Felk
哦!!现在我明白了!通过在顶部获取用户输入,答案会过滤到if/else-if块中,保留值并允许userGen==compGen代码正确执行。而且我仍然可以拥有“猜测太高”的代码,因为我在循环中获得了int。您真是非常聪明。 :) - Ungeheuer
1
谢谢,我正在学习这些内容。但你使用了 do while 而不是 while,实际上已经使用了正确的工具来完成任务。我不知道你是否已经读过我在答案中添加的最后一段话。 - Felk
我选择了你的答案作为正确的答案,因为它有助于简化代码,并让我再次思考如何将其减少。再次感谢。我确实读了你的段落。我们的老师提到do-while循环很有用,但直到这个实验室,我真的没有看到它的价值,但现在它变得非常清晰明了。 - Ungeheuer

3
你正在循环过程中设置用户输入,然后在之后进行检查。尝试像这样将else if(userGen==compGen)块的主体移动到循环之后:
public static void main(String[] args) 
    {   
    Scanner userInput = new Scanner(System.in);//Scanner
    int compGen = (int)(Math.random()* 10 + 1);//compGen is computer number
    System.out.println(compGen); //USED TO VERIFY FAILURE. VALUE WAS ENTERED TO TEST CODE
    int guessTrack = 0;//tracks number of guesses
    int tooHighTrack = 0;//CREATING INTS TO TRACK STUFF
    int tooLowTrack = 0;
    System.out.println("Welcome to the integer guessing game that everyoone loves!");//PROMPT 
    System.out.println("Please enter your guess for the integer. Remeber, it is between one and ten.");//GREETING
    int userGen = userInput.nextInt();//USER GUESS  

    do
    {
        guessTrack++;//Increase guess value
        if(userGen > compGen)//checks user value in relation to computer generated int
        {
            System.out.println("Try again! Your guess was too high!");//inform user of bad guess
            userGen = userInput.nextInt();//new guess
            tooHighTrack++;//if guess is too high, this int tracker increases
        }
        else if(userGen < compGen)//checks user value in relation to computer generated int
        {
            System.out.println("Try again! Your guess was too low!");//inform user of guess
            userGen = userInput.nextInt();//new guess
            tooLowTrack++;//increases if user guess is too low
        }
    }
    while (userGen != compGen);//condition to be ultimately checked

    //The numbers have matched since it exited the loop.
    System.out.println("Great job! You guessed the right number!");//congratulate
    if(guessTrack>1)
    {
        System.out.println("It took you: "+guessTrack+" guess to get the right answer.");//print guess tracked int
    }
    else
    {
        System.out.println("It took you: "+guessTrack+" guesses to get the right answer.");//print guess tracked int
    }               
    System.out.println(tooHighTrack +" guesses were too high and "+ tooLowTrack+ " were too low.");//print how many guess were too big or too low
    System.out.println("HELLO"); //Used to verify failure of code
    userInput.close();//close scanner object
}

1
我明白你的意思。我甚至没有想到当userGen和compGen相等时,循环就停止了。有时候我感觉自己好蠢啊。谢谢!! - Ungeheuer
1
@JohnnyCoder 不用担心,这种情况发生在每个人身上。只有当你回头看时,错误才显而易见。 - Pokechu22

1
当程序到达循环内部代码的结尾时,会立即检查while条件。因此,假设输入了错误的数字,程序会说它太低或太高,然后要求输入另一个数字。
userGen = userInput.nextInt();//new guess

假设这个新数字是正确的。程序完成了你的if语句,然后到达循环的结尾。此时,userGen等于compGen。因此,while条件不满足,程序立即退出循环,而没有执行打印结果的代码。
解决方法之一是将判断语句 userGen == compGen 打印结果的逻辑移出循环——也就是在循环结束后执行。这样,无论何时退出循环,该逻辑都会被执行。需要注意的是,当你退出循环时,我们知道userGen == compGen,因为如果不是这样,循环会再次运行。

你和@Pokechu22说了同样的话,非常感谢。我不知道我哪里出了问题。实际上我是一个相当不错的程序员,但有时候我会变得非常愚蠢。 - Ungeheuer
@JohnnyCoder 是的,我能看出你是个不错的编程人员。我也是一个,我已经做了37年了,但我仍然会犯一些愚蠢的错误。这并不是你的问题,我们都会有偶尔的盲点。如果你决定将编程作为职业,我认为你会做得很好。 - ajb

1
假设计算机生成的数字是3,你猜测是5。 5>3,因此执行if(userGen > compGen)语句:
        System.out.println("Try again! Your guess was too high!");//inform user of bad guess
        userGen = userInput.nextInt();//new guess
        tooHighTrack++;//if guess is too high, this int tracker increases

你打印信息、获取新的猜测,然后增加计数器……但是当你得到新的猜测时,如果它是正确答案3,userGen现在等于compGen(都是3),现在while条件被评估为:
while (userGen != compGen)
这是错误的,因为userGen == compGen(都为3)。你的代码没有机会打印正确的消息,因为循环退出之前这件事无法发生。希望这可以帮助到你。

谢谢Rick,你和其他两个人指出了同样的问题。你们都很棒。非常感谢你们的帮助,特别是你们的快速回复。 - Ungeheuer

0

您的userGen在每次用户输入后都没有被检查。

问题在于您将检查放在了else-if块内,这会在循环回到开头之前检查while语句的结尾。

如果您更改

else if(userGen==compGen)

if(userGen==compGen)

因为它不是 if-else 块的一部分,所以它将在每次输入之后被检查(在 while 条件被检查之前)。

或者,您可以将用户输入移动到 do-while 块的开头,像这样:

package Chapter_3.Lab03_Chapter3;
import java.util.*;

public class Guess 
{
    public static void main(String[] args) 
    {   
    Scanner userInput = new Scanner(System.in);//Scanner
    int compGen = (int)(Math.random()* 10 + 1);//compGen is computer number
    System.out.println(compGen); //USED TO VERIFY FAILURE. VALUE WAS ENTERED TO TEST CODE
    int guessTrack = 0;//tracks number of guesses
    int tooHighTrack = 0;//CREATING INTS TO TRACK STUFF
    int tooLowTrack = 0;
    System.out.println("Welcome to the integer guessing game that everyoone loves!");//PROMPT 
    System.out.println("Please enter your guess for the integer. Remeber, it is between one and ten.");//GREETING
    int userGen = -1;//USER GUESS  

    do
    {
        userGen = userInput.nextInt();
        guessTrack++;//Increase guess value
        if(userGen > compGen)//checks user value in relation to computer generated int
        {
            System.out.println("Try again! Your guess was too high!");//inform user of bad guess
            userGen = userInput.nextInt();//new guess
            tooHighTrack++;//if guess is too high, this int tracker increases
        }
        else if(userGen < compGen)//checks user value in relation to computer generated int
        {
            System.out.println("Try again! Your guess was too low!");//inform user of guess
            userGen = userInput.nextInt();//new guess
            tooLowTrack++;//increases if user guess is too low
        }
        else if(userGen==compGen)//if both values are equivalent, execute THIS IS THE PROBLEM STATEMENT!!
        {
            System.out.println("Great job! You guessed the right number!");//congratulate
            if(guessTrack>1)
            {
                System.out.println("It took you: "+guessTrack+" guess to get the right answer.");//print guess tracked int
            }
            else
            {
                System.out.println("It took you: "+guessTrack+" guesses to get the right answer.");//print guess tracked int
            }               
            System.out.println(tooHighTrack +" guesses were too high and "+ tooLowTrack+ " were too low.");//print how many guess were too big or too low
            System.out.println("HELLO"); //Used to verify failure of code
            userInput.close();//close scanner object
        }
    }
    while (userGen != compGen);//condition to be ultimately checked         
}
}

这将导致每当用户输入数据时都会检查您的if-else块,然后再检查do-while的条件。


谢谢。另一个用户指出将 nextInt() 移动到块的顶部。我喜欢使用 if 来改变 if-else 的想法。它创建了另一个块,IDE 必须检查,这也会使代码运行。好主意,谢谢! - Ungeheuer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接