用Python写一个算24点的小程序

一、运行界面

二、显示答案——递归介绍

工作流程:

1. 基本情况:函数首先检查输入的数字列表 nums 的长度。如果列表中只剩下一个数字,它会判断这个数字是否接近 24(使用 abs(nums[0] - 24) < 1e-10 来处理浮点数精度问题)。如果是,它返回 True 和这个数字的字符串表示;否则返回 False 和空字符串。

2. 递归组合:如果列表中有多个数字,函数会通过双重循环选择两个数字 a 和 b(nums[i] 和 nums[j]),并从列表中移除这两个数字,形成一个新的数字列表 remaining。

3. 运算符尝试:接下来,函数会遍历定义的运算符字典 ops,对选中的两个数字进行运算。对于每个运算符,函数会尝试计算 result = ops[op](a, b)。如果运算符是除法,还会检查除数 b 是否为零,以避免除以零的错误。

4. 递归调用:如果运算成功,函数会递归调用 evaluate,将计算结果 result 和剩余的数字列表 remaining 组合成新的列表进行下一轮计算。如果在递归中找到了有效的解法,函数会返回成功的标志和相应的算式字符串。

5. 返回结果:如果所有组合都尝试过后仍未找到解法,函数会返回 False 和空字符串。

以输入数字[4, 2, 3, 1]为例:

步骤操作说明
1选择4和1进行加法运算 → 5剩余数字变为[2, 3, 5]
2选择5和3进行乘法运算 → 15剩余数字变为[2, 15]
3选择15和2进行减法运算 → 13未满足24,回溯尝试其他路径
4找到有效路径如 (4*(3*(2/1)))最终返回算式字符串‌

三、完整代码

"""
24点游戏
这是一个使用tkinter开发的24点游戏,玩家需要使用给定的4个数字和基本运算符(+、-、*、/)计算出24。
"""

import tkinter as tk
from tkinter import messagebox
import random
import itertools
import operator


