简体   繁体   中英

While loop not exiting

New to Java on this end. I'm trying to run a program that rolls two dice and when the total roll between the two die is either 7 or 11 the program will exit. For some reason my while statement is executing over and over again, and I can't figure out why. Any help would be really appreciated. Code is below.

Again, very new to this. Not so much focused on a more efficient way to do this at the very moment, but rather the semantic details of why this is not functioning.

// import required packages for the program
// import all classes to be on the safe side
// will be using input/ouput and math, so those imports are needed
import java.io.*;
import java.math.*;
import java.text.*;

// Declare a class, class name Dice chosen
public class Dice
{
// need to use throws IOException because we are dealing with input and output, simple main method will not suffice
    public static void main(String[] args) throws IOException
    {

        // declare variables for the two dice, randomize each
        // die can each be rolled for # between 1-6
        double dice1 = Math.round(Math.random() * 6) + 1;
        double dice2 = Math.round(Math.random() * 6) + 1;

        // declare variable for combined roll
        double totalRoll = dice1 + dice2;

        //create loop to determine if totalRoll is a 7 or 11, if not continue rolling
        while ((totalRoll != 7.0) || (totalRoll != 11.0))
            {
            dice1 = Math.round(Math.random() * 6) + 1;
            dice2 = Math.round(Math.random() * 6) + 1;

            totalRoll = dice1 + dice2;

            System.out.println("The roll on die 1 is: " + dice1);
            System.out.println("The roll on die 2 is: " + dice2);
            System.out.println("The total of the two rolls is: " + totalRoll + "\n");

            if ((totalRoll == 7.0) || (totalRoll == 11.0)) 
            {
            System.out.println("You win!");
            }
            }


        /*
        // declare in as a BufferedReader; used to gain input from the user
        BufferedReader in;
        in = new BufferedReader(new InputStreamReader(System.in));

        //Simulate tossing of two dice
        */




    }
}

I think you want to swap your OR for an AND . With an OR , that while statement will always evaluate to true, because a single number can not be both 7 and 11 at the same time (unless it's some brutal quantum computing, but I'll assume it's not).

while(totalRoll != 7.0 && totalRoll != 11.0) {
    // Continue.
}

NOTE : If you are trying to make a quantum dice, then one could argue you'd need to roll the dice an infinite amount of times, given the single di face could equal all numbers simultaneously, so in this context your program is working beautifully... just food for thought.

Serious NOTE : Using a double to represent a value on a dice is really wasteful. You're reserving a lot more memory than you need to. Use an int or even a byte , if you wanted to optimize your memory usage.

Edit in response to comment

You added the break to your if statement; I am assuming. Well, you see, this is different. You're claiming if the number equals one of these numbers. Let me run an example for you.

When dealing with equality

The logic in your if statement is fine, because, let's say:

double totalRoll = 7.0;

if(totalRoll == 7.0 || totalRoll == 11.0)
{
    // Do something.
}

This evaluates to:

if(7.0 == 7.0 || 7.0 == 11.0)
{
}

Which becomes:

if(true || false)

And because TRUE OR X == TRUE , it becomes:

if(true)

Likewise, if you set totalRoll to 9.0 :

if(9.0 == 7.0 || 9.0 == 11.0)
{
}

Which becomes.

if(false || false)

Which finally evaluates to:

if(false)

So we have proven by demonstration, that this if statement can handle input. Let's try out your while loop.

When dealing with inequality

double totalRoll = 7.0;

// We expect this to stop the loop..
while(totalRoll != 7.0 || totalRoll != 11.0)

Evaluates to

while(7.0 != 7.0 || 7.0 != 11.0)

And that evaluates to:

while(false || true)

Once again, X OR TRUE == TRUE so.

while(true)

Oh dear. So as you can see, the only way this while loop will ever break, is if the value of totalRoll is both 7.0 and 11.0 at the same time.

Why the solution works

We fix it, by swapping the OR for an AND .

double totalRoll = 7.0;

while(7.0 != 7.0 && 7.0 != 11.0)
{
}

Evaluates to..

while(false && true)

And we know that FALSE AND X == FALSE so

while(false)

And the loop breaks. The same will happen with 11.0 , but not with any other number.

You could add an break, right after the System.out.print

if ((totalRoll == 7.0) || (totalRoll == 11.0))
    {
        System.out.println("You win!");
        break;
    }

You probably would like the while statement to be this--it's clearer:

   while (!(totalRoll == 7.0 || totalRoll == 11.0))

"While it is not true that roll equals 7 or 11..."

Re: @Paranix "& is bitwise"...

Here's a quote from SO:

"The && and || operators 'short-circuit' , meaning they don't evaluate the right hand side if it isn't necessary. The & and | operators, when used as logical operators, always evaluate both sides."

I found that and 31 up votes here and found similar wording elsewhere. But maybe that quote needs modification, since & does do "bitwise and", period .

That is, if both operands happen to be boolean, they're integers, either 1 or 0, so bitwise stuff applies.

1&1 is true (equals 1); 1&0, 0&1, 0&0 are false (equal 0).

The statement below prints 0,0,0,1:

System.out.println((1&0) + "," + (0&1) + "," + (0&0) + "," + (1&1));

You get error if using (1 && 0) since && requires boolean operands.

In any event, the modified dice code works correctly with either & or &&.

I've read that && is definitely required if there's any chance the right-hand operand is null, but I can't demonstrate that.

Comparing doubles like that is very problematic; due to the way double values are represented chances are that totalRoll == 7.0 will not give you true, even if totalRoll is exactly 7.0. A better way to compare doubles (if you have to use them) would be something like this:

while (Math.abs(totalRoll - 7.0) > 0.0001 && Math.abs(totalRoll - 11.0) > 0.0001) { ... }

That way the inaccuracy of saving double values doesn't hurt you as much.

Edit: As there have been downvotes, I'll post some more information to back up what I'm saying:

Also, the following code prints false for me:

System.out.println(((7.0 / 100) * 100) == 7.0);

If anyone has information that disproves what I'm saying then please tell me about it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM