Github: acromema/CPGenerator
写一个能自动生成小学四则运算题目的命令行软件,满足以下要求:
PSP 2.1 | Personal Software Process Stages | 预估耗时(min) | 实际耗时(min) |
---|---|---|---|
Planning | 计划 | 60 | |
Estimate | 估计这个任务需要多少时间 | 60 | |
Development | 开发 | 2400 | |
Analysis | 需求分析(包括学习新技术) | 360 | |
Design Spec | 生成设计文档 | 120 | |
Design Review | 设计复审(和同事审核审计文档) | 60 | |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 60 | |
Design | 具体设计 | 360 | |
Coding | 具体编码 | 600 | |
Code Review | 代码复审 | 480 | |
Test | 测试(自我测试,修改代码,提交修改) | 360 | |
Reporting | 报告 | 420 | |
Test Report | 测试报告 | 120 | |
Size Measurement | 计算工作量 | 120 | |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 180 | |
合计 | 2880 |
程序要同时支持整数和真分数的四则运算,由于分数无法直接运算,因此单独进行处理。
分工为:我完成分数题目部分,队友完成整数部分和界面部分。
队友传送门->
闪bo
定义class PF
真分数类,包含:
int mother
分母int son
分子PF()
随机生成分母分子值的构造函数PF(int _mother, int _son)
指定分母分子值的构造函数Display()
显示函数(将分数显示在命令行中方便调试)ConvertString()
真分数转字符串的转换函数(方便存储到字符串中)GetRandomSeed()
随机数种子函数(用于随机生成分母分子值)MaxComDivisor(int x, int y)
最大公因子函数(用于约分化简)operator +-*/(PF p1, PF p2)
重载四种运算符(用于分数分四则运算)定义class Problem
题目类,包含:
string op1 op2 op3
3个运算符PF p1 p2 p3 p4
4个运算数Problem()
生成一道题目的构造函数NextProblem()
生成下一道题目的函数CalValue()
表达式求值函数(计算当前题目答案)ConvertString()
真分数转字符串的转换函数(方便存储到字符串中)GetRandomSeed()
随机数种子函数(用于随机生成分母分子值)MaxComDivisor(int x, int y)
最大公因子函数(用于约分化简)operator +-*/(PF p1, PF p2)
重载四种运算符(用于分数分四则运算)1.随机生成真分数(构造函数)
public PF()
{
Random rand = new Random(GetRandomSeed());
mother = rand.Next(3,10);
son = rand.Next(1,2);
int maxDivisor = MaxComDivisor(Math.Abs(mother), Math.Abs(son));
mother /= maxDivisor;
son /= maxDivisor;
}
2.重载四个运算符
public static PF operator+ (PF p1,PF p2)
{
int mother = p1.mother * p2.mother;
int son1 = p1.son * p2.mother;
int son2 = p2.son * p1.mother;
int son = son1 + son2;
PF sum = new PF(mother, son);
return sum;
}
public static PF operator- (PF p1,PF p2)
{
int mother = p1.mother * p2.mother;
int son1 = p1.son * p2.mother;
int son2 = p2.son * p1.mother;
int son = son1 - son2;
PF result = new PF(mother, son);
return result;
}
public static PF operator* (PF p1,PF p2)
{
int mother = p1.mother * p2.mother;
int son = p1.son * p2.son;
PF result = new PF(mother, son);
return result;
}
public static PF operator/ (PF p1,PF p2)
{
int mother = p1.mother * p2.son;
int son = p1.son * p2.mother;
PF result = new PF(mother, son);
return result;
}
3.出题
public Problem()
{
string[] op = new string[]{"+", "-", "*", "/", "-", "+"};
Random rand = new Random(GetRandomSeed());
op1 = op[rand.Next(6)];
op2 = op[rand.Next(6)];
op3 = op[rand.Next(6)];
p1 = new PF();
int baseMother = rand.Next(2,5)*p1.mother;
p2 = new PF(baseMother,rand.Next(1,baseMother));
baseMother = rand.Next(2,5)*p1.mother;
p3 = new PF(baseMother,rand.Next(1,baseMother));
baseMother = rand.Next(2,5)*p1.mother;
p4 = new PF(baseMother,rand.Next(1,baseMother));
problem = p1.ConvertString() + " " + op1 + " " + p2.ConvertString() + " " + op2 + " " + p3.ConvertString() + " " + op3 + " " + p4.ConvertString();
}
4.转化为逆波兰表达式并求值
public PF CalValue()
{
string[] symbols = {"1", op1, "2", op2, "3", op3, "4"};
Stack<string> operaStack = new Stack<string>();
Queue<string> valueQueue = new Queue<string>();
Stack<PF> numStack = new Stack<PF>();
for (int i = 0; i < symbols.Length; i++)
{
if (IsInt(symbols[i]))
{
valueQueue.Enqueue(symbols[i]);
}
else if (IsOperator(symbols[i]))
{
while (operaStack.Count != 0 && GetOpLevel(operaStack.Peek())>=GetOpLevel(symbols[i]))
{
valueQueue.Enqueue(operaStack.Pop());
}
operaStack.Push(symbols[i]);
}
}
while (operaStack.Count != 0)
{
valueQueue.Enqueue(operaStack.Pop());
}
while(valueQueue.Count != 0)
{
if(IsInt(valueQueue.Peek()))
{
switch (valueQueue.Peek())
{
case "1":
numStack.Push(p1);
break;
case "2":
numStack.Push(p2);
break;
case "3":
numStack.Push(p3);
break;
case "4":
numStack.Push(p4);
break;
default:
break;
}
valueQueue.Dequeue();
// numStack.Peek().Display();
// Console.WriteLine(" ");
}
else
{
string operation = valueQueue.Dequeue();
numStack.Push(GetResult(operation, numStack.Pop(), numStack.Pop()));
}
}
PF result = numStack.Pop();
return result;
}
PSP 2.1 | Personal Software Process Stages | 预估耗时(min) | 实际耗时(min) |
---|---|---|---|
Planning | 计划 | 60 | 60 |
Estimate | 估计这个任务需要多少时间 | 60 | 60 |
Development | 开发 | 2400 | 2130 |
Analysis | 需求分析(包括学习新技术) | 360 | 300 |
Design Spec | 生成设计文档 | 120 | 120 |
Design Review | 设计复审(和同事审核审计文档) | 60 | 60 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 60 | 30 |
Design | 具体设计 | 360 | 300 |
Coding | 具体编码 | 600 | 720 |
Code Review | 代码复审 | 480 | 360 |
Test | 测试(自我测试,修改代码,提交修改) | 360 | 240 |
Reporting | 报告 | 420 | 270 |
Test Report | 测试报告 | 120 | 90 |
Size Measurement | 计算工作量 | 120 | 90 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 180 | 120 |
合计 | 2880 | 2460 |