class TwentyFourGame:
    """
    24点游戏的主类
    负责创建游戏界面、处理游戏逻辑和用户交互
    """

    def __init__(self):
        """
        初始化游戏窗口和基本设置
        创建主窗口、设置样式、初始化游戏变量
        """
        self.window = tk.Tk()
        self.window.title("24点游戏")
        self.window.geometry("400x500")
        self.window.configure(bg="#f0f0f0")

        # 设置界面样式
        self.style = {
            'bg': "#f0f0f0",  # 背景色
            'button_bg': "#4CAF50",  # 按钮背景色
            'button_fg': "white",  # 按钮文字颜色
            'font': ("Arial", 12),  # 字体设置
            'entry_bg': "white",  # 输入框背景色
            'entry_fg': "black"  # 输入框文字颜色
        }

        # 创建游戏界面组件
        self.create_widgets()

        # 初始化游戏数据
        self.numbers = []  # 存储当前游戏的4个数字
        self.solution = ""  # 存储当前游戏的解法
        self.new_game()  # 开始新游戏

    def create_widgets(self):
        """
        创建游戏界面的所有组件
        包括标题、数字显示区、输入框、按钮等
        """
        # 创建游戏标题
        title = tk.Label(
            self.window,
            text="24点游戏",
            font=("Arial", 20, "bold"),
            bg=self.style['bg']
        )
        title.pack(pady=20)

        # 创建数字显示区域
        self.numbers_frame = tk.Frame(self.window, bg=self.style['bg'])
        self.numbers_frame.pack(pady=20)

        # 创建4个数字标签
        self.number_labels = []
        for i in range(4):
            label = tk.Label(
                self.numbers_frame,
                text="",
                font=self.style['font'],
                width=4,
                height=2,
                relief="solid",
                bg=self.style['entry_bg']
            )
            label.pack(side=tk.LEFT, padx=5)
            self.number_labels.append(label)

        # 创建算式输入框
        self.expression_var = tk.StringVar()
        self.expression_entry = tk.Entry(
            self.window,
            textvariable=self.expression_var,
            font=self.style['font'],
            width=30,
            bg=self.style['entry_bg'],
            fg=self.style['entry_fg']
        )
        self.expression_entry.pack(pady=20)

        # 创建按钮区域
        button_frame = tk.Frame(self.window, bg=self.style['bg'])
        button_frame.pack(pady=20)

        # 创建提交答案按钮
        submit_btn = tk.Button(
            button_frame,
            text="提交答案",
            command=self.check_answer,
            font=self.style['font'],
            bg=self.style['button_bg'],
            fg=self.style['button_fg'],
            width=10
        )
        submit_btn.pack(side=tk.LEFT, padx=5)

        # 创建新游戏按钮
        new_game_btn = tk.Button(
            button_frame,
            text="新游戏",
            command=self.new_game,
            font=self.style['font'],
            bg=self.style['button_bg'],
            fg=self.style['button_fg'],
            width=10
        )
        new_game_btn.pack(side=tk.LEFT, padx=5)

        # 创建显示答案按钮
        show_answer_btn = tk.Button(
            button_frame,
            text="显示答案",
            command=self.show_answer,
            font=self.style['font'],
            bg=self.style['button_bg'],
            fg=self.style['button_fg'],
            width=10
        )
        show_answer_btn.pack(side=tk.LEFT, padx=5)

        # 创建提示标签
        self.hint_label = tk.Label(
            self.window,
            text="请输入算式,使用 + - * / 和括号",
            font=self.style['font'],
            bg=self.style['bg']
        )
        self.hint_label.pack(pady=10)

    def new_game(self):
        """
        开始新游戏
        随机生成4个1-9之间的数字,并计算一个可能的解法
        """
        self.numbers = [random.randint(1, 9) for _ in range(4)]
        for i, num in enumerate(self.numbers):
            self.number_labels[i].config(text=str(num))
        self.expression_var.set("")
        self.solution = self.find_solution()

    def find_solution(self):
        """
        寻找当前数字组合的一个可能解法
        使用递归方法尝试所有可能的运算组合
        返回:如果找到解法返回算式字符串,否则返回"无解"
        """
        # 定义基本运算符
        ops = {
            '+': operator.add,
            '-': operator.sub,
            '*': operator.mul,
            '/': operator.truediv
        }

        def evaluate(nums):
            """
            递归计算所有可能的运算组合
            参数:
                nums: 待计算的数字列表
            返回:
                (是否找到解法, 算式字符串)
            """
            if len(nums) == 1:
                return abs(nums[0] - 24) < 1e-10, str(nums[0])

            # 尝试所有可能的数字组合和运算符
            for i in range(len(nums)):
                for j in range(i + 1, len(nums)):
                    a, b = nums[i], nums[j]
                    remaining = nums[:i] + nums[i + 1:j] + nums[j + 1:]

                    for op in ops:
                        try:
                            result = ops[op](a, b)
                            if op == '/':
                                if abs(b) < 1e-10:  # 避免除以0
                                    continue
                            success, expr = evaluate(remaining + [result])
                            if success:
                                return True, f"({a}{op}{b}){expr}"
                        except:
                            continue
            return False, ""

        success, expr = evaluate(self.numbers)
        return expr if success else "无解"

    def check_answer(self):
        """
        检查用户输入的答案是否正确
        验证:
        1. 是否只使用了给定的数字
        2. 计算结果是否等于24
        """
        try:
            expr = self.expression_var.get()
            # 移除所有空格
            expr = expr.replace(" ", "")
            # 检查是否只使用了给定的数字
            used_nums = [int(n) for n in expr if n.isdigit()]
            if sorted(used_nums) != sorted(self.numbers):
                messagebox.showerror("错误", "请只使用给定的数字!")
                return

            result = eval(expr)
            if abs(result - 24) < 1e-10:
                messagebox.showinfo("恭喜", "答案正确!")
            else:
                messagebox.showerror("错误", f"计算结果为 {result},不等于24")
        except:
            messagebox.showerror("错误", "请输入有效的算式!")

    def show_answer(self):
        """
        显示当前游戏的一个可能解法
        """
        if self.solution:
            messagebox.showinfo("答案", f"一个可能的解法:{self.solution}")
        else:
            messagebox.showinfo("答案", "这组数字无解!")

    def run(self):
        """
        运行游戏主循环
        """
        self.window.mainloop()


if __name__ == "__main__":
    game = TwentyFourGame()
    game.run()

四、Readme

## 功能特点

