2

I'm having an issue with my very first program in Java. I'm trying to reproduce a game you play with matches, but the program never stops when it's supposed to...

When I enter numbers like 6, 3, 2, 1 or 7, 3, 2, 1 the loop should stop there but it just continues to the next turn as if nothing happened, even though the variables have the right value and should match the end conditions.
I'm pretty sure the problem lies in the while part of the main loop (at the very end) but I can't see it! It's probably something obvious, but well...

Here is the full source code (the rules of the game are below it):

import java.util.Scanner;


public class JeuDeNim {

  public static void main(String[] args) {

    Scanner sc = new Scanner(System.in);

    //Starting the game
    int totalMatches;
    do {
        System.out.println("How many matches do you want to play with? "
        + "(from 6 to 60)");
        totalMatches = sc.nextInt();
    }
    while(totalMatches < 6 || totalMatches > 60);


    int matchesPlayer1 = 0;//to keep track of
    int matchesPlayer2 = 0;//the previous round
    int i = 1;//to know whose turn it is
    do{

        //player 1

        if(!(i % 2 == 0)) {//if odd number, player 1

            //round 1

            if(i == 1) {
                do {
                    System.out.println("Player 1: How many matches do you "
                    + "want to pick? (1, 2 or 3)");
                    matchesPlayer1 = sc.nextInt();
                }
                while(matchesPlayer1 < 1 || matchesPlayer1 > 3);

                totalMatches = totalMatches - matchesPlayer1;
                i++;
            }

            //odd round x

            else {
                do {
                    System.out.println("Player 1: How many matches do you "
                    + "want to pick this turn?");
                    matchesPlayer1 = sc.nextInt();

                    if(totalMatches - matchesPlayer1 < 0) {
                    System.out.println("Pick a smaller number");
                    //totalMatches cannot be negative
                    } else if(matchesPlayer1 == matchesPlayer2) {
                    System.out.println("You cannot pick the same number "
                    + "of matches as Player 2");
                    }
                }
                while(matchesPlayer1 < 1 || matchesPlayer1 > 3 
                        || (totalMatches - matchesPlayer1 < 0)
                        || (matchesPlayer1 == matchesPlayer2));

                totalMatches = totalMatches - matchesPlayer1;
                if(totalMatches == 0
                    || (totalMatches == 1 && matchesPlayer1 == 1)) {
                    System.out.println("Player 1 Wins!");
                }
                i++;
            }
        }

        //player 2

        else {

            //round 2

            if(i == 2) {
                do {
                    System.out.println("Player 2: How many matches do you "
                    + "want to pick? (1, 2 or 3)");
                    matchesPlayer2 = sc.nextInt();
                    if(matchesPlayer2 == matchesPlayer1) {
                        System.out.println("You cannot pick the same "
                        + "number of matches as Player 2");
                    }
                }
                while(matchesPlayer2 < 1 || matchesPlayer2 > 3
                        || matchesPlayer2 == matchesPlayer1);

                totalMatches = totalMatches - matchesPlayer2;
                i++;
            }

            //even round x

            else {
                do {
                    System.out.println("Player 2: How many matches do you "
                    + "want to pick this turn?");
                    matchesPlayer2 = sc.nextInt();

                    if (totalMatches - matchesPlayer2 < 0) {
                        System.out.println("Pick a smaller number");
                        //totalMatches cannot be negative
                    } else if(matchesPlayer2 == matchesPlayer1) {
                    System.out.println("You cannot pick the same number "
                    + "of matches as Player 1");
                    }
                }
                while(matchesPlayer2 < 1 || matchesPlayer2 > 3
                        || (totalMatches - matchesPlayer2 < 0)
                        || (matchesPlayer2 == matchesPlayer1));

                totalMatches = totalMatches - matchesPlayer2;
                if(totalMatches == 0
                    || (totalMatches == 1 && matchesPlayer2 == 1)) {
                    System.out.println("Player 2 Wins!");
                }
                i++;
            }
        }
        System.out.println("totalMatches: " + totalMatches + " "
        + "matchesPlayer1: " + matchesPlayer1 + " " + "matchesPlayer2: "
        + matchesPlayer2);//to check that everything is working. It is not...
    }
    while(totalMatches > 0
            || !(!(i % 2 == 0) && totalMatches == 1 && matchesPlayer1 == 1)
            || !((i % 2 == 0) && totalMatches == 1 && matchesPlayer2 == 1));
  }
}

