Question from bjarne stroustrup programming principles and practice

Hi, I have been trying to figure out a question from the programming principles book since yesterday and I can not figure out the solution.

The question is :
Write a program to play a numbers guessing game. The user thinks of a number between 1 and 100 and your program asks questions to figure out what the number is. Your program should be able to identify the number after asking no more than seven questions. Hint : Use the < and <= operators and the if-else construct.


I have been trying to solve this by having two int variables one set to 0 and one set to 100, and then ask the user if the number is greater than 50, if so set the 0 variable to 50, if not, set the 100 variable to 50, and repeat this, halving the value each time, in hopes that eventually one variable will be answer - 1, and the other variable will be answer + 1, so then the number is known. However this takes a lot more than 7 questions. Ive have tried it numerous different ways, but in no way can get it to solve is 7 questions or less.

I have seen solutions using while loops etc, but I would like to stick to what the book is saying and use the else if statements.

If anyone possibly has a solution for this issue, or some tips on what I should do it would be appreciated. I would have liked to have worked through this issue myself, but after spending a day on it, I kind of just want to know how it is done.

This is sort of what I have been trying, I have deleted and retried numerous times, so not got a lot of code in this part, but it shows what i was going for
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int first = 0;
	int end = 100;
	int temp;
	char a;

	cout << "Is your number greater than 50\n";
	if (a == 'y')															//Number between 50 and 100, first set to 50
	{
		first = end / 2;													//First = 50
		cout << "Is your number greater than " << (first + end) / 2;		// Is the number greater than 75
		if (a == 'y')
		{
			first = (first + end) / 2;										// First = 75
			cout << "Is your number greater than " << (first + end) / 2; // Is the number greater than 88
		}
		else
		{
			end = first + (first / 2);										// End = 75
		}
	}
	else																	//Number between 0 and 50, end set to 50
	{
		end = end / 2;														// End = 50
	}
The point of using a while loop is to keep from writing so many else-if statements! You'll still need them even when looping.


I can see you were trying to be logical, but you've got to re-examine your approach. The way you change the variables "first" and "end" are different make it impossible to guess certain numbers since you'll skip over several numbers through that division. Look at this code:

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
int main()
{
	int high = 100;
	int low = 0;
	bool win = false;
	int guess;
	int cguess = 50; //Opening Guess
	char a;

	std::cout << "enter Number between 0 and 100 to Guess: ";
	std::cin >> guess; //Ask for the number so we can know when it has been guessed

	for(int i = 0; !win; i++) //To loop through and also keep track of our tries
	{
		if (cguess == guess) //Check when it has guessed correctly
		{
			win = true;
			std::cout << "Your number was: " << cguess << " And it Took " << i << " Tries to Guess it!\n\n";
			break;
		}

		std::cout << "Is " << cguess << " too High(y/n): ";
		std::cin >> a;
		if (a == 'y')
		{
			high = cguess; //If the guess is too high, make that guess our maximum
		}
		else
		{
			low = cguess; //If the guess is too low, make that guess our minimum
		}
                cguess = (low + high) / 2; //Guess should be between the highest and lowest values
	}
}



Notice how we box in the possibilities and our guess is always the number between our highest and lowest values. If too high, chop off anything higher than it. If too low, chop off anything lower than it. Then take the in-between number to guess. Repeat until you've got it.
Last edited on
Hello kmce,

Your first task is to understand how the game works. Based on your code I do not feel that you do.

Lets say the number to find is 42. The computers first guess would be 50 which you tell it that it is to high. The next guess would be half of 50 or 25 which you tell it that it is to low. The next guess would be 37 which you say is to low. Next is half way between 37 and 50 or 43 which you say is to high. Next is half way between 37 an 43 or 40 which is to low. The next guess is half way between 40 and 43 or 41 which is to low. the last guess is between 41 and 43 or 42 which is correct.

If I counted right that would be seven tries.

Understanding how the game works you can write code for the computer guessing the number or the user guessing the number.

Your program is a good start and zapshe has one solution that can help.

Starting with your code:

