6

I'm trying to build the Bulls & Cows game in C++. I've implemented most of the logic. The game runs continuously with the use of an infinite loop and generates a random value at each run.

What I'm trying to do now is to now is to take the user input and run the code if the input is valid (can ONLY be a 4 digit integer). This is my implementation:

#include ...

using namespace std;

vector<int> getDigits(int modelValue) {
    vector<int> vectorValue;
    int extractedDigit = 0;
    int modulant = 10000;
    int divisor = 1000;

    for (int i = 0; i < 4; i++) {
        extractedDigit = (modelValue % modulant) / divisor;
        vectorValue.push_back(extractedDigit);
        modulant /= 10;
        divisor /= 10;
    }return vectorValue;
}


int main() {
    for (;;) {
        int model = rand() % 9000 + 1000;
        int guess = 0000;
        int bulls = 0;
        int cows = 0;
        int counter = 1;

        cout << "This is the random 4-digit integer: " << model << endl;
        cout << "Enter a value to guess: ";
        cin >> guess;

        if ((guess >= 1000) && (guess <= 9999) && (cin)) {

            vector<int> modelVector = getDigits(model);
            vector<int> guessVector = getDigits(guess);

            for (int i = 0; i < 4; i++) {

                if (find(modelVector.begin(), modelVector.end(), guessVector[i]) != modelVector.end()) {
                    if (modelVector[i] == guessVector[i]) { bulls += 1; }
                    else { cows += 1; }
                }
            }cout << "There are " << bulls << " bulls and " << cows << " cows" << endl;
        }
        else {
            cout << "Please enter a valid 4-digit integer between 0000 and 9999" << endl;
            cin.clear();
        }
    }return 0;
}

But when I run and input something invalid, what I get is a continuously running console.

Onur-Andros Ozbek
  • 2,998
  • 2
  • 29
  • 78
  • 1
    You aren't breaking out of the loop anywhere... – Luke Ramsden May 16 '18 at 14:46
  • Can you clarify "continuously running console"? Is it at least showing the error message and asking for more input, or is it just hanging? What inputs have you tried? – Brandon McKenzie May 16 '18 at 14:58
  • @LukeRamsden what I want to do is to `cout` an error message incase of a weird input and start over. @Brandon McKenzie. The console just runs continously. Its basically "hanging" if you will. – Onur-Andros Ozbek May 16 '18 at 15:11
  • I have just posted an answer for the very same problem [here](https://stackoverflow.com/q/50374003/3545273) (cannot mark it as a duplicate until other answer is accepted or upvoted) – Serge Ballesta May 16 '18 at 15:37
  • @SergeBallesta why don't you post that answer relevant to this question and delete that one so I can accept your answer? – Onur-Andros Ozbek May 16 '18 at 15:43
  • 1
    @OnurOzbek: Nice proposal, but I am too lazy for it :-) – Serge Ballesta May 16 '18 at 15:45
  • Also @SergeBallesta a 2nd look shows a difference. I already have a `cin` check in my code. Previously I tried `cin.fail()`. It made no difference. – Onur-Andros Ozbek May 16 '18 at 16:28

2 Answers2

1

There's nothing wrong with the way you read the user input, it just doesn't check for the input type before assigning the value into your 'guess' variable.

So, if an user put any value that isn't accepted by the integer type it would crash your application generating this infinite loop.

To protect your integer variable from wrong user inputs you must replace your direct input assignment:

cin >> guess;

By a protected one:

while(!(cin >> guess) || (guess < 1000)){
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cout << "Invalid input. Please, try again: ";
}

Into the while above you can see the "numeric_limits::max()" which is explained here:

Returns the maximum finite value representable by the numeric type T. Meaningful for all bounded types.

At the end you have a while holding the user into this reading loop while its input is under 1000 (as requested) or isn't a valid integer.

0

Try out cin.ignore(). It'll help you flush the cin buffer.

  • 1
    But that's not the problem. – Onur-Andros Ozbek May 16 '18 at 16:36
  • 1
    Well, yes it is. If someone enters something that cannot be extracted into an `int`, that something doesn't go away, and you still won't be able to extract it into an `int` on the next loop iteration either. It's still in the buffer, waiting for you to extract it into something compatible. You need to skip over it, to remove it from the input buffer. This has been covered many, many times on Stack Overflow, and should also be explained in your C++ book. – Lightness Races in Orbit May 16 '18 at 16:54
  • @LightnessRacesinOrbit he changed his answer. Initially he asked me to switch to a while loop, when that wasn't what I was asking. – Onur-Andros Ozbek May 16 '18 at 17:05
  • @OnurOzbek: Ah yes, I see that now. Okay! – Lightness Races in Orbit May 16 '18 at 17:07