24点

  24点是一个非常经典的游戏,从扑克牌里抽4张牌,其中J=11,Q=12,K=13,然后经过+,-,*,/,(),的计算后,使得计算得值为24,例如抽到1,2,2,5四张牌,那么

  (1+5)*(2+2)=24;

  这就是可以凑成24点的一种情况,作为一个经典题目,在leetcode上也有对应的题目进行练习

  PS 看见知乎大佬有一种必24点的算法,但是要用到阶乘和次方 式子为(a0+b0+c0+d0)! =24

一、总体思路

  1.因为是简单暴力向的,所以我们的做法就是直接穷举出所有可能的情况,首先是考虑四个数a,b,c,d的排列情况

    如b,a,c,d等等,通过排列组合可以得到 4*3*2*1 = 24 种情况

  2.然后考虑a,b,c,d中的三个运算符的情况设一个自定义的运算符为$,$可以是+,-,*,/中的任意一个

    则有 a$b$c$d 这个式子,同样,运算符的可能性有 3*4 = 12 种

  3.最后考虑()的情况,我们规定,每次一对()只框住两个数,比如a+b+c+d =(((a+b)+c)+d) = ((r1+c)+d)=(r2+d)=r3(其中r1=a+b,r2=r1+c,r3=r2+d)

    ()的情况其实就是运算优先级的问题,无论运算符是什么,都一定是先运算括号里的内容

    所以我们可以穷举出情况

    第一种r1=a$b,r2=r1$c,r3=r2$d;

    第二种r1=b$c,r2=a$r1,r3=r2$d;

    第三种r1=b$c,r2=r1$d,r3=a$r2;

    第四种r1=c$d,r2=b$r1,r3=a$r2;

    第五种r1=a$b,r2=c$d,r3=r1$r2;

  仔细观察不难发现,我们控制了运算符和数字的绝对顺序从左到右的顺序严格是a$b$c$d,不论任何情况都不会改变abcd的顺序,是因为我们在上面已经排出来了所有的24种情况,所以我们这就可以严格控制abcd的顺序了

二、代码实现

 #include <iostream>
