Guessing game

This is my first code in c++. The problem is when the player loses the game the program write this : "Too Low!Too Low! You Lose!" or "Too High!Too High! You Lose!" And you can only win while you type 41.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    int srand(time(0));
    int secretNum = rand();
    int guess;
    int guessCount = 0;
    int guessLimit = 20;
    bool outOfGuesses = false;

    while(secretNum != guess && !outOfGuesses) {
        if(guessCount < guessLimit){
            cout << "Guess: ";
            cin >> guess;
            guessCount++;
            } else {
              outOfGuesses = true;
        }
          if(guess > secretNum ){
            cout << "Too High! ";
        } else if( guess < secretNum){
            cout << "Too Low! ";
        }
    }


          if(outOfGuesses){
            cout << "You Lose!";
          } else {
            cout << "You Win !";
          }




    return 0;
}
Consider the 19th guess. Lines 17-19 prompt for a guess and increment guessCount to 20. Let's assume the guess is too high, so line 24 prints "Too High! "

Now the fun begins....

outOfGuesses is still false, so the loop runs again.
At line 16, guessCount is now 20, so guessCount < guessLimit is false. Line 21 executes, setting outOfGuesses to true.

Line 23 executes, but guess is still the old value, so it prints "Too High!" again.

Control returns to the loop at line 15. outOfGuesses is true so the loop ends and the program goes to line 31. outOfGuesses is true so it prints "You Lose!"

To fix this, get rid of variable outofGuesses and just check if guessCount<guessLimit in the while loop. This simplifies the code.

Note also that I changed line 8 to call srand(). In your original code, you actually declared a local int variable called srand and initialized it to the value of time(0). This is one of the failings of C++ syntax: sometimes a simple misstatement creates valid code that doesn't mean anythink like what you intended.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    srand(time(0));
    int secretNum = rand();
    int guess;
    int guessCount = 0;
    int guessLimit = 20;

    while(secretNum != guess && guessCount < guessLimit) {
	cout << "Guess: ";
	cin >> guess;
	guessCount++;
	if(guess > secretNum ){
            cout << "Too High! ";
        } else if( guess < secretNum){
            cout << "Too Low! ";
        }
    }

    if(guessCount >= guessLimit) {
	cout << "You Lose!";
    } else {
	cout << "You Win !";
    }
    return 0;
}

You should limit the random number that you are producing to some reasonable range instead of using the whole range of rand. So maybe number = rand() % 100 + 1. This picks a number from 1 to 100.

Also, in dhayden's code, it should test if (guess != secretNum) at the end or else it will consider guessing the number on the last guess a loss.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
    const int RandLimit = 100;
    const int GuessLimit = 10;

    srand(time(0));
    int number = rand() % RandLimit + 1;

    cout << "I have chosen a number from 1 to " << RandLimit
         << ". You have " << GuessLimit <<  " guesses.\n";

    int guessCount = 0, guess = 0;
    while (guessCount < GuessLimit && number != guess) {
        cout << "Guess #" << guessCount + 1 << ": ";
        cin >> guess;
        guessCount++;
        if (guess > number)
            cout << "  Too High!\n";
        else if (guess < number)
            cout << "  Too Low!\n";
    }

    if (guess != number)
        cout << "You lose.\nThe number was: " << number << '\n';
    else
        cout << "You win!\n";
}

Last edited on
Thank you for your helping ! I learn c++ in my free time as an IT student, so sometimes I write a bad things or good things but the wrong order. Anyway, I learned now lots of thigns from this 2 comments so I want you to thank you again guys, I appreciate that!
Last edited on
Hello hgeza06,

Between dhayden and tpb you have some good code to work with.

I changed your original code a bit and this is what could be done:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
	srand(static_cast<size_t>(time(0)));
	
	constexpr int GUESSLIMIT{ 7 };  // <--- Changed.

	int secretNum = rand() % 100 + 1;  // <--- Changed.
	int guess{};  // <--- Changed. Needed to be initialized.
	int guessCount = 0;
	bool outOfGuesses = false;

	while (secretNum != guess && !outOfGuesses)
	{
		if (guessCount < GUESSLIMIT)
		{
			cout << "\n Guess: ";
			cin >> guess;
			guessCount++;

			// <--- Moved the if/else here to work properly.
			if (guess > secretNum)
			{
				cout << "\n Too High!\n";
			}
			else if (guess < secretNum)
			{
				cout << "\n Too Low!\n";
			}
		}
		else
			outOfGuesses = true;
	}


	if (outOfGuesses)
		cout << "You Lose!";
	else
		cout << "You Win !";

	// <--- Used mostly for testing in Debug mode. Removed if compiled for release.
	// <--- Used to keep the console window open in Visual Studio Debug mode.
	// The next line may not be needed. If you have to press enter to see the prompt it is not needed.
	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
	std::cout << "\n\n Press Enter to continue: ";
	std::cin.get();

	return 0;
}

