2024/10/15日 日志 ---》对多年级多需求四则运算的初步解决

昨天我们进行了一次小的题目测试,题目的主体为四则运算
1、可定制(数量):输入大的出题数量值,测试一下系统是否崩溃,反向查找系统是否优化的余地;
2、定制操作数的个数、定制是否有乘除法、定制是否有括号(随机加入)、定制数值范围(确定操作数的取值范围);
3、定义方法实现错题集、错题重练并记录错题的次数功能。
4、能处理大数和浮点数计算。
5、要求可以同时定义小学二年级口算题、小学三年级口算题、小学四年级口算题。
(1)小学二年级口算题操作数为两个、可进行加减乘除运算(除法必须可以整除),操作数范围不超过100。
(2)小学三年级口算题操作数不超过4个,可以进行加减乘除,操作数范围不超过1000.(要求采用继承小学二年级出题类的方式,实现小学三年级的出题类)。
(3)小学四年级口算题操作数不超过5个,可以进行加减乘除,还可以加入括号运算。 (要求采用继承小学三年级出题类的方式,实现小学四年级的出题类)。
6、学生实时答题结束后,可以选择是否进行下一套题目答题,如果选择是,则抽取下一套题进行答题,答题结束可以通过查看错题本,查询今日做题正确率阶段;也可以针对错题进行二次答题。
7、要求将题目输出到文本文件中,三题一行,用户做完后,将文本导入,判读正误,显示统计结果。
基于昨日时间仓促,只对题目有了架构但没实现,今天对其进行了初步实现:
Moontest.java

点击查看代码
//张一衡 20234023
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Timer;