#include <string>
using namespace std;
int mark_int[] = { ,,, };
string mark_char = "+-*/";
double cal(double a, int m, double b)
{
switch (m)
{
case : return a + b;
case : return a - b;
case : return a * b;
case : return a / b;
}
} bool cal1(double a, double b, double c, double d, int m1, int m2, int m3)
{
double r1;
double r2;
double r3;
r1 = cal(a, m1, b);
r2 = cal(r1, m2, c);
r3 = cal(r2, m3, d);
if (r3 == )
{
cout << "(((" << a << mark_char[m1 - ] << b << ")" << mark_char[m2 - ] << c << ")" << mark_char[m3 - ] << d << ")" << endl;
return ;
}
return ;
} bool cal2(int a, int b, int c, int d, int m1, int m2, int m3)
{
double r1;
double r2;
double r3;
r1 = cal(b, m1, c);
r2 = cal(a, m2, r1);
r3 = cal(r2, m3, d);
if (r3 == )
{
cout << "((" << a << mark_char[m1 - ] << "(" << b << mark_char[m2 - ] << c << "))" << mark_char[m3 - ] << d << ")" << endl;
return ;
}
return ;
} bool cal3(int a, int b, int c, int d, int m1, int m2, int m3)
{
double r1;
double r2;
double r3;
r1 = cal(b, m1, c);
r2 = cal(r1, m2, d);
r3 = cal(a, m3, r2);
if (r3 == )
{
cout << "(" << a << mark_char[m1 - ] << "((" << b << mark_char[m2 - ] << c << ")" << mark_char[m3 - ] << d << "))" << endl;
return ;
}
return ;
} bool cal4(int a, int b, int c, int d, int m1, int m2, int m3)
{
double r1;
double r2;
double r3;
r1 = cal(c, m1, d);
r2 = cal(b, m2, r1);
r3 = cal(a, m3, r2);
if (r3 == )
{
cout << "(" << a << mark_char[m1 - ] << "(" << b << mark_char[m2 - ] << "(" << c << mark_char[m3 - ] << d << ")))" << endl;
return ;
}
return ;
} bool cal5(int a, int b, int c, int d, int m1, int m2, int m3)
{
double r1;
double r2;
double r3;
r1 = cal(a, m1, b);
r2 = cal(c, m3, d);
r3 = cal(r1, m2, r2);
if (r3 == )
{
cout << "((" << a << mark_char[m1 - ] << b << ")" << mark_char[m2 - ] << "(" << c << mark_char[m3 - ] << d << "))" << endl;
return ;
}
return ;
} bool all_cal(int a, int b, int c, int d)
{
for (int i = ; i <= ; i++)
for (int j = ; j <= ; j++)
for (int k = ; k <= ; k++)
{
if (cal1(a, b, c, d, i, j, k) == true || cal2(a, b, c, d, i, j, k) == true || cal3(a, b, c, d, i, j, k) == true || cal4(a, b, c, d, i, j, k) == true || cal5(a, b, c, d, i, j, k) == true)
return ;
}
return ;
} bool judge(int a, int b, int c, int d)
{
int all[][] = {
{a,b,c,d},{a,b,d,c},{a,c,b,d},{a,c,d,b},{a,d,b,c},{a,d,c,b},
{b,a,c,d},{b,a,d,c},{b,c,a,d},{b,c,d,a},{b,d,a,c},{b,d,c,a},
{c,a,b,d},{c,a,d,b},{c,b,a,d},{c,b,d,a},{c,d,a,b},{c,d,b,a},
{d,a,b,d},{d,a,d,b},{d,b,a,c},{d,b,c,a},{d,c,a,b},{d,c,b,a},
};
for (int i = ; i < ; i++)
{
if (all_cal(all[i][], all[i][], all[i][], all[i][]))
return ;
}
return ;
} int main()
{
int a, b, c, d;
cin >> a >> b >> c >> d;
if (!judge(a, b, c, d))
cout << "凑不成24点" << endl; }

三、代码解释

先做一个计算两个数的函数,用数组int mark_int[4] = {1,2,3,4}的四个数表示+ - * /,string mark_char是用来最后显示的

 int mark_int[] = { ,,, };
string mark_char = "+-*/";
double cal(double a, int m, double b)
{
switch (m)//用switch来进行运算符的选择
{
case : return a + b;
case : return a - b;
case : return a * b;
case : return a / b;
}
}

我们在实现五种括号的函数,并且我们规定运算一定是 a m1 b m2 c m3 d(m1,m2,m3是三个运算符的代号),如果成功返回运算的过程和true,否则返回false

 bool cal1(double a, double b, double c, double d, int m1, int m2, int m3)
{
double r1;
double r2;
double r3;
r1 = cal(a, m1, b);
r2 = cal(r1, m2, c);
r3 = cal(r2, m3, d);
if (r3 == )
{
cout << "(((" << a << mark_char[m1 - ] << b << ")" << mark_char[m2 - ] << c << ")" << mark_char[m3 - ] << d << ")" << endl;
return ;
}
return ;
}//第一种r1=a$b,r2=r1$c,r3=r2$d; bool cal2(int a, int b, int c, int d, int m1, int m2, int m3)
{
double r1;
double r2;
double r3;
r1 = cal(b, m1, c);
r2 = cal(a, m2, r1);
r3 = cal(r2, m3, d);
if (r3 == )
{
cout << "((" << a << mark_char[m1 - ] << "(" << b << mark_char[m2 - ] << c << "))" << mark_char[m3 - ] << d << ")" << endl;
return ;
}
return ;
}//第二种r1=b$c,r2=a$r1,r3=r2$d; bool cal3(int a, int b, int c, int d, int m1, int m2, int m3)
{
double r1;
double r2;
double r3;
r1 = cal(b, m1, c);
r2 = cal(r1, m2, d);
r3 = cal(a, m3, r2);
if (r3 == )
{
cout << "(" << a << mark_char[m1 - ] << "((" << b << mark_char[m2 - ] << c << ")" << mark_char[m3 - ] << d << "))" << endl;
return ;
}
return ;
}//第三种r1=b$c,r2=r1$d,r3=a$r2; bool cal4(int a, int b, int c, int d, int m1, int m2, int m3)
{
double r1;
double r2;
double r3;
r1 = cal(c, m1, d);
r2 = cal(b, m2, r1);
r3 = cal(a, m3, r2);
if (r3 == )
{
cout << "(" << a << mark_char[m1 - ] << "(" << b << mark_char[m2 - ] << "(" << c << mark_char[m3 - ] << d << ")))" << endl;
return ;
}
return ;
}//第四种r1=c$d,r2=b$r1,r3=a$r2; bool cal5(int a, int b, int c, int d, int m1, int m2, int m3)
{
double r1;
double r2;
double r3;
r1 = cal(a, m1, b);
r2 = cal(c, m3, d);
r3 = cal(r1, m2, r2);
if (r3 == )
{
cout << "((" << a << mark_char[m1 - ] << b << ")" << mark_char[m2 - ] << "(" << c << mark_char[m3 - ] << d << "))" << endl;
return ;
}
return ;
}//第五种r1=a$b,r2=c$d,r3=r1$r2;

