Random number seems to get stuck in a loop?

So, I'm working on a number guessing game in command console. Right now, the player enters a number, the computer has to guess it, points are incremented to the score based on how many tries are made. Once number is found, a new round will start.

The problem is, that after a few rounds, the computer seems to get stuck after guessing a few numbers. Any idea on what I am doing wrong?

Not everything is done yet, as it is part of a larger project.

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
  #include <iostream>
#include <cstdlib>
#include <ctime>
#include <chrono>
#include <thread>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;


void myBannerTop(void)

{
	cout << "\n************************************************************************\n";
	cout << "\t\t\t" "       " << "Welcome to:\n";
	cout << "\t\t\tGuess The Secret Number!\n";
	cout << "************************************************************************\n";
}



void myBannerBottom(int x)
{
	cout << "\n************************************************************************\n\n";
	cout << "\n\nRules:\n\n";
	sleep_for(seconds(0));
	cout << "1. - All numbers must be whole, POSITIVE numbers between 1 and 100!\n\n";
	cout << "2. - The lower your ammount of guesses, the more points you will earn!\n\n";
	cout << "3. - Beat me with a higher score to win the round and possibly the game!\n\n\n";
	sleep_for(seconds(0));
	cout << "*********\n";
	cout << "Round: " << x << "\n";
	cout << "*********\n\n";
}


void storeGuess(int MAX_VALUE, unsigned int myArray[] , int index, int myInput)
{
	if (index < MAX_VALUE)
	{
		myArray[index] = myInput;
		index++;
	}
	else
	{
		index = 0;
	}
}


int main()

{
	//Declare Variables
	unsigned int secretNumber;
	unsigned int hiVal = 0;
	unsigned int loVal = 0;
	unsigned int guess = 0;
	unsigned int tries = 0;
	unsigned int round = 1;
	int computerScore = 0;
	int playerScore = 0;
	int points = 150;
	bool exit = false;
	bool validGuess = true;
	bool playerTurn = true; //MAKE SURE TO CHANGE THIS TO TRUE AFTER ADDING PLAYER TURN!!!!!!!!!!!
	bool setupDone = false;
	unsigned int myIndex = 0;
	const unsigned int MAX_VAL = 20;
	unsigned int guessList[MAX_VAL];
	guessList[0] = 0;
	string playerName = "Player";
	string computerName = "Computer";
	char confirm;


	//Setup loop

	//Switch between players.
	while (round <= 10)
	{
		//Computer's takes turn.
		while (playerTurn == false)

		{
			myBannerTop();
			cout << "\t\t\t       Score Board\n";
			cout << "\t" << playerName << ": " << playerScore << "\t\t\t\t     " << computerName << ": " << computerScore;
			myBannerBottom(round);

			while (true)
			{

				cout << "My turn!\n\n";

				cout << "Enter a secret number between 1 and 100 for me to guess: ";
				cin >> secretNumber;

				if (secretNumber > 100 || secretNumber < 1)
				{
					cout << "\n\nError: Invalid Number!!!";
					sleep_for(seconds(2));
					cout << "\n\nResetting.";
					sleep_for(seconds(1));
					system("CLS");
					secretNumber = 0;
					continue;
				}

				else
				{
					system("CLS");
					break;
				}
			}

			while (true)

			{
				validGuess = true;

				if (tries == 0)
				{
					srand(static_cast<unsigned int> (time(0)));
					guess = (rand() % (100 - 90 + 1)) + 90;
					++tries;
				}
				else if (tries == 1)
				{
					srand(static_cast<unsigned int> (time(0)));
					guess = (rand() % (50 - 1 + 1)) + 1;
					++tries;
				}

				else
				{
					srand(static_cast<unsigned int> (time(0)));
					guess = (rand() % (hiVal - loVal + 1)) + loVal;
				}

				sleep_for(seconds(1));

				for (size_t i = 0; i < MAX_VAL; i++)
				{
					if (guessList[i] == guess)
					{
						validGuess = false;
						i = 0;
						break;
					}
				}


				if (validGuess != true)
				{
					continue;
				}

				else if (secretNumber > guess)
				{
					cout << "\n\n" << guess;
					cout << "\nToo low!";
					loVal = guess;
					++tries;
					storeGuess(MAX_VAL, guessList, myIndex, guess);

				}
				else if (secretNumber < guess)
				{
					cout << "\n\n" << guess;
					cout << "\nToo high!";
					hiVal = guess;
					++tries;
					storeGuess(MAX_VAL, guessList, myIndex, guess);

				}

				else
				{
					cout << "\n\n" << guess;
					cout << "\nI guessed it in " << tries << " attempts!\n";

					if (tries <= 15)
					{
						for (unsigned int i = 0; i < tries; i++)
						{
							points -= 10;
						}

						computerScore += points;
						round++;
					}

					else
					{
						points = 0;
					}

					cout << "\n\n************************************************************************\n";
					cout << "\t\t\tPoints earned: " << points;
					cout << "\n\t\t\tComputer's score: " << computerScore;
					cout << "\n************************************************************************\n\n";

					points = 150; //Resets points;
					system("PAUSE");
					system("CLS");
					cout << "\n\n************************************************************************\n";
					cout << "\t\t\t" << "Starting Round: " << round;
					cout << "\n************************************************************************\n";
					guess = 0;
					secretNumber = 0;
					tries = 0;
					myIndex = 0;

					//Clear array index values.
					for (size_t i = 0; i < MAX_VAL; i++)
					{
						guessList[i] = 0;
						break;
					}

					sleep_for(seconds(3));
					system("CLS");
					playerTurn = true;
					break;
				}

			}

		}
	}

	//Scoreboard and exit code.

	return 0;
}
> Not everything is done yet, as it is part of a larger project.
Well the first thing I suggest you do is move some of the 200 lines of code in main() out into other functions, so you can focus in detail as to what is supposed to be doing.

