hhrのblog
首页项目归档照片墙音乐灵境说说杂谈友链关于
封面

java实验4

写作时间:2026-07-04 18:09:11
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;
public class MathPractice extends JFrame implements ActionListener {
    // 界面组件
    JLabel titleLab, questionLab, tipLab, scoreLab;
    JTextField ansInput;
    JButton submitBtn, nextBtn;
    JComboBox<String> levelBox;

    // 业务变量
    Random random = new Random();
    int score = 0; // 得分
    double num1, num2; // 两个操作数
    char op; // 运算符
    int level; // 难度 1简单 2中等 3困难

    // 构造方法:初始化窗口
    public MathPractice() {
        initWindow();
        initComponent();
        createQuestion(); // 初始生成第一道题
    }
        // 窗口基础设置
    private void initWindow() {
        setTitle("小学生算术练习器");
        setSize(450, 320);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null); // 窗口居中
        setLayout(null); // 绝对布局,方便新手
        setResizable(false);
    }
        // 初始化所有控件
    private void initComponent() {
        // 标题
        titleLab = new JLabel("算术练习题", SwingConstants.CENTER);
        titleLab.setFont(new Font("黑体", Font.BOLD, 24));
        titleLab.setBounds(80, 20, 300, 35);
        add(titleLab);

        // 难度下拉框
        JLabel levelLab = new JLabel("选择难度:");
        levelLab.setBounds(60, 70, 80, 25);
        add(levelLab);
        String[] levels = {"简单(整数10以内)", "中等(整数100以内)", "困难(小数)"};
        levelBox = new JComboBox<>(levels);
        levelBox.setBounds(140, 70, 200, 25);
        add(levelBox);

        // 题目显示
        questionLab = new JLabel("题目:", SwingConstants.CENTER);
        questionLab.setFont(new Font("宋体", Font.BOLD, 20));
        questionLab.setBounds(50, 110, 350, 30);
        add(questionLab);

        // 答案输入框
        ansInput = new JTextField();
        ansInput.setBounds(100, 150, 120, 30);
        ansInput.setFont(new Font("宋体", Font.PLAIN, 18));
        add(ansInput);

        // 提交、下一题按钮
        submitBtn = new JButton("提交答案");
        submitBtn.setBounds(240, 150, 90, 30);
        submitBtn.addActionListener(this);
        add(submitBtn);

        nextBtn = new JButton("换一题");
        nextBtn.setBounds(140, 190, 130, 30);
        nextBtn.addActionListener(this);
        add(nextBtn);

        // 对错提示
        tipLab = new JLabel("请输入答案", SwingConstants.CENTER);
        tipLab.setBounds(50, 230, 350, 25);
        add(tipLab);

        // 得分
        scoreLab = new JLabel("当前得分:0");
        scoreLab.setBounds(160, 260, 120, 25);
        add(scoreLab);
    }
        // 生成随机算式
    private void createQuestion() {
        tipLab.setText("请输入答案");
        ansInput.setText("");
        // 获取选中难度
        level = levelBox.getSelectedIndex() + 1;
        // 随机运算符 + - * /
        char[] ops = {'+', '-', '*', '/'};
        op = ops[random.nextInt(4)];

        if (level == 1) {
            // 简单:1~10整数
            num1 = random.nextInt(10) + 1;
            num2 = random.nextInt(10) + 1;
        } else if (level == 2) {
            // 中等:1~100整数
            num1 = random.nextInt(100) + 1;
            num2 = random.nextInt(100) + 1;
        } else {
            // 困难:1~50小数,保留1位小数
            num1 = Math.round((1 + random.nextDouble() * 49) * 10.0) / 10.0;
            num2 = Math.round((1 + random.nextDouble() * 49) * 10.0) / 10.0;
        }

        // 除法避免除0
        while (op == '/' && num2 == 0) {
            if (level <= 2) num2 = random.nextInt(100)+1;
            else num2 = Math.round((1 + random.nextDouble() * 49) * 10.0) / 10.0;
        }
        questionLab.setText(num1 + " " + op + " " + num2 + " = ?");
    }
        @Override
    public void actionPerformed(ActionEvent e) {
        // 换一题按钮
        if (e.getSource() == nextBtn) {
            createQuestion();
            return;
        }
        // 提交答案按钮
        if (e.getSource() == submitBtn) {
            String inputStr = ansInput.getText().trim();
            if (inputStr.isEmpty()) {
                tipLab.setText("提示:请输入数字!");
                tipLab.setForeground(Color.RED);
                return;
            }
            double userAns;
            try {
                userAns = Double.parseDouble(inputStr);
            } catch (Exception ex) {
                tipLab.setText("输入格式错误,请输入数字!");
                tipLab.setForeground(Color.RED);
                return;
            }

            // 计算标准答案
            double realAns = switch (op) {
                case '+' -> num1 + num2;
                case '-' -> num1 - num2;
                case '*' -> num1 * num2;
                case '/' -> num1 / num2;
                default -> 0;
            };

            // 允许微小误差(小数精度问题)
            if (Math.abs(userAns - realAns) < 0.01) {
                tipLab.setText("回答正确!+10分");
                tipLab.setForeground(new Color(0, 150, 0));
                score += 10;
            } else {
                tipLab.setText("回答错误,正确答案:" + String.format("%.2f", realAns));
                tipLab.setForeground(Color.RED);
            }
            scoreLab.setText("当前得分:" + score);
        }
    }
        public static void main(String[] args) {
        // Swing程序建议在UI线程启动
        SwingUtilities.invokeLater(() -> {
            new MathPractice().setVisible(true);
        });
    }
}

