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);
}

}

posted @ 2025-10-15 22:59  muyuxiaxing  阅读(2)  评论(0)    收藏  举报