游戏规则:
4张扑克牌 A~K分别代表 1点至13点,要求4张牌加减乘除后得到点数为24.(除法必须整除)
代码实现思路:
-
构建初始变量
-
实现初始化变量值
-
实现运算
-
分析可能出现的运算组合
不考虑运算符优先级,组合3/5/7重复(最后会解释为什么不考虑运算符优先级,注1) -
代码实现将扑克牌的排列组合,与所有运算可能取笛卡尔积进行运算判断
-
接上文
-
结果输出格式化
点击查看代码
package algorithm;
import java.util.*;
/**
* 扑克牌24点游戏,4张牌(1~13)加减乘除得到点数24
*/
public class Poker24 {
//扑克牌最小值
private static Integer minPoker = 1;
//扑克牌最大值
private static Integer maxPoker = 13;
//正确结果
private static Integer correctResult = 24;
//运算数组 1 -> + 2 -> - 3 -> * 4 -> /
private static Integer[] operateArr = {1, 2, 3, 4};
//运算符 -> 用来格式化输出结果
private static String[] operateStr = {"?","+", "-", "*", "/"};
//扑克牌的所有组合
private static List<Integer[]> pokerList = new ArrayList<>();
//运算符的所有可能组合
private static List<Integer[]> operateList = new ArrayList<>();
public static void main(String[] args) {
//2_1.构建扑克牌的所有组合
for (int poker1 = minPoker; poker1 <= maxPoker; poker1++) {
for (int poker2 = minPoker; poker2 <= maxPoker; poker2++) {
for (int poker3 = minPoker; poker3 <= maxPoker; poker3++) {
for (int poker4 = minPoker; poker4 <= maxPoker; poker4++) {
pokerList.add(new Integer[]{poker1, poker2, poker3, poker4});
}
}
}
}
//2_2.构建加减乘除运算的所有可能排序 -> 4张扑克 三次运算
for (int ope1 = 1; ope1 <= operateArr.length; ope1++) {
for (int ope2 = 1; ope2 <= operateArr.length; ope2++) {
for (int ope3 = 1; ope3 <= operateArr.length; ope3++) {
operateList.add(new Integer[]{ope1, ope2, ope3});
}
}
}
//3.实现扑克牌的加减乘除 -> calculator
//4.列出一组扑克牌的7种组合情况 -> 从前向后顺序执行 不需要考虑优先级
//1 poker1 poker2 poker3 poker4
//2 (poker1 poker2) (poker3 poker4)
//3 (poker1 poker2 poker3) poker4 -> 执行顺序同第一种
//4 poker1 (poker2 poker3) poker4
//5 poker1 (poker2 poker3 poker4)
//6 poker1 poker2 (poker3 poker4) -> 执行顺序,同第二种
//7 (poker1 poker2) poker3 poker4 -> 执行顺序,同第一种
//5.将扑克牌的排列组合,与所有运算可能取笛卡尔积进行运算判断
List<PokerResult> resultPokerList = new ArrayList<>();
pokerList.forEach(poker -> {
List<String> tempResultList = new ArrayList<>();
operateList.forEach(operate -> {
//第一种poker1 poker2 poker3 poker4
int calculator1 = calculator(
calculator(
calculator(poker[0], poker[1], operate[0]),
poker[2],
operate[1]),
poker[3],
operate[2]
);
if (calculator1 == correctResult) {
String resultStr = toResultStr(poker, operate, 1);
tempResultList.add(resultStr);
}
//第二种(poker1 poker2) (poker3 poker4)
int calculator2 = calculator(
calculator(poker[0], poker[1], operate[0]),
calculator(poker[2], poker[3], operate[2]),
operate[1]);
if (calculator2 == correctResult) {
String resultStr = toResultStr(poker, operate, 2);
tempResultList.add(resultStr);
}
//第四种 poker1 (poker2 poker3) poker4
int calculator4 = calculator(
calculator(
poker[0],
calculator(poker[1], poker[2], operate[1]),
operate[0]
),
poker[3],
operate[2]);
if (calculator4 == correctResult) {
String resultStr = toResultStr(poker, operate, 4);
tempResultList.add(resultStr);
}
//第五中 poker1 (poker2 poker3 poker4)
int calculator5 = calculator(
poker[0],
calculator(
calculator(poker[1], poker[2], operate[1]),
poker[3],
operate[2]
),
operate[0]);
if (calculator5 == correctResult) {
String resultStr = toResultStr(poker, operate, 5);
tempResultList.add(resultStr);
}
});
if(tempResultList.size() != 0){
PokerResult pokerResult = new PokerResult(poker, tempResultList);
Optional<PokerResult> first = resultPokerList.stream()
.filter(resultPoker -> resultPoker.getCode().equals(pokerResult.getCode()))
.findFirst();
if(!first.isPresent()){
resultPokerList.add(new PokerResult(poker,tempResultList));
}
}
});
System.out.println("debug to see result");
resultPokerList.forEach(resultPoker -> System.out.println(resultPoker.toString()));
System.out.println(resultPokerList.size());
}
//计算方法
public static int calculator(int num1, int num2, int operate) {
int res = 0; // res 用于存放计算的结果
switch (operate) {
case 1:
res = num1 + num2;
break;
case 2:
res = num1 - num2;// 注意顺序
break;
case 3:
res = num1 * num2;
break;
case 4:
try{
if (num1 % num2 == 0) {
res = num1 / num2;
} else {
res = 999;
}
}catch (Exception e){
//除数为0会报错,捕获
res = 999;
}
break;
default:
break;
}
return res;
}
public static String toResultStr(Integer[] poker, Integer[] operate, Integer type) {
StringBuilder resultBuilder = new StringBuilder();
switch (type) {
case 1:
// poker1 poker2 poker3 poker4
resultBuilder.append(poker[0]).append(operateStr[operate[0]]).append(poker[1])
.append(operateStr[operate[1]]).append(poker[2]).append(operateStr[operate[2]]).append(poker[3]);
break;
case 2:
// (poker1 poker2) (poker3 poker4)
resultBuilder.append("(").append(poker[0]).append(operateStr[operate[0]]).append(poker[1]).append(")")
.append(operateStr[operate[1]]).append("(").append(poker[2]).append(operateStr[operate[2]]).append(poker[3]).append(")");
break;
case 3:
// (poker1 poker2 poker3) poker4
resultBuilder.append("(").append(poker[0]).append(operate[0]).append(poker[1])
.append(operate[1]).append(poker[2]).append(")").append(operate[2]).append(poker[3]);
break;
case 4:
// poker1 (poker2 poker3) poker4
resultBuilder.append(poker[0]).append(operateStr[operate[0]]).append("(").append(poker[1])
.append(operateStr[operate[1]]).append(poker[2]).append(")").append(operateStr[operate[2]]).append(poker[3]);
break;
case 5:
// poker1 (poker2 poker3 poker4)
resultBuilder.append(poker[0]).append(operateStr[operate[0]]).append("(").append(poker[1])
.append(operateStr[operate[1]]).append(poker[2]).append(operateStr[operate[2]]).append(poker[3]).append(")");
break;
case 6:
// poker1 poker2 (poker3 poker4)
resultBuilder.append(poker[0]).append(operate[0]).append(poker[1]).append(operate[1])
.append("(").append(poker[2]).append(operate[2]).append(poker[3]).append(")");
break;
case 7:
// poker1 poker2 (poker3 poker4)
resultBuilder.append(poker[0]).append(operateStr[operate[0]]).append(poker[1]).append(operateStr[operate[1]])
.append("(").append(poker[2]).append(operateStr[operate[2]]).append(poker[3]).append(")");
break;
}
return resultBuilder.toString();
}
}
class PokerResult{
PokerResult(Integer[] resultPoker,List<String> resultString){
this.resultPoker = resultPoker;
this.resultString = resultString;
Arrays.sort(this.resultPoker);
StringBuilder builder = new StringBuilder();
for (Integer poker : this.resultPoker) {
builder.append(poker);
}
this.code = Integer.parseInt(builder.toString());
}
// 扑克牌
private Integer[] resultPoker;
// 对应的组合集
private List<String> resultString;
private Integer code;
public Integer[] getResultPoker() {
return resultPoker;
}
public void setResultPoker(Integer[] resultPoker) {
this.resultPoker = resultPoker;
}
public List<String> getResultString() {
return resultString;
}
public void setResultString(List<String> resultString) {
this.resultString = resultString;
}
public Integer getCode() {
return code;
}
public void printResult() {
System.out.println(this.code);
}
@Override
public String toString() {
return "PokerResult{" +
"resultPoker=" + Arrays.toString(resultPoker) +
", resultString=" + resultString +
'}';
}
}
注1:不考虑运算符优先级,因为按优先级运算的排列组合也会出现.
列: 1 + 3 * 2 + 4 代码执行顺序为(1+ 3) * 2 + 4,会出现组合为2 * 3 + 1 + 4的组合解决