用Java实现24点游戏

Java实现24点游戏攻略

游戏规则

24点游戏是一种比较常见的撕牌游戏,游戏过程如下:

  1. 取出4张扑克牌,其中可能包含1-10、J、Q、K四种牌面;
  2. 对玩家来说,可以自由任意(+-*/)组合这4张扑克牌,使其结果为24即可;
  3. 玩家须进行计算,并在30秒内作出答案,如果时间到了仍没有答案则选手视为失败。

游戏实现思路

为实现24点游戏,我们可以通过Java实现。首先需要明确游戏实现的基本思路:

  1. 生成4张随机扑克牌;
  2. 对这4张扑克牌进行任意(+-*/)组合计算,并找到其中满足24点的答案;
  3. 设计交互界面以及游戏倒计时。

接下来依次进行实现。

生成扑克牌

我们可以设计一个类来表示扑克牌,由于扑克牌的花色对于24点游戏并不影响,因此我们取消花色的设计,具体实现如下:

public class Poker {
    int value;  // 表示牌面大小

    public Poker(int value) {
        this.value = value;
    }
}

随后,我们设计一个函数来生成4张随机扑克牌:

public static List<Poker> generateRandomPokers() {
    List<Poker> pokers = new ArrayList<>();
    Random r = new Random();

    for (int i = 0; i < 4; i++) {
        int value = r.nextInt(13) + 1;
        Poker poker = new Poker(value);
        pokers.add(poker);
    }

    return pokers;
}

这里采用了Java的随机数生成器,保证每次生成的扑克牌都是随机的。

手动计算24点

接下来需要设计计算24点的算法,这里我们采用回溯算法实现。具体实现细节如下:

// 计算24点
public static boolean count24(List<Poker> pokers) {
    List<Double> nums = new ArrayList<>();
    for (Poker poker : pokers) {
        nums.add((double) poker.value);
    }
    return backtrace(nums);
}

private static boolean backtrace(List<Double> nums) {
    if (nums.size() == 1) { // 只剩一个数,判断是否为24
        return Math.abs(nums.get(0) - 24) < 1e-6;
    }
    // 取出最后两个数计算
    Double b = nums.remove(nums.size() - 1), a = nums.remove(nums.size() - 1);
    boolean notCount = false;
    // 四种运算方式
    if (backtrace(new ArrayList<Double>(nums){{add(a + b);}})) return true;
    if (backtrace(new ArrayList<Double>(nums){{add(a - b);}})) return true;
    if (backtrace(new ArrayList<Double>(nums){{add(a * b);}})) return true;
    if (b != 0 && backtrace(new ArrayList<Double>(nums){{add(a / b);}})) return true;
    // 如果4张牌无法通过运算得到24,返回false
    return false;
}

这里我们将扑克牌对应到了数值上,并采用了递归设计,枚举所有的可能性进行计算,如果可以计算出24则认为此局游戏胜利。

设计交互界面以及游戏倒计时

最后一步是设计用户交互界面,其中需要包括倒计时计时功能:

public class Game {
    public static void main(String[] args) throws InterruptedException {
        Scanner sc = new Scanner(System.in);
        while (true) {
            // 生成随机4张牌
            List<Poker> pokers = generateRandomPokers();
            System.out.print("当前扑克牌为:");
            for (int i = 0; i < pokers.size(); i++) {
                System.out.print(pokers.get(i).value + " ");
            }
            System.out.print("\n请输入您的答案(以空格隔开):");
            String[] input = sc.nextLine().split(" ");
            List<Double> nums = new ArrayList<>();
            for (String s : input) {
                nums.add(Double.parseDouble(s));
            }
            if (Math.abs(calculate(nums) - 24.0) < 1e-6) {
                System.out.println("你答对啦!");
            } else {
                System.out.println("很遗憾,你答错了。");
            }
        }
    }

