You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
7.4 KiB
212 lines
7.4 KiB
package com.example.mathsystemtogether;
|
|
|
|
import java.util.*;
|
|
|
|
/**
|
|
* 选择题生成器
|
|
*/
|
|
public class ChoiceQuestionGenerator {
|
|
private final Random random = new Random();
|
|
private final int MAX_OPERAND_VALUE = 50; // 降低数值范围,便于计算
|
|
private final int MIN_OPERAND_VALUE = 1;
|
|
|
|
/**
|
|
* 生成指定数量的选择题
|
|
*/
|
|
public List<Question> generateQuestions(Level level, int count) {
|
|
List<Question> questions = new ArrayList<>();
|
|
Set<String> usedQuestions = new HashSet<>();
|
|
|
|
int attempts = 0;
|
|
int maxAttempts = count * 100; // 最大尝试次数
|
|
|
|
while (questions.size() < count && attempts < maxAttempts) {
|
|
Question question = generateSingleQuestion(level, questions.size() + 1);
|
|
String questionKey = question.getQuestionText();
|
|
|
|
if (!usedQuestions.contains(questionKey)) {
|
|
usedQuestions.add(questionKey);
|
|
questions.add(question);
|
|
}
|
|
attempts++;
|
|
}
|
|
|
|
return questions;
|
|
}
|
|
|
|
/**
|
|
* 生成单个选择题
|
|
*/
|
|
private Question generateSingleQuestion(Level level, int questionNumber) {
|
|
switch (level) {
|
|
case 小学:
|
|
return generatePrimaryQuestion(questionNumber);
|
|
case 初中:
|
|
return generateJuniorQuestion(questionNumber);
|
|
case 高中:
|
|
return generateSeniorQuestion(questionNumber);
|
|
default:
|
|
return generatePrimaryQuestion(questionNumber);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 生成小学题目
|
|
*/
|
|
private Question generatePrimaryQuestion(int questionNumber) {
|
|
int a = MIN_OPERAND_VALUE + random.nextInt(MAX_OPERAND_VALUE);
|
|
int b = MIN_OPERAND_VALUE + random.nextInt(MAX_OPERAND_VALUE);
|
|
|
|
String operation = getRandomOperation("+*-");
|
|
String questionText = String.format("%d %s %d = ?", a, operation, b);
|
|
int correctAnswer = calculate(a, b, operation);
|
|
|
|
// 生成错误选项
|
|
List<Integer> options = generateWrongOptions(correctAnswer);
|
|
options.add(correctAnswer);
|
|
Collections.shuffle(options);
|
|
|
|
return new Question(questionText,
|
|
String.valueOf(options.get(0)),
|
|
String.valueOf(options.get(1)),
|
|
String.valueOf(options.get(2)),
|
|
String.valueOf(options.get(3)),
|
|
String.valueOf(correctAnswer),
|
|
questionNumber);
|
|
}
|
|
|
|
/**
|
|
* 生成初中题目
|
|
*/
|
|
private Question generateJuniorQuestion(int questionNumber) {
|
|
int a = MIN_OPERAND_VALUE + random.nextInt(MAX_OPERAND_VALUE);
|
|
|
|
// 50%概率生成平方或开方题目
|
|
if (random.nextBoolean()) {
|
|
// 平方题目
|
|
String questionText = String.format("%d² = ?", a);
|
|
int correctAnswer = a * a;
|
|
List<Integer> options = generateWrongOptions(correctAnswer);
|
|
options.add(correctAnswer);
|
|
Collections.shuffle(options);
|
|
|
|
return new Question(questionText,
|
|
String.valueOf(options.get(0)),
|
|
String.valueOf(options.get(1)),
|
|
String.valueOf(options.get(2)),
|
|
String.valueOf(options.get(3)),
|
|
String.valueOf(correctAnswer),
|
|
questionNumber);
|
|
} else {
|
|
// 开方题目
|
|
int perfectSquare = (int) Math.pow(random.nextInt(10) + 1, 2);
|
|
String questionText = String.format("√%d = ?", perfectSquare);
|
|
int correctAnswer = (int) Math.sqrt(perfectSquare);
|
|
List<Integer> options = generateWrongOptions(correctAnswer);
|
|
options.add(correctAnswer);
|
|
Collections.shuffle(options);
|
|
|
|
return new Question(questionText,
|
|
String.valueOf(options.get(0)),
|
|
String.valueOf(options.get(1)),
|
|
String.valueOf(options.get(2)),
|
|
String.valueOf(options.get(3)),
|
|
String.valueOf(correctAnswer),
|
|
questionNumber);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 生成高中题目
|
|
*/
|
|
private Question generateSeniorQuestion(int questionNumber) {
|
|
int angle = random.nextInt(360);
|
|
String[] functions = {"sin", "cos", "tan"};
|
|
String function = functions[random.nextInt(functions.length)];
|
|
|
|
String questionText = String.format("%s(%d°) = ?", function, angle);
|
|
double result = calculateTrigFunction(function, angle);
|
|
int correctAnswer = (int) Math.round(result * 100) / 100; // 保留两位小数
|
|
|
|
List<Integer> options = generateWrongOptions(correctAnswer);
|
|
options.add(correctAnswer);
|
|
Collections.shuffle(options);
|
|
|
|
return new Question(questionText,
|
|
String.valueOf(options.get(0)),
|
|
String.valueOf(options.get(1)),
|
|
String.valueOf(options.get(2)),
|
|
String.valueOf(options.get(3)),
|
|
String.valueOf(correctAnswer),
|
|
questionNumber);
|
|
}
|
|
|
|
/**
|
|
* 生成错误选项
|
|
*/
|
|
private List<Integer> generateWrongOptions(int correctAnswer) {
|
|
List<Integer> options = new ArrayList<>();
|
|
Set<Integer> usedOptions = new HashSet<>();
|
|
usedOptions.add(correctAnswer);
|
|
|
|
while (options.size() < 3) {
|
|
int wrongAnswer;
|
|
if (correctAnswer == 0) {
|
|
wrongAnswer = random.nextInt(20) - 10;
|
|
} else {
|
|
// 生成接近正确答案的错误选项
|
|
int variation = random.nextInt(Math.max(1, Math.abs(correctAnswer) / 2)) + 1;
|
|
wrongAnswer = correctAnswer + (random.nextBoolean() ? variation : -variation);
|
|
}
|
|
|
|
if (!usedOptions.contains(wrongAnswer)) {
|
|
options.add(wrongAnswer);
|
|
usedOptions.add(wrongAnswer);
|
|
}
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|
|
/**
|
|
* 计算基本运算
|
|
*/
|
|
private int calculate(int a, int b, String operation) {
|
|
switch (operation) {
|
|
case "+": return a + b;
|
|
case "-": return a - b;
|
|
case "*": return a * b;
|
|
case "/": return b != 0 ? a / b : 0;
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 计算三角函数
|
|
*/
|
|
private double calculateTrigFunction(String function, int angle) {
|
|
double radians = Math.toRadians(angle);
|
|
switch (function) {
|
|
case "sin": return Math.sin(radians);
|
|
case "cos": return Math.cos(radians);
|
|
case "tan": return Math.tan(radians);
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取随机运算符
|
|
*/
|
|
private String getRandomOperation(String operations) {
|
|
int index = random.nextInt(operations.length());
|
|
return String.valueOf(operations.charAt(index));
|
|
}
|
|
|
|
/**
|
|
* 难度级别枚举
|
|
*/
|
|
public enum Level {
|
|
小学, 初中, 高中
|
|
}
|
|
}
|