cin.ignore()首次循环未触发输入延迟的问题求助
问题描述
我正在和朋友复刻移动端饮酒游戏Picolo——原版APP的问题太腻,想自定义问题。程序预期流程是:先提示输入玩家数量,随机打乱问题顺序,逐个展示问题。我用cin.ignore()等待用户按回车后显示下一题,但除首次循环外其余都正常:输入玩家姓名后,前两个问题会直接一起打印,之后才恢复正常。
源代码
#include<iostream> using std::cin; using std::cout; using std::endl; #include<algorithm> using std::random_shuffle; #include<fstream> using std::ifstream; #include<cstdlib> #include<string> using std::string; #include<time.h> const int numQuestions = 19; int vir6rounds; bool activeVir6 = false; int v6counter = 0; void getQuestion(int questionNumber, string players[], int numPlayers); int getRandom(); int main() { srand(time(0)); // 创建玩家姓名数组 cout << "Enter \"quit\" to end game" << endl; cout << "How many players?" << endl; int numPlayers; cin >> numPlayers; cout << "Enter players' names: " << endl; string players[numPlayers]; for (int i = 0; i < numPlayers; i++) cin >> players[i]; bool loop = true; int qArray[numQuestions]; // 填充问题索引数组 for (int i = 0; i < numQuestions; i++) { qArray[i] = i; } while (loop) { // 每次循环重新打乱问题顺序 random_shuffle(qArray, qArray + numQuestions); for (int i = 0; i < numQuestions; i++) { // 随机选择3个玩家 random_shuffle(players, players + numPlayers); getQuestion(qArray[i], players, numPlayers); cin.ignore(); // 问题出在这里 } cout << "Game over; press enter to play again" << endl; cin.ignore(); } } void getQuestion(int questionNumber, string players[], int numPlayers) { if (activeVir6 == true) { v6counter++; if (v6counter == vir6rounds) { cout << "Pong loser can speak again." << endl; cin.ignore(); activeVir6 = false; v6counter = 0; } } string player1 = players[0]; string player2 = players[1]; string player3 = players[2]; switch (questionNumber) { case 0: cout << "Going around, Play rock paper scissors with the player to your left." << endl; cout << "Losers take two drinks." << endl; break; case 1: cout << player1 << ", who would win in a fight? " << player2 << " or " << player3 << "?"; cin.ignore(); cout << "Loser takes two drinks." << endl;; break; case 2: cout << player1 << " chooses the next song" << endl; break; case 3: cout << "Whoever took a shower the least recently has to take a drink" << endl; break; case 4: cout << player1 << ", take as many penalties as you want."; cin.ignore(); cout << "However many you took, " << player2 << " has to take double." << endl; break; case 5: cout << "Everyone switch drinks to the left" << endl; break; case 6: cout << "virus: " << player1 << " versus " << player2 << " in pong." << endl; cout << "loser can't speak until otherwise" << endl; activeVir6 = true; vir6rounds = getRandom(); break; case 7: cout << player1 << " take as many penalties as the youngest players age.\nIf you're the youngest, everyone else take 2." << endl; break; case 8: cout << player1 << ", buy " << player2 << " a red bull or take 15 penalties" << endl; break; case 9: cout << player1 << ", let " << player2 << " look through your snap memories or take 8 penalties" << endl; break; case 10: cout << player1 << " has to say yes to " << player2 << " for 5 minutes or take 8 penalties" << endl; break; case 11: cout << player1 << ", show off ur best cartwheel" << endl; break; case 12: cout << player1 << ", change clothes with " << player2 << " or they pick how many penalties you take" << endl; break; case 13: cout << player1 << ", pick someone new to go on aux or they take 5 penalties" << endl; break; case 14: cout << player1 << ", cook " << player2 << " a meal or take 9 penalties" << endl; break; case 15: cout << player1 << ", pick two people to shotgun" << endl; break; case 16: cout << player1 << ", let " << player2 << " paint ur nails or take 10 penalties" << endl; break; case 17: cout << player1 << ", every time you talk to " << player2 << " take 3 penalties until otherwise" << endl; break; case 18: cout << player1 << ", kill yourself or take a penalty." << endl; break; default: cout << "question has not been defined yet" << endl; } return; }
示例输入输出
/* Enter "quit" to end game How many players? 7 Enter players' names: john kevin mark stacy helen jenna dylan helen, buy john a red bull or take 15 penalties dylan chooses the next song mark, let stacy look through your snap memories or take 8 penalties helen has to say yes to mark for 5 minutes or take 8 penalties Everyone switch drinks to the left */
解决方案
问题根源
用cin >>读取玩家数量和姓名时,输入结束后的换行符会留在输入缓冲区里。第一次执行cin.ignore()时,实际是忽略了这个残留的换行符,没有等待用户输入,直接进入下一次循环,导致两个问题连续打印。
修复步骤
- 清空输入缓冲区残留的换行符:
首先在代码开头包含<limits>头文件:
然后在输入完所有玩家姓名的循环后,添加代码清空缓冲区:#include <limits>cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); - 统一处理等待逻辑:代码里
getQuestion函数内部也有cin.ignore()(比如case1、case4),这些会和主循环的等待重复,导致需要按两次回车。可以二选一:- 去掉主循环里的
cin.ignore(),只保留函数内的等待逻辑; - 去掉函数内的
cin.ignore(),统一用主循环的等待。
- 去掉主循环里的
新手友好小建议
- 避免使用变长数组(
string players[numPlayers];),C++标准不支持这种写法,换成std::vector<std::string>更安全:#include <vector> // ... std::vector<std::string> players(numPlayers); - 你声明了
getRandom()函数但没实现,运行会报错,补一个简单实现:int getRandom() { return rand() % 5 + 1; // 生成1-5的随机数,可按需调整范围 }
内容的提问来源于stack exchange,提问作者scumjag
相关产品推荐
相关产品推荐

