C++ 24点扑克游戏全解

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秒钟给出结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值