public class Moontest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请选择年级(2/3/4):");
        int grade = scanner.nextInt();
        System.out.println("请输入出题数量:");
        int numQuestions = scanner.nextInt();

        CountJFrame frame = new CountJFrame(grade, numQuestions);

        boolean continueTesting = true;
        while (continueTesting) {
            System.out.println("是否进行下一套题目答题(y/n)?");
            String choice = scanner.next();
            if (choice.equalsIgnoreCase("y")) {
                System.out.println("请输入出题数量:");
                numQuestions = scanner.nextInt();
                frame = new CountJFrame(grade, numQuestions);
            } else {
                continueTesting = false;
            }
        }

        System.out.println("是否查看错题本(y/n)?");
        String viewWrongChoice = scanner.next();
        if (viewWrongChoice.equalsIgnoreCase("y")) {
            try {
                BufferedWriter writer = new BufferedWriter(new FileWriter("wrong_answers.txt"));
                for (Operation wrongAnswer : frame.wrongAnswers) {
                    writer.write(wrongAnswer.toString() + " (正确答案: " + wrongAnswer.result + ")\n");
                }
                writer.close();
                System.out.println("错题已保存到 wrong_answers.txt 文件中。");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Operation.java

点击查看代码
class Operation {
    int num1;
    int num2;
    char operator;
    int result;

    // 用于嵌套运算
    Operation nestedOperation; // 可能是另一个Operation实例

    public Operation(int n1, int n2, char op) {
        num1 = n1;
        num2 = n2;
        operator = op;
        calculateResult();
    }

    // 用于嵌套运算的构造函数
    public Operation(Operation nestedOp, int n, char op) {
        this.nestedOperation = nestedOp;
        this.num2 = n;
        this.operator = op;
        calculateResult();
    }

    private void calculateResult() {
        int value1 = (nestedOperation != null) ? nestedOperation.result : num1; // 如果有嵌套运算,使用其结果
        switch (operator) {
            case '+':
                result = value1 + num2;
                break;
            case '-':
                result = value1 - num2;
                break;
            case '*':
                result = value1 * num2;
                break;
            case '/':
                if (num2 != 0 && value1 % num2 == 0) {
                    result = value1 / num2;
                }
                break;
        }
    }

    @Override
    public String toString() {
        if (nestedOperation != null) {
            return "(" + nestedOperation + ") " + operator + " " + num2 + " =?";
        } else {
            return num1 + " " + operator + " " + num2 + " =?";
        }
    }
}

Grade2.java

点击查看代码
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Grade2{
    protected Random random = new Random();
    protected List<Operation> operations = new ArrayList<>();

    public Grade2(int numQuestions) {
        generateQuestions(numQuestions);
    }

    protected void generateQuestions(int numQuestions) {
        for (int i = 0; i < numQuestions; i++) {
            int num1 = random.nextInt(100);
            int num2 = random.nextInt(100);
            char operator;
            switch (random.nextInt(4)) {
                case 0:
                    operator = '+';
                    break;
                case 1:
                    operator = '-';
                    break;
                case 2:
                    operator = '*';
                    break;
                case 3:
                    operator = '/';
                    break;
                default:
                    operator = '+';
            }
            operations.add(new Operation(num1, num2, operator));
        }
    }

    public List<Operation> getOperations() {
        return operations;
    }
}

Grade3.java

点击查看代码
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Grade3 extends Grade2{
    public Grade3(int numQuestions) {
        super(numQuestions);
        for (Operation operation : operations) {
            // 如果是除法且除数为0,重新生成除数
            if (operation.operator == '/') {
                while (operation.num2 == 0) {
                    operation.num2 = random.nextInt(999) + 1; // 确保除数不为0
                }
            }
            operation.num1 = random.nextInt(1000);
            operation.num2 = random.nextInt(1000);
            operation = new Operation(operation.num1, operation.num2, operation.operator); // 重新生成Operation
        }
    }
}

Grade4.java

点击查看代码
import java.util.List;
import java.util.Random;

public class Grade4 extends Grade3 {
    private Random random = new Random();

    public Grade4(int numQuestions) {
        super(numQuestions);
    }

    @Override
    protected void generateQuestions(int numQuestions) {
        super.generateQuestions(numQuestions); // 先生成基础的操作

        for (int i = 0; i < operations.size(); i++) {
            Operation operation = operations.get(i);
            // 随机给操作数加上额外的值
            if (random.nextBoolean()) {
                operation.num1 = (int) ((random.nextDouble() * 1000) + operation.num1);
                operation.num2 = (int) ((random.nextDouble() * 1000) + operation.num2);
            }
            // 随机决定是否添加括号
            if (random.nextBoolean()) {
                operations.set(i, addParentheses(operation)); // 更新操作为带括号的版本
            }
        }
    }

    // 添加括号的逻辑
    private Operation addParentheses(Operation operation) {
        int n1 = operation.num1;
        int n2 = operation.num2;
        char op = operation.operator;

        // 随机决定括号的放置
        int n3 = random.nextInt(1000); // 随机生成 n3

        if (random.nextBoolean()) {
            // (n1 op n2) op n3
            return new Operation(new Operation(n1, n2, op), n3, random.nextBoolean() ? '+' : '-');
        } else {
            // n1 op (n2 op n3)
            Operation nestedOperation = new Operation(n2, n3, random.nextBoolean() ? '+' : '-'); // 创建一个嵌套操作
            return new Operation(n1, nestedOperation.result, op);
        }
    }
}

CountJFrame.java

点击查看代码
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

class CountJFrame extends JFrame {
    List<Operation> operations;
    JTextField[] inputFields;
    JLabel timerLabel;
    Timer timer;
    int remainingTime = 180;
    List<Operation> wrongAnswers = new ArrayList<>();

    public CountJFrame(int grade, int numQuestions) {
        switch (grade) {
            case 2:
                operations = new Grade2(numQuestions).getOperations();
                break;
            case 3:
                operations = new Grade3(numQuestions).getOperations();
                break;
            case 4:
                operations = new Grade4(numQuestions).getOperations();
                break;
        }
        initJFrame();
        initView();
        startTimer();
        this.setVisible(true);
    }

    private void initJFrame() {
        this.setSize(500, 400);
        this.setTitle("四则运算--升级版");
        this.setAlwaysOnTop(true);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.setLayout(null);
    }

    private void initView() {
        int numQuestions = operations.size();
        inputFields = new JTextField[numQuestions];

        timerLabel = new JLabel("剩余时间: " + remainingTime + "秒");
        timerLabel.setBounds(10, 10, 200, 30);
        this.getContentPane().add(timerLabel);

        JPanel questionPanel = new JPanel();
        questionPanel.setLayout(new GridLayout(0, 2, 10, 10));
        for (int i = 0; i < numQuestions; i++) {
            JLabel questionLabel = new JLabel(operations.get(i).toString());
            questionLabel.setBorder(new BevelBorder(BevelBorder.LOWERED));
            questionPanel.add(questionLabel);

            inputFields[i] = new JTextField();
            questionPanel.add(inputFields[i]);
        }

        JScrollPane scrollPane = new JScrollPane(questionPanel);
        scrollPane.setBounds(10, 50, 460, 250);
        this.getContentPane().add(scrollPane);

        JButton submitButton = new JButton("提交");
        submitButton.setBounds(380, 310, 80, 30);
        submitButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                StringBuilder incorrectAnswers = new StringBuilder();
                boolean allCorrect = true;

                for (int i = 0; i < inputFields.length; i++) {
                    String userInput = inputFields[i].getText();
                    if (!userInput.equals(String.valueOf(operations.get(i).result))) {
                        incorrectAnswers.append(operations.get(i)).append(" (正确答案: ")
                                .append(operations.get(i).result).append(")\n");
                        allCorrect = false;
                        wrongAnswers.add(operations.get(i));
                    }
                }

                JDialog dialog = new JDialog(CountJFrame.this, "结果", true);
                dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
                dialog.setAlwaysOnTop(true);
                dialog.setLocationRelativeTo(CountJFrame.this);

                if (allCorrect) {
                    JOptionPane.showMessageDialog(dialog, "所有答案正确!");
                } else {
                    JOptionPane.showMessageDialog(dialog, "有答案不正确,请查看:\n" + incorrectAnswers.toString());
                }
                timer.stop();
            }
        });
        this.getContentPane().add(submitButton);
    }

    private void startTimer() {
        timer = new Timer(1000, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                remainingTime--;
                timerLabel.setText("剩余时间: " + remainingTime + "秒");
                if (remainingTime <= 0) {
                    timer.stop();
                    JOptionPane.showMessageDialog(null, "时间到,请提交答案!");
                    StringBuilder incorrectAnswers = new StringBuilder();
                    boolean allCorrect = true;

                    for (int i = 0; i < inputFields.length; i++) {
                        String userInput = inputFields[i].getText();
                        if (!userInput.equals(String.valueOf(operations.get(i).result))) {
                            incorrectAnswers.append(operations.get(i)).append(" (正确答案: ")
                                    .append(operations.get(i).result).append(")\n");
                            allCorrect = false;
                            wrongAnswers.add(operations.get(i));
                        }
                    }

                    if (allCorrect) {
                        JOptionPane.showMessageDialog(null, "所有答案正确!");
                    } else {
                        JOptionPane.showMessageDialog(null, "有答案不正确,请查看:\n" + incorrectAnswers.toString());
                    }
                }
            }
        });
        timer.start();
    }
}

尽管如此,但程序仍不能完全满足题目需求,甚至对一些需求进行了简化处理,Grade4的括号问题是目前无从下手的地方,亟待解决。
接下来,我将继续修改优化代码,对简化处理部分进行复原并更改原有基础结构以完成题目要求。

posted @   Moonbeamsc  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
返回顶端
点击右上角即可分享
微信分享提示