Here are the rules of the game: it's a two-player game, where the players take turns picking matches (1, 2 or 3) and cannot pick the same number of matches as the other player: if player one picks 2 matches, player two will have to pick either 1 or 3 matches. The player who cannot pick anymore matches loses the game, which means there are two end scenarios : when there are no more matches, or there is 1 but the other player picked 1 during the previous round.

14
  • 2
    Can't you just remove most of that long text and just state the question and narrow down the code? People just want to help you find the specific code bug and move on. There are guidelines for posting questions here. "Pretend you are talking to a busy colleague". Commented Mar 30, 2015 at 20:04
  • 1
    Everything he said is relevant. He could have said it a bit shorter, but its fine. Commented Mar 30, 2015 at 20:09
  • 2
    @xathien That site is not for fixing bugs in code. Commented Mar 30, 2015 at 20:20
  • 1
    kevinlelo when do you want that the program stops? When someone won? Commented Mar 30, 2015 at 20:21
  • 2
    @Tom: Before his edit, he was also asking for a code review, so I pointed him in the right direction. :) Commented Mar 30, 2015 at 20:21

2 Answers 2

1

Look at the conditions in your final while loop

totalMatches > 0 ||
!(!(i % 2 == 0) && totalMatches == 1 && matchesPlayer1 == 1) ||
!((i % 2 == 0) && totalMatches == 1 && matchesPlayer2 == 1));

This means the loop will repeat as long as there are any matches left, or it isn't player 1's turn with 1 match left and a pick of 1 match, or it isn't player 2's turn with 1 match left and a pick of 1 match.

This can never happen because (among other reasons), it requires i%2==0 and i%2 != 0. Switch the || to &&, and it should fix the problem. As was pointed out in the comments, you also need to reverse the player turn check, because the turn counter has already been incremented by this point.

The reason you want to use && here instead of ||, like in the other spots in your code is that your checking for a different concept. Every other time, you check the reasons why the loop should be repeated. This time, you check the reasons why the loop should end, and negate them. When in doubt, actually plug in values for the comparison, and see if it evaluates to what you think it should.

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

5 Comments

I've just tried that but it only works when there are no more matches, not with the other end scenario. Also I don't understand why I should use && when it is logical to use ||? As for the turns, i is incremented at the end of each turn so I think I've taken that into consideration?
@kevinlelo I haven't fully worked through the logic of your code, but I'm guessing that's because the turn counter has already been incremented at that point. Switch the turn checks would probably fix it.
It works! I've swiched || to && and inverted i%2==0 and i%2 != 0 as you said and now it works fine in both cases :-) It still doesn't seem logical to me though... I'll keep testing to see if it's fixed for good
Thank you for your help! :-) I think it works fine now! If you have time would you mind telling me how you found out about the solution? I'm using || in every other do-while loop and it doesn't seem to be causing any problem...
@kevinlelo I tried to explain it a little bit. You're basically checking for the opposite thing in the final loop ("should I exit" vs "should I repeat"). Because of the way boolean logic works, you can't just do a ! on each of the "should I exit" conditions; you also need to switch from '||' to '&&'.
1

The game ends when there is no more matches left. So while(totalMatches > 0); is just enough.

Remove the unnecessary lines:

|| !(!(i % 2 == 0) && totalMatches == 1 && matchesPlayer1 == 1) || !((i % 2 == 0) && totalMatches == 1 && matchesPlayer2 == 1));

2 Comments

See the rules below the code, there are two ways the game can end. Also every time I run the program, it doesn't stop even when totalMatches is 0.
Indeed, i missed that.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.