1

I just finished working on this marble game program and it works fine except I need to do one more thing to protect it from invalid input. The program responds properly to all integer based invalid input but if you input a non integer the program crashes. I've been using the cin.fail() function and it works but then gets stuck in a loop. If the user enters a non integer i want the program to tell the user that was invalid input and prompt the user to input their selection again.

I added return 1; after the invalid input statement to end the program instead of it crashing but that's not what I want to do. I want it to print "invalid input" and then re-prompt the user to input their selection again.

#include <iostream>
using namespace std;

int main()
{
    cout << "*** The Game of Nim ***\n\n" << endl;

    string player1, player2, currentPlayer;
    int marbles, selection;
    bool isDone = false;

    cout << "Enter a name for Player 1: ";
    cin >> player1;
    cout << "Enter a name for Player 2: ";
    cin >> player2;
    cout << "Enter how many marbles you would like to start with in the pile: ";
    cin >> marbles;

    cout << "\nThere are " << marbles << " marbles in the pile\n" << endl;

    currentPlayer = player1;

    do
    {
        bool turnDone = false;

        while (turnDone == false && marbles != 0)
        {
            if (currentPlayer == player1)
            {
                cout << currentPlayer << "\n";

                cout << "How many marbles would you like to draw? : ";
                cin >> selection;

                if (cin.fail())
                {
                    cout << "\nInvalid Input\n";
                    return 1;

                }


                if (selection < marbles / 2 + 1 && marbles > 1 && selection != 0)
                {
                    marbles = marbles - selection;

                    if (marbles == 1)
                    {
                        cout << "\nUh Oh! There is only 1 marble remaining in the pile\n" << endl;

                        currentPlayer = player2;
                        turnDone = true;
                        break;
                    }

                    cout << "\nThere are " << marbles << " marbles remaining in the pile\n" << endl;

                    currentPlayer = player2;

                    turnDone = true;

                }else if (marbles == 1)
                {
                    marbles = marbles - selection;

                    if (marbles <= 0)
                    {
                        cout << "\nThere are 0 marbles remianing in the pile\n";

                        cout << "You drew the last marble!" << endl;
                        cout << "You lose!\n\n" << endl;
                        cout << player2 << " wins\n\n" << endl;

                        turnDone = true;

                        return 0;

                    }

                }else if (selection == 0 || selection > marbles / 2 + 1)
                {
                    cout << "\nYou must draw at least 1 marble, and no more than half the pile\n" << endl;
                }

            }else if (currentPlayer == player2)
            {
                cout << currentPlayer << "\n";

                cout << "How many marbles would you like to draw? : ";
                cin >> selection;

                if (selection < marbles / 2 +1 && marbles > 1 && selection != 0)
                {
                    marbles = marbles - selection;

                    if (marbles == 1)
                    {
                        cout << "\nUh Oh! There is only 1 marble remaining in the pile\n" << endl;

                        currentPlayer = player1;
                        turnDone = true;
                        break;
                    }

                    cout << "\nThere are " << marbles << " marbles remaining in the pile\n" << endl;

                    currentPlayer = player1;

                    turnDone = true;

                }else if (marbles == 1)
                {
                    marbles = marbles - selection;

                    if (marbles <= 0)
                    {
                        cout << "\nThere are 0 marbles remianing in the pile\n";

                        cout << "You drew the last marble!" << endl;
                        cout << "You lose!\n\n" << endl;
                        cout << player1 << " wins!\n\n" << endl;

                        turnDone = true;

                        return 0;

                    }

                }else if (selection == 0 || selection > marbles / 2 + 1)
                {
                    cout << "\nYou must draw at least 1 marble, and no more than half the pile\n" << endl;
                }
            }
        }
    }while (isDone == false);

    return 0;
}
RootFire
  • 119
  • 1
  • 2
  • 11

2 Answers2

1

Here's how to use std::cin.fail() in your program:

int marbles;
bool check = false;
do {
    std::cout << "Enter how many marbles you would like to start with in the pile: ";
    std::cin >> marbles;
    if (std::cin.fail()) {
        std::cin.clear();
        std::cin.ignore();
    }
    else
        check = true;
}while(!check);

cin.fail() will return a boolean saying wether or not the expected income as been received
If not, you'll have to use clear() wich will put the fail value to false and then ignore the given input
Hope that helped

Treycos
  • 7,373
  • 3
  • 24
  • 47
  • http://stackoverflow.com/questions/17906990/meaning-of-cin-fail-in-c google helps a lot – Treycos Oct 04 '16 at 21:38
  • I swapped out return 0; with cin.clear() and cin.ignore() followed by break; and it produced the desired outcome – RootFire Oct 04 '16 at 22:18
0

Get the user input in a string and check if there's any number in it:

std::string input; 
std::cin >> input;
int marbles = std::atoi(input.c_str()); //Returns the first number met in the char table, if there is none, returns 0

if(marbles)
    std::cout << marbles;
Treycos
  • 7,373
  • 3
  • 24
  • 47
  • 2
    Use `strtol` instead, which provides a way to differentiate between "failed to parse" and "successfully parsed `0`" – Ben Voigt Oct 04 '16 at 20:52
  • I appreciate the info guys. I should've mentioned I am a beginning programming student in the first month of a c++ class. I haven't learned about the methods you are suggesting yet. I would like to try and accomplish this using cin.fail(), since we have learned about that, even though it might not be the most efficient way to go about it. – RootFire Oct 04 '16 at 20:59
  • Erm.. you didn't learn how to use it? ^^ So what have you learnt about it then? – Treycos Oct 04 '16 at 21:01
  • Erm...I learned that it is a function that can be used to protect against invalid input, such as a user inputting a character when the program is expecting an integer. I learned how to implement it and exit the program as I've demonstrated in my code. What I haven't been able to figure out in this particular case is how to continue on with the program rather than ending it and that is the reason for my post. – RootFire Oct 04 '16 at 21:23
  • I'm re-answering then – Treycos Oct 04 '16 at 21:27