24点游戏
一、题目描述
用户初始生命值为一给定值(比如3),初始分数为0。随机生成4个代表扑克牌牌面的数字或字母,由用户输入包含这4个数字或字母的运算表达式(可包含括号),如果表达式计算结果为24则代表用户赢了此局。
二、问题分析
题目的难点有两个,一个是对用户输入的带括号的运算式进行计算,一个是计时器控制输入的进行。
三、算法设计
四、代码实现
头文件:
#pragma once
#include<iostream>
#include <stdlib.h>
#include<time.h>
#include<string>
#include<thread>
#include <windows.h>
using namespace std;
class Game {
public:
int score = 0;
int hp = 3;
int a[4];
string s[4];
void Game_Start();
void Generate();
int culmulate(string);
void control();
int flag = 2;
private:
thread t1;
};
主函数:
int main()
{
Game g;
thread t1(&Game::control, &g);//创建线程
while (g.hp > 0)
{
g.flag = 2;
t1.joinable();//线程开始
g.Game_Start();
g.flag = 1;//通过flag这个变量控制计时器线程的运行
}
system("pause");
}
函数实现:
void Game::Game_Start()//进行一次猜数
{
string in;
Generate();
cout << "生命值:" << hp << "\t分数:" << score << endl;
for (int i = 0; i < 4; i++)
cout << s[i] << '\t';
cout << "请输入计算式" << endl;
cin >> in;
if (in == "00") cout<<"跳过当前的题目"<<endl;
else if (in == "0");
else if (culmulate(in) == 24) { cout << culmulate(in); score += 1; cout << "分数+1" << endl; }
else { cout << culmulate(in); hp--; cout << "生命值-1" << endl; }
}
void Game::Generate()//生成随机数
{
srand((unsigned)time(NULL));
for (int i = 0; i < 4; i++)
{
a[i] = (rand() % 13) + 1;
if (a[i] < 10)
s[i] = a[i] + 48;
else switch (a[i])
{
case 10:s[i] = "10";
case 11:s[i] = "J";
case 12:s[i] = "Q";
case 13:s[i] = "K";
default:
break;
}
}
}
int Game::culmulate(string s)//计算输入的字符串
{
int a, b;
int c = 0, d = 0, e = 0;
string st = "";
for (int i = 0; s[i] != '\0'; i++)
{
if (s[i] == 40) a = i;
}
for (int i = s.length(); i>-1; i--)
{
if (s[i] == 41) b = i;
}
for (int i = a+1; ; i++)
{
if (s[i + 1] < 58 && s[i + 1]>48) c = (s[i++] - 48) * 10 + s[i++] - 48;
else c = s[i++] - 48;
i+=1;
if (s[i + 1] < 58 && s[i + 1]>48) d = (s[i] - 48) * 10 + s[i+1] - 48;
else d = s[i] - 48;
i--;
switch (s[i])
{
case 43:e = c + d; break;//'+'=43
case 45:e = c - d; break;//'-'=45
case 42:e = c * d; break;//'*'=42
case 47:e = c / d; break;//'/'=47
default:
break;
}
break;
}
for (int i = 0; i < a; i++)
st += s[i];
for (;;)
{
if(e / 10 == 0)
{
st += (e + 48);
break;
}
else
{
st += ((e / 10) + 48);
st += ((e % 10) + 48);
break;
}
}
for (int i = b+1; i < s.length(); i++)
st += s[i];
if (!(a == 0 && b == s.length() - 1))
e=culmulate(st);
return e;
}
void Game::control()//计时器
{
int a;
while (hp)
{
a = 0;
for (int i = 0; i < 20000; i++)
{
Sleep(1);
if (flag == 1)
{
a = 1;
break;
}
}
if (a == 0)
{
hp--;
while (1)
{
while (flag == 1);
cin.ignore();//清空缓冲区
cout << "计时结束,生命值-1,现为"<<hp<<"连续输入两个0以继续" << endl;
cin >> a;//用一个待输入的变量暂停计时器
flag = 2;
break;
}
}
}
}
五、调试和运行结果
调试截图:
运行结果:
六、心得总结
线程之间的相互控制较为困难,容易形成复杂的数据关系。想要让一个结束运行的线程在循环之中重新启动似乎也是不可行的。同时,计时器计时结束时,若还在算式输入的过程中,会出现显示的混乱。