用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构建图形界面
- 实现了自动求解算法
- 包含输入验证和错误处理
- 采用面向对象编程方式开发
相关推荐
烂蜻蜓1 小时前
深入理解 HTML 元素:构建网页的基础
开发语言·前端·css·html·html5
程序员张小厨2 小时前
【0014】Python数据类型-元组类型详解
python·元组·python推导式·python元组·python元组数据类型·元组数据类型·python元组遍历
孟and平2 小时前
Flask 打包为exe 文件
后端·python·flask
天天进步20154 小时前
Python项目-基于Django的在线教育平台开发
python
大只因bug4 小时前
基于Django的协同过滤算法养老新闻推荐系统的设计与实现
后端·python·django·协同过滤算法推荐系统·新闻推荐网站系统·养老新闻推荐系统·个性化新闻推荐网站系统
Jason-河山5 小时前
如何在PHP爬虫中处理异常情况的详细指南
开发语言·爬虫·php
kesteler5 小时前
R语言——数据类型
开发语言·r语言
Jason-河山5 小时前
利用PHP爬虫根据关键词获取17网(17zwd)商品列表:实战指南
开发语言·爬虫·php
论迹5 小时前
【JavaEE】-- 多线程(初阶)4
java·开发语言·java-ee
VBA63375 小时前
VBA之Word应用第三章第七节:文档Document对象的方法(一)
开发语言