游戏设计需求:

随机给出4个数字,玩家通过输入由这4个数字以及加减乘除括号运算符组成的表达式,若表达式结果为24则分数加一,玩家可以通过查询答案查询最少一组答案
程序截图:

开始界面

游戏界面

回答正确

回答错误

防错处理

程序设计

游戏准备:随机生成4个1~9的数字,通过穷举法列举所有可能的表达式若,若没有结果为24则重新生成,若有记录第一次的表达式并记录下来作为玩家可以用来查询的答案
游戏过程:由玩家输入一个表达式,利用栈运算求值判断是否正确

程序内容

  1. 引用的头文件
    Windows——使用函数ZeroMemory()使指针所指内容清0
    algorithm——使用函数next_permutation()生成数列的全排列,用于穷举法寻找答案

  2. 栈运算

https://blog.csdn.net/believe_s/article/details/76473908——栈在表达式中的应用

玩家输入一个表达式,如何计算这个表达式是游戏的核心内容,难点在于传统的运算表达式为中缀表达式,例如4*(2+2*2),,运算符是包含在数字之间(中缀的含义),有先乘除后加减的优先级顺序,以及有括号能够改变优先级,通过程序计算的难度比较大,因此选择通过栈将中缀表达式转化为后缀表达式,如4222*+*的形式,这个时候计算就不用考虑括号跟乘除的优先级,简化了计算时需要考虑的因素

//转化函数:将中缀表达式转化后后缀表达式,将表达式以队列的形式返回(使用栈的话需要把最终的结果反过来才是后缀表达式)queue<char> _24::change(char *expression) {//error为类中变量代表表达式的输入是否错误,错误则为truequeue<char> exp;stack<char> sign;                            //储存符号的栈char *p = expression;for (; *p != 0; p++) {if (*p <= '9'&&*p > '0') exp.push(*p);      //若指针的值为数字则入队else {                                     //若指针的值为符号if (sign.empty() || *p == '(') {        sign.push(*p);                     //如果符号栈为空或者遇到左括号符号直接入栈}else if ( *p == '+' || *p == '-') {   //若符号为加减,因为加减的优先级是最低的,所以意味着前面的符号运算已经告一段落不需要在栈中储存了,因此将储存栈的符号入队while ( !sign.empty()&&sign.top() != '('){exp.push(sign.top());sign.pop();}sign.push(*p);}else if (*p == '*' || *p == '/') {//因为乘除的优先级关系,只能代表之前的乘除运算完成,不难代表加减完成,因此只有乘号跟除号出栈入队while (!sign.empty() && sign.top()!='('&&(sign.top() == '*'||sign.top() == '/')){exp.push(sign.top());sign.pop();}sign.push(*p);}else if (*p == ')') {//遇到右括号,将左括号之前的符号入队,并且让左括号出栈(不用入队),如果找不到左括号则表达错误while (!sign.empty() && sign.top() != '('){exp.push(sign.top());sign.pop();}if (!sign.empty() && sign.top() == '(') sign.pop();else error = true;}else error = true;}}//将符号栈剩下的全部出栈入队while (!sign.empty() && sign.top() != '('){exp.push(sign.top());sign.pop();}//如果还有未匹配的左括号则表达式错误if (!sign.empty() && sign.top() == '(') error = true;return exp;
}   

计算后缀表达式的值,队列中的元素依次出队,若未数字则入栈,若为符号,则栈中弹出2个元素(因为是后缀表达式符号之前肯定有2个数字,否则表达式为错误)按符号的运算得到结果,将结果入栈,重复此步骤,最终栈只剩下唯一的元素即是计算结果
Eg:4222*+,前面4个数字直接入栈,队列下一个元素为,栈中弹出2个元素即2个2,2个2按号运算得到结果4,结果4入栈,此时栈中元素为424,下一个符号为+,重复上述步骤得到栈为46,下一个元素为,结果为24