> srand(static_cast<unsigned int> (time(0)));
You do this ONCE at the start of main.

Doing this every time resets your rand() values.
In storeGuess(), you are changing index but as this is passed by value, not by ref that change isn't reflected back in the calling function.
Thanks for the replies!

I've moved most of the repeating code into functions already at the top.
In Visual Studio, I can shrink the loops in the tree anyway. I just removed the data for the other turn for clarity here. I re-wrote a stripped down version of the code to get a better idea of what is happening.

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <chrono>
#include <thread>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;

int main()
{
	unsigned int round = 1;
	unsigned int loVal = 1;
	unsigned int hiVal = 100;
	unsigned int secretNumber = 0;
	unsigned int guess =0 ;
	unsigned int lastGuess =0 ;
	unsigned int tries = 0;
	unsigned int points = 150;
	unsigned int computerScore = 0;


	srand(static_cast<unsigned int> (time(0)));


	while (round <= 10)
	{

		cout << "My turn!\n\n";

		cout << "Enter a secret number between 1 and 100 for me to guess: ";
		cin >> secretNumber;

		while (true)
		{
			sleep_for(seconds(0));

			//Generate random number
			guess = (rand() % (hiVal - loVal + 1)) + loVal;

			//Condition if guess is too low.
			if (guess < secretNumber)
			{
				cout << "\n\n" << guess;
				cout << "\nToo low!";
				loVal = guess;
				++tries;
			}
			//Condition if guess is too high.
			else if (guess > secretNumber)
			{
				cout << "\n\n" << guess;
				cout << "\nToo high!";
				hiVal = guess;
				++tries;
			}
			//Win condition.
			else if (guess == secretNumber)
			{
				cout << "\nI guessed it in " << tries << " attempts!\n";

				if (tries <= 15)
				{
					for (unsigned int i = 0; i < tries; i++)
					{
						points -= 10;
					}

					computerScore += points;
				}

				else
				{
					points = 0;
				}

				cout << "\n\n************************************************************************\n";
				cout << "\t\t\tPoints earned: " << points;
				cout << "\n\t\t\tComputer's score: " << computerScore;
				cout << "\n************************************************************************\n\n";
				round++;
				points = 150; //Resets points;
				system("PAUSE");
				system("CLS");
				cout << "\n\n************************************************************************\n";
				cout << "\t\t\t" << "Starting Round: " << round;
				cout << "\n************************************************************************\n";
				guess = 0;
				secretNumber = 0;
				tries = 0;
				sleep_for(seconds(3));
				system("CLS");
				break;
			}
			//If none of these conditions are filled, disregard guess and try again.
			else
			{
				continue;
			}
		}

	}

	return 0;
}



So, running this code, it again works for a while but then starts repeating the same number in an infinite loop. The extra entries in the previous code, just tell the computer to guess again if the number generated is the same as a previous one. However, what happens if I do that, is that it gets caught in an infinite loop of guessing the same exact number but I can't actually see what is going on.

The problem seems to be more with the srand() and rand() functions. :\

Any suggestions on using something better perhaps?
Hello MobMessenjah,

Add some blank lines to your code to make it more readable.

You could use the "<random>" header file and 1 of the RNGs there, but that may not solve the problem.

In the else if (guess == secretNumber) you missed 2 variables.
1
2
3
4
5
6
7
8
9
10
cout <<
    "\n\n************************************************************************\n"
    "\t\t\tStarting Round: " << round <<
    "\n************************************************************************\n";

guess = 0;
secretNumber = 0;
tries = 0;
hiVal = 100;
loVal = 1;

By not setting the last 2 variables they have their last value, so in the next round it does not work. Sometimes it may work if your new number is far enough away to change 1 of the values for "loval" or "hival".

