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. jmeter之断言复制过来的内容也会失败

    今天遇到个很纳闷的事儿,就决定记下来,在做jmeter断言的时候,明明我是从相应文本中拷贝出来的内容,但是依旧会断言失败,差了很多资料无果,最终请教了大佬才发现是特殊字符的问题 jmeter断言中不会 ...

  2. 使用MacOS自带的SVN客户端

    原文链接:https://jingyan.baidu.com/article/5552ef479c1554518ffbc92f.html 摘要:mac环境下有自带的SVN服务端和客户端,SVN是许多公 ...

  3. fpdf fpdi 操作pdf文件 写入中文汉字

      今天给公司做一个线上合同签约功能,用户签约后 生成pdf版的文件 .网上搜了搜大概都是用fpdf进行操作的  , 通过fpdi 可以进行读取pdf模板. 在通过继承fpdf 操作现有的pdf文档 ...

  4. Skill 脚本演示 ycBusNet.il

    https://www.cnblogs.com/yeungchie/ ycBusNet.il 用于原理图中按照一定格式,批量创建 Bus . 回到目录

  5. MySQL中EXPLAIN命令详细解析

    很多情况下我们需要知道某条SQL语句的性能,都会通过EXPLAIN命令来查看查询优化器是如何执行的. 如何使用 使用EXPLAIN很简单,只需要在执行的SQL前面加上EXPLAIN即可 explain ...

  6. 关于 ORA-01033: ORACLE initialization or shutdown in progress

    第一步:   这个错误首先查看服务进程是否正常启动: 第二步:   一般情况下第一步都没问题,问题出在可能误删了日志文件: 当然可能不是你删除的,可能被某些清理软件删除的: 或者是其他情况导致日志出错 ...

  7. ios企业签名为什么会掉签?

      我们都知道ios用户无法直接安装App Store之外的应用,对于那些无法上架苹果应用商店的APP,开发者们一般会选择苹果签名的形式.   目前的苹果签名有ios企业签名.超级签名和TF上架这三种 ...

  8. Ubuntu16.04忘记用户登录密码以及管理员密码,重置密码的解决方案

    1. 问题现象: 密码遗忘 2. 问题原因 问题原因,搞不懂,只是修改了/etc/shadow和/etc/sudoers这俩文件 3. 解决方案 在系统开机前常按shift键进入grub界面,如下: ...

  9. 014_go语言中的变参函数

    代码演示 package main import "fmt" func sum(nums ...int) { fmt.Print(nums, " ") toto ...

  10. Python 进程与多线程

    10 进程和多线程 10.1 多进程 # -*- coding: utf-8 -*- import os pid=os.fork() print ('process (%s)start ...' %o ...