“时间飞逝。由你来担任导航员”。很多时候,我们未能做出正确的决定是因为我们没有足够快地抓住提供给我们的机会。当开始学习编程时,我们不太担心我们的创作时间。不幸的是,当我们超越专业环境时,我们不仅面临多重限制,而且还面临各种截止日期,这是一项艰巨的要求。在真正的高端项目中,10 秒的延迟可能会造成代价高昂的损失,这就是为什么大多数程序的宽限期延迟低至毫秒的原因。
现在在我们的日常生活中,即使我们玩电子游戏,能够做我们想做的事情归结为一个时间游戏:如果你在处理一个时间敏感的项目时不强迫自己,你最终可能会加班.如果您是一名游戏玩家,您可能会发现自己在玩射击游戏并因为时机不对而输掉了一场比赛,因为您决定在敌人即将到来时重新加载。
如果我们想进行深思熟虑和快速的计划,我们还应该训练自己能够工作并对遇到的任何事情做出快速反应。我将在这里展示的简单游戏将帮助您练习快速计时。这个程序的子部分可以用于许多其他事情,所以不要害怕“弗兰肯斯坦”你的程序来创造一个杰作。
我们首先从头文件开始:这个文件用于设置我们将要使用的类。
#ifndef HEADER_H
#define HEADER_H
#include <mutex>
#include <chrono>
#include <future>
using namespace std;
class MyClass
{
bool bKeepRunning;
std::mutex mtx_t;
std::condition_variable cv_t;
vector<double> results;
public:
MyClass();
string createCounter();
double getAvrg();
void pauseThread(int time);
string createPrompt();
bool running();
};
#endif
类文件
然后我们转到 cpp 文件,它实际上是整个程序的花里胡哨。 当然,我们从构造函数方法开始,默认情况下将我们的布尔变量初始化为 true。
#include "MyClass.h"
#include <iostream>
#include <chrono>
#include <string>
#include <thread>
using namespace std;
MyClass::MyClass()
{
bKeepRunning = true;
}
bool MyClass::running() {
return bKeepRunning;
}
string MyClass::createCounter()
{
int counter = 0;
bKeepRunning = true;
string count;
while (running())
{
counter ;
count = "[" to_string(counter) "]";
for (int i = 0; i < count.size(); i ) {
cout << count[i];
std::this_thread::sleep_for(chrono::milliseconds(100));
}
cout << endl;
this->pauseThread(1);//Wait for x seconds
if (counter == 3) {
bKeepRunning = false;
}
}
return createPrompt();
}
void MyClass::pauseThread(int time)
{
std::unique_lock<std::mutex> lck_t(mtx_t);
cv_t.wait_for(lck_t, chrono::seconds(time));
}
string MyClass::createPrompt() {
string line;
cout << "NOW! "; // Type a number and press enter
chrono::steady_clock::time_point begin = chrono::steady_clock::now();
getline(cin, line);
chrono::steady_clock::time_point end = chrono::steady_clock::now();
double R = double(chrono::duration_cast<chrono::milliseconds>(end - begin).count()) / 1000.0;
cout << "Time difference = " << R << " [s]" << std::endl;
results.push_back(R);
return line;
}
double MyClass::getAvrg() {
double r =0;
for (int i = 0; i < results.size(); i ) {
r =results.at(i);
}
r /= results.size();
return r;
}
我们工具库中的下一个方法当然是 createCounter,我们将在其中充分利用布尔变量。此方法的功能是创建一个倒计时计数器,以在用户必须按 Enter 时发出信号。不仅如此,而且为了增加一些天赋,倒计时显示就像正在输入一样。时间就是一切,我们在运行某些代码行之前等待多长时间会让事情变得更加有趣。此方法包含 2 个不同的函数,用于减慢计时速度:sleep_for 和 pauseThread。
现在可以对两条线都使用其中之一,但我决定以这种方式向您展示可能性,我们在这里创建了 pauseThread 方法,它足以减慢速度(您可以在如果您需要进一步的解释,请发表评论)。 count 语句被组合成一个字符串,然后每个字符一个一个地打印出来,中间有一定的延迟,以便给人一种打字慢的错觉。您当然可以个性化此语句,但如果字符串太长,您将必须相应地管理时间。计数器与计数变量结合使用,不仅可以打印计时器,还可以管理所述计时器的持续时间。在此方法结束时,是调用 createPrompt 方法的正确时机。
此方法显示消息,通知用户现在是尽快按下回车键的正确时机。然后,我们计算了从消息显示到用户按下键所经过的时间。
然后我们将转到主 cpp 文件。这里是我们创建用于运行游戏的类对象的地方。在这个文件中,我们将以一种非常特殊的方式运行类方法:我们将使用 async 函数将方法作为线程启动。现在这样做并不是构建这个游戏的唯一方式,而是我选择的方式,让时间恰到好处,让所有线程等待轮到它们,总共运行5个线程,并提示用户按下回车键 5 次。在循环的最后,我们将平均我们存储的所有时间。
#include <iostream>
#include <sstream>
#include <string>
#include <future> // std::async, std::future
#include <chrono> // std::chrono::milliseconds
#include "MyClass.h"
using namespace std;
int main(int argc, char* argv[])
{
MyClass app;
future<string> fut;
string tmp;
int counter = 0;
do {
counter ;
fut = async(std::launch::async, &MyClass::createCounter, &app);
fut.wait();
tmp = fut.get();
cout << endl;
} while (counter <=5);
cout << "average is " << app.getAvrg() << endl;
}
最后的想法
现在,这个程序在本质上是简单的,但正是这种简单性为改进提供了机会。 通过一些额外的更改,您可以让程序提示用户按下特定的字母键,甚至输入特定的单词。 你甚至可以创建一个计算平均打字速度的类方法。 虽然令人印象深刻,但该程序有一些错误,例如如果您在提示出现之前多次按 enter 键,则会发生意外行为。
结论
确保一切都遵循正确的顺序是编程的一个组成部分:从一个简单的循环到一个完整的银行应用程序。 现在一路走来都会犯错误,这是不可否认的。 但是把这些错误当作学习机会并成长。
很高兴为大家构建这个程序。 让我们继续学习,共同创造伟大的事物。 在任何询问下方评论,不要忘记关注。
,