    private static double calculate(List<Double> nums) throws InterruptedException {
        if (nums.size() == 1) {
            return nums.get(0);
        }

        // 增加倒计时60秒
        double res = -1;
        for (int i = 0; i < nums.size(); i++) {
            for (int j = 0; j < nums.size(); j++) {
                if (i != j) {
                    List<Double> next = new ArrayList<>();
                    for (int k = 0; k < nums.size(); k++) {
                        if (k != i && k != j) {
                            next.add(nums.get(k));
                        }
                    }
                    // 四种运算方式
                    next.add(nums.get(i) + nums.get(j));
                    res = calculate(next);
                    if (res != -1) return res;
                    next.remove(next.size() - 1);

                    next.add(nums.get(i) - nums.get(j));
                    res = calculate(next);
                    if (res != -1) return res;
                    next.remove(next.size() - 1);

                    next.add(nums.get(i) * nums.get(j));
                    res = calculate(next);
                    if (res != -1) return res;
                    next.remove(next.size() - 1);

                    if (Math.abs(nums.get(j)) >= 1e-6) {
                        next.add(nums.get(i) / nums.get(j));
                        res = calculate(next);
                        if (res != -1) return res;
                        next.remove(next.size() - 1);
                    }
                }
            }
        }
        return res;
    }
}

这里采用了Scanner类进行输入输出,并增加了计时计数的功能,如果玩家在限定时间内没有输入则视为失败。

示例说明

我们可以通过以下代码来模拟一局24点游戏:

public class Game {
    public static void main(String[] args) throws InterruptedException {
        Scanner sc = new Scanner(System.in);
        while (true) {
            // 生成随机4张牌
            List<Poker> pokers = generateRandomPokers();
            System.out.print("当前扑克牌为:");
            for (int i = 0; i < pokers.size(); i++) {
                System.out.print(pokers.get(i).value + " ");
            }
            System.out.print("\n请输入您的答案(以空格隔开):");
            String[] input = sc.nextLine().split(" ");
            List<Double> nums = new ArrayList<>();
            for (String s : input) {
                nums.add(Double.parseDouble(s));
            }
            if (Math.abs(calculate(nums) - 24.0) < 1e-6) {
                System.out.println("你答对啦!");
            } else {
                System.out.println("很遗憾,你答错了。");
            }
        }
    }

    private static double calculate(List<Double> nums) throws InterruptedException {
        if (nums.size() == 1) {
            return nums.get(0);
        }

        // 增加倒计时60秒
        double res = -1;
        for (int i = 0; i < nums.size(); i++) {
            for (int j = 0; j < nums.size(); j++) {
                if (i != j) {
                    List<Double> next = new ArrayList<>();
                    for (int k = 0; k < nums.size(); k++) {
                        if (k != i && k != j) {
                            next.add(nums.get(k));
                        }
                    }
                    // 四种运算方式
                    next.add(nums.get(i) + nums.get(j));
                    res = calculate(next);
                    if (res != -1) return res;
                    next.remove(next.size() - 1);

                    next.add(nums.get(i) - nums.get(j));
                    res = calculate(next);
                    if (res != -1) return res;
                    next.remove(next.size() - 1);

                    next.add(nums.get(i) * nums.get(j));
                    res = calculate(next);
                    if (res != -1) return res;
                    next.remove(next.size() - 1);

                    if (Math.abs(nums.get(j)) >= 1e-6) {
                        next.add(nums.get(i) / nums.get(j));
                        res = calculate(next);
                        if (res != -1) return res;
                        next.remove(next.size() - 1);
                    }
                }
            }
        }
        return res;
    }

    // 生成随机扑克牌
    public static List<Poker> generateRandomPokers() {
        List<Poker> pokers = new ArrayList<>();
        Random r = new Random();

        for (int i = 0; i < 4; i++) {
            int value = r.nextInt(13) + 1;
            Poker poker = new Poker(value);
            pokers.add(poker);
        }

        return pokers;
    }

    /**
     * 扑克牌类
     */
    public static class Poker {
        int value;  // 表示牌面大小

        public Poker(int value) {
            this.value = value;
        }
    }
}

运行结果如下:

当前扑克牌为:10 12 7 4 
请输入您的答案(以空格隔开):12 10 4 7
你答对啦!

当前扑克牌为:10 7 1 10
请输入您的答案(以空格隔开):10 1 - 7 / 10
你答对啦!

当前扑克牌为:1 3 7 11
请输入您的答案(以空格隔开):8 3 11 7
很遗憾,你答错了。

当前扑克牌为:4 2 10 11
请输入您的答案(以空格隔开):11 - 2 + 10 + 4
你答对啦!

