|
|
|
|
@ -0,0 +1,408 @@
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <ctime>
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
#include <limits>
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 数学题目基类
|
|
|
|
|
class MathProblem {
|
|
|
|
|
protected:
|
|
|
|
|
vector<string> generatedProblems;//存储生成过的题目
|
|
|
|
|
|
|
|
|
|
int randInt(int min, int max) {//生成min-max范围的随机整数
|
|
|
|
|
return min + rand() % (max - min + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isProblemExists(const string& problem) {
|
|
|
|
|
for (size_t i = 0; i < generatedProblems.size(); i++) {//循环,判断题目是否已经存在
|
|
|
|
|
if (generatedProblems[i] == problem) {return true;}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
MathProblem() {}
|
|
|
|
|
virtual ~MathProblem() {}
|
|
|
|
|
|
|
|
|
|
virtual string generateProblem() = 0;
|
|
|
|
|
|
|
|
|
|
vector<string> generateProblems(int count) { //题目生成
|
|
|
|
|
vector<string> problems;
|
|
|
|
|
int attempts = 0;
|
|
|
|
|
const int MAX_ATTEMPTS = 1000;
|
|
|
|
|
|
|
|
|
|
while (problems.size() < count && attempts < MAX_ATTEMPTS) {
|
|
|
|
|
string problem = generateProblem();
|
|
|
|
|
if (!isProblemExists(problem)) {
|
|
|
|
|
problems.push_back(problem);
|
|
|
|
|
generatedProblems.push_back(problem);
|
|
|
|
|
}
|
|
|
|
|
attempts++;
|
|
|
|
|
}
|
|
|
|
|
return problems;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void clear() {
|
|
|
|
|
generatedProblems.clear();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 小学题目生成器
|
|
|
|
|
class PrimaryMath : public MathProblem {
|
|
|
|
|
private:
|
|
|
|
|
char getOperator() {
|
|
|
|
|
char operators[] = {'+', '-', '*', '/'};
|
|
|
|
|
return operators[rand() % 4];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string Expression(int numCount) {
|
|
|
|
|
stringstream expr;
|
|
|
|
|
for (int i = 0; i < numCount; i++) {
|
|
|
|
|
expr << randInt(1, 100);
|
|
|
|
|
if (i < numCount - 1) {
|
|
|
|
|
expr << " " << getOperator() << " ";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return expr.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string addParentheses(const string& expr, int numCount) {
|
|
|
|
|
if (numCount > 2 && randInt(0, 1)) {
|
|
|
|
|
if (numCount == 3) {
|
|
|
|
|
if (randInt(0, 1)) {
|
|
|
|
|
return "(" + expr + ")";
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
stringstream result;
|
|
|
|
|
int splitPoint = randInt(1, numCount-1);
|
|
|
|
|
result << "(";
|
|
|
|
|
for (int i = 0; i < splitPoint; i++) {
|
|
|
|
|
result << randInt(1, 100);
|
|
|
|
|
if (i < splitPoint - 1) {
|
|
|
|
|
result << " " << getOperator() << " ";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
result << ") " << getOperator() << " ";
|
|
|
|
|
for (int i = splitPoint; i < numCount; i++) {
|
|
|
|
|
result << randInt(1, 100);
|
|
|
|
|
if (i < numCount - 1) {
|
|
|
|
|
result << " " << getOperator() << " ";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result.str();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return expr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
string generateProblem() {
|
|
|
|
|
int numCount = randInt(2, 5);
|
|
|
|
|
stringstream problem;
|
|
|
|
|
|
|
|
|
|
string expression = Expression(numCount);
|
|
|
|
|
expression = addParentheses(expression, numCount);
|
|
|
|
|
problem << expression << " = ";
|
|
|
|
|
|
|
|
|
|
return problem.str();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 初中题目生成器
|
|
|
|
|
class JuniorMath : public MathProblem {
|
|
|
|
|
private:
|
|
|
|
|
char getOperator() {
|
|
|
|
|
char operators[] = {'+', '-', '*', '/'};
|
|
|
|
|
return operators[rand() % 4];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string Expression(bool& hasAdvancedOp) {
|
|
|
|
|
stringstream part;
|
|
|
|
|
if (!hasAdvancedOp && randInt(0, 1)) {
|
|
|
|
|
if (randInt(0, 1)) {
|
|
|
|
|
part << randInt(1, 10) << "^2"; // 使用^2表示平方
|
|
|
|
|
} else {
|
|
|
|
|
part << "√" << randInt(1, 100);
|
|
|
|
|
}
|
|
|
|
|
hasAdvancedOp = true;
|
|
|
|
|
} else {
|
|
|
|
|
part << randInt(1, 100);
|
|
|
|
|
}
|
|
|
|
|
return part.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string addOperator(const string& expr, bool hasAdvancedOp) {
|
|
|
|
|
if (!hasAdvancedOp) {
|
|
|
|
|
if (randInt(0, 1)) {
|
|
|
|
|
return "(" + expr + ")^2";
|
|
|
|
|
} else {
|
|
|
|
|
return "√(" + expr + ")";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return expr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
string generateProblem() {
|
|
|
|
|
int numCount = randInt(2, 5);
|
|
|
|
|
stringstream problem;
|
|
|
|
|
bool hasAdvancedOp = false;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < numCount; i++) {
|
|
|
|
|
problem << Expression(hasAdvancedOp);
|
|
|
|
|
if (i < numCount - 1) {
|
|
|
|
|
problem << " " << getOperator() << " ";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string expression = problem.str();
|
|
|
|
|
expression = addOperator(expression, hasAdvancedOp);
|
|
|
|
|
|
|
|
|
|
stringstream finalProblem;
|
|
|
|
|
finalProblem << expression << " = ";
|
|
|
|
|
return finalProblem.str();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 高中题目生成器
|
|
|
|
|
class SeniorMath : public MathProblem {
|
|
|
|
|
private:
|
|
|
|
|
char getOperator() {
|
|
|
|
|
char operators[] = {'+', '-', '*', '/'};
|
|
|
|
|
return operators[rand() % 4];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string getTrigFunction() {
|
|
|
|
|
string functions[] = {"sin", "cos", "tan"};
|
|
|
|
|
return functions[rand() % 3];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string Expression(bool& hasTrigOp) {
|
|
|
|
|
stringstream part;
|
|
|
|
|
if (!hasTrigOp && randInt(0, 1)) {
|
|
|
|
|
part << getTrigFunction() << "(" << randInt(1, 100) << ")";
|
|
|
|
|
hasTrigOp = true;
|
|
|
|
|
} else {
|
|
|
|
|
part << randInt(1, 100);
|
|
|
|
|
}
|
|
|
|
|
return part.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string addTrigFunction(const string& expr, bool hasTrigOp) {
|
|
|
|
|
if (!hasTrigOp) {
|
|
|
|
|
return getTrigFunction() + "(" + expr + ")";
|
|
|
|
|
}
|
|
|
|
|
return expr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
string generateProblem() {
|
|
|
|
|
int numCount = randInt(2, 5);
|
|
|
|
|
stringstream problem;
|
|
|
|
|
bool hasTrigOp = false;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < numCount; i++) {
|
|
|
|
|
problem << Expression(hasTrigOp);
|
|
|
|
|
if (i < numCount - 1) {
|
|
|
|
|
problem << " " << getOperator() << " ";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string expression = problem.str();
|
|
|
|
|
expression = addTrigFunction(expression, hasTrigOp);
|
|
|
|
|
|
|
|
|
|
stringstream finalProblem;
|
|
|
|
|
finalProblem << expression << " = ";
|
|
|
|
|
return finalProblem.str();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Account {
|
|
|
|
|
|
|
|
|
|
string username;
|
|
|
|
|
string password;
|
|
|
|
|
string type;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
vector<Account> accounts;
|
|
|
|
|
MathProblem* currentGenerator = NULL;
|
|
|
|
|
string nowUserType = "";
|
|
|
|
|
string nowUsername = "";
|
|
|
|
|
|
|
|
|
|
bool Verify(const string& username, const string& password, string& userType); //账号验证函数
|
|
|
|
|
void CreateFolder(const string& username);//创建用户文件夹
|
|
|
|
|
string GetTimestamp();//获取时间戳
|
|
|
|
|
void SaveToFile(const vector<string>& problems, const string& username);//保存题目到文件夹中
|
|
|
|
|
void Login();//用户登录
|
|
|
|
|
void ProblemGeneration_Menu();//题目生成过程菜单
|
|
|
|
|
void TypeSwitching();//类型转换
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Verify(const string& username, const string& password, string& userType) {
|
|
|
|
|
for (size_t i = 0; i < accounts.size(); i++) {
|
|
|
|
|
if (accounts[i].username == username && accounts[i].password == password) { //检验账号密码是否正确,正确的话就提取账号类型
|
|
|
|
|
userType = accounts[i].type;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建用户文件夹
|
|
|
|
|
void CreateFolder(const string& username) {
|
|
|
|
|
string folderName = username + "_papers";
|
|
|
|
|
string command = "mkdir \"" + folderName + "\" 2>nul";
|
|
|
|
|
system(command.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取当前时间戳
|
|
|
|
|
string GetTimestamp() {
|
|
|
|
|
time_t now = time(NULL);
|
|
|
|
|
struct tm* timeinfo = localtime(&now);
|
|
|
|
|
char filename[100];
|
|
|
|
|
strftime(filename, sizeof(filename), "%Y-%m-%d-%H-%M-%S.txt", timeinfo);
|
|
|
|
|
return string(filename);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 保存题目到文件
|
|
|
|
|
void SaveToFile(const vector<string>& problems, const string& username) {
|
|
|
|
|
CreateFolder(username);
|
|
|
|
|
string filename = GetTimestamp();
|
|
|
|
|
string fullPath = username + "_papers/" + filename;
|
|
|
|
|
|
|
|
|
|
cout << "正在保存文件到: " << fullPath << endl;
|
|
|
|
|
|
|
|
|
|
ofstream file(fullPath.c_str());
|
|
|
|
|
if (file.is_open()) {
|
|
|
|
|
for (size_t i = 0; i < problems.size(); i++) {
|
|
|
|
|
file << (i + 1) << ". " << problems[i] << "\n\n";
|
|
|
|
|
}
|
|
|
|
|
file.close();
|
|
|
|
|
cout << "题目已成功保存到: " << fullPath << endl;
|
|
|
|
|
} else {
|
|
|
|
|
cout << "错误:无法创建文件 " << fullPath << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建题目生成器
|
|
|
|
|
MathProblem* createGeneratorByType(const string& type) {
|
|
|
|
|
if (type == "小学") return new PrimaryMath();
|
|
|
|
|
else if (type == "初中") return new JuniorMath();
|
|
|
|
|
else if (type == "高中") return new SeniorMath();
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理类型切换
|
|
|
|
|
void TypeSwitching() {
|
|
|
|
|
while(true){
|
|
|
|
|
cout << "如需切换类型,请输入\"切换为XX\"(XX为小学、初中、高中),直接按回车继续当前模式: ";
|
|
|
|
|
|
|
|
|
|
string input;
|
|
|
|
|
getline(cin, input);
|
|
|
|
|
if (input.empty()) {
|
|
|
|
|
cout << "继续使用当前" << nowUserType << "出题模式" << endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
string newType = input.substr(6);
|
|
|
|
|
|
|
|
|
|
if (newType == "小学" || newType == "初中" || newType == "高中") {
|
|
|
|
|
nowUserType = newType;
|
|
|
|
|
if (currentGenerator) {
|
|
|
|
|
delete currentGenerator;
|
|
|
|
|
currentGenerator = createGeneratorByType(newType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cout << "已切换为" << newType << "出题模式" << endl;
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
cout << "请输入小学、初中和高中三个选项中的一个" << endl;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理用户登录
|
|
|
|
|
void Login() {
|
|
|
|
|
string username, password;
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
cout << "===== 中小学数学卷子自动生成程序 =====" << endl;
|
|
|
|
|
cout << "请输入用户名和密码(用空格隔开): ";
|
|
|
|
|
cin >> username >> password;
|
|
|
|
|
|
|
|
|
|
string userType;
|
|
|
|
|
if (Verify(username, password, userType)) {
|
|
|
|
|
nowUsername = username;
|
|
|
|
|
nowUserType = userType;
|
|
|
|
|
|
|
|
|
|
if (currentGenerator) delete currentGenerator;
|
|
|
|
|
currentGenerator = createGeneratorByType(userType);
|
|
|
|
|
|
|
|
|
|
cout << "当前选择为" << userType << "出题" << endl;
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
cout << "请输入正确的用户名、密码" << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理题目生成过程
|
|
|
|
|
void ProblemGeneration_Menu() {
|
|
|
|
|
while (true) {
|
|
|
|
|
cout << "准备生成" << nowUserType << "数学题目,请输入生成题目数量(10-30,-1退出): ";
|
|
|
|
|
int count;
|
|
|
|
|
cin >> count;
|
|
|
|
|
|
|
|
|
|
if (count == -1) {
|
|
|
|
|
if (currentGenerator) currentGenerator->clear();
|
|
|
|
|
cout<< "已退出程序,请重新登录" <<endl;
|
|
|
|
|
system("cls");
|
|
|
|
|
Login();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (count < 10 || count > 30) {
|
|
|
|
|
cout << "题目数量应在10-30之间" << endl;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector<string> problems = currentGenerator->generateProblems(count);
|
|
|
|
|
SaveToFile(problems, nowUsername);
|
|
|
|
|
cin.ignore(numeric_limits<streamsize>::max(), '\n');
|
|
|
|
|
// 类型切换功能调用
|
|
|
|
|
TypeSwitching();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 主函数
|
|
|
|
|
int main() {
|
|
|
|
|
srand(time(NULL));
|
|
|
|
|
accounts.push_back((Account){"张三1", "123", "小学"});
|
|
|
|
|
accounts.push_back((Account){"张三2", "123", "小学"});
|
|
|
|
|
accounts.push_back((Account){"张三3", "123", "小学"});
|
|
|
|
|
|
|
|
|
|
accounts.push_back((Account){"李四1", "123", "初中"});
|
|
|
|
|
accounts.push_back((Account){"李四2", "123", "初中"});
|
|
|
|
|
accounts.push_back((Account){"李四3", "123", "初中"});
|
|
|
|
|
|
|
|
|
|
accounts.push_back((Account){"王五1", "123", "高中"});
|
|
|
|
|
accounts.push_back((Account){"王五2", "123", "高中"});
|
|
|
|
|
accounts.push_back((Account){"王五3", "123", "高中"});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Login();
|
|
|
|
|
ProblemGeneration_Menu();
|
|
|
|
|
|
|
|
|
|
if (currentGenerator) delete currentGenerator;
|
|
|
|
|
|
|
|
|
|
cout << "程序结束,感谢使用!" << endl;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|