在一本关于游戏编程的书中,我有以下练习。
用户会想到一个数字,然后程序会尝试猜测它,用户会提供反馈。
我解决这个问题的方法只是允许CPU在高和低之间选择一个随机数(基于以前的猜测)而不是快速查找数字(猜测高低之间的中间数字) )。所以它可以工作,但是有一个错误,即CPU不止一次地猜出相同的数字。我哪里出错了,如何解决?
enum statuses {NEUTRAL, HIGH, LOW};
int status = NEUTRAL;
int cpuguess, high = 100, low = 1;
char winner, highorlow, playAgain;
do {
cout << "Guess My Number" << endl << endl;
cout << "Press Enter to Play !" << endl;
cin.ignore();
cin.get();
do {
cpuguess = getGuess(status, high, low);
cout << "Is your guess " << cpuguess << " ?" << endl;
cout << "(y/n)";
cin >> winner;
winner = toupper(winner);
if(winner == 'N')
{
WrongInputHL:
cout << "Too HIGH or Too LOW ? O_O" << endl;
cout << "(h/l)";
cin >> highorlow;
highorlow = toupper(highorlow);
if(highorlow == 'H')
{
status = HIGH;
high = cpuguess;
}
else if(highorlow == 'L')
{
status = LOW;
low = cpuguess;
}
else
{
goto WrongInputHL;
}
}
} while (winner == 'N');
cout << "I won ! :D" << endl << endl;
cout << "Do you want to play again ?" << endl;
cout << "(y/n)" << endl;
cin >> playAgain;
playAgain = toupper(playAgain);
}while(playAgain == 'Y');
欢迎所有其他改进建议。
答案 0 :(得分:1)
问题似乎在本节
{
WrongInputHL:
cout << "Too HIGH or Too LOW ? O_O" << endl;
cout << "(h/l)";
cin >> highorlow;
highorlow = toupper(highorlow);
if(highorlow == 'H')
{
status = HIGH;
high = cpuguess;
}
else if(highorlow == 'L')
{
status = LOW;
low = cpuguess;
}
您的算法的基础似乎是二进制搜索,但请注意如何设置高端和低端。高端可能会重复,因为它可能是可选择的。
试试这个:
WrongInputHL:
cout << "Too HIGH or Too LOW ? O_O" << endl;
cout << "(h/l)";
cin >> highorlow;
highorlow = toupper(highorlow);
if(highorlow == 'H')
{
status = HIGH;
high = cpuguess-1;
}
else if(highorlow == 'L')
{
status = LOW;
low = cpuguess+1;
}
这样,如果数字太高,则新范围变为(低,cpuguess-1) 如果它太低就会变成(cpuguess + 1,high) 这将忽略之前选择的计算机编号。
希望它有所帮助。 :)
答案 1 :(得分:0)
我认为其他人会帮助你了解程序的逻辑,所以我会帮助你完成你的结构;也就是说,你如何逻辑地概述了该计划以及我认为你可以做得更好的方式。请注意,我实际上并没有在这里运行任何代码 - 我目前没有这样做的环境。
我开始通过自动格式化代码并将其从do-while循环迁移到简单的while循环。另外,我将变量声明更接近于它们的使用位置。在现实世界中,一些编码标准禁止最后一步,但我觉得它提高了程序的可读性,并且它可以帮助你理解我的逻辑。
enum statuses { NEUTRAL, HIGH, LOW };
int status = NEUTRAL;
char input;
int cpuguess, high = 100, low = 1;
bool playing = true; // use booleans to represent true/false state, rather than characters
while (playing) { // "playing" closer to declaration = arguably easier to read & find purpose
cout << "Guess My Number" << endl << endl;
cout << "Press Enter to Play !" << endl;
cin.ignore();
cin.get();
bool gameWon = false;
while (!gameWon) {
cpuguess = getGuess(status, high, low);
cout << "Is your guess " << cpuguess << " ?" << endl;
cout << "(y/n)";
cin >> input;
gameWon = toupper(input) == 'Y';
if (!gameWon)
{
status = NEUTRAL;
while (status == NEUTRAL) {
cout << "Too HIGH or Too LOW ? O_O" << endl;
cout << "(h/l)";
cin >> input;
input = toupper(input);
if (input == 'H') {
status = HIGH;
high = cpuguess;
} else if (input == 'L') {
status = LOW;
low = cpuguess;
}
}
}
}
cout << "I won ! :D" << endl << endl;
cout << "Do you want to play again ?" << endl;
cout << "(y/n)" << endl;
cin >> input;
playing = toupper(input) == 'Y';
}
-
在您的计划中,您经常希望用户给出两个答案中的一个。实际上,我们看到类似于
的代码cout << "Is your guess " << cpuguess << " ?" << endl;
cout << "(y/n)";
cin >> input;
gameWon = toupper(input) == 'Y';
三次!也许,我们可以引入一个新函数,比如getAnswer,它会提出一个问题和两个可能的答案(即'y'和'n')并返回用户的答案?此外,我选择在打印大写Y / N选项时保持一致,并将'\ 0'视为用户永远不会输入的值。因此,如果option1或option2为小写,则程序将不再正常运行。有很多方法可以解决这个问题,例如在getAnswer函数的开头验证option1和option2 isupper(c),尽管我还没有这样做。
char getAnswer(const char * question, const char option1, const char option2);
void main() { // or whatever entry-point signature you've used
enum statuses { NEUTRAL, HIGH, LOW };
int status = NEUTRAL;
char input;
int cpuguess, high = 100, low = 1;
bool playing = true; // use booleans to represent true/false state, rather than characters
while (playing) { // "playing" closer to declaration = arguably easier to read & find purpose
cout << "Guess My Number" << endl << endl;
cout << "Press Enter to Play !" << endl;
cin.ignore();
cin.get();
bool gameWon = false;
while (!gameWon) {
cpuguess = getGuess(status, high, low);
stringstream ss;
ss << "Is your guess " << cpuguess << " ?";
gameWon = getAnswer(ss.c_str(), 'Y', 'N') == 'Y';
if (!gameWon) {
status = getAnswer("Too HIGH or Too LOW ? O_O", 'H', 'L') == 'H' ? HIGH : LOW;
if (status == HIGH)
high = cpuguess;
else
low = cpuguess;
}
}
cout << "I won ! :D" << endl << endl;
playing = getAnswer("Do you want to play again?", 'Y', 'N') == 'Y';
}
}
char getAnswer(const char * question, const char option1, const char option2) {
char response = '\0';
while (response != option1 && response != option2) {
cout << question << endl;
cout << "(" << option1 << "/" << option2 << ")" << endl;
cin >> response;
response = toupper(response);
}
return response;
}
太棒了,我们的代码看起来更清晰,但是我们仍然没有将代码分解成逻辑部分,所以让我们尝试这样做。请注意,我已将部分控制台输出移至外部while循环之外,并将“是您的猜测”更改为“是您的数字”。以前,如果用户声明他们想要再玩一次,他们就必须在那之后按回车,这很烦人!
enum class GuessStatus { NEUTRAL, HIGH, LOW }; // I elected to use c++11's 'enum class'
// these are called forward declarations
void runIntroduction();
void playGame();
// I elected to use const char * and const char here. They weren't necessary, though.
char getAnswer(const char * question, const char option1, const char option2);
void main() { // or whatever entry-point signature you've used
runIntroduction();
bool playing = true; // use booleans to represent true/false state, rather than characters
while (playing) { // "playing" closer to declaration = arguably easier to read & find purpose
playGame();
playing = getAnswer("Do you want to play again?", 'Y', 'N') == 'Y';
}
}
void runIntroduction() {
cout << "Guess My Number" << endl << endl;
cout << "Press Enter to Play !" << endl;
cin.ignore();
cin.get();
}
void playGame () {
int guessHigh = 100, guessLow = 1;
GuessStatus status = GuessStatus::NEUTRAL; // I'd suggest having GuessState::INITIAL = NEUTRAL to improve readability. Either that, or throwing in a comment to describe why you use NEUTRAL.
bool gameWon = false;
while (!gameWon) {
int cpuguess = getGuess(status, high, low);
stringstream ss;
ss << "Is your number " << cpuguess << " ?";
gameWon = getAnswer(ss.c_str(), 'Y', 'N') == 'Y';
if (!gameWon) {
status = getAnswer("Too HIGH or Too LOW ? O_O", 'H', 'L') == 'H' ? GameStatus::HIGH : GameStatus::LOW;
if (status == GameStatus::HIGH)
high = cpuguess;
else // status == GameStatus::LOW
low = cpuguess;
}
}
cout << "I won ! :D" << endl << endl;
}
char getAnswer(const char * question, const char option1, const char option2) {
char response = '\0';
while (response != option1 && response != option2) {
cout << question << endl;
cout << "(" << option1 << "/" << option2 << ")" << endl;
cin >> response;
response = toupper(response);
}
return response;
}
就这一切而言,如果有什么令人困惑的话,请随时提问。