|
|
|
|
@ -0,0 +1,410 @@
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <random>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <ctime>
|
|
|
|
|
#include <iomanip>
|
|
|
|
|
#include <filesystem>
|
|
|
|
|
#include <set>
|
|
|
|
|
#include <locale>
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#include <io.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
|
|
|
|
|
|
// 用户账号结构
|
|
|
|
|
struct User {
|
|
|
|
|
string username;
|
|
|
|
|
string password;
|
|
|
|
|
string type; // "小学", "初中", "高中"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 数学题目结构
|
|
|
|
|
struct MathQuestion {
|
|
|
|
|
string question;
|
|
|
|
|
int answer;
|
|
|
|
|
|
|
|
|
|
bool operator<(const MathQuestion& other) const {
|
|
|
|
|
return question < other.question;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class MathExamGenerator {
|
|
|
|
|
private:
|
|
|
|
|
vector<User> users;
|
|
|
|
|
User currentUser;
|
|
|
|
|
bool isLoggedIn;
|
|
|
|
|
string currentType;
|
|
|
|
|
random_device rd;
|
|
|
|
|
mt19937 gen;
|
|
|
|
|
|
|
|
|
|
// 存储已生成的题目,避免重复
|
|
|
|
|
map<string, set<MathQuestion>> generatedQuestions;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
MathExamGenerator() : gen(rd()), isLoggedIn(false) {
|
|
|
|
|
initializeUsers();
|
|
|
|
|
loadExistingQuestions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 初始化预设账号
|
|
|
|
|
void initializeUsers() {
|
|
|
|
|
// 小学账号
|
|
|
|
|
users.push_back({"xiaoxue1", "123456", "小学"});
|
|
|
|
|
users.push_back({"xiaoxue2", "123456", "小学"});
|
|
|
|
|
users.push_back({"xiaoxue3", "123456", "小学"});
|
|
|
|
|
|
|
|
|
|
// 初中账号
|
|
|
|
|
users.push_back({"chuzhong1", "123456", "初中"});
|
|
|
|
|
users.push_back({"chuzhong2", "123456", "初中"});
|
|
|
|
|
users.push_back({"chuzhong3", "123456", "初中"});
|
|
|
|
|
|
|
|
|
|
// 高中账号
|
|
|
|
|
users.push_back({"gaozhong1", "123456", "高中"});
|
|
|
|
|
users.push_back({"gaozhong2", "123456", "高中"});
|
|
|
|
|
users.push_back({"gaozhong3", "123456", "高中"});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 加载已存在的题目
|
|
|
|
|
void loadExistingQuestions() {
|
|
|
|
|
for (const auto& user : users) {
|
|
|
|
|
string folderPath = user.username;
|
|
|
|
|
if (fs::exists(folderPath)) {
|
|
|
|
|
for (const auto& entry : fs::directory_iterator(folderPath)) {
|
|
|
|
|
if (entry.is_regular_file() && entry.path().extension() == ".txt") {
|
|
|
|
|
loadQuestionsFromFile(entry.path().string(), user.username);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从文件加载题目
|
|
|
|
|
void loadQuestionsFromFile(const string& filename, const string& username) {
|
|
|
|
|
ifstream file(filename);
|
|
|
|
|
string line;
|
|
|
|
|
while (getline(file, line)) {
|
|
|
|
|
if (!line.empty() && line.find('.') != string::npos) {
|
|
|
|
|
// 提取题目部分(去掉题号)
|
|
|
|
|
size_t dotPos = line.find('.');
|
|
|
|
|
if (dotPos != string::npos && dotPos + 1 < line.length()) {
|
|
|
|
|
string question = line.substr(dotPos + 1);
|
|
|
|
|
// 去掉前后空格
|
|
|
|
|
question.erase(0, question.find_first_not_of(" \t"));
|
|
|
|
|
question.erase(question.find_last_not_of(" \t") + 1);
|
|
|
|
|
|
|
|
|
|
MathQuestion mq;
|
|
|
|
|
mq.question = question;
|
|
|
|
|
mq.answer = 0; // 这里简化处理
|
|
|
|
|
generatedQuestions[username].insert(mq);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
file.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 用户登录
|
|
|
|
|
bool login(const string& username, const string& password) {
|
|
|
|
|
for (const auto& user : users) {
|
|
|
|
|
if (user.username == username && user.password == password) {
|
|
|
|
|
currentUser = user;
|
|
|
|
|
currentType = user.type;
|
|
|
|
|
isLoggedIn = true;
|
|
|
|
|
cout << "当前选择为" << currentType << "出题" << endl;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成小学数学题
|
|
|
|
|
MathQuestion generatePrimaryQuestion() {
|
|
|
|
|
uniform_int_distribution<> opCount(2, 3); // 操作数2-3个
|
|
|
|
|
uniform_int_distribution<> numDist(1, 50); // 数值范围1-50
|
|
|
|
|
uniform_int_distribution<> opDist(0, 1); // 0:加法, 1:减法
|
|
|
|
|
|
|
|
|
|
int operandCount = opCount(gen);
|
|
|
|
|
vector<int> numbers;
|
|
|
|
|
vector<char> operators;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
numbers.push_back(numDist(gen));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operandCount - 1; i++) {
|
|
|
|
|
operators.push_back(opDist(gen) == 0 ? '+' : '-');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建题目字符串
|
|
|
|
|
stringstream ss;
|
|
|
|
|
ss << numbers[0];
|
|
|
|
|
int result = numbers[0];
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operators.size(); i++) {
|
|
|
|
|
ss << " " << operators[i] << " " << numbers[i + 1];
|
|
|
|
|
if (operators[i] == '+') {
|
|
|
|
|
result += numbers[i + 1];
|
|
|
|
|
} else {
|
|
|
|
|
result -= numbers[i + 1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 确保结果为正数
|
|
|
|
|
if (result < 0) {
|
|
|
|
|
return generatePrimaryQuestion();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ss << " = ?";
|
|
|
|
|
|
|
|
|
|
MathQuestion question;
|
|
|
|
|
question.question = ss.str();
|
|
|
|
|
question.answer = result;
|
|
|
|
|
|
|
|
|
|
return question;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成初中数学题
|
|
|
|
|
MathQuestion generateMiddleQuestion() {
|
|
|
|
|
uniform_int_distribution<> opCount(3, 4); // 操作数3-4个
|
|
|
|
|
uniform_int_distribution<> numDist(1, 100); // 数值范围1-100
|
|
|
|
|
uniform_int_distribution<> opDist(0, 2); // 0:加法, 1:减法, 2:乘法
|
|
|
|
|
|
|
|
|
|
int operandCount = opCount(gen);
|
|
|
|
|
vector<int> numbers;
|
|
|
|
|
vector<char> operators;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
numbers.push_back(numDist(gen));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operandCount - 1; i++) {
|
|
|
|
|
int op = opDist(gen);
|
|
|
|
|
if (op == 0) operators.push_back('+');
|
|
|
|
|
else if (op == 1) operators.push_back('-');
|
|
|
|
|
else operators.push_back('*');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建题目字符串
|
|
|
|
|
stringstream ss;
|
|
|
|
|
ss << numbers[0];
|
|
|
|
|
int result = numbers[0];
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operators.size(); i++) {
|
|
|
|
|
ss << " " << operators[i] << " " << numbers[i + 1];
|
|
|
|
|
if (operators[i] == '+') {
|
|
|
|
|
result += numbers[i + 1];
|
|
|
|
|
} else if (operators[i] == '-') {
|
|
|
|
|
result -= numbers[i + 1];
|
|
|
|
|
} else {
|
|
|
|
|
result *= numbers[i + 1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ss << " = ?";
|
|
|
|
|
|
|
|
|
|
MathQuestion question;
|
|
|
|
|
question.question = ss.str();
|
|
|
|
|
question.answer = result;
|
|
|
|
|
|
|
|
|
|
return question;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成高中数学题
|
|
|
|
|
MathQuestion generateHighQuestion() {
|
|
|
|
|
uniform_int_distribution<> opCount(4, 5); // 操作数4-5个
|
|
|
|
|
uniform_int_distribution<> numDist(1, 100); // 数值范围1-100
|
|
|
|
|
uniform_int_distribution<> opDist(0, 3); // 0:加法, 1:减法, 2:乘法, 3:除法
|
|
|
|
|
|
|
|
|
|
int operandCount = opCount(gen);
|
|
|
|
|
vector<int> numbers;
|
|
|
|
|
vector<char> operators;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
numbers.push_back(numDist(gen));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operandCount - 1; i++) {
|
|
|
|
|
int op = opDist(gen);
|
|
|
|
|
if (op == 0) operators.push_back('+');
|
|
|
|
|
else if (op == 1) operators.push_back('-');
|
|
|
|
|
else if (op == 2) operators.push_back('*');
|
|
|
|
|
else {
|
|
|
|
|
operators.push_back('/');
|
|
|
|
|
// 确保除法结果为整数
|
|
|
|
|
numbers[i + 1] = numbers[i] % numbers[i + 1] == 0 ? numbers[i + 1] :
|
|
|
|
|
(numbers[i] / numbers[i + 1] + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建题目字符串
|
|
|
|
|
stringstream ss;
|
|
|
|
|
ss << numbers[0];
|
|
|
|
|
double result = numbers[0];
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operators.size(); i++) {
|
|
|
|
|
ss << " " << operators[i] << " " << numbers[i + 1];
|
|
|
|
|
if (operators[i] == '+') {
|
|
|
|
|
result += numbers[i + 1];
|
|
|
|
|
} else if (operators[i] == '-') {
|
|
|
|
|
result -= numbers[i + 1];
|
|
|
|
|
} else if (operators[i] == '*') {
|
|
|
|
|
result *= numbers[i + 1];
|
|
|
|
|
} else {
|
|
|
|
|
if (numbers[i + 1] != 0) {
|
|
|
|
|
result /= numbers[i + 1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ss << " = ?";
|
|
|
|
|
|
|
|
|
|
MathQuestion question;
|
|
|
|
|
question.question = ss.str();
|
|
|
|
|
question.answer = (int)result;
|
|
|
|
|
|
|
|
|
|
return question;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据类型生成题目
|
|
|
|
|
MathQuestion generateQuestion(const string& type) {
|
|
|
|
|
if (type == "小学") {
|
|
|
|
|
return generatePrimaryQuestion();
|
|
|
|
|
} else if (type == "初中") {
|
|
|
|
|
return generateMiddleQuestion();
|
|
|
|
|
} else {
|
|
|
|
|
return generateHighQuestion();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查题目是否重复
|
|
|
|
|
bool isQuestionDuplicate(const MathQuestion& question) {
|
|
|
|
|
return generatedQuestions[currentUser.username].count(question) > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成试卷
|
|
|
|
|
void generateExam(int questionCount) {
|
|
|
|
|
vector<MathQuestion> questions;
|
|
|
|
|
|
|
|
|
|
// 生成不重复的题目
|
|
|
|
|
while (questions.size() < questionCount) {
|
|
|
|
|
MathQuestion question = generateQuestion(currentType);
|
|
|
|
|
if (!isQuestionDuplicate(question)) {
|
|
|
|
|
questions.push_back(question);
|
|
|
|
|
generatedQuestions[currentUser.username].insert(question);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建用户文件夹
|
|
|
|
|
string folderPath = currentUser.username;
|
|
|
|
|
if (!fs::exists(folderPath)) {
|
|
|
|
|
fs::create_directory(folderPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成文件名(年-月-日-时-分-秒.txt)
|
|
|
|
|
auto now = chrono::system_clock::now();
|
|
|
|
|
auto time_t = chrono::system_clock::to_time_t(now);
|
|
|
|
|
auto tm = *localtime(&time_t);
|
|
|
|
|
|
|
|
|
|
stringstream filename;
|
|
|
|
|
filename << folderPath << "/"
|
|
|
|
|
<< put_time(&tm, "%Y-%m-%d-%H-%M-%S") << ".txt";
|
|
|
|
|
|
|
|
|
|
// 写入文件
|
|
|
|
|
ofstream file(filename.str());
|
|
|
|
|
for (int i = 0; i < questions.size(); i++) {
|
|
|
|
|
file << (i + 1) << ". " << questions[i].question << endl;
|
|
|
|
|
if (i < questions.size() - 1) {
|
|
|
|
|
file << endl; // 题目之间空一行
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
|
|
cout << "试卷已生成并保存到: " << filename.str() << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 切换类型
|
|
|
|
|
bool switchType(const string& newType) {
|
|
|
|
|
if (newType == "小学" || newType == "初中" || newType == "高中") {
|
|
|
|
|
currentType = newType;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 主运行循环
|
|
|
|
|
void run() {
|
|
|
|
|
cout << "=== 中小学数学卷子自动生成程序 ===" << endl;
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
if (!isLoggedIn) {
|
|
|
|
|
cout << "请输入用户名和密码(用空格隔开): ";
|
|
|
|
|
string username, password;
|
|
|
|
|
cin >> username >> password;
|
|
|
|
|
|
|
|
|
|
if (login(username, password)) {
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
cout << "请输入正确的用户名、密码" << endl;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cout << "准备生成" << currentType << "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):";
|
|
|
|
|
string input;
|
|
|
|
|
cin >> input;
|
|
|
|
|
|
|
|
|
|
// 检查是否是切换命令
|
|
|
|
|
if (input.find("切换为") == 0) {
|
|
|
|
|
string newType = input.substr(3); // 去掉"切换为"
|
|
|
|
|
if (switchType(newType)) {
|
|
|
|
|
cout << "准备生成" << currentType << "数学题目,请输入生成题目数量:";
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
cout << "请输入小学、初中和高中三个选项中的一个" << endl;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
int count = stoi(input);
|
|
|
|
|
|
|
|
|
|
if (count == -1) {
|
|
|
|
|
isLoggedIn = false;
|
|
|
|
|
cout << "已退出登录" << endl;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (count >= 10 && count <= 30) {
|
|
|
|
|
generateExam(count);
|
|
|
|
|
} else {
|
|
|
|
|
cout << "题目数量必须在10-30之间" << endl;
|
|
|
|
|
}
|
|
|
|
|
} catch (const exception& e) {
|
|
|
|
|
cout << "请输入有效的数字" << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
// 设置控制台编码为UTF-8,解决中文乱码问题
|
|
|
|
|
SetConsoleOutputCP(CP_UTF8);
|
|
|
|
|
SetConsoleCP(CP_UTF8);
|
|
|
|
|
|
|
|
|
|
// 设置locale为中文
|
|
|
|
|
setlocale(LC_ALL, "zh_CN.UTF-8");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
MathExamGenerator generator;
|
|
|
|
|
generator.run();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|