C++ 24点扑克游戏全解
背景:在52张扑克牌中(去掉大小王)任意选取四张扑克,使用加减乘除括号这些基本算法实现最终结果为24,其中J对应11、Q对应12、K对应13、A对应1
废话不多说,直接上干货
#include <iostream>
#include <chrono>
static int pocker_matirx[1820][4] = {}; //四张扑克牌的所有组合
static int pocker_order[24][4] = {}; //四张扑克的顺序组合
static int operators[64][3] = {}; //加减乘除运算符的顺序
void set_pocker_order() {
int index = 0;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
if (i != j) {
for (int m = 0; m < 4; ++m) {
if (m != j && m != i) {
for (int n = 0; n < 4; ++n) {
if (n != i && n != j && n != m) {
pocker_order[index][0] = i;
pocker_order[index][1] = j;
pocker_order[index][2] = m;
pocker_order[index][3] = n;
++index;
printf("{%d,%d,%d,%d},\n", i, j, m, n);
}
}
}
}
}
}
}
}
void set_mathematical_operators_order(){
int cnt = 0;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
for (int m = 0; m < 4; ++m) {
operators[cnt][0] = i;
operators[cnt][1] = j;
operators[cnt][2] = m;
++cnt;
}
}
}
}
void set_all_pocker() {
int cnt = 0;
for (int i = 1; i <= 13; ++i) {
for (int j = i; j <= 13; ++j) {
for (int m = j; m <= 13; ++m) {
for (int n = m; n <= 13; ++n) {
pocker_matirx[cnt][0] = i;
pocker_matirx[cnt][1] = j;
pocker_matirx[cnt][2] = m;
pocker_matirx[cnt][3] = n;
++cnt;
}
}
}
}
}
double sumoff(double a, double b, int type) {
switch (type) {
case 0:
return double(a + b);
case 1:
return double(a - b);
case 2:
return double(a * b);
case 3:
return double(a / b);
}
}
char ff(int type) {
switch (type) {
case 0:
return '+';
case 1:
return '-';
case 2:
return '*';
case 3:
return '/';
}
}
bool solution_yesorno(int tp[4]) {
for (int i = 0; i < 24; ++i) {
double a0 = tp[pocker_order[i][0]];
double a1 = tp[pocker_order[i][1]];
double a2 = tp[pocker_order[i][2]];
double a3 = tp[pocker_order[i][3]];
for (int j = 0; j < 64; ++j) {
double res1 = sumoff(sumoff(a0, a1, operators[j][0]),
sumoff(a2, a3, operators[j][1]), operators[j][2]);
if (res1 < 24.00001 && res1 > 23.99999) {
std::cout << '(' << a0 << ff(operators[j][0]) << a1 << ')'
<< ff(operators[j][2]) << '(' << a2
<< ff(operators[j][1]) << a3 << ") = " << res1;
return true;
}
double res2 = sumoff(sumoff(a0, sumoff(a1, a2, operators[j][1]),
operators[j][0]), a3, operators[j][2]);
if (res2 < 24.00001 && res2 > 23.99999) {
std::cout << '(' << a0 << ff(operators[j][0]) << '(' << a1
<< ff(operators[j][1]) << a2 << "))"
<< ff(operators[j][2]) << a3 << " = " << res2;
return true;
}
double res3 = sumoff(sumoff(sumoff(a0, a1, operators[j][0]),
a2, operators[j][1]), a3, operators[j][2]);
if (res3 < 24.00001 && res3 > 23.99999) {
std::cout << "((" << a0 << ff(operators[j][0]) << a1 << ')'
<< ff(operators[j][1]) << a2 << ')'
<< ff(operators[j][2]) << a3 << " = " << res3;
return true;
}
double res4 = sumoff(a3, sumoff(sumoff(a0, a1, operators[j][0]),
a2, operators[j][1]), operators[j][2]);
if (res4 < 24.00001 && res4 > 23.99999) {
std::cout << a3 << ff(operators[j][2]) << "((" << a0
<< ff(operators[j][0]) << a1 << ')'
<< ff(operators[j][1]) << a2 << ')' << " = " << res4;
return true;
}
double res5 = sumoff(a3, sumoff(a2, sumoff(a0, a1,
operators[j][0]), operators[j][1]), operators[j][2]);
if (res5<24.00001 && res5 >23.99999) {
std::cout << a3 << ff(operators[j][2]) << '(' << a2
<< ff(operators[j][1]) << "((" << a1
<< ff(operators[j][0]) << a0 << ")) = " << res5;
return true;
}
}
}
return false;
}
int main(){
auto start = std::chrono::high_resolution_clock::now();
set_all_pocker();
set_mathematical_operators_order();
set_pocker_order();
for (int i = 0; i < 1820; ++i) {
std::cout << "["<< i + 1 << "] {" << pocker_matirx[i][0] << ", "
<< pocker_matirx[i][1] << ", " << pocker_matirx[i][2] << ", "
<< pocker_matirx[i][3] << "} ";
auto ret = solution_yesorno(pocker_matirx[i]);
if (ret == false) {
std::cout << " 无解" << std::endl;
}else{
std::cout << std::endl;
}
}
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> duration = end - start;
std::cout << "函数运行时间为:" << duration.count() << " 秒" << std::endl;
return 0;
}
解析:
-
52张牌任意选择4张的所有可能是1820种
-
四张扑克牌的排列顺序有24种
-
加减乘除的运算顺序有64种
-
针对括号的方式分3大种,细分的话是5小种,分别是
-
(a ~ b)~(c ~ d)二分
-
((a ~ b) ~ c) ~ d (a ~ (b ~ c)) ~ d 前三(前置、后置)
-
a ~ (b ~ (c ~ d)) a ~ ((b ~ c) ~ d) 后三(前置、后置)
如果觉得逻辑没想通,可以看下是这三种是否包含了所有的可能性,针对乘除优先级较高而忽略括号作用的情况暂时不考虑
最终所有的情况将在0.1秒钟给出结果