Why won't my while loop work?

Hi,

Thanks for taking the time to help with this. I’m a beginner to java and coding in general. I’m running through the ‘Java The Hard Way’ book and exercises and have become stuck. I wrote code to play a coin toss game to learn more about “while” loops. I can’t figure out what I’ve done wrong.

The loop doesn’t loop back around and always ends after one coin toss even when heads wins.

Any help on why this is happening would be greatly appreciated. The code is:

import static java.lang.System.*;
import java.util.Scanner;

public class coinFlipWhile 
{
	public static void main(String [] args)
	{
		Scanner keyboard = new Scanner(System.in);
		String again = "n";
		int streak = 0;
		double flip;

		out.println("Welcome to Mr. Flippy. Only HEADS win.");

		
		while (again.equals("y"));
		{
			flip = Math.random();
			//out.println("Test = " + flip);

			if (flip < 0.5)
			{	
				streak++;
				out.println("You flip a coin and it is ... HEADS");
				out.println("\tThat's " + streak + " in a row... ");
				out.print("\tWould you like to flip again (y/n)? ");
				again = keyboard.next();
			}
			else
			{	
				out.println("You flip a coin and it is ... TAILS");
				out.println("\tYou lose everything!");
				out.println("\tYou should have quit while you were aHEAD!");
				streak = 0;
				again = "n";
			}
		} 

		out.println("Final score: " + streak + "\n");
	}
}

Thanks!

Then you would look at what values are involved in your condition right? …Since that’s what determines whether there’s another iteration.

Yeah. From what I can make of it, I’ve said if the flip generates a random number below 0.5 then call it heads. That should then follow the if (flip < 0.5) route. That bit works fine. But, when it gets to the again = keyboard.next() part, I type in y and the program jumps out of the while loop and prints “Final score: 1”.

I would have thought it should loop back to the start of the while statement, generate a new random number and go again… …?

you typed y but what’s the value of the string you assigned that variable to?

Correct. And the while loop should keep going every time it comes up heads AND I type y, right? If I type anything else after winning heads it should jump out of the loop. Or am I missing how this works?

oh it really is "y". I expected it would evaluate to false if the loop isn’t repeating

well, here’s what your code looks like when I run an automatic formatter on it, note how the loop gets formatted:

import static java.lang.System.*;

import java.util.Scanner;

public class coinFlipWhile {
  public static void main(String[] args) {
    Scanner keyboard = new Scanner(System.in);
    String again = "n";
    int streak = 0;
    double flip;

    out.println("Welcome to Mr. Flippy. Only HEADS win.");

    while (again.equals("y"))
      ;
    {
      flip = Math.random();
      // out.println("Test = " + flip);

      if (flip < 0.5) {
        streak++;
        out.println("You flip a coin and it is ... HEADS");
        out.println("\tThat's " + streak + " in a row... ");
        out.print("\tWould you like to flip again (y/n)? ");
        again = keyboard.next();
      } else {
        out.println("You flip a coin and it is ... TAILS");
        out.println("\tYou lose everything!");
        out.println("\tYou should have quit while you were aHEAD!");
        streak = 0;
        again = "n";
      }
    }

    out.println("Final score: " + streak + "\n");
  }
}

also note that your variable starts out as "n" which means there are zero iterations, not one

What I meant with looking at the value of again is that if you’re comparing it to "y" and that’s turning out false, then that means it’s got a different value and then you should probably be looking at it. But like my above post says, that’s not what’s going on

I tried changing the initial value of String again = "n" to “y” but it doesn’t work. I can put anything in that initial definition just to avoid the compiling error that says “error: variable again might not have been initialized
while (again.equals(“y”));”
I’ve put “y” and it doesn’t work.
I’ve put “dfah” and it works (but doesn’t keep looping in the while loop)
I’ve put “n” and it works (but doesn’t keep looping in the while loop).

Yeah but ask yourself which of those two it should be if the loop is to run at least once. Use the one it should be, and then move on to next problem whatever that is (I already mentioned what that next problem is, look at how the loop got formatted by an automatic formatter, why is it formatted that way? and, if the loop makes zero iterations, then why would your code run once? that means it isn’t in the loop at all because if it was then it would run zero times)

So don’t “try” things. You are the one deciding what it should be.

I see that silly mistake now. Thanks for that. I’ve removed the ; after the while.

I’ve changed the first use of again to String again = "y". and now the program hangs. It prints “Welcome to Mr. Flippy. Only HEADS win.” and then nothing.

Something about that is inconsistent. What you are saying there does not add up.

I’ve managed to get it work correctly using a boolean flip instead of double flip.

That code with boolean is:

import static java.lang.System.*;
import java.util.Scanner;