下面计算函数的实现:

bool _24::calculate(char *expression) {queue<char> exp = change(expression);   //转化为后缀表达式stack<int> tem;     //栈储存运算数以及运算结果if (error) return false;    //表达式错误则返回map<int, int> num;         //用于判断玩家输入的4个数字是否为提供的4个数字,使用匹配数组,检查到数字则匹配的值减1,值为0时删除,最终完全匹配时map应该为空int i, left,right;//left为左操作数,right为右操作数char sign;      //运算符for (i = 0; i < 4; i++) {if (num.find(number[i]) == num.end()) num[number[i]] = 1;else num[number[i]]++;//为map赋值}while (!exp.empty()){if (exp.front() <= '9'&&exp.front() > '0') {//若为数字,先判断map中是否有这个元素,否则错误if (num.find(exp.front() - '0') == num.end()) {error = true;return false;}else {num[exp.front() - '0']--;if (num[exp.front() - '0'] == 0) num.erase(exp.front() - '0');}tem.push(exp.front() - '0');exp.pop();}else {if (!tem.empty()) {right = tem.top();tem.pop();}if (!tem.empty()) {left = tem.top();tem.pop();}else {error = true;return false;}sign = exp.front();exp.pop();switch (sign){case '+':left += right;break;case '-':left -= right;break;case '*':left *= right;break;case '/'://前面输入的时候已经排除了输入0的可能性,除法应该满足整除关系(因为计算机的运算整形不整除会舍弃小数部分造成玩家无法理解的运算成为答案,如4*(5+3/2)=24)if (left%right != 0) {error = true;return false;}left /= right;break;default:break;}tem.push(left); //将计算结果放入栈中 }}if (!num.empty()) {error = true;return false;}left = tem.top();if (left == 24) return true;else return false;
}

穷举法寻找答案

首先考虑所有的可能性,数字的排列不同,符号的不同,括号位置的不同均会导致运算结果的不同,其中数字的排列会因为相同数字的个数而不同,最坏的情况为4个数字均不同,全排列的结果为24种,符号的不同为4的三次方,64种,括号的位置具体分为单括号4选2合计6种跟双括号4种,括号合计10种可能,如果依次寻找答案的话,一组数字需要查询24*64*10=15360种可能性,如果连续多次数字不符(找不到答案)对游戏性能的影响非常大,因此我通过思考舍弃了其中一些不可能或者必定会重复的情况

首先数字需要进行全排列,而全排列的数字必然会出现对称的情况,比如1234,某一次排列会变成4321,因此在符号对称或者括号对称的情况是重复的,比如1*2+3+4跟4+3+2*1的结果是一致的,因此是重复的,所以符号运算以及括号位置可以将对称的结构删除
然后排除不可能的情况,符号运算中,3个符号不可能均为-号或者/号,因为4个数字通过这两个符号只能变得更小,不可能组合成24,因此这2个符号的组合情况不可能,同时想2个+号跟1个/号也不可能,因为两个数相除,如果考虑被除数为1的情况,那么除号能用×号代替,如果不为1,10以内结果最大为8/2=4,加上2个均小于10的数不可能为24
最终挑选出来的符号可能性为21种,括号可能性为4种+1种没有括号的情况
此时的可能性有24*21*5=2520种,比起一开始已经优化了很多了
最后排除不需要加括号时的情况:符号为同一优先级的时候,合计6种情况
最后可能性2520-6*24*5=1800种

