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
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 不存重复元素,就用它来记录已出的题目;还试着用方法重载写了两个判题方法,一个判整数答案,一个判浮点数答案(虽然最后作业没用到浮点数,但也算练了手)。做完后把随机数生成、题目合法性校验的方法整理到一个工具类里,下次同学要做类似作业时,直接把这个类发给他,他改改参数就能用,这才体会到整理代码仓库的必要 —— 不是为了 “存着”,而是下次遇到类似问题时,不用从头写起,效率能高很多。