Java实现24点纸牌游戏


题目介绍

24点游戏是经典的纸牌益智游戏。
常见游戏规则:
从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求编程解决24点游戏。
基本要求: 随机生成4个代表扑克牌牌面的数字字母,程序自动列出所有可能算出24的表达式,用擅长的语言(C/C++/Java或其他均可)实现程序解决问题。


思路分析

本题主要解决4个数字的全排列后的运算结果,重点在于输出四个数字的全排列,以及对于五种运算方法的穷举,分别是(\*代表任意运算符):
1.((A*B)*C)*D
2.(A*(B*C))*D
3.(A*B)*(C*D)
4.A*(B*(C*D))
5.A*((B*C)*D)
符号位置固定,只需通过迭代,遍历出所有的符号组合即可。

核心算法

1.四个数字的全排列遍历

利用递归算法,遍历四个数字的全排列
代码如下(示例):

/**
     * @return void
     * @params []
     * @author Wang Rongqiang
     * @Description //TODO 获取纸牌全排列
     * @date 2021/5/9 18:45
     */
    public void getArrange(int n) {
        if (n == num.length) {
        	// 得到一种排列组合,对齐进行操作
            // insertSymbol();
        } else {
            for (int i = n; i < num.length; i++) {
                swap(i, n);
                getArrange(n + 1);
                swap(i, n);
            }
        }
    }

    /**
     * @return void
     * @params [i, n]
     * @author Wang Rongqiang
     * @Description //TODO 交换数组num中下标为i、n的元素位置
     * @date 2021/5/9 18:57
     */
    private void swap(int i, int n) {
        int tmp = num[i];
        num[i] = num[n];
        num[n] = tmp;
    }

2.构造计算式并验证结果

代码如下(示例):

/**
     * @return void
     * @params []
     * @author Wang Rongqiang
     * @Description //TODO 在不同的位置插入不同运算符
     * @date 2021/5/9 19:03
     */
    private void insertSymbol() {
        char[] oper = new char[3];
        int i, j, k;
        for (i = 0; i < 4; i++) {    //对4种运算符的3个位置排列
            oper[0] = symbol[i];
            for (j = 0; j < 4; j++) {
                oper[1] = symbol[j];
                for (k = 0; k < 4; k++) {
                    oper[2] = symbol[k];
                    // 构建运算表达式
                    getResult(oper);
                }
            }
        }
    }

    /**
     * @return void
     * @params [oper]
     * @author Wang Rongqiang
     * @Description //TODO 根据运算符号集构建计算式并验证
     * @date 2021/5/9 19:16
     */
    private void getResult(char[] oper) {
        // 记录运算结果
        double t;
        //穷举运算次序
        //1.((A*B)*C)*D
        t = 0;
        t = getValue(num[0], num[1], oper[0]);
        t = getValue(t, num[2], oper[1]);
        t = getValue(t, num[3], oper[2]);
        // 验证运算结果
        if (Math.abs(t - 24) < 0.0001) {
            result.add("((" + card[num[0] - 1] + " " + oper[0] + " " + card[num[1] - 1] + ") "
                    + oper[1] + " " + card[num[2] - 1] + ") " + oper[2] + " " + card[num[3] - 1] + " = 24");
            return;
        }

        //2.(A*(B*C))*D
        t = 0;
        t = getValue(num[1], num[2], oper[1]);
        t = getValue(num[0], t, oper[0]);
        t = getValue(t, num[3], oper[2]);
        // 验证运算结果
        if (Math.abs(t - 24) < 0.0001) {
            result.add("(" + card[num[0] - 1] + " " + oper[0] + " (" + card[num[1] - 1] + " " +
                    oper[1] + " " + card[num[2] - 1] + ")) " + oper[2] + " " + card[num[3] - 1] + " = 24");
            return;
        }

        //3.(A*B)*(C*D)
        t = 0;
        t = getValue(getValue(num[0], num[1], oper[0]), getValue(num[2], num[3], oper[2]), oper[1]);
        // 验证运算结果
        if (Math.abs(t - 24) < 0.0001) {
            result.add("(" + card[num[0] - 1] + " " + oper[0] + " " + card[num[1] - 1] + ") " +
                    oper[1] + " (" + card[num[2] - 1] + " " + oper[2] + " " + card[num[3] - 1] + ") = 24");
            return;
        }

        //4.A*(B*(C*D))
        t = 0;
        t = getValue(num[2], num[3], oper[2]);
        t = getValue(num[1], t, oper[1]);
        t = getValue(num[0], t, oper[0]);
        // 验证运算结果
        if (Math.abs(t - 24) < 0.0001) {
            result.add(card[num[0] - 1] + " " + oper[0] + " (" + card[num[1] - 1] + " " +
                    oper[1] + " (" + card[num[2] - 1] + " " + oper[2] + " " + card[num[3] - 1] + ")) = 24");
            return;
        }

        //5.A*((B*C)*D)
        t = 0;
        t = getValue(num[1], num[2], oper[1]);
        t = getValue(t, num[3], oper[2]);
        t = getValue(num[0], t, oper[0]);
        // 验证运算结果
        if (Math.abs(t - 24) < 0.0001) {
            result.add(card[num[0] - 1] + " " + oper[0] + " ((" + card[num[1] - 1] + " " +
                    oper[1] + " " + card[num[2] - 1] + ") " + oper[2] + " " + card[num[3] - 1] + ") = 24");
        }
    }

    /**
     * @return double
     * @params [a, b, symb]
     * @author Wang Rongqiang
     * @Description //TODO 计算a b两数根据symb符号进行运算的结果
     * @date 2021/5/10 19:40
     */
    private double getValue(double a, double b, char symb) {
        double result = 0;

        switch (symb) {
            case '+':
                result = a + b;
                break;
            case '-':
                result = a - b;
                break;
            case '*':
                result = a * b;
                break;
            case '/':
                result = a / b;
                break;
            default:
                break;
        }

        return result;

    }

总结

此次程序设计方法学的作业,让我学到了很多,让我加深了对穷举法的认识,训练了我运用穷举法解决实际问题的能力。同时让我对java的面向对象的编程思想又有了更深层的理解。我将会继续将这种思想运用在自己的程序设计中,强化自己的技能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值