bool _24::is_right() {bool right=false;vector<int> num = number;sort(num.begin(), num.end());char bracket = '(';char *tem = new char[15]();char sign[21][3] = { {'+','+','+'},{ '*','+','+' },{ '+','*','+' },{ '*','*','+' },{ '*','+','*' },{ '*','*','*' },{ '-','+','+' },{ '+','-','+' },{ '-','*','*' },{ '*','-','*' },{ '/','*','*' },{ '*','/','*' },{ '*','+','-' },{ '-','*','+' },{ '*','-','+' },{ '*','+','/' },{ '/','*','+' },{ '*','/','+' },{ '*','-','/' },{ '/','*','-' },{ '*','/','-' }};//储存的时括号可能在的位置,-1表示这个地方没有括号int brackets[5][4] = {{-1,-1,-1,-1},{0,4,-1,-1},{ -1,2,6,-1 },{ -1,2,-1,8 },{ 0,4,6,10 }};while (!right&&next_permutation(num.begin(), num.end())){for (int i = 0; i < 21&&!right; i++) {if (((sign[i][0] == '+' || sign[i][0] == '-')&&(sign[i][1] == '+' || sign[i][1] == '-')&&(sign[i][1] == '+' || sign[i][1] == '-'))|| ((sign[i][0] == '*' || sign[i][0] == '/') && (sign[i][1] == '*' || sign[i][1] == '/') && (sign[i][1] == '*' || sign[i][1] == '/'))) {int k = 0;tem[k++] = num[0] + '0';tem[k++] = sign[i][0];tem[k++] = num[1] + '0';tem[k++] = sign[i][1];tem[k++] = num[2] + '0';tem[k++] = sign[i][2];tem[k++] = num[3] + '0';right = calculate(tem);error = false;if (!right) ZeroMemory(tem, 15);}else {for (int j = 0; j < 5&&!right; j++) {int k = 0;if (k == brackets[j][0]) {tem[k++] = bracket;bracket = ')';}tem[k++] = num[0] + '0';tem[k++] = sign[i][0];if (k == brackets[j][1]) {tem[k++] = bracket;bracket = ')';}tem[k++] = num[1] + '0';if (k == brackets[j][1]) {tem[k++] = bracket;bracket = '(';}tem[k++] = sign[i][1];if (k == brackets[j][2]) {tem[k++] = bracket;bracket = ')';}tem[k++] = num[2] + '0';if (k == brackets[j][2]) {tem[k++] = bracket;bracket = '(';}tem[k++] = sign[i][2];tem[k++] = num[3] + '0';if (k == brackets[j][3]) {tem[k++] = bracket;bracket = '(';}right = calculate(tem);error = false;if (!right) ZeroMemory(tem, 15);}}}}if (right) strcpy_s(result,15, tem); //如果结果正确,将此时的表达式存为答案return right;
}

(考虑符号情况时可能会有些地方欠佳21种可能不是很全面,如果发现不足望能回复补充)

程序原码以及可执行程序下载:

https://download.csdn.net/download/qq_39584959/10590581

