0

Im learning java with "programmingbydoing" and i have a problem with Nim game, everything works fine apart from one thing, which is that both:

"System.out.print(n1 + ", choose a pile: ");" 

and

"System.out.print(n2 + ", choose a pile: ");"

is out printed twice after the first time.

Here is code:

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);

        System.out.print("Player one, enter your name: ");
        String n1 = input.nextLine();

        System.out.print("Player two, enter your name: ");
        String n2 = input.nextLine();

        int a = 3;
        int b = 4;
        int c = 5;
        int count = 1;

        System.out.println("A: "+a+" B: "+b+" C: "+c);

        nim_loop:while(a > 0 || b > 0 || c > 0) {

            while(count % 2 != 0 ) {
                System.out.print(n1+", choose a pile: ");
                String first = input.nextLine();

                if (first.contains("a") || first.contains("A")) {
                    System.out.print("How many to remove from pile " + first + "? ");
                    int second = input.nextInt();
                    count = count + 1;

                    a = a - second;

                    System.out.println("A: " + a + " B: " + b + " C: " + c);

                    if(a <= 0 && b <= 0 && c <= 0){
                        break nim_loop;
                    }

                }
                else if (first.contains("b") || first.contains("B")) {
                    System.out.print("How many to remove from pile " + first + "? ");
                    int second = input.nextInt();
                    count = count + 1;

                    b = b - second;

                    System.out.println("A: " + a + " B: " + b + " C: " + c);

                    if(a <= 0 && b <= 0 && c <= 0){
                        break nim_loop;
                    }
                }
                else if (first.contains("c") || first.contains("C")) {
                    System.out.print("How many to remove from pile " + first + "? ");
                    int second = input.nextInt();
                    count = count + 1;

                    c = c - second;

                    System.out.println("A: " + a + " B: " + b + " C: " + c);

                    if(a <= 0 && b <= 0 && c <= 0){
                        break nim_loop;
                    }

                }
            }

            while(count % 2 == 0) {
                System.out.print(n2 + ", choose a pile: ");

                String third = input.nextLine();

                if (third.contains("a") || third.contains("A")) {
                    System.out.print("How many to remove from pile " + third + "? ");
                    int fourth = input.nextInt();
                    count = count + 1;

                    a = a - fourth;

                    System.out.println("A: " + a + " B: " + b + " C: " + c);
                } else if (third.contains("b") || third.contains("B")) {
                    System.out.print("How many to remove from pile " + third + "? ");
                    int fourth = input.nextInt();
                    count = count + 1;

                    b = b - fourth;

                    System.out.println("A: " + a + " B: " + b + " C: " + c);
                } else if (third.contains("c") || third.contains("C")) {
                    System.out.print("How many to remove from pile " + third + "? ");
                    int fourth = input.nextInt();
                    count = count + 1;

                    c = c - fourth;

                    System.out.println("A: " + a + " B: " + b + " C: " + c);
                }
            }

        }

        if (count % 2 != 0) {

            System.out.println("Game ended, Player " + n1 + " is a winner.");
        } else if (count % 2 == 0){
            System.out.println("Game ended, Player " + n2 + " is a winner.");
        } 
    }
}

And here are the pictures of what happens when i run it:

What happens

DimaSan
  • 10,315
  • 10
  • 56
  • 68
Biafra
  • 63
  • 2
  • 9
  • 4
    Have you tried debugging your program? – f1sh Oct 05 '16 at 11:11
  • If you have not yet learned to use a debugger (a) consider learning it (b) until you learn, you may put in extra `System.out.println()` calls that can tell you which parts of the code are executed and how many times. – Ole V.V. Oct 05 '16 at 11:27
  • 1
    Ok thanks I think I will learn debugging then :) – Biafra Oct 05 '16 at 12:05

1 Answers1

1

When the first if condition in first inner loop is true and when you get the user input by using nextInt() it only reads the int value and does not consume the last new line character i,e \n. So the subsequent call to nextLine() will be skipped i,e the nextLine() call in second inner while loop will be skipped without any value but System.out.print(n2 + ", choose a pile: "); will be printed as it is before nextLine() call and control goes back to outer while loop.

Now the count value is 2 so first inner while condition will be false and control goes to second inner while loop. And again it prints b, choose a pile:. Hope this clears your question

Workaround is fire a blank nextLine() call after every nextInt() or use nextLine() inside if condition and parse the user input using Integer.parseInt(String) method.

Example code :

if (first.contains("a") || first.contains("A")) {
  System.out.print("How many to remove from pile " + first + "? ");
  int second = input.nextInt();
  input.nextLine(); // firing an blank nextLine call
  count = count + 1;
  a = a - second;
  System.out.println("A: " + a + " B: " + b + " C: " + c);

  if(a <= 0 && b <= 0 && c <= 0){
     break nim_loop;
  }

For more information - Scanner is skipping nextLine() after using next(), nextInt() or other nextFoo() methods

Community
  • 1
  • 1
Ravikumar
  • 871
  • 11
  • 21
  • Yea i know, the condition "if(a <= 0 && b <= 0 && c <= 0)" will be false, it's good that it doesnt break when only one value is 0 (a in this case), becouse the game is suppose to end only when all three values a, b and c reach 0 or less. My question is when it enters next inner loop and prints out "b, choose a pile:" , why does it print it twice? – Biafra Oct 05 '16 at 12:03
  • @Biafra I have updated the answer, it will solve your problem. – Ravikumar Oct 05 '16 at 12:26
  • Thank You, Im not sure i understand why i have to do this but it works :). Will check out that link You provided to find out. Thanks – Biafra Oct 05 '16 at 12:42
  • @Biafra Okay, What is happening is that the call to `nextLine()` in second while loop first finishes the line where the user enters `How many to remove from pile ` this is because `nextInt()` reads only one int and does not finish that particular line. This is the behavior of `Scanner`, you can read more about Scanner here - [Doc](http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html) – Ravikumar Oct 05 '16 at 12:48
  • Ok after reading it again i finally understand it, i have to say You explaned it very well:) – Biafra Oct 05 '16 at 12:56
  • @Biafra Glad that you understood. – Ravikumar Oct 05 '16 at 13:19