接下来是12种的符号的排列情况,如果有一种括号情况满足,我们就返回true,否则返回false

 bool all_cal(int a, int b, int c, int d)
{
for (int i = ; i <= ; i++)
for (int j = ; j <= ; j++)
for (int k = ; k <= ; k++)
{
if (cal1(a, b, c, d, i, j, k) == true || cal2(a, b, c, d, i, j, k) == true || cal3(a, b, c, d, i, j, k) == true || cal4(a, b, c, d, i, j, k) == true || cal5(a, b, c, d, i, j, k) == true)
return ;
}
return ;
}

最后是在总判断函数中写入24种的abcd排列情况

 bool judge(int a, int b, int c, int d)
{
int all[][] = {
{a,b,c,d},{a,b,d,c},{a,c,b,d},{a,c,d,b},{a,d,b,c},{a,d,c,b},
{b,a,c,d},{b,a,d,c},{b,c,a,d},{b,c,d,a},{b,d,a,c},{b,d,c,a},
{c,a,b,d},{c,a,d,b},{c,b,a,d},{c,b,d,a},{c,d,a,b},{c,d,b,a},
{d,a,b,d},{d,a,d,b},{d,b,a,c},{d,b,c,a},{d,c,a,b},{d,c,b,a},
};
for (int i = ; i < ; i++)
{
if (all_cal(all[i][], all[i][], all[i][], all[i][]))
return ;
}
return ;
}

主函数调用judge就完成整个算法了✿✿ヽ(°▽°)ノ✿

 int main()
{
int a, b, c, d;
cin >> a >> b >> c >> d;
if (!judge(a, b, c, d))
cout << "凑不成24点" << endl; }

失败的话会显示“凑不成24点”

其实这个算法的话我写的可以说基本没有优化,就是枚举所有情况实现的,csdn上有大佬是有更好的思路的,这篇文章也是看了csdn的大佬的代码然后自己修修补补写出来的(我原来看的那篇有bug,大佬自己没发现好像。。。)

就酱

睡觉!

  