24点游戏c++实现相关推荐

  1. php 24点算法,PHP实现简单的24点游戏

    忽然想到做一个小应用,需要使用到24点判断,故而写一个简单版的. 代码粗糙,轻拍. /** * 24点游戏 * @author 长安猎人 */ $arr = [10, 4, 5, 3]; $opArr ...

  2. 【c#】24点游戏的实现(可存档且局域网互联)

    (更新,附上此款游戏的源代码供大家学习吧!http://download.csdn.net/detail/gshengod/5774531) lz辛苦考上了北邮的研究生,刚进入实验室,就接到了一个棘手 ...

  3. Java黑皮书课后题第3章:**3.24(游戏:抽牌)编写程序,模拟从一副52张的牌中抽一张牌,程序应显示牌的大小、花色

    **3.24(游戏:抽牌)编写程序,模拟从一副52张的牌中抽一张牌,程序应显示牌的大小.花色 题目 题目概述 运行示例 破题 代码 题目 题目概述 **3.24(游戏:抽牌)编写程序,模拟从一副52张 ...

  4. python游戏开发步骤_详解Python GUI版24点游戏制作过程

    本文作者为浙江温州永嘉县教师发展中心应根球老师,电子邮箱:ycicada@163.com. 传统用扑克牌算24点游戏用于小学低中段学生训练四则运算效果不错,也可用于防止老年痴呆.本项目模拟传统扑克24 ...

  5. 用matlab算24点小游戏,24点游戏的Matlab程序

    function GUI_games24 S.fh = figure('units','pixels',... 'position',[500 500 800 200],... 'menubar',' ...

  6. 基于android平台的24点游戏设计与实现需求分析,基于Android平台的24点游戏设计与实现需求分析_毕业设计论文.doc...

    基于Android平台的24点游戏设计与实现 摘要 随着移动设备的普及以及移动设备的硬件的提升,移动设备的功能越来越完善,移动设备的系统平台也日渐火热起来.目前国内最常见的移动开发平台有Symbian ...

  7. 1.16 24点游戏

    24点游戏的解决办法,也是采取穷举法的思路,4个数,有4!=24中排列的方法,然后3个操作符号,有4×4×4 = 64种结果,再加上括号,有5种结果,于是,每4个数有24*66*5 = 7680中结果 ...

  8. 24点游戏详细截图介绍以及原型、Alpha、Beta对比

    原型设计 图片展示 功能与界面设计 1.登录注册 2.手机号验证 3.24点游戏 4.粉色系女生界面 Alpha 图片展示 功能与界面设计 1.24点游戏 2.背景音乐 3.可查看多种可能的答案 4. ...

  9. 用python代替人脑运算24点游戏

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:老方玩编程 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...

  10. cdoj 1252 24点游戏 dfs

    24点游戏 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1252 Descr ...

最新文章

  1. 什么是三层交换机、网关、DNS、子网掩码、MAC地址
  2. 台湾大学林轩田机器学习基石课程学习笔记1 -- The Learning Problem
  3. jq中ajax返回数据的json_encode,jQuery AJAX使用JSON返回对PHP脚本的调用
  4. linux 生成和使用动态链接库和静态链接库的Makefile编写
  5. DivideMix: Salesforce提出使用半监督学习大幅改进含噪声标签的学习
  6. Ping突然出现请求超时的问题
  7. Selenium自动化测试-浏览器基本操作
  8. cvsaveimage 异常_C++ IplImage*的若干bug之三:cvSaveImage問題
  9. linux+模块与设备关系,linux内核设计与实现读书笔记——设备和模块
  10. Prism发布了第一个版本+Entlib3.1在VS2008下工作的解决方案
  11. vscode如何查看修改过的部分_如何查看和修改Windows远程桌面端口
  12. Java学习手册:JDBC中getString()方法与getObject()方法有什么区别?
  13. java汉字的编码_Java中文编码问题小结
  14. word从第三页插入页码
  15. 面试考点:逻辑思维面试题(软件测试)
  16. java.lang.IllegalArgumentException: Receiver not registered
  17. 索尼笔记本E系列,关闭触摸板
  18. Windows系统安装时,新硬盘手动命令创建主分区和逻辑分区
  19. 360网站卫士php-dos,360网站卫士的CDN缓存加速功能详解
  20. 高级建模方法(Gurobi):线性化、分段线性函数、逻辑变量/约束

热门文章

  1. 功能安全是什么?FSoE是什么?Safety over EtherCAT
  2. 手机网页html怎样阻止广告,Webview拦截广告
  3. python小游戏 打地鼠小游戏设计与实现
  4. JS实现打地鼠小游戏案例,文末附素材
  5. 自定义IP地址安装固定驱动柯美c266打印机,并自动销毁安装程序
  6. 汇编语言笔记(10)CALL和RET指令
  7. 爱丁堡大学研究生计算机科学专业,爱丁堡大学计算机科学硕士专业
  8. 垄断的需求弹性_6μm 锂电铜箔迈入需求持续高增长周期
  9. JBOSS启动警告 Not installing optional component org.springframework.web.context.request.async.Standard
  10. 斜率,截距,回归方程