1

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!
2
  • 2
    You would benefit from a do {} while(); loop in this case. Commented Aug 27, 2016 at 1:03
  • Ah Stack Overflow, leave a thousand comments requesting compilable test cases and a problem statement, then downvote the rare questions that actually give you what you want. Keep doing what you're doing, guys. Commented Aug 27, 2016 at 1:31

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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!");
    }
}

4 Comments

Yes, I believe I understand what you mean. However, when I attempted to put either of the while statements above and choose numbers that go into the negative for all three piles, the game continues. How does that work?
@Trying What you are describing doesn't make sense, pile1 > 0 || pile2 > 0 || pile3 > 0 would correctly evaluate to false if all three were negative. Are you 1) sure you didn't make a typo in your modified condition and 2) sure that your observations about the game continuing are correct and not a misinterpretation of a different issue? For example, does the game continue indefinitely when all 3 are negative, or does it just go for one extra iteration? I mean, your current loop structure does carry the game one extra step after it should quit, regardless of the while condition issue.
@Trying The game instructions also say that you don't need to validate negative inputs. So you don't need to bother testing with them.
@Jason C You are absolutely right. I jumped to the conclusion that all negatives still continued and did not carry out one more iteration. It terminated after that next iteration.
1

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;
         }

1 Comment

The assignment says "You do not need to check for errors like a wrong pile name, or if someone tries to take more counters from the pile than the pile has."
0

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!");

        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.