1
votes

I made a tic-tac-toe game which works good. Recently I decided to add a reset game feature. Here is the part where I take input from user

void playerMove() //Gets the player move and updates the box variables
{
    int boxnumber;
    while(1)      //Set's loop if the player enters a invalid input
    {
       cout << "\n Player " << player << "'s turn!(Press 0 to reset the game!): ";
       cin >> boxnumber;
       if(box[boxnumber-1] == 'X' || box[boxnumber-1] == 'O' || boxnumber > 9 || boxnumber < 0) // Checks if the input is valid or not
       {
           system("CLS");//If invalid, show error and loop back to start to get new input
           displayBoard();
           cout << "\n Invalid Input! Try again!\n";

       }else if(boxnumber == 0)
       {
           refreshGame();
           displayBoard();
       }else
       {
           box[boxnumber-1] = player;//If inputs are fine, set the box variable's and break out of loop!
           break;
       }
    }

}

Now, in debug mode, when I press 0, everything runs fine and the game is reset, but in release build, when I press 0, it gives me the "Invalid Input! Try again!"

Things I have tried the didnt work: -Rebuild the entire release and debug version. -Making a new project and copy-pasting my code. Same thing, debug works, release doesnt.

For anyone wondering, I am using code::blocks IDE. The compiler is GNU GCC. Thanks for the help! :)

2
i don't think you can get box[-1] - apple apple
What is boxnumber-1 going to be in box[boxnumber-1] when you enter 0? - NathanOliver

2 Answers

4
votes

You have undefined behavior.

In the "first" if you have box[boxnumber-1], so when you enter 0 (as you have stated in your question), you're trying to access element with index -1. That's UB, as you're reading "invalid" memory.

You should check for 0 first (and for negative numbers also).

3
votes

In the if statement, put the range checks in front of the value checks. That is, change

if(box[boxnumber-1] == 'X' || box[boxnumber-1] == 'O' || boxnumber > 9 || boxnumber < 0)

to

if(boxnumber < 0 || box number > 9 || box[boxnumber-1] == 'X' || box[boxnumber-1] == 'O')

That takes advantage of short-circuiting: if the input value is less than 0 or greater than 9 the value checks won't be executed. That will avoid checking things like box[10], which isn't valid.

That still leaves a problem: if the user inputs 0, this code will happily check box[-1], which is also out of range. To get rid of this, move the branch of the if statement that tests box number == 0 in front of this part:

if (box number == 0)
    // whatever
else if (box[boxnumber-1] == 'X' || box[boxnumber-1] == 'O' || boxnumber > 9 || boxnumber < 0)
    // whatever else