- 图形用户界面,操作简单直观
- 随机生成4个1-9之间的数字
- 支持基本的四则运算(+、-、*、/)和括号
- 实时验证答案的正确性
- 提供答案提示功能
- 支持开始新游戏

## 系统要求

- Python 3.x
- Tkinter(Python标准库,通常随Python一起安装)

## 安装说明

1. 确保您的系统已安装Python 3.x
2. 下载或克隆此仓库
3. 运行游戏:
   ```bash
   python 24_points_game.py
   ```

## 游戏规则

1. 游戏会随机生成4个1-9之间的数字
2. 使用这4个数字,通过加减乘除运算和括号,得到24
3. 每个数字必须且只能使用一次
4. 运算结果必须精确等于24

## 使用方法

1. 启动游戏后,界面会显示4个随机数字
2. 在输入框中输入您的算式(例如:`(3+5)*(6-3)`)
3. 点击"提交答案"按钮检查答案
4. 如果遇到困难,可以点击"显示答案"查看一个可能的解法
5. 随时可以点击"新游戏"开始新的挑战

## 注意事项

- 请确保输入的算式格式正确
- 只能使用给定的4个数字
- 每个数字只能使用一次
- 运算结果必须精确等于24

## 技术实现

- 使用Tkinter构建图形界面
- 实现了自动求解算法
- 包含输入验证和错误处理
- 采用面向对象编程方式开发

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/984219.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【长安大学】苹果手机/平板自动连接认证CHD-WIFI脚本(快捷指令)

背景&#xff1a; 已经用这个脚本的记得设置Wifi时候&#xff0c;关闭“自动登录” 前几天实在忍受不了CHD-WIFI动不动就断开&#xff0c;一天要重新连接&#xff0c;点登陆好几次。试了下在网上搜有没有CHD-WIFI的自动连接WIFI自动认证脚本&#xff0c;那样我就可以解放双手&…

双击PPT文件界面灰色不可用,需要再次打开该PPT文件才能正常打开

双击PPT文件界面灰色不可用&#xff0c;需要再次打开该PPT文件才能正常打开 1. 软件环境⚙️2. 问题描述&#x1f50d;3. 解决方法&#x1f421;解决步骤 4. 结果预览&#x1f914; 1. 软件环境⚙️ Windows10 或 Windows11 专业版64位&#xff0c;安装MotionGo软件&#xff08…

蓝桥杯[每日两题] 真题:好数 神奇闹钟 (java版)

题目一&#xff1a;好数 题目描述 一个整数如果按从低位到高位的顺序&#xff0c;奇数位&#xff08;个位、百位、万位 &#xff09;上的数字是奇数&#xff0c;偶数位&#xff08;十位、千位、十万位 &#xff09;上的数字是偶数&#xff0c;我们就称之为“好数”。给定…

蓝桥杯刷题周计划(第二周)

目录 前言题目一题目代码题解分析 题目二题目代码题解分析 题目三题目代码题解分析 题目四题目代码题解分析 题目五题目代码题解分析 题目六题目代码题解分析 题目七题目代码题解分析 题目八题目题解分析 题目九题目代码题解分析 题目十题目代码题解分析 题目十一题目代码题解分…

ThinkPHP框架

在电脑C磁盘中安装composer 命令 在电脑的D盘中创建cd文件夹 切换磁盘 创建tp框架 创建一个aa的网站&#xff0c;更换路径到上一步下载的tp框架路径 在管理中修改路径 下载压缩包public和view 将前面代码中的public和view文件替换 在PHPStom 中打开文件 运行指定路径 修改demo…

Spring学习笔记:工厂模式与反射机制实现解耦

1.什么是Spring? spring是一个开源轻量级的java开发应用框架&#xff0c;可以简化企业级应用开发 轻量级 1.轻量级(对于运行环境没有额外要求) 2.代码移植性高(不需要实现额外接口) JavaEE的解决方案 Spring更像是一种解决方案&#xff0c;对于控制层&#xff0c;它有Spring…

爬虫案例八js逆向爬取网易音乐

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、js逆向的前期准备二、网站分析三、代码 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 爬取网易音乐 提示&#xff1a;以下是本篇…

【02】Web网页基础