经典游戏--24点--c++代码实现和总体思路(简单暴力向)的更多相关文章

  1. 经典趣味24点游戏程序设计(python)

    一.游戏玩法介绍: 24点游戏是儿时玩的主要益智类游戏之一,玩法为:从一副扑克中抽取4张牌,对4张牌使用加减乘除中的任何方法,使计算结果为24.例如,2,3,4,6,通过( ( ( 4 + 6 ) - ...

  2. C++复现经典游戏——扫雷

    国庆小长假,当大家都去看人山人海的时候,我独自一人狂码代码.这两天想要实现的内容是Windows上的一个经典游戏——扫雷.相信90后和一些上班族对此并不陌生.然而,从win8开始,扫雷就不再是Wind ...

  3. JAVA开发--游戏24点

    也比较简单,写的不好,代码里用到了LOOKANDFELL,QUAQUA8.0的包 package com.Game24; import java.awt.Container; import java. ...

  4. Cocos2D-ObjC:在RPG游戏中混合Swift代码

    我之前写过一个RPG游戏<<熊猫之魂 SoulOfPanda>> 编译器使用的是SpriteBuilder,很好很强大!全部代码都由Objc完成,现在想尝试一下在其中混入Swi ...

  5. 微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js)

    微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞 ...

  6. 微信小游戏 demo 飞机大战 代码分析 (三)(spirit.js, animation.js)

    微信小游戏 demo 飞机大战 代码分析(三)(spirit.js, animation.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞机大战 代码 ...

  7. 微信小游戏 demo 飞机大战 代码分析 (二)(databus.js)

    微信小游戏 demo 飞机大战 代码分析(二)(databus.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞机大战 代码分析(三)(spirit. ...

  8. 微信小游戏 demo 飞机大战 代码分析 (一)(game.js, main.js)

    微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞机大战 代码分析(二)(databus.js) 微信小游戏 demo 飞机大战 代码分析(三)(spirit. ...

  9. Unity2017 经典游戏开发教程 算法分析与实现 (张帆 著)

    https://meta.box.lenovo.com/link/view/82c451b41ce34e81a4b34cb46747d3d5 第1章 熟悉Unity软件的操作 第2章 打地鼠 (已看) ...

随机推荐

  1. 搭建vue项目的步骤

    新建vue脚手架 vue-element-cms步骤: 1. vue create ……………(文件名)---这里取为vue-element-cms 2. 命令行工具进入这个文件夹,安装路由依赖包 n ...

  2. Apache Tomcat/8.5.51 secretRequired="true"

    1.报错IllegalArgumentException: The AJP Connector is configured with secretRequired="true" b ...

  3. PHP ignore_user_abort() 函数

    实例 设置为 false(默认)- 与客户机断开会终止脚本的执行: <?phpignore_user_abort();?>高佣联盟 www.cgewang.com 上面代码的输出如下: 0 ...

  4. luogu P4769 [NOI2018]冒泡排序 结论 树状数组 卡特兰数

    LINK:冒泡排序 神题. 可以想到爆搜 期望得分5~10分. 打成这个样子心态不得爆炸? 仔细分析 一个不合法序列还有什么标志. 容易想到某个数字离自己位置相反的方向多走了一步. 考虑单独对每个数字 ...

  5. luogu P1128 [HNOI2001]求正整数 dp 高精度

    LINK:求正整数 比较难的高精度. 容易想到贪心不过这个贪心的策略大多都能找到反例. 考虑dp. f[i][j]表示前i个质数此时n的值为j的最小的答案. 利用高精度dp不太现实.就算上FFT也会T ...

  6. day16.内置方法与模块

    一.内置方法 1.abs 绝对值函数 res = abs(-100) print(res) 2.round 四舍五入 (n.5 n为偶数则舍去 n.5 n为奇数,则进一!) ""& ...

  7. 8道python练习题,能做出来的没几个

    变量的定义 程序就是用来处理数据的,而变量就是用来存储数据的 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道 ...

  8. 连通图算法详解之① :Tarjan 和 Kosaraju 算法

    相关阅读: 双连通分量 ,割点和桥 简介 在阅读下列内容之前,请务必了解 图论相关概念 中的基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly ...

  9. linxu系统安装WordPress

    确保在安装wordpress之前,安装了nginx,php,mysql 没有安装的翻我之前的博文有安装方法 进入官网下载压缩包 wget https://wordpress.org/latest.ta ...

  10. 如何实现数据库CDP,即数据库连续数据保护

    备份可以分为定期备份和实时备份.定期备份与实时备份相比存在两大劣势:一是备份需要时间窗口,对于很多24小时业务运行的机构,线上业务不允许有过多的业务系统停机去进行数据备份:二是定期备份无法保证数据丢失 ...