java作业练习:24点

本文介绍了一款使用Java编写的24点游戏程序。该程序通过穷举法计算四张扑克牌(数值1至13)的所有可能组合,以找出能够通过加减乘除运算得到24的牌组,并输出所有不重复的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作业题目:24点游戏

所用语言:java

所用类:Main    MainTest

其他文件:null

程序流程:Main方法中开始执行程序,获得一组范围由1到13的(闭区间)4张牌组,通过穷举法把四张牌两两运算(加减乘除)得出最后结果是24的卡组视为胜出。若没有得出24的卡组视为失败,随即下一组继续运算直到发现存在24的卡组,然后输出不带重复的得出24的数学表达式。

代码如下:

import java.util.ArrayList;
import java.util.Random;

public class Main {
    public static void main(String[] args) {
        boolean flag = true;//判断第一个出现24点的人
        System.out.println("all right,游戏开始~!!");
        while (flag) {
            System.out.println("发牌ing");
            ArrayList<Integer> random = getCardNumber();//获得4个范围由1到13的随机卡组
            System.out.println("这组牌是"+random);
            flag = gameStart(random);//传入参数正式开始运算
            if (flag == true) {
                System.out.println("这组牌没有24点,下一组");
            }
        }
    }

    private static boolean gameStart(ArrayList<Integer> random) {
        ArrayList<String> allOpeations = new ArrayList<>();//用于存储所有的运算式
        boolean isExist = true;//给主函数返回计算结果,判断是否存在运算可以算的24
        int first = 0, second = 0, third = 0;//first第一轮运算的运算符,second第二轮运算的运算符,third第三轮运算的运算符
        //穷举法计算各种情况
        for (first = 0; first < 4; first++) {
            for (int i = 0; i < 4; i++)
                for (int j = 0; j < 4; j++) {
                    if (i != j) {
                        double result1 = CaculateResults((double) random.get(i), (double) random.get(j), first);
                        String[] operators = new String[3];
                        operators[0] = getOperator(first);
                        for (second = 0; second < 4; second++) {
                            for (int k = 0; k < 4; k++) {
                                if (k != i && k != j) {
                                    double result2 = CaculateResults(result1, (double) random.get(k), second);
                                    operators[1] = getOperator(second);
                                    for (third = 0; third < 4; third++) {
                                        for (int m = 0; m < 4; m++) {
                                            if (m != i && m != j && m != k) {
                                                double result3 = CaculateResults(result2, (double) random.get(m), third);
                                                operators[2] = getOperator(third);
                                                if (result3 == 24) {
                                                    //最后的格式是两两运算的顺序
                                                    allOpeations.add("[" + "(" + random.get(i) + operators[0] + random.get(j) + ")" + operators[1] + random.get(k) + "]" + operators[2] + random.get(m));
                                                    isExist = false;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
        }
        //把所有的公式传参后去排除相同的公式
        showResults(allOpeations);
        return isExist;
    }

    private static void showResults(ArrayList<String> allOpeations) {
        System.out.println("看来我们已经有了一个赢家!而且他的组合牌是!");
        ArrayList<String> list1 = new ArrayList();//list1用来存放所有的()小括号里的表达式,只要确保()小括号里的表达式一至就能有效排除相同的公式
        //分割表达式
        for (int i = 0; i < allOpeations.size(); i++) {
            list1.add(splitString(allOpeations.get(i), "(", ")"));
        }
        //list2用来存放所有相同的方程式,有多少相同的就放多少,最后用于删除
        ArrayList<String> list2 = new ArrayList<>();
        for (int i = 0; i < list1.size(); i++) {
            for (int index = 0; index < list1.get(i).length(); index++) {
                //遍历表达式判断运算符,因为+和*有特殊性
                if (list1.get(i).charAt(index) == '+') {
                    String[] temp = list1.get(i).split("[+]");
                    String chekStr = temp[1] + "+" + temp[0];
                    allOpeations.get(i).replaceAll(list1.get(i), chekStr);
                    for (int j = i + 1; j < allOpeations.size(); j++) {
                        if (allOpeations.get(i).equals(allOpeations.get(j))) {
                            list2.add(allOpeations.get(i));
                            break;
                        }
                    }
                } else if (list1.get(i).charAt(index) == '*') {
                    String[] temp = list1.get(i).split("[*]");
                    String chekStr = temp[1] + "*" + temp[0];
                    allOpeations.get(i).replaceAll(list1.get(i), chekStr);
                    for (int j = i + 1; j < allOpeations.size(); j++) {
                        if (allOpeations.get(i).equals(allOpeations.get(j))) {
                            list2.add(allOpeations.get(i));
                            break;
                        }
                    }
                } else if (list1.get(i).charAt(index) == '-') {
                    for (int a = i + 1; a < list1.size(); a++) {
                        if (allOpeations.get(a).equals(allOpeations.get(i))) {
                            list2.add(allOpeations.get(i));
                            break;
                        }
                    }
                } else if (list1.get(i).charAt(index) == '/') {
                    for (int a = i + 1; a < list1.size(); a++) {

                        if (allOpeations.get(a).equals(allOpeations.get(i))) {
                            list2.add(allOpeations.get(i));
                            break;
                        }
                    }
                }
            }
        }
        //删除所有表达式中存在于list2的表达式
        for (int j = 0; j < list2.size(); j++)
        {
            String temp = list2.get(j);
            allOpeations.remove(temp);
        }
        //输出不一样的表达式
        for (int length = 0; length < allOpeations.size(); length++)
        {
            System.out.println(allOpeations.get(length));
        }
    }
    //用于分割表达式,有目标表达式,分割开始的字符(串),分割结束的字符(串)
    public static String splitString(String target, String begin, String end) {
        int left = target.indexOf(begin);
        int right = target.indexOf(end);
        String result = target.substring(left + 1, right);
        return result;
    }
//根据运算的参数来判断返回到公式里的运算符
    private static String getOperator(int first) {
        String str = null;
        if (first == 0)
            return str = "+";
        if (first == 1)
            return str = "-";
        if (first == 2)
            return str = "*";
        if (first == 3)
            return str = "/";
        return str;
    }
//用参数判断计算的类型
    private static double CaculateResults(double x, double y, int operator) {
        double result = 0;
        if (operator == 0) {
            result = x + y;
            return result;
        }
        if (operator == 1) {
            result = x - y;
            return result;
        }
        if (operator == 2) {
            result = x * y;
            return result;
        }
        if (operator == 3) {
            if (y != 0) {
                result = x / y;
                return result;
            }
        }
        return result;
    }
//获得随机牌组
    public static ArrayList getCardNumber() {
        Random random = new Random();
        ArrayList<Integer> randomNumber = new ArrayList();
        while (randomNumber.size() != 4) {
            int i = random.nextInt(14);
            if (i > 0) {
                if (randomNumber.size() == 0) {
                    randomNumber.add(i);
                } else {
                    randomNumber.add(i);
                }
            }
        }
        return randomNumber;
    }
}

 


不要急着关!不要慌!看我给你慢慢道来!!!

我的程序计算上可能比较繁琐,但是比较好理解。

首先:

程序由Main开始

 public static void main(String[] args) {
        boolean flag = true;//判断第一个出现24点的人
        System.out.println("all right,游戏开始~!!");
        while (flag) {
            System.out.println("发牌ing");
            ArrayList<Integer> random = getCardNumber();//获得4个范围由1到13的随机卡组
            System.out.println("这组牌是"+random);
            flag = gameStart(random);//传入参数正式开始运算
            if (flag == true) {
                System.out.println("这组牌没有24点,下一组");
            }
        }
    }

random是获得随机数的牌组,怎么获得的呢??通过限制随机数的范围和随机数的数量,拿到了就跟扑克牌一样A(1),2,3,4,5,6,7,8,9,10,J(11),K(12),Q(13),没有王。返回了一个存放整数的列表。

public static ArrayList getCardNumber() {
        Random random = new Random();
        ArrayList<Integer> randomNumber = new ArrayList();
        while (randomNumber.size() != 4) {
            int i = random.nextInt(14);
            if (i > 0) {
                if (randomNumber.size() == 0) {
                    randomNumber.add(i);
                } else {
                    randomNumber.add(i);
                }
            }
        }
        return randomNumber;
    }

拿到卡之后就发卡?,flag用来标记能通过两两运算后得到的结果来判断游戏什么时候结束。

boolean flag = true;//判断第一个出现24点的人
        System.out.println("all right,游戏开始~!!");
        while (flag) {
            System.out.println("发牌ing");
            ArrayList<Integer> random = getCardNumber();//获得4个范围由1到13的随机卡组
            System.out.println("这组牌是"+random);
            flag = gameStart(random);//传入参数正式开始运算
            if (flag == true) {
                System.out.println("这组牌没有24点,下一组");
            }
        }

 来!算!?代码里注释给的很清楚,从下面的for开始就是在选择两两数字去计算,具体计算在CaculateResults里计算,注意其中的first用来标注第一次运算的运算符。second 和 third的用法一样。

 private static boolean gameStart(ArrayList<Integer> random) {
        ArrayList<String> allOpeations = new ArrayList<>();//用于存储所有的运算式
        boolean isExist = true;//给主函数返回计算结果,判断是否存在运算可以算的24
        int first = 0, second = 0, third = 0;//first第一轮运算的运算符,second第二轮运算的运算符,third第三轮运算的运算符
        //穷举法计算各种情况
        for (first = 0; first < 4; first++) {
            for (int i = 0; i < 4; i++)
                for (int j = 0; j < 4; j++) {
                    if (i != j) {
                        double result1 = CaculateResults((double) random.get(i), (double) random.get(j), first);
                        String[] operators = new String[3];
                        operators[0] = getOperator(first);
                        for (second = 0; second < 4; second++) {
                            for (int k = 0; k < 4; k++) {
                                if (k != i && k != j) {
                                    double result2 = CaculateResults(result1, (double) random.get(k), second);
                                    operators[1] = getOperator(second);
                                    for (third = 0; third < 4; third++) {
                                        for (int m = 0; m < 4; m++) {
                                            if (m != i && m != j && m != k) {
                                                double result3 = CaculateResults(result2, (double) random.get(m), third);
                                                operators[2] = getOperator(third);
                                                if (result3 == 24) {
                                                    //最后的格式是两两运算的顺序
                                                    allOpeations.add("[" + "(" + random.get(i) + operators[0] + random.get(j) + ")" + operators[1] + random.get(k) + "]" + operators[2] + random.get(m));
                                                    isExist = false;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
        }
        //把所有的公式传参后去排除相同的公式
        showResults(allOpeations);
        return isExist;
    }

而CacluateResults是这样实现的?,很简单对吧。

private static double CaculateResults(double x, double y, int operator) {
        double result = 0;
        if (operator == 0) {
            result = x + y;
            return result;
        }
        if (operator == 1) {
            result = x - y;
            return result;
        }
        if (operator == 2) {
            result = x * y;
            return result;
        }
        if (operator == 3) {
            if (y != 0) {
                result = x / y;
                return result;
            }
        }
        return result;
    }

那每次运算后要把包括运算符和数字存放到allOpeations中来存放所有的运算式,那肯定要确定存放某个运算式的时候考虑怎么存放这个运算符,存放哪个运算符对吧,?这里头的first只是个参数,不要和上面的first混淆。

private static String getOperator(int first) {
        String str = null;
        if (first == 0)
            return str = "+";
        if (first == 1)
            return str = "-";
        if (first == 2)
            return str = "*";
        if (first == 3)
            return str = "/";
        return str;
    }

算完了拿到结果了最后就是筛选结果。怎么获得不带重复样的表达式呢??

 private static void showResults(ArrayList<String> allOpeations) {
        System.out.println("看来我们已经有了一个赢家!而且他的组合牌是!");
        ArrayList<String> list1 = new ArrayList();//list1用来存放所有的()小括号里的表达式,只要确保()小括号里的表达式一至就能有效排除相同的公式
        //分割表达式
        for (int i = 0; i < allOpeations.size(); i++) {
            list1.add(splitString(allOpeations.get(i), "(", ")"));
        }
        //list2用来存放所有相同的方程式,有多少相同的就放多少,最后用于删除
        ArrayList<String> list2 = new ArrayList<>();
        for (int i = 0; i < list1.size(); i++) {
            for (int index = 0; index < list1.get(i).length(); index++) {
                //遍历表达式判断运算符,因为+和*有特殊性
                if (list1.get(i).charAt(index) == '+') {
                    String[] temp = list1.get(i).split("[+]");
                    String chekStr = temp[1] + "+" + temp[0];
                    allOpeations.get(i).replaceAll(list1.get(i), chekStr);
                    for (int j = i + 1; j < allOpeations.size(); j++) {
                        if (allOpeations.get(i).equals(allOpeations.get(j))) {
                            list2.add(allOpeations.get(i));
                            break;
                        }
                    }
                } else if (list1.get(i).charAt(index) == '*') {
                    String[] temp = list1.get(i).split("[*]");
                    String chekStr = temp[1] + "*" + temp[0];
                    allOpeations.get(i).replaceAll(list1.get(i), chekStr);
                    for (int j = i + 1; j < allOpeations.size(); j++) {
                        if (allOpeations.get(i).equals(allOpeations.get(j))) {
                            list2.add(allOpeations.get(i));
                            break;
                        }
                    }
                } else if (list1.get(i).charAt(index) == '-') {
                    for (int a = i + 1; a < list1.size(); a++) {
                        if (allOpeations.get(a).equals(allOpeations.get(i))) {
                            list2.add(allOpeations.get(i));
                            break;
                        }
                    }
                } else if (list1.get(i).charAt(index) == '/') {
                    for (int a = i + 1; a < list1.size(); a++) {

                        if (allOpeations.get(a).equals(allOpeations.get(i))) {
                            list2.add(allOpeations.get(i));
                            break;
                        }
                    }
                }
            }
        }
        //删除所有表达式中存在于list2的表达式
        for (int j = 0; j < list2.size(); j++)
        {
            String temp = list2.get(j);
            allOpeations.remove(temp);
        }
        //输出不一样的表达式
        for (int length = 0; length < allOpeations.size(); length++)
        {
            System.out.println(allOpeations.get(length));
        }
    }

然后输出就OK了呀?。

游戏截图:

Coder:Flyige

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值