0

我正在阅读 Bjarne Stroustrup 的“Programming Principles and Practice Using 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。

有什么线索可以让我走吗?我想我已经很接近了,但会感谢一些帮助。

谢谢,

马特

4

3 回答 3

1
 double range = ( upperBound - lowerBound ) / 2;

这条线会给你带来问题,因为所有的操作数都int因此被评估为 int 而不是double. 如果这不是故意的,请更改2->2.0以解决此问题。

int rangeDelta = range - (int)range;

你也确定你不想要double rangeDelta

于 2013-01-06T11:09:50.293 回答
0

我认为您的代码中仍然存在问题(即使之前发出信号的错误已修复):应该清楚的是,上限和下限都包含在剩余的可能数字中,这从您的代码中不清楚:在第一个问题,如果我回答'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 传递,而是使用整数除法和模数来处理它们(并且不要使用 double 来表示整数)。

希望能帮助到你!

于 2013-01-09T13:11:04.130 回答
0

您也可以使用数组来实现这一点,第 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";
于 2014-09-27T20:02:40.823 回答