First post the whole program. As is there is no way to test you code without guessing at the header files that should be there.

The first variables are usable, but looking at zapshe's code "low" and "high" are a better choice and easier to understand.

"temp" is never used and you can delete it.

For your "char" avoid using a single letter variable. Give it a name that means something. The best choice is a noun that describes what it is or what it does. I would consider something like "lowHigh" because that is what you are checking for.

Line 6 is a prompt for the user to enter something. I would write the line as cout << "\n Is your number greater than 50: ";. The "\n " at the beginning is what I have come to use most often. Ending the string with the ": " keeps the input on the same line and tends to make more sense this way.

Between lines (6) and (7) you missed the "std::cin" to get any type of input from the user.

Line 7 is checking an uninitialized variable which has a garbage value against "y". It would be a very rare occasion for this to be a true statement.

Another thing you are working on is that the user can follow directions. Do not count on this.

There are three options that you can use:
1
2
3
4
5
6
7
8
std::cin>>lowHigh;
lowHigh = std::tolower(lowHigh);  // <--- Needs header file <cctype>

if (std::tolower(lowHigh) == 'y')

or

if (lowHigh == 'y' || lowHigh == 'Y')

Any one would work. For the "std::tolower()" or the opposite "std::toupper()" you will need the header file "<cctype>". If you are not familiar with it have a look at http://www.cplusplus.com/reference/cctype/ There is a nice table showing the ascii codes from 0 to 255 or 0x00 to 0x7F and what functions can be used with each character in the table along with all the functions that are available.

That said what you are really looking for is "l" (low) or "h" (high) not "y" for yes.

I do agree with zapshe you do need a loop. This could be a for loop, a while loop or even a do/while loop. All can work. For a for loop I would consider this
for (tries = 0; !win && tries < 7; tries++)

Since the point is that the number can be guessed in 7 tries or less the for loop needs to account for this. Also by defining "tries" outside of the for loop yo can use the final value after the for loop if yo need it. I am thing something like:
std::cout << "\n The computer took " << tries << " to guess the number"<< std::endl;. You could even use an if/else to print a different message should "tries" exceed seven.

I leave the rest to see what you come up with.

Hope that helps,

Andy
Hi, Just wanted to say thanks for the replies. I managed to solve the problem using both of your inputs, so thank you for that. The first solution I came up with was

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
#include "std_lib_facilities.h"

using namespace std;

int main()
{
	int min = 0;
	int max = 100;
	int temp = 0;
	int guess;
	char ansInput = 0;

	cout << "\n Enter a number between 1 and 100: ";
	cin >> guess;



	while (temp != guess)
	{
		temp = (min + max) / 2;
		cout << "\n Is your number larger than: " << temp;
		cin >> ansInput;
		if (ansInput == 'y')
		{
			min = temp;
		}
		else if (ansInput == 'n')
		{
			max = temp;
		}
	}
	cout << "\n Your number is: " << temp;

	system("pause");
	return 0;
}


But I decided to try again, and not have the computer know the number the user input. So using some help from another solution i found online, I managed to come up with this

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 "std_lib_facilities.h"

using namespace std;

int main()
{
	int min = 0;
	int max = 100;
	int temp = 0;
	int guess;
	char ansInput = 0;

	cout << "\n Enter a number between 1 and 100: ";
	while (min < max)
	{
		temp = (min + max) / 2;
		cout << "\n Is your number larger than: " << temp << " ";
		cin >> ansInput;
		if (ansInput == 'y')
		{
			min = temp + 1;
		}
		else if (ansInput == 'n')
		{
			max = temp;
		}
	}
	cout << "\n Your number is: " << min;

	system("pause");
	return 0;
}
But I decided to try again, and not have the computer know the number the user input.

The only reason that was there was so that you wouldn't have to confirm with the user whether or not it was the correct number.


The issue with your new program is that it WILL guess your number but ONLY after skipping over it once or twice. To avoid that, you should let the user also have the option to convey when their number was guessed. I avoided this all together by simply always checking if the number was the same. It's not like the computer is cheating off it!
Topic archived. No new replies allowed.