Java实现扑克牌24点游戏

发布时间 2023-06-25 10:53:27作者: 推荐了再走

游戏规则:

4张扑克牌 A~K分别代表 1点至13点,要求4张牌加减乘除后得到点数为24.(除法必须整除)

代码实现思路:

  1. 构建初始变量
    image

  2. 实现初始化变量值
    image

  3. 实现运算
    image

  4. 分析可能出现的运算组合
    image
    不考虑运算符优先级,组合3/5/7重复(最后会解释为什么不考虑运算符优先级,注1)

  5. 代码实现将扑克牌的排列组合,与所有运算可能取笛卡尔积进行运算判断
    image

  6. 接上文
    image

  7. 结果输出格式化
    image

点击查看代码
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的组合解决