Usually with this type of program the first computer guess would be 50 and the 2nd guess would be 1/2 of 50 either less than or greater than. In the range of 1 to 100 it should only take 7 tries for the computer to guess the number.

When I added the 2 variables and reset "loval" and "hival" it appears to work, although I have not run the program to its conclusion.

You do not need a "cout" statement for each line that you output. The example shows how you can use insertion operator (<<) to chain everything together into 1 statement. And if each line is only a quoted string it will be considered 1 string.

Also be careful using the tab (\t). At the beginning of a string it is not generally a problem. Any (\t) after some text may not space out the way that you want. I tend to like using std::string(20, ' '). This is the fill ctor of the string class. the first parameter is how many you want and the 2nd parameter if the character to fill with. Here it is a space, but you can use any character that will print on the screen. I find it better than using (\t).

You have defined several variables as "unsigned int" consider using uInt = unsigned int; and then in "main" uInt round{ 1 };. Also you do not need to use the " = 1". Just use the {}s. Empty the compiler will use the proper form of (0)zero needed or you can put anything between the {}s that you need including a quoted string for a "std::string". Much easier to type.

Andy
> Any suggestions on using something better perhaps?
Well the normal approach to guess the number is to pick the number half way between the known low and high bounds.

rand will get there, just not optimally.
Also rand by its very nature will sometimes give you the same answer as last time.

Your main() is still way too long.
If you can't see the first and last brace of a function on screen at the same time, then your ability to just look at it and know what it's doing falls rapidly.

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <chrono>
#include <thread>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;

unsigned int getSecret(unsigned int loVal, unsigned int hiVal) {
  cout << "Enter a secret number between "
        << loVal
        << " and "
        << hiVal
        << " for me to guess: ";
  int secretNumber;
  cin >> secretNumber;
  return secretNumber;
}

unsigned int playRound(unsigned int secretNumber, unsigned int loVal, unsigned int hiVal) {
  unsigned int tries = 0;
  unsigned int guess;
  do {
    tries++;
    guess = (rand() % (hiVal - loVal + 1)) + loVal;
    //Condition if guess is too low.
    if (guess < secretNumber) {
      cout << guess << " Too low!\n";
      loVal = guess;
    }
    //Condition if guess is too high.
    else if (guess > secretNumber) {
      cout << guess << " Too high!\n";
      hiVal = guess;
    }
    else if (guess == secretNumber) {
      cout << "\nI guessed it in " << tries << " attempts!\n";
    }
  } while ( guess != secretNumber );
  return tries;
}

int main() {
  unsigned int round = 1;
  unsigned int loVal = 1;
  unsigned int hiVal = 100;
  unsigned int computerScore = 0;

  srand(static_cast < unsigned int >(time(0)));

  while (round <= 10) {
    cout << "My turn!\n\n";
    unsigned int secretNumber = getSecret(loVal, hiVal);
    unsigned int tries = playRound(secretNumber, loVal, hiVal);
    unsigned int points = 150;

    if (tries <= 15) {
      points -= tries * 10;
      computerScore += points;
    }

    cout << "\n\n************************************************************************\n";
    cout << "\t\t\tPoints earned: " << points;
    cout << "\n\t\t\tComputer's score: " << computerScore;
    cout << "\n************************************************************************\n\n";

    round++;
    cout << "\n\n************************************************************************\n";
    cout << "\t\t\t" << "Starting Round: " << round;
    cout << "\n************************************************************************\n";
  }

  return 0;
}


$ ./a.out 
My turn!

Enter a secret number between 1 and 100 for me to guess: 42
51 Too high!
14 Too low!
25 Too low!
43 Too high!
31 Too low!
33 Too low!
43 Too high!
41 Too low!

I guessed it in 9 attempts!


************************************************************************
			Points earned: 60
			Computer's score: 60
************************************************************************



************************************************************************
			Starting Round: 2
************************************************************************
My turn!

Enter a secret number between 1 and 100 for me to guess: 66
3 Too low!
6 Too low!
46 Too low!
94 Too high!
91 Too high!
72 Too high!
64 Too low!
64 Too low!
64 Too low!

I guessed it in 10 attempts!

The second one is a good example.
Anyone playing the game would not have picked 3.
Nor would they pick the same number again.
You are using hiVal and loVal for two different purposes. At line 39, they are the high and low bounds for the generated number. At lines 46 & 54, they are the high and low bounds of what the number could be. Eventually they narrow down enough so that line 39 only ever generates one number.
If this is for an assignment, you might be doing it wrong. Normally when playing against the computer, the user picks a number but doesn't enter it into the program. After all, how do they know that the program doesn't cheat? Normally the program generates a guess and asks the user if it's high, low, or correct. If not correct, it makes another guess.

Picking a random number between the high and low values isn't a very good strategy. Can you think of a better strategy for the computer to use?
Topic archived. No new replies allowed.