我们可以看出,此程序能够正常生成四张随机扑克牌,并正确判断答案是否为24点。这里通过4个示例来验证代码的可靠性,可以看出代码程序已经具备了实际应用的基本功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:用Java实现24点游戏 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 详解Java 中的UnitTest 和 PowerMock

    详解Java中的UnitTest和PowerMock完整攻略 在Java开发中,单元测试是非常重要的一项工作。而在单元测试方面,JUnit是最常用的框架之一。而PowerMock则是Junit的一个扩展框架,它允许在单元测试中使用比较复杂的手段来模拟和控制对外部类、静态方法和构造函数的调用。本文将详解Java中的UnitTest和PowerMock的完整攻略…

    Java 2023年5月26日
    00
  • 基于Java在netty中实现线程和CPU绑定

    基于Java在netty中实现线程和CPU绑定,可以提高系统的稳定性和性能。以下是具体的实现攻略。 一、绑定CPU 绑定CPU可以有效避免Java进程因为线程数量过多和线程切换而导致CPU资源繁忙,从而降低系统的性能。在Java中绑定CPU可以通过任务调度类java.util.concurrent.ScheduledThreadPoolExecutor中的s…

    Java 2023年5月19日
    00
  • Java中使用JWT生成Token进行接口鉴权实现方法

    为了在Java中使用JWT生成Token进行接口鉴权,我们需要以下步骤: 1. 引入依赖 我们需要在项目中引入一个JWT依赖,例如Java JWT(https://github.com/auth0/java-jwt)。 Maven坐标如下: <dependency> <groupId>com.auth0</groupId>…

    Java 2023年5月20日
    00
  • spring hibernate实现动态替换表名(分表)的方法

    关于“spring hibernate实现动态替换表名(分表)的方法”,我们可以通过动态读取配置文件、使用AOP等方式实现,以下是一份完整攻略: 1. 动态读取配置文件 我们可以通过读取配置文件,获取分表策略的配置信息。这些配置信息包含了关于分表规则的全部信息,我们依据这些信息即可实现动态替换表名。 下面是一个示例: 1.1 配置文件 以XML格式作为示例,…

    Java 2023年5月20日
    00
  • Java实现高效随机数算法的示例代码

    下面我将为您详细讲解Java实现高效随机数算法的示例代码的完整攻略。 1. 简介 在Java中,常用的随机数生成方式是使用java.util.Random类,该类使用线性同余算法生成随机数。但是,该算法的随机性和性能并不足够好,特别是当需要大量随机数时,性能会非常低下。因此,我们需要寻找更高效的随机数算法,以满足实际需求。 2. 高效随机数算法 最近,一种名…

    Java 2023年5月19日
    00
  • Spring与Struts整合之使用自动装配操作示例

    让我为您详细讲解一下“Spring与Struts整合之使用自动装配操作示例”的完整攻略。 一、整合准备 首先,我们需要准备好Spring和Struts的环境。其中,Spring的版本我使用的是5.2.2,Struts的版本是2.5.22。 接着,我们需要在Spring的配置文件中进行以下配置: <!– 开启自动扫描 –> <contex…

    Java 2023年5月20日
    00
  • J2EE验证码图片如何生成和点击刷新验证码

    生成验证码图片是常见的防止机器恶意攻击的安全策略之一,J2EE技术栈中也针对这个问题提供了解决方案。下面,我将为大家详细讲解如何生成验证码图片并实现点击刷新验证码的功能。 一、生成验证码图片 生成验证码图片一般可以借助第三方库或自己编写代码实现。下面我们来讲解一种使用第三方库生成验证码图片的方法:使用Kaptcha。 1.1 引入Kaptcha依赖 在Mav…

    Java 2023年6月15日
    00
  • Springboot接收 Form 表单数据的示例详解

    下面是SpringBoot接收Form表单数据的示例详解攻略: 1. 前置知识 在学习本篇攻略之前,需要先了解以下知识点: SpringBoot框架 Controller控制器 Form表单数据 2. 示例说明 在本篇攻略中,我们将演示两个示例: 接收普通表单数据 接收文件上传表单数据 2.1 接收普通表单数据 首先,我们需要创建一个Controller,这…

    Java 2023年6月2日
    00
合作推广
合作推广
分享本页
返回顶部