1 #3

Merged
hnu202326010315 merged 1 commits from main into develop 5 months ago

@ -0,0 +1,151 @@
import java.util.Random;
public class ElementaryQuestionStrategy implements QuestionStrategy {
private final Random random = new Random();
private final String[] operators = {"+", "-", "*", "/"};
@Override
public String generateQuestion() {
int operandsCount = random.nextInt(4) + 2; // 操作数 2~5
StringBuilder sb = new StringBuilder();
// 生成运算符序列
String[] chosenOps = generateOperators(operandsCount);
// 随机决定括号
int[] parentheses = decideParentheses(operandsCount, chosenOps);
// 拼接表达式
buildExpression(sb, operandsCount, chosenOps, parentheses);
return sb.toString();
}
/**
*
*
*
* @param operandsCount
* @return -1
*/
private String[] generateOperators(int operandsCount) {
String[] chosenOps = new String[operandsCount - 1];
for (int i = 0; i < operandsCount - 1; i++) {
chosenOps[i] = operators[random.nextInt(operators.length)];
}
return chosenOps;
}
/**
*
* 3
*
* @param operandsCount
* @param chosenOps
* @return [openParenIndex, closeParenIndex]-1
*/
private int[] decideParentheses(int operandsCount, String[] chosenOps) {
int openParenIndex = -1;
int closeParenIndex = -1;
if (operandsCount > 2 && random.nextBoolean()) {
openParenIndex = random.nextInt(operandsCount - 1);
closeParenIndex = random.nextInt(operandsCount - openParenIndex - 1) + openParenIndex + 1;
// 如果括号包裹整个表达式,则不需要括号
if (openParenIndex == 0 && closeParenIndex == operandsCount - 1) {
openParenIndex = -1;
closeParenIndex = -1;
} else {
// 检查括号内的运算符优先级是否相同,如果相同则不需要括号
boolean samePrecedence = checkPrecedenceEquality(chosenOps, openParenIndex, closeParenIndex);
if (samePrecedence) {
openParenIndex = -1;
closeParenIndex = -1;
}
}
}
return new int[]{openParenIndex, closeParenIndex};
}
/**
*
*
*
* @param chosenOps
* @param openParenIndex
* @param closeParenIndex
* @return truefalse
*/
private boolean checkPrecedenceEquality(String[] chosenOps, int openParenIndex, int closeParenIndex) {
int precedence = getPrecedence(chosenOps[openParenIndex]);
for (int i = openParenIndex; i < closeParenIndex; i++) {
if (getPrecedence(chosenOps[i]) != precedence) {
return false;
}
}
return true;
}
/**
*
*
*
* @param sb StringBuilder
* @param operandsCount
* @param chosenOps
* @param parentheses [openParenIndex, closeParenIndex]
*/
private void buildExpression(StringBuilder sb, int operandsCount, String[] chosenOps, int[] parentheses) {
int prevNum = random.nextInt(100) + 1;
int openParenIndex = parentheses[0];
int closeParenIndex = parentheses[1];
// 处理第一个操作数可能的开括号
if (openParenIndex == 0) sb.append("(");
sb.append(prevNum);
// 处理最后一个操作数可能的闭括号
if (closeParenIndex == operandsCount - 1) sb.append(")");
// 构建剩余的操作数和运算符
for (int i = 1; i < operandsCount; i++) {
String op = chosenOps[i - 1];
sb.append(" ").append(op).append(" ");
// 根据运算符生成下一个操作数
int num = generateOperand(op, prevNum);
// 添加括号(如果需要)
if (i == openParenIndex) sb.append("(");
sb.append(num);
if (i == closeParenIndex) sb.append(")");
prevNum = num; // 更新上一个数字,供下一轮计算使用
}
}
/**
*
*
*
* @param op
* @param prevNum
* @return
*/
private int generateOperand(String op, int prevNum) {
int num = random.nextInt(100) + 1; // 默认生成1-100之间的随机数
// 如果是减法运算符,确保不会出现负数结果
if (op.equals("-") && num > prevNum) {
num = random.nextInt(prevNum) + 1; // 保证 num <= prevNum避免负数结果
}
return num;
}
private int getPrecedence(String op) {
if (op.equals("+") || op.equals("-")) return 1;
if (op.equals("*") || op.equals("/")) return 2;
return 0;
}
}