Both dhayden and tpb have mentioned "srand" and if you are not familiar with its use this may help. http://www.cplusplus.com/reference/cstdlib/srand/?kw=srand

The variable "GUESSLIMIT" I defined as a constant because this is a variable that should not be changed in the program. The capital letters are the generally accepted form for a constant, although I do not recall having read anything thet says do it this way, but this is what I most often see.

As tpb point out putting a limit on on the call to "rand()" means you have a smaller range of numbers to use. One of the times I ran your code "rand()" produced a number of "31123". Not something you want to try to guess.

Another point on "GUESSLIMIT". For a program like this the maximum number of guesses allowed it seven not twenty. Usually on a range of 1 to 100 done properly you can guess the number in less than 7 tries.

Fixing your code is not the best answer, but it does point out some of the coding that you can do and a logic/flow problem.

Hope that helps,

Andy
Thanks for working my code Andy, I appreciate that.

But, I've got an error in Line 11 .

constexpr int GUESSLIMIT{ 7 }; // <--- Changed.

And another question:

constexpr mean that the GUESSLIMIT variable can not be changed?
@Andy, Should you cast the return value of time() to an unsigned int instead of size_t? srand says it takes an unsigned int, although that restricts it to 32 bits on 64-bit systems that make int 32-bits (where size_t should presumably be 64-bits).
Last edited on
@tpb,

My understanding and what I have learned over time is that "size_t" is a built in typedef for "unsigned int". I have been told that it is something that started in C and carried over to C++.

I have also found functions like "string.size()" or "string.length()" and others return a "size_t" value.

I have also seen "srand((unsigned)time(null));". Forgive me if I got this wrong because it has been awhile since I have seen it.

I honestly do not know if "size_t" is 32 bits or 64 bits. I would say that it is the size of an "unsigned int" on the computer and along with the compiler being used. As I have read here some systems/computers are different when it comes to the size of different variables.

Hope that helps,

Andy
@Handy Andy,

It's more of an alias for unsigned long. size_t is usually 64-bits on 64-bit machines. unsigned int is often only 32-bits.

Interestingly, it isn't a keyword but a typedef in std (more properly expressed as std::size_t). So this will complain that size_t is unknown (with or without std::) :
int main() {std::size_t i = 0;}
But common headers apparently not only define it but expose it globablly.

BTW, std::streamsize is a basically a signed version of size_t (like ssize_t in posix).

But it doesn't really need to be cast at all since it doesn't matter. Strangely, time(0) isn't even guaranteed (by the standard) to return anything that would be useful as a seed for srand! (What in the world is a time_t (undefined in the standard)? Why is there that crazy pointer return route?) I assume that pretty much all imps return a seconds-since-the-epoch count, though.
Last edited on
Thank you tpb for pointing out the bug in my code.

Ironically, I had another version that I was going to post also and that one fixes the bug. Here it is. The big difference is in the loop and the test for a winner. In this version, the loop goes through the number of guesses and there's a break statement if you guess correctly. Some might find this logic easier to follow. The other change is explicitly checking for a win, rather than doing it implicitly with other variables. Explicit code is always better.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    srand(time(0));
    int secretNum = rand();
    int guess;
    int guessLimit = 5;

    for (int guessCount=0; guessCount < guessLimit; ++guessCount) {
	cout << "Guess: ";
	cin >> guess;
	guessCount++;
	if(guess > secretNum ){
            cout << "Too High! ";
        } else if( guess < secretNum){
            cout << "Too Low! ";
        } else {
	    break;
	}
    }

    if(guess != secretNum) {
	cout << "You Lose!";
    } else {
	cout << "You Win !";
    }
    return 0;
}

Topic archived. No new replies allowed.