public class coinFlipWhile1 
{
	public static void main(String [] args)
	{
		Scanner keyboard = new Scanner(System.in);
		String coin, again = "y";
		int streak = 0;
		boolean flip;

		while (again.equals("y")) //do
		{
			flip = Math.random() < 0.5;

			if (flip)
				coin = "HEADS";
			else
				coin = "TAILS";

			out.println("You flip a coin and it is ... " + coin);

			if (flip)
			{
				streak++;
				out.println("\tThat's " + streak + " in a row... ");
				out.println("\tWould you like to flip again (y/n)? ");
				again = keyboard.next();
			}
			else
			{
				out.println("\tYou lose everything!");
				out.println("\tYou should have quit while you were aHEAD!");
				streak = 0;
				again = "n";
			}
		} 

		out.println("Final score: " + streak);
	}
}

The code with double is now:

import static java.lang.System.*;
import java.util.Scanner;

public class coinFlipWhile 
{
	public static void main(String [] args)
	{
		Scanner keyboard = new Scanner(System.in);
		String again = "y";
		int streak = 0;
		double flip;

		out.println("Welcome to Mr. Flippy. Only HEADS win.");

		
		while (again.equals("y"));
		{
			flip = Math.random();
			//out.println("Test = " + flip);

			if (flip < 0.5)
			{	
				streak++;
				out.println("You flip a coin and it is ... HEADS");
				out.println("\tThat's " + streak + " in a row... ");
				out.print("\tWould you like to flip again (y/n)? ");
				again = keyboard.next();
			}
			else
			{	
				out.println("You flip a coin and it is ... TAILS");
				out.println("\tYou lose everything!");
				out.println("\tYou should have quit while you were aHEAD!");
				streak = 0;
				again = "n";
			}
		} 

		out.println("Final score: " + streak + "\n");
	}
}

I still don’t understand why the double version doesn’t work (now that it’s fixed for the ; and y errors)

those both use boolean

doesn’t matter, I’m guessing you’re changing something else as well and attributing the difference to the wrong change

sorry … I edited ^ the second one. now it’s the double one

And no doubt I’m attributing it to the wrong thing. Just hoping to figure out what that is

You’ve got lots of differences, make them equivalent and change only the one thing you are comparing.
This is begging for attributing the difference to the wrong change.

Thanks ionatan. I’ll rewrite it to reduce changes and see how I go. I couldn’t figure out a way to do a one for one change when using double versus boolean. But will give it another shot.

Well, copy it, right?

Anyway it’s not a significant change. Both would-be versions use double and bool. Each one obtains a random value between 0 and 1, compares it to 0.5, makes a choice based on that comparison.

okay … as far as I can see, the only changes now are the boolean versus double (and how they’re implemented). The version with the boolean works, the one with the double hangs.

Boolean:

import static java.lang.System.*;
import java.util.Scanner;

public class coinFlipWhile1 
{
	public static void main(String [] args)
	{
		Scanner keyboard = new Scanner(System.in);
		String again = "y";
		int streak = 0;
		boolean flip;

		out.println("Welcome to Mr. Flippy. Only HEADS win.");

		while (again.equals("y")) 
		{
			flip = Math.random() < 0.5;

			if (flip)
			{
				streak++;
				out.println("You flip a coin and it is ... HEADS");
				out.println("\tThat's " + streak + " in a row... ");
				out.println("\tWould you like to flip again (y/n)? ");
				again = keyboard.next();
			}
			else
			{
				out.println("You flip a coin and it is ... TAILS");
				out.println("\tYou lose everything!");
				out.println("\tYou should have quit while you were aHEAD!");
				streak = 0;
				again = "n";
			}
		} 

		out.println("Final score: " + streak + "\n");
	}
}

and double:

import static java.lang.System.*;
import java.util.Scanner;

public class coinFlipWhile 
{
	public static void main(String [] args)
	{
		Scanner keyboard = new Scanner(System.in);
		String again = "y";
		int streak = 0;
		double flip;

		out.println("Welcome to Mr. Flippy. Only HEADS win.");
		
		while (again.equals("y"));
		{
			flip = Math.random();
			
			if (flip < 0.5)
			{	
				streak++;
				out.println("You flip a coin and it is ... HEADS");
				out.println("\tThat's " + streak + " in a row... ");
				out.print("\tWould you like to flip again (y/n)? ");
				again = keyboard.next();
			}
			else
			{	
				out.println("You flip a coin and it is ... TAILS");
				out.println("\tYou lose everything!");
				out.println("\tYou should have quit while you were aHEAD!");
				streak = 0;
				again = "n";
			}
		} 

		out.println("Final score: " + streak + "\n");
	}
}

then don’t compare by eye.

and, you wouldn’t need to compare if you copied one of them and then made changes

Thanks ionatan. As a beginner, I need to get better at and more focused on checking the details.

Can I ask, what are you using to compare the two codes?

All works now. I appreciate your help.