@ -0,0 +1,64 @@
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
/**
*
*/
public class FileUtils {
// 生成文件名
public static String generateFileName() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
return sdf.format(new Date()) + ".txt";
}
// 保存题目到用户文件夹
public static void saveQuestionsToFile(String userId, String fileName, List<MathQuestion> questions) {
File userFolder = new File(userId);
if (!userFolder.exists()) {
userFolder.mkdirs();
}
File file = new File(userFolder, fileName);
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
for (MathQuestion question : questions) {
writer.write("题号 " + question.getQuestionNumber() + ": " + question.getQuestionText());
writer.newLine();
writer.newLine();
}
writer.flush();
} catch (IOException e) {
throw new RuntimeException("写文件失败: " + file.getAbsolutePath(), e);
}
}
// 读取用户文件夹下所有 txt 文件中已存在的题目
public static Set<String> loadExistingQuestions(String userId) {
Set<String> existingQuestions = new HashSet<>();
File userFolder = new File(userId);
if (!userFolder.exists() || !userFolder.isDirectory()) return existingQuestions;
File[] files = userFolder.listFiles((dir, name) -> name != null && name.endsWith(".txt"));
if (files == null) return existingQuestions;
for (File f : files) {
try (BufferedReader reader = new BufferedReader(new FileReader(f))) {
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.isEmpty()) continue;
if (line.startsWith("题号")) {
int idx = line.indexOf(":");
if (idx != -1 && idx + 1 < line.length()) {
existingQuestions.add(line.substring(idx + 1).trim());
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
return existingQuestions;
}
}

@ -0,0 +1,42 @@
import java.util.Random;
public class HighSchoolQuestionStrategy implements QuestionStrategy {
private final Random random = new Random();
private final String[] basicOps = {"+", "-", "*", "/"};
private final String[] trigFuncs = {"sin", "cos", "tan"};
@Override
public String generateQuestion() {
// 随机操作数个数 2-5
int operandsCount = random.nextInt(4) + 2;
StringBuilder sb = new StringBuilder();
boolean hasTrig = false;
for (int i = 0; i < operandsCount; i++) {
int num = random.nextInt(100) + 1;
// 每个操作数有概率加三角函数
if (random.nextBoolean()) {
String func = trigFuncs[random.nextInt(trigFuncs.length)];
sb.append(func).append("(").append(num).append(")");
hasTrig = true;
} else {
sb.append(num);
}
if (i != operandsCount - 1) {
String op = basicOps[random.nextInt(basicOps.length)];
sb.append(" ").append(op).append(" ");
}
}
// 确保至少一个三角函数
if (!hasTrig) {
String func = trigFuncs[random.nextInt(trigFuncs.length)];
int num = random.nextInt(100) + 1;
return func + "(" + num + ") + " + sb.toString();
}
return sb.toString();
}
}

@ -0,0 +1,100 @@
import java.io.IOException;
import java.util.Scanner;
/**
*
*/
public class Main {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
User currentUser = null;
// 登录流程
while (true) {
while (currentUser == null) {
System.out.print("请输入用户名和密码,用空格分隔:");
String username = scanner.next();
String password = scanner.next();
currentUser = User.login(username, password);
if (currentUser == null) {
System.out.println("请输入正确的用户名、密码");
} else {
clearScreen(); //登录成功清屏
System.out.println("当前选择为 " + currentUser.getRole() + " 出题");
}
}
// 每次登录后初始化当前出题类型(账号默认类型)
String currentRole = currentUser.getRole();
// 题目生成流程
while (true) {
System.out.println("准备生成 " + currentRole
+ " 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录");
String input = scanner.next();
// 退出登录
if (input.equals("-1")) {
currentUser = null;
clearScreen();
System.out.println("已退出当前用户,重新登录...");
break;
}
// 检测切换命令
if (input.startsWith("切换为")) {
String newRole = input.substring(3).trim();
if (!newRole.equals("小学") && !newRole.equals("初中") && !newRole.equals("高中")) {
System.out.println("请输入小学、初中和高中三个选项中的一个"+"(当前类型为"+currentRole+")");
continue;
}
currentRole = newRole;
clearScreen();
System.out.println("系统提示:准备生成 " + currentRole + " 数学题目,请输入生成题目数量");
continue;
}
// 输入题目数量
int questionCount;
try {
questionCount = Integer.parseInt(input);
} catch (NumberFormatException e) {
System.out.println("请输入有效的数字或使用“切换为小学/初中/高中”命令"+"(当前类型为"+currentRole+")");
continue;
}
if (questionCount < 10 || questionCount > 30) {
System.out.println("请输入有效的题目数量 (10-30) 或 -1 退出");
continue;
}
clearScreen();
// 把 currentRole 传给 QuestionGenerator
QuestionGenerator generator = new QuestionGenerator(currentUser, currentRole);
generator.generateQuestions(questionCount);
System.out.println("题目已生成并保存!\n");
}
}
}
/**
*
*/
public static void clearScreen() {
try {
if (System.getProperty("os.name").contains("Windows")) {
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
} else {
new ProcessBuilder("clear").inheritIO().start().waitFor();
}
} catch (Exception e) {
for (int i = 0; i < 50; i++) {
System.out.println();
}
}
}
}

@ -0,0 +1,21 @@
/**
*
*/
public class MathQuestion {
private int questionNumber;
private String questionText;
// 构造方法
public MathQuestion(int questionNumber, String questionText) {
this.questionNumber = questionNumber;
this.questionText = questionText;
}
public int getQuestionNumber() {
return questionNumber;
}
public String getQuestionText() {
return questionText;
}
}

@ -0,0 +1,47 @@
import java.util.Random;
public class MiddleSchoolQuestionStrategy implements QuestionStrategy {
private final Random random = new Random();
private final String[] basicOps = {"+", "-", "*", "/"}; // 基本运算符
@Override
public String generateQuestion() {
// 随机操作数个数 2-5
int operandsCount = random.nextInt(4) + 2;
StringBuilder sb = new StringBuilder();
boolean hasSquareOrRoot = false;
// 生成运算符和操作数
for (int i = 0; i < operandsCount; i++) {
int num = random.nextInt(100) + 1; // 生成1-100之间的数字
// 每个操作数有概率平方或开根号
if (random.nextBoolean()) {
if (random.nextBoolean()) {
sb.append("(").append(num).append(")^2");
hasSquareOrRoot = true; // 标记是否已经使用了平方或根号
} else {
// 确保根号下的数为正
int rootNumber = random.nextInt(100) + 1; // 始终生成正整数
sb.append("√(").append(rootNumber).append(")");
hasSquareOrRoot = true; // 标记是否已经使用了平方或根号
}
} else {
sb.append(num); // 普通数字
}
// 添加运算符(除最后一个操作数外)
if (i != operandsCount - 1) {
String op = basicOps[random.nextInt(basicOps.length)];
sb.append(" ").append(op).append(" ");
}
}
// 如果没有平方或根号,强制添加一个
if (!hasSquareOrRoot) {
// 确保根号下的数为正
int rootNumber = random.nextInt(100) + 1; // 始终生成正整数
sb.append(" + √(").append(rootNumber).append(")");
}
return sb.toString();
}
}

@ -0,0 +1,51 @@
import java.io.IOException;
import java.util.*;
/**
*
*/
public class QuestionGenerator {
private User user;
private String role;
public QuestionGenerator(User user, String role) {
this.user = user;
this.role = role;
}
public void generateQuestions(int questionCount) throws IOException {
// 获取策略
QuestionStrategy strategy = QuestionStrategyFactory.getStrategy(role);
// 读出该用户所有历史题目
Set<String> existingQuestions = FileUtils.loadExistingQuestions(user.getUsername());
Set<String> newQuestionsSet = new HashSet<>();
List<MathQuestion> questions = new ArrayList<>();
System.out.println("以下为生成的题目列表:\n");
int i = 1;
int tryCount = 0;
while (questions.size() < questionCount) {
String questionText = strategy.generateQuestion();
tryCount++;
if (existingQuestions.contains(questionText) || newQuestionsSet.contains(questionText)) {
// 如果题库太小可能死循环,这里设置最大尝试次数
if (tryCount > questionCount * 100) {
System.out.println("题库不足,无法生成足够不重复的题目");
break;
}
continue;
}
newQuestionsSet.add(questionText);
MathQuestion question = new MathQuestion(i, questionText);
questions.add(question);
System.out.println("题号 " + i + "" + questionText + "\n");
i++;
}
String fileName = FileUtils.generateFileName();
FileUtils.saveQuestionsToFile(user.getUsername(), fileName, questions);
}
}

@ -0,0 +1,26 @@
import java.util.HashSet;
import java.util.Set;
/**
*
*/
public class QuestionRepository {
private Set<String> generatedQuestions = new HashSet<>();
/**
*
* @param question
* @return
*/
public boolean isDuplicate(String question) {
return generatedQuestions.contains(question);
}
/**
*
* @param question
*/
public void addQuestion(String question) {
generatedQuestions.add(question);
}
}

@ -0,0 +1,6 @@
/**
*
*/
public interface QuestionStrategy {
String generateQuestion();
}

@ -0,0 +1,17 @@
/**
* role
*/
public class QuestionStrategyFactory {
public static QuestionStrategy getStrategy(String role) {
switch (role) {
case "小学":
return new ElementaryQuestionStrategy();
case "初中":
return new MiddleSchoolQuestionStrategy();
case "高中":
return new HighSchoolQuestionStrategy();
default:
throw new IllegalArgumentException("未知的角色: " + role);
}
}
}

@ -0,0 +1,52 @@
/**
*
*/
public class User {
private String username;
private String password;
private String role;
// 构造方法
public User(String username, String password, String role) {
this.username = username;
this.password = password;
this.role = role;
}
/**
*
* @param username
* @param password
* @return null
*/
public static User login(String username, String password) {
String[][] users = {
{"张三1", "123", "小学"}, {"张三2", "123", "小学"}, {"张三3", "123", "小学"},
{"李四1", "123", "初中"}, {"李四2", "123", "初中"}, {"李四3", "123", "初中"},
{"王五1", "123", "高中"}, {"王五2", "123", "高中"}, {"王五3", "123", "高中"}
};
for (String[] user : users) {
if (user[0].equals(username) && user[1].equals(password)) {
return new User(username, password, user[2]);
}
}
return null;
}
/**
*
* @return
*/
public String getRole() {
return this.role;
}
/**
*
* @return
*/
public String getUsername() {
return this.username;
}
}
Loading…
Cancel
Save