‍

Java Swing 图形界面实验心得体会

本次实验围绕 Java Swing 开发小学生算术练习软件展开,系统学习了 GUI 图形界面编程与事件处理机制,从搭建窗口、布局组件到实现随机出题、答案校验、难度切换等完整功能,收获颇丰,也发现了自身存在的不少问题。在前期知识点学习阶段,我明白了 Swing 各类组件(JFrame、JLabel、JButton、JTextField、下拉框 JComboBox)的作用,理清了 GUI 编程核心逻辑:界面组件搭建、事件源绑定、事件监听器处理三者配合运行。之前只写过纯控制台程序,初次接触可视化界面时,对窗口大小、坐标布局、字体样式调整较为陌生,通过不断调整控件位置、修改字体颜色,慢慢熟悉了可视化界面的设计思路,也意识到美观、简洁的界面能大幅提升软件使用体验。

实验核心难点是事件处理机制。所有按钮点击、下拉框切换功能都依靠 ActionListener 监听实现,最开始分不清事件源、监听接口、重写方法三者的关系,多次出现点击按钮无响应的问题。排查后发现是忘记为控件绑定监听器,或是判断点击对象时逻辑写错。通过分步调试,我掌握了统一实现 ActionListener 接口、重写 actionPerformed 方法来区分不同按钮业务逻辑的写法,理解了图形程序是依靠用户操作触发代码执行,而非控制台顺序执行的运行逻辑。

随机出题功能的实现让我巩固了随机数、分支判断、浮点运算等基础语法。区分简单、中等、困难三种难度,分别生成整数、小数四则运算,还要处理除法除数不能为 0、小数精度误差等细节问题。最初没有考虑浮点数计算精度,出现答案正确却判定错误的 bug,后来通过差值对比允许微小误差才解决问题,让我懂得开发程序不能只实现基础功能,还要预判边界异常场景,做好容错处理,比如输入非数字时给出提示、输入为空拦截提交。同时本次实验也锻炼了代码分层思想,我将窗口初始化、控件创建、生成题目、事件处理拆分为独立方法,代码结构清晰,便于修改和扩展。实验要求可拓展分数运算、错题记录、计时功能,也让我意识到软件开发具备很强的可扩展性,后续可以基于现有框架新增功能,不用大面积重构代码。对比选做的终端扫雷游戏需求,也分清了控制台程序与 Swing 图形程序开发思路的差异,图形界面交互更直观,但组件、事件逻辑更复杂。在实操过程中,我也暴露了不少不足:一是界面布局不够熟练,使用绝对坐标布局不够灵活,后期可以学习流式布局、网格布局优化界面;二是异常处理意识薄弱,一开始没有对输入内容做校验,容易造成程序崩溃;三是代码复用性不足,重复代码较多。后续我会多练习布局管理器,养成输入校验、异常捕获的编码习惯,多用方法封装重复逻辑。整体而言,这次实验打通了 Java 图形化开发的完整流程,不再只会枯燥的控制台代码,学会将代码转化为可视化交互软件,深刻理解了面向对象思想在 GUI 中的应用,同时培养了调试排错、需求拆解、功能拓展的工程思维,为后续学习桌面程序、图形交互开发打下了扎实基础。
‍

avatar

higher

一个普通人。

RECOMMENDED

形式化方法

2026-05-31 17:39:40

prime number

2026-05-31 17:47:29

枚举类型应用场景

2026-05-31 17:55:09