10.13
四则运算
package 测试;
import javax.swing.;
import java.io.;
import java.nio.file.;
import java.util.;
public class MathTest {
private static final Random R = new Random();
private static final int QUESTIONS_PER_ROUND = 30;
private static final int QUESTIONS_PER_LINE = 3;
private static final String EXPORT_FILE = "siZe_test_export.txt";
private static class Item {
String exp; // 原式子,如 "3+5="
double std; // 标准答案
String user; // 用户原始输入
boolean ok; // 是否做对
}
public static void main(String[] args) {
/* 启动菜单:重新测验 or 导入旧文件判分 */
String[] options = {"重新测验", "导入旧文件判分"};
int choice = JOptionPane.showOptionDialog(
null,
"选择操作方式",
"四则运算测验",
JOptionPane.DEFAULT_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if (choice == 0) {
startNewRound();
} else if (choice == 1) {
importAndCheck();
} else {
JOptionPane.showMessageDialog(null, "已取消");
}
}
/* =========================================================
* 流程 A:重新测验
* ========================================================= */
private static void startNewRound() {
Item[] paper = generatePaper(QUESTIONS_PER_ROUND);
StringBuilder msg = new StringBuilder();
/* 逐题提问 */
for (int i = 0; i < paper.length; i++) {
Item it = paper[i];
String input = JOptionPane.showInputDialog(
null,
(i + 1) + ". " + it.exp,
"数学测验 - 第 " + (i + 1) + " 题",
JOptionPane.QUESTION_MESSAGE);
if (input == null) { // 用户点“取消”
JOptionPane.showMessageDialog(null, "测验已取消");
return;
}
it.user = input.trim();
/* 解析用户答案 */
double userVal;
try {
userVal = Double.parseDouble(it.user);
} catch (NumberFormatException ex) {
userVal = Double.NaN;
}
it.ok = Math.abs(userVal - it.std) < 1e-6;
msg.append(i + 1)
.append(". ")
.append(it.exp)
.append(it.user)
.append(" → ")
.append(it.ok ? "正确" : "错误,正确答案:" + formatAns(it.std))
.append("\n");
}
/* 统计 */
long wrong = Arrays.stream(paper).filter(it -> !it.ok).count();
double accuracy = (QUESTIONS_PER_ROUND - wrong) * 100.0 / QUESTIONS_PER_ROUND;
msg.append("\n------------------\n")
.append(String.format("错题数:%d / %d,正确率:%.2f%%",
wrong, QUESTIONS_PER_ROUND, accuracy));
JOptionPane.showMessageDialog(null, msg.toString(), "测验结果", JOptionPane.INFORMATION_MESSAGE);
/* 导出文件(三题一行) */
exportToTxt(paper);
/* 错题本 */
showWrongList(paper);
/* 阶段 1:询问是否再来一套 */
int goon = JOptionPane.showConfirmDialog(
null,
"是否立即进行下一套题目?",
"再来一套?",
JOptionPane.YES_NO_OPTION);
if (goon == JOptionPane.YES_OPTION) {
startNewRound(); // 递归再来
}
}
/* =========================================================
* 流程 B:导入旧文件自动判分
* ========================================================= */
private static void importAndCheck() {
File f = new File(EXPORT_FILE);
if (!f.exists()) {
JOptionPane.showMessageDialog(null, "未找到导出文件:" + EXPORT_FILE);
return;
}
List<Item> list = new ArrayList<>();
try (BufferedReader br = Files.newBufferedReader(f.toPath())) {
String line;
while ((line = br.readLine()) != null) {
if (line.trim().isEmpty()) continue;
/* 每行三题,TAB 分隔 */
String[] groups = line.split("\t");
for (String g : groups) {
/* 每组格式:序号. 表达式=用户答案 → 结果 */
String[] seg = g.split("→");
if (seg.length != 2) continue;
String head = seg[0].trim(); // "1. 3+5=8"
String result = seg[1].trim(); // "正确" 或 "错误,正确答案:x"
/* 拆表达式 */
String[] tmp = head.split("\\.", 2);
if (tmp.length != 2) continue;
String expAndAns = tmp[1].trim(); // "3+5=8"
/* 找最后一个 = 号 */
int eq = expAndAns.lastIndexOf('=');
if (eq <= 0) continue;
String exp = expAndAns.substring(0, eq + 1); // "3+5="
String uStr = expAndAns.substring(eq + 1); // "8"
Item it = new Item();
it.exp = exp;
it.std = calculate(exp);
it.user = uStr;
it.ok = result.startsWith("正确");
list.add(it);
}
}
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "读取文件失败:\n" + ex.getMessage());
return;
}
if (list.isEmpty()) {
JOptionPane.showMessageDialog(null, "文件解析失败,无有效记录");
return;
}
/* 重新统计 */
Item[] paper = list.toArray(new Item[0]);
long wrong = Arrays.stream(paper).filter(it -> !it.ok).count();
double accuracy = (paper.length - wrong) * 100.0 / paper.length;
String summary = String.format("导入共 %d 题,错题:%d,正确率:%.2f%%",
paper.length, wrong, accuracy);
JOptionPane.showMessageDialog(null, summary, "导入判分结果", JOptionPane.INFORMATION_MESSAGE);
/* 错题本 */
showWrongList(paper);
}
/* =========================================================
* 生成一套题目
* ========================================================= */
private static Item[] generatePaper(int n) {
Item[] arr = new Item[n];
for (int i = 0; i < n; i++) {
Item it = new Item();
it.exp = generateExpression();
it.std = calculate(it.exp);
arr[i] = it;
}
return arr;
}
/* =========================================================
* 把一轮结果导出成文本(三题一行)
* ========================================================= */
private static void exportToTxt(Item[] paper) {
StringBuilder sb = new StringBuilder();
int idx = 0;
while (idx < paper.length) {
/* 拼三题 */
for (int j = 0; j < QUESTIONS_PER_LINE && idx < paper.length; j++, idx++) {
Item it = paper[idx];
sb.append(idx + 1)
.append(". ")
.append(it.exp)
.append(it.user)
.append(" → ")
.append(it.ok ? "正确" : "错误,正确答案:" + formatAns(it.std));
if (j < QUESTIONS_PER_LINE - 1 && idx < paper.length - 1) sb.append('\t');
}
sb.append('\n');
}
try {
Files.write(Paths.get(EXPORT_FILE), sb.toString().getBytes());
JOptionPane.showMessageDialog(null, "已导出文件:" + EXPORT_FILE);
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "导出失败:\n" + ex.getMessage());
}
}
/* =========================================================
* 弹出错题本
* ========================================================= */
private static void showWrongList(Item[] paper) {
StringBuilder w = new StringBuilder("【错题本】\n");
Arrays.stream(paper)
.filter(it -> !it.ok)
.forEach(it ->
w.append(it.exp)
.append(" 你的答案:")
.append(it.user)
.append(" 正确答案:")
.append(formatAns(it.std))
.append('\n'));
if (w.length() == 6) w.append("恭喜,本轮全对!");
JOptionPane.showMessageDialog(null, w.toString(), "错题本", JOptionPane.INFORMATION_MESSAGE);
}
/* =========================================================
* 表达式生成 & 计算(沿用你原来的算法)
* ========================================================= */
private static String generateExpression() {
int a = 0, b = 0, opType;
while (true) {
opType = R.nextInt(4);
switch (opType) {
case 0: // 加
a = 1 + R.nextInt(100);
b = 1 + R.nextInt(100);
break;
case 1: // 减,保证非负
a = 1 + R.nextInt(100);
b = 1 + R.nextInt(a);
break;
case 2: // 乘,控制在 999 以内
a = 1 + R.nextInt(31);
b = 1 + R.nextInt(31);
if (a * b > 999) continue;
break;
case 3: // 除,整除
b = 1 + R.nextInt(100);
int q = 1 + R.nextInt(100 / b + 1);
a = q * b;
break;
}
break;
}
char operator = "+-*/".charAt(opType);
return "" + a + operator + b + '=';
}
private static double calculate(String exp) {
String[] parts = exp.split("[-+*/=]");
int a = Integer.parseInt(parts[0]);
int b = Integer.parseInt(parts[1]);
char op = exp.replaceAll("[0-9]|=", "").charAt(0);
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return (double) a / b;
default: return 0;
}
}
private static String formatAns(double v) {
return v % 1 == 0 ? String.valueOf((long) v) : String.valueOf(v);
}
}

浙公网安备 33010602011771号