user3869709
user3869709

Reputation:

java while loop counting error

I am trying to create a Nim game in Java following tutorials from ProgrammingByDoing (https://programmingbydoing.com/a/baby-nim.html). In this first attempt, I'm not so worried about error checking or going past zero, but it seems that as long as two of the three groups/piles reach zero then the game ends. However, I want all three piles to reach or exceed zero before the game ends.

My code is:

import java.util.Scanner;

public class BabyNim
{
    public static void main(String[] args) {

        Scanner keyboard = new Scanner(System.in);

            int pile1 = 10;
            int pile2 = 10;
            int pile3 = 10;
            String pileChoice = "";
            int amount; 

            System.out.print("A: " + pile1 + "\t" + "B: " + pile2 + "\t" + "C: " + pile3 + "\n" );
            System.out.print("Choose a pile: ");
            pileChoice = keyboard.next();
            System.out.print("How many to remove from pile " + pileChoice + ": ");
            amount = keyboard.nextInt();
            System.out.println("");

            while ( pile1 > 0 && pile2 > 0 && pile3 > 0 )
            {
                if ( pileChoice.equals("A") ) {
                    pile1 -= amount;
                } else if ( pileChoice.equals("B") ) {
                    pile2 -= amount;
                } else {
                    pile3 -= amount;
                }

                System.out.print("A: " + pile1 + "\t" + "B: " + pile2 + "\t" + "C: " + pile3 + "\n" );
                System.out.print("Choose a pile: ");
                pileChoice = keyboard.next();
                System.out.print("How many to remove from pile " + pileChoice + ": ");
                amount = keyboard.nextInt();
                System.out.println("");
            }

            System.out.println("");
            System.out.println("All piles are empty. Good job!");

        }
    }

My problem is that I get results such as:

A: 10   B: 10   C: 10

Choose a pile: B

How many to remove from pile B: 8

A: 10   B: 2    C: 10

Choose a pile: C

How many to remove from pile C: 9

A: 10   B: 2    C: 1

Choose a pile: A

How many to remove from pile A: 8

A: 2    B: 2    C: 1

Choose a pile: C

How many to remove from pile C: 1

A: 2    B: 2    C: 0

Choose a pile: A

How many to remove from pile A: 1


All piles are empty. Good job!

Upvotes: 1

Views: 163

Answers (4)

whyn0t
whyn0t

Reputation: 301

I really had fun doing this program :D, seems like I'm not the only one

this is what i suggest
1- remove redundant code before the loop by a do...while, and review the condition
2- replace the final else by an if( you are expecting a C but any letter except A B is accepted as a C) 3- you can end up with a negative piles since you don't check the remaining.

import java.util.Scanner;

public class BabyNim
{
    public static void main(String[] args) {

            Scanner keyboard = new Scanner(System.in);
            int pile1 = 10;
            int pile2 = 10;
            int pile3 = 10;
            String pileChoice = "";
            int amount; 
            do{
                // the incorrect inputs (other letters or values greater the amount) are ignored by the loop  
                System.out.print("A: " + pile1 + "\t" + "B: " + pile2 + "\t" + "C: " + pile3 + "\n" );
                System.out.print("Choose a pile: ");
                pileChoice = keyboard.next();
                System.out.print("How many to remove from pile " + pileChoice + ": ");
                amount = Math.abs(keyboard.nextInt());// only positive numbers
                System.out.println("");                

                if ( pileChoice.equals("A") && pile1 >= amount) {
                    pile1 -= amount;
                } 
                if ( pileChoice.equals("B") && pile2 >= amount) {
                    pile2 -= amount;
                }
                if ( pileChoice.equals("C") && pile3 >= amount){
                    pile3 -= amount;
                }
            }while ( pile1 > 0 || pile2 > 0 || pile3 > 0 );

            System.out.println("All piles are empty. Good job!");

        }
    }

Upvotes: 0

user6528991
user6528991

Reputation:

You used while ( pile1 > 0 && pile2 > 0 && pile3 > 0 ). According to AND operator if any one of them are false, then whole result becomes false. That's why the loop exits if any one of them is <=0.

So, to exit the loop only when all the piles are empty you should use

while( pile1>0 || pile2>0 || pile3>0). According to OR operator, if all of them are false, then only the whole result becomes false(which you need). Even if one of them is true the whole result would be true.

Hope you understood about operators.


Update:

I have edited your code to get the output you have shown in the link. It works fine.

import java.util.Scanner;

public class BabyNim
{
    public static void main(String[] args) {

        Scanner keyboard = new Scanner(System.in);

            int pile1 = 10;
            int pile2 = 10;
            int pile3 = 10;
            String pileChoice = "";
            int amount; 


            do
            {
                System.out.print("A: " + pile1 + "\t" + "B: " + pile2 + "\t" + "C: " + pile3 + "\n" );
                System.out.print("Choose a pile: ");
                pileChoice = keyboard.next();
                System.out.print("How many to remove from pile " + pileChoice + ": ");
                amount = keyboard.nextInt();
                System.out.println("");
                if ( pileChoice.equals("A") ) 
                {
                    pile1 -= amount;
                } else if ( pileChoice.equals("B") )
                {
                    pile2 -= amount;
                } else 
                {
                    pile3 -= amount;
                }


            }while ( pile1 > 0 || pile2 > 0 || pile3 > 0 );

            System.out.print("A: " + pile1 + "\t" + "B: " + pile2 + "\t" + "C: " + pile3 + "\n" );
            System.out.println("All piles are empty. Good job!");

        }
    }

Instead of while() use do{}while(); because it is an exit based loop. You can also use while() but do{}while(); is convenient as we don't want to check the initial condition to enter the loop.

You don't need to write asking user for his input 2 times, inside and outside of loop. Just write it once after entering the loop.

Hope it helps.

Upvotes: 2

castletheperson
castletheperson

Reputation: 33496

Your loop ends as soon as any of the piles are empty. Instead, it needs to end when all of the piles are empty. In other words, it should continue while at least one of the piles isn't empty.

It should be:

while (pile1 > 0 || pile2 > 0 || pile3 > 0)

Or maybe this would make more sense:

while (pile1 + pile2 + pile3 > 0)

Also, you should ask for input before doing the check by using a do..while loop:

import java.util.Scanner;
public class BabyNim {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int pile1 = 10, pile2 = 10, pile3 = 10;

        do {
            System.out.printf("A: %d\tB: %d\tC: %d%n", pile1, pile2, pile3);
            System.out.print("Choose a pile: ");
            String pileChoice = in.next();
            System.out.printf("How many to remove from pile %s: ", pileChoice);
            int amount = in.nextInt();
            System.out.println();

            if (pileChoice.equals("A")) {
                pile1 -= amount;
            } else if (pileChoice.equals("B")) {
                pile2 -= amount;
            } else {
                pile3 -= amount;
            }
        } while (pile1 + pile2 + pile3 > 0);

        System.out.println("\nAll piles are empty. Good job!");
    }
}

Upvotes: 1

Mr. Robot
Mr. Robot

Reputation: 186

Here is issue with you while loop condition which says :

   while ( pile1 > 0 && pile2 > 0 && pile3 > 0 )

if any of the pile is 0 then don't go into the while loop so your code should be like this :

    while ( pile1 > 0 || pile2 > 0 || pile3 > 0 )

you must also add add some check inside if else while you are subtracting amount from pile that the amount you entered should be less than the current pile size otherwise pile size will be negative .

Eg .

if ( pileChoice.equals("A") && amount <= pile1) {
                pile1 -= amount;
         }

Upvotes: 1

Related Questions