Я изучаю «Принципы и практика программирования с использованием C ++» Бьярна Страуструпа. Я в главе 4, упражнение 4.
Упражнение выглядит следующим образом:
Напишите программу для игры в угадайку чисел. Пользователь думает о числе от 1 до 100, и ваша программа задает вопросы, чтобы выяснить, что это за число (например, «Число, о котором вы думаете, меньше 50?»). Ваша программа должна быть в состоянии определить номер после того, как задала не более семи вопросов. Подсказка: используйте < а также <= операторы и конструкции if-else.
Теперь это здорово, и мне удалось это реализовать.
Я думал, что попробую подтолкнуть себя и попытаться реализовать это, используя цикл и каждый раз корректируя нижние или верхние границы.
Вот мой код:
#include "std_lib_facilities.h"
int main( ){
int count = 0;
int lowerBound = 0;
int upperBound = 100;
string userInput = "";
while ( lowerBound != upperBound ){
// Increment count
++count;
int halfRange = 0;
// Make halfRange a while number, round up if any decimal portion.
double range = ( upperBound - lowerBound ) / 2;
int rangeDelta = range - (int)range;
if ( rangeDelta != 0 )
halfRange = (int)range + 1;
else
halfRange = range;
cout << count <<": Is your number between " << lowerBound << " and " << lowerBound + halfRange << "? ";
cin >> userInput;
// Reset the bounds
if ( userInput == "y" || userInput == "Y" )
upperBound -= halfRange;
else if ( userInput == "n" || userInput == "n" )
lowerBound += halfRange;
else {
--count;
cout << "Error! Answer could not be understood.";
}
}
cout << "lowerBound: " << lowerBound << ", upperBound: " << upperBound << "\n\n";
cout << "Your number is: " << lowerBound << "\n";
return 0;
}
Эта проблема? Ну, это происходит, когда он достигает чисел, где есть десятичная часть, и использует целочисленное деление, которое выбрасывает десятичную часть. Если вы используете число 48, программа угадывает до 47 и 47.
Какие-нибудь подсказки, чтобы заставить меня идти? Я думаю, что я довольно близко, но буду признателен за некоторую помощь.
Спасибо,
Matt
Я думаю, что в вашем коде все еще есть проблема (даже если исправленные ошибки исправлены): должно быть ясно, что верхняя и нижняя границы включены в возможных оставшихся числах, и это не ясно из вашего кода: на первом вопросе, если я отвечу ‘y’, новый интервал будет [0,50], а если я отвечу ‘n’, новый интервал будет [50,100], что не так! 50 не должны быть включены во второй интервал.
Чтобы это исправить, вы должны изменить обновление своих границ на что-то вроде:
if ( userInput == "y" || userInput == "Y" )
upperBound = lowerBound + halfRange;
else if ( userInput == "n" || userInput == "n" )
lowerBound = lowerBound + halfRange + 1;
Теперь с последним вопросом все еще остается проблема, которая остается неизменной навсегда. Проблема в том, что когда range = 1, у вас также есть halfrange = 1, и вопрос остается прежним.
Чтобы решить эту проблему, вы должны округлить вниз спектр. Просто определите это так:
int halfRange = ( upperBound - lowerBound ) / 2;
и теперь ваш код должен работать. Вот код, который я бы использовал для цикла while:
while ( lowerBound != upperBound ){
// Increment count
++count;
int halfRange = ( upperBound - lowerBound ) / 2;
int midpoint = lowerBound + halfRange;
cout << count <<": Is your number between " << lowerBound << " and " << midpoint << "? (both included) ";
cin >> userInput;
// Reset the bounds
if ( userInput == "y" || userInput == "Y" )
upperBound = midpoint;
else if ( userInput == "n" || userInput == "n" )
lowerBound = midpoint + 1;
else {
--count;
cout << "Error! Answer could not be understood.";
}
}
Обратите внимание, что теперь мы используем только целые числа, а не двойные! Если вы используете целые числа, старайтесь избегать прохода через двойные числа, а для работы с ними используйте довольно целочисленное деление и по модулю (и не используйте двойные для представления целых чисел).
Надеюсь, поможет!
double range = ( upperBound - lowerBound ) / 2;
Эта строка доставит вам проблемы, так как все операнды int
таким образом, он оценивается как int вместо double
, Если это не является преднамеренным, измените 2
-> 2.0
чтобы исправить эту проблему.
int rangeDelta = range - (int)range;
Также вы уверены, что не хотите double rangeDelta
Вы также можете достичь этого с помощью массивов, что объясняется в главе 4.
int min = 1; // range for our guessing game
int max = 10;
int guess = 0; // value to keeep track of guessing
char choice = ' ';
vector<int>v;
// put all our values into a vector
for(int i = min; i <= max; i++) {
v.push_back(i);
}while (v.size() != 1) { // if there is only one value left, no guessing needed. jump out of loop
guess = v[v.size()/2]; // find median
cout << "\nIs your number less than " << guess << "? (y/n)\n"; // ask user for hint
cin >> choice;
if(choice == 'y') { //y: value is below median, pop values of median and above out of our range of values
for(int i = 0; i < v.size(); i++)
v.pop_back();
}
else { // n: value is median or above. erase the lower values out of our range of values
for(int i = 0; i < v.size(); i++){
v.erase(v.begin());
}
}
} // end while
cout << "The number is " << v[0] << "\n";