课后 10.8

import java.util.Random;
import java.util.Scanner;
import java.util.HashSet;
import java.util.Timer;
import java.util.TimerTask;

public class Math {
private static HashSet questionSet = new HashSet<>();
private static int total = 0;
private static int correct = 0;
private static int wrong = 0;
private static boolean isTimeUp = false;
private static int timeLimit;

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.print("请输入答题时间(秒):");
    timeLimit = sc.nextInt();
    startCountdown();
    makeQuestion();
    showResult();
    sc.close();
}
private static void startCountdown() {
    Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            if (timeLimit <= 0) {
                isTimeUp = true;
                System.out.println("\n时间到!");
                timer.cancel();
            } else if (timeLimit <= 10) { // 最后10秒提醒
                System.out.println("剩余时间:" + timeLimit + "秒");
            }
            timeLimit--;
        }
    }, 0, 1000);
}
private static void showResult() {
    System.out.println("\n===== 答题结果 =====");
    System.out.println("总题数:" + total);
    System.out.println("做对:" + correct);
    System.out.println("做错:" + wrong);
    if (total > 0) {
        System.out.println("正确率:" + (correct * 100.0 / total) + "%");
    }
}
public static void makeQuestion() {
    for (int i = 0; i < 30 && !isTimeUp; i++) {
        Random num = new Random();
        int end = 0;
        char op=' ';
        boolean check=false;
        int num1 = num.nextInt(100);
        int num2 = num.nextInt(100);
        int num_meddle = num.nextInt(4);
        switch (num_meddle) {
            case 0:
                end = num1 + num2;
                op = '+';
                break;
            case 1:
                end = num1 - num2;
                op = '-';
                break;
            case 2:
                end = num1 * num2;
                op = '*';
                break;
            case 3:
                end = num1 / num2;
                op = '/';
                break;
        }
        // 检查题目有效性和重复性
        check = checkQuestion(num1, num2, op);
        String question = num1 + "" + op + "" + num2 + "=";

        // 如果题目无效或重复,重新生成
        if (!check || questionSet.contains(question) || isTimeUp) {
            i--;
            continue;
        }
        // 除法需要重新计算正确结果
        if (op == '/') {
            end = num1 / num2;
        }
        // 记录已出现的题目
        questionSet.add(question);
        total++;
        // 显示题目并处理答题
        System.out.print(question);
        if (isTimeUp) {
            wrong++;
            continue;
        }
        // 处理答题结果
        if (answerQuestion(end)) {
            correct++;
            System.out.println("正确");
        } else {
            wrong++;
            System.out.println("错误,正确答案是:" + end);
        }
    }
}
public static boolean answerQuestion(int end) {
    if (isTimeUp) return false;

    Scanner input = new Scanner(System.in);
    try {
        int answer = input.nextInt();
        return answer == end;
    } catch (Exception e) {
        return false;
    }
}
public static boolean checkQuestion(int num1, int num2, char op) {
    switch (op) {
        case '-':
            return num1 >= num2;
        case '*':
            return num1 * num2 < 1000;
        case '/':
            return num2 != 0 && num1 % num2 == 0;
        default: // '+'
            return true;
    }
}

}

学完这节 Java 方法课,最大的感受是之前对 “方法” 的理解太浅了 —— 原来它不只是写个函数那么简单,而是像 PPT 里说的 “懒人造就方法”,把复杂问题拆成小块、重复利用。比如百万行代码分模块那例子,以前总觉得把代码堆在一起也能跑,直到自己试着写一个小工具时,把所有逻辑塞在 main 方法里,后来想改个答题计时功能,差点把整个代码搅乱,这才真正懂了模块化的意义:把计时、出题、判题拆成独立方法后,改其中一个功能时,其他部分完全不受影响,维护起来特别清爽。
还有处理大数字和浮点数的坑,印象特别深。之前算 20 的阶乘,用 int 类型结果变成了负数,换成 long 类型后,算到 30 的阶乘又不对了,翻 PPT 才想起 “类型有范围限制”,赶紧换成 BigInteger,看着控制台输出一长串正确的数字,才真正意识到基础类型的边界不是摆设。浮点数的坑也踩过,一开始用 == 比较 0.1+0.2 和 0.3,结果输出 false,当时还以为是代码写错了,后来按 PPT 里说的 “比差值绝对值”,用 Math.abs ((0.1+0.2)-0.3) < 1e-10 来判断,才得到正确结果,这些细节在课本上看时没太在意,实际写代码时却很容易掉进去
最后做四则运算的作业时,才算把零散的知识点串了起来:用 Random 类生成数字时,一开始没考虑除法要整除,后来加了判断 “num1 % num2 == 0”;遇到重复题目时,想起 HashSet 不存重复元素,就用它来记录已出的题目;还试着用方法重载写了两个判题方法,一个判整数答案,一个判浮点数答案(虽然最后作业没用到浮点数,但也算练了手)。做完后把随机数生成、题目合法性校验的方法整理到一个工具类里,下次同学要做类似作业时,直接把这个类发给他,他改改参数就能用,这才体会到整理代码仓库的必要 —— 不是为了 “存着”,而是下次遇到类似问题时,不用从头写起,效率能高很多。

posted @ 2025-10-08 16:39  Ceoberus  阅读(9)  评论(0)    收藏  举报