The Problem
I have created a simple console reaction game.
But there is a bug that I can't solve even after reading many related posts and trying many different ways. The bug is that the user can get a nonsensical fast reaction time by prematurely react when he/she is expected to wait.
If the user cooperates, a part of the output could be: (not include // ...)
Press <Enter> when you are ready... // The user press enter and wait
Time's up!!! Press <ENTER> to react // The user press enter after seeing this line
time used to react: 0.311523 seconds
|
In contrast, if the user cheats, it would become:
Press <Enter> when you are ready... // The user press enter and "react" (press enter again)
Time's up!!! Press <ENTER> to react // The user does not need to react at all
time used to react: 0.0019532 seconds
|
The Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
default_random_engine generator;
generator.seed(chrono::system_clock::now().time_since_epoch().count());
uniform_int_distribution<int> distribution(3, 10);
typedef chrono::duration<double, ratio<1>> myseconds;
cout << "Press <Enter> when you are ready...";
getline(cin, string());
auto after = distribution(generator);
// randomly after 3 seconds to 10 seconds
auto timesup = chrono::system_clock::now() + chrono::seconds(after);
while (chrono::system_clock::now() < timesup) {
// wait...
// bug: the user can cheat by pressing enter while waiting
}
cout << "Time's up!!! Press <ENTER> to react";
getline(cin, string()); // if the user cheated, it is read immediately
auto timeUsed = chrono::duration_cast<myseconds>(chrono::system_clock::now() - timesup);
cout << "time used to react: " << timeUsed.count() << " seconds\n";
|
Full code :
https://gist.github.com/anonymous/5e29349389027c20d79c
What I Have Tried
1 2 3
|
cout << "Time's up!!! Press <ENTER> to react";
cin.ignore(numeric_limits<streamsize>::max());
getline(cin, string());
|
By using ignore, I want to discard all leftover in the input buffer such that what getline reads would be input after "time's up".
It fails because after discarding character in the input buffer (if any), ignore keep requiring input for it to ignore.
The only way I can escape from ignore is to input ctrl-z (the EOF char).
1 2 3
|
cout << "Time's up!!! Press <ENTER> to react";
cin.ignore(numeric_limits<streamsize>::max(), '\n');
getline(cin, string());
|
This fails again because it assume the user will cheat. It require the user to discard one line before he/she reacts. There is no different from placing two getline. And still, the user can cheat by pressing enter multiple times.
1 2 3
|
cout << "Time's up!!! Press <ENTER> to react";
cin.sync();
getline(cin, string());
|
This fails but this time I do not know the reason. Actually, I do not know much about sync. I use it because of the example shown in the reference.
So...
I can't think of other ways now.
What can I do to remove the bug?
And what happens in the buffer when I call sync?