一、网页的组成 1、HTML 2、CSS 3、javascript 二、网页的结构 三、节点树及节点间的关系 四、选择器 一、网页的组成 网页可以分为三大部分 —— HTML、CSS 和 JavaScript。如果把网页比作一个人的话&#xff0c;HTML 相当于骨架&#xff0c;JavaScript 相当于肌肉&#…

Dify部署踩坑指南(Windows+Mac)

组件说明 Dify踩坑及解决方案 ⚠️ 除了修改镜像版本&#xff0c;nginx端口不要直接修改docker-compose.yaml &#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 1、更换镜像版本 这个文件是由.env自动生成的&#xff0c;在.env配置 …

​​《从事件冒泡到处理:前端事件系统的“隐形逻辑”》

“那天在document见到你的第一眼&#xff0c;我就下定决心要陪你到天荒地老” ---React 我将从事件从出现到被处理的各个过程来介绍事件机制&#xff1a; 这张图片给我们展示了react事件的各个阶段&#xff0c;我们可以看到有DOM&#xff0c;合成事件层&#xff0c;还有…

tiktok web登录 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向分析 部分代码 response reques…

【音视频】ffplay常用命令

一、 ffplay常用命令 -x width&#xff1a;强制显示宽度-y height&#xff1a;强制显示高度 强制以 640*360的宽高显示 ffplay 2.mp4 -x 640 -y 360 效果如下 -fs 全屏显示 ffplay -fs 2.mp4效果如下&#xff1a; -an 禁用音频&#xff08;不播放声音&#xff09;-vn 禁…

手机屏幕摔不显示了,如何用其他屏幕临时显示,用来导出资料或者清理手机

首先准备一个拓展坞 然后 插入一个外接的U盘 插入鼠标 插入有数字小键盘区的键盘 然后准备一根高清线&#xff0c;一端链接电脑显示器,一端插入拓展坞 把拓展坞的连接线&#xff0c;插入手机充电口&#xff08;可能会需要转接头&#xff09; 然后确保手机开机 按下键盘…

基于SpringBoot的“文物管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“文物管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体功能模块图 E-R实体图 系统首页界面 系统…

微信小程序投票系统的构建与实现

在数字化时代&#xff0c;微信小程序已经成为人们日常生活的重要组成部分。无论是企业宣传、活动组织还是社交互动&#xff0c;小程序都展现出了其强大的功能和便捷的用户体验。其中&#xff0c;微信小程序的投票系统尤为突出&#xff0c;它不仅能简化投票流程&#xff0c;还能…

【Java篇】数据类型与变量:窥见程序的天地万象

文章目录 Java 数据类型与变量基础&#xff1a;从零开始&#xff0c;轻松掌握前言一、字面常量1.1 什么是字面常量&#xff1f;1.2 字面常量的分类1.2.1 字符串常量1.2.2 整形常量1.2.3 浮点数常量1.2.4 字符常量1.2.5 布尔常量1.2.6 空常量 1.3 字面常量与数据类型 二、Java 中…

绿盟春招面试题

《网安面试指南》https://mp.weixin.qq.com/s/RIVYDmxI9g_TgGrpbdDKtA?token1860256701&langzh_CN 5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39…

操作系统控制台-健康守护我们的系统

引言基本准备体验功能健康守护系统诊断 收获提升结语 引言 阿里云操作系统控制平台作为新一代云端服务器中枢平台&#xff0c;通过创新交互模式重构主机管理体验。操作系统控制台提供了一系列管理功能&#xff0c;包括运维监控、智能助手、扩展插件管理以及订阅服务等。用户可以…

Linux系统基于ARM平台的LVGL移植

软硬件介绍&#xff1a;Ubuntu 20.04 ARM 和&#xff08;Cortex-A53架构&#xff09;开发板 基本原理 LVGL图形库是支持使用Linux系统的Framebuffer帧缓冲设备实现的&#xff0c;如果想要实现在ARM开发板上运行LVGL图形库&#xff0c;那么就需要把LVGL图形库提供的关于帧缓冲设…

DIY Tomcat:手写一个简易Servlet容器

在Java Web开发领域&#xff0c;Tomcat堪称经典&#xff0c;它作为Servlet容器&#xff0c;承载着无数Web应用的运行。今天&#xff0c;我将带大家一同探索如何手写一个简易的Tomcat&#xff0c;深入理解其底层原理。 一、背景知识 在开始之前&#xff0c;我们需要对几个关键…