【软件工程基础】结对项目之四则运算题目生成
一,项目介绍
项目的github地址:https://github.com/qqqqqianru/sizeyunsuantimushengcheng
二、项目要求
第一阶段:写一个能够自动生成小学四则运算题目的命令行软件,分别满足下面的各种需求,下面的这些需求都可以用命令行参数的形式来指定:
a)一次可以出1000道题目,并且没有重复的,把题目写入一个文件中
b)当有多于一个运算符的时候,如何对一个表达式求值?逐步扩展功能和可以支持的表达式类型,最后希望支持下面类型的题目(最多10个运算符,括号的数量不限制)
25-34-2/2+89=?
1/2+1/3-1/4=?
(5-4)(3+28)=?
c)除了整数以外,还要支持真分数的四则运算
d)让程序能接受用户输入答案,并判定对错,最后给出总对/错的数量。
第二阶段:
增加一个运算符,要求支持乘方运算。乘方运算的优先级高于乘除法。
如何表示乘方,有两种表示方法:^或**。
第三阶段:结对的同学商量一下,从以下几个方向中选择一个,对程序进行扩展。
把程序变成一个windows/mac/linux电脑图形界面的程序(取决于你目前使用的电脑)同时增加倒计时功能,每个题目必须在20秒钟完成,如果完不成,则得0分并进入下一题。增加“历史纪录”功能,把用户做题的成绩记录下来并可以展现历史纪录。
把程序变成一个智能手机程序,增加倒计时和历史纪录功能。
把程序变成一个网页程序,用户通过设定参数,就可以得到各种题目。
选一个你从来没有学过的编程语言,试一试实现基本功能。估计这个软件所需要的时间,并且写出大概的设计步骤和实现算法。
把这个程序的思路变成一个可以一步一步演示的动画,写一个带有图形界面的程序。
三、项目分析
PSP2.1 | Personal Software Process Stages | 预估耗时(min) | 实际耗时 |
---|---|---|---|
Planning | 计划 | 30 | 40 |
Estimate | 估计这个任务需要多少时间 | 1800 | 1900 |
Development | 开发 | 1200 | 1000 |
Analysis | 需求分析(包括学习新技术) | 360 | 300 |
Design Spec | 生成设计文档 | 120 | 170 |
Design Review | 设计复审(和同事审核设计文档) | 30 | 40 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 30 | 40 |
Design | 具体设计 | 180 | 200 |
Coding | 具体编码 | 600 | 650 |
Code Review | 代码复审 | 60 | 50 |
Test | 测试(自我测试,修改代码,提交修改) | 180 | 200 |
Reporting | 报告 | 60 | 50 |
Test Report | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 10 | 30 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 60 | 60 |
合计 | 1800 | 2000 |
第一、二阶段: 第一阶段是项目的核心部分,主要包含出题、保存、解题、比对四个部分,第二阶段则是第一阶段的补充。
出题部分,要求生成不重复的四则运算,最多1000道,要求支持括号、分数运算功能。
保存部分,将出的题目保存到文件中,这一部分比较容易实现。
解题部分,要求通过相应的算法将前一部分所出的题目解出正确答案。
比对部分,将解出的答案与用户输入相比对,得出结果并进行统计,这一部分比较容易实现。
本阶段的重点在于出题和解题部分,下面将详细分析:
首先是在生成题目方面,我们应该首先建立一个文件存储算式或者在程序中有创立一个相关文件,然后生成操作者规定生成的个数的随机数字(题目要求为1000,这里为了方便调试我们可采用较小的数字),并且在他们之间穿插括号,四则运算符号等生成四则运算,并将他们写入文件中 ,以满足题目要求。
然后是解决题目方面,这里我们阅读了很多学长学姐的代码,大多数都是建立一个类来存储数字信息来实现支持分数运算,然后使用堆栈来完成算式的读取和运算。经过我们的讨论,决定采用与他们不同的递归方式来完成运算。具体算法如下:
先判断是否有括号,有的话,找到最内部的括号,优先运算括号内部,返回括号左边内容+括号内运算结果+括号右边内容,并去掉这个括号,将返回值作为新题目处理;
没有括号的话再找乘方运算,如果有乘方先判断是否还有加减乘除,如果都没有,进行所有乘方运算,直接返回值。既有乘方又有加减时,先进行乘方运算,将结果与其他部分串联起来作为新题目处理。这里为了处理分数的乘方问题,将分数单独列出来分类讨论。要注意的是,乘方右边的符号一定要是整数,否则会出现根号的情况,无法处理,这一点在出题部分已经考虑过了。
下面是乘除运算,需要考虑参与运算的是否为分数,并在运算完成后化简分数到最简形式。为了支持分数运算,引入了一个符号#,代表它前后的数字是一个分数。围绕#号作分类讨论,并返回不同的值。
然后是加减运算,思路与乘除基本一致,需要注意加减的两个数都是分数的情况,需要进行通分再运算。
当式子中没有任何运算,只有数字和代表分数的#号时,即可返回答案。
第三阶段:
这一阶段我们选择了C#来开发图形界面程序,并增加倒计时、历史纪录功能。C#与C++的语法有着很大的不同,为了使前面的代码能够正确应用,我们将之前的出题、解题函数稍加改进,做成了两个可执行文件,并写了一个调用函数来实现跨语言的调用。
在windows图形界面程序题目的生成中我们只有一个窗体,在窗体左侧可以设置出题数量、乘方表示形式,出题数量默认为10,如果输入不合理的数字或非数字则会提示输入错误信息。右侧从上到下分别为所出的题目、用户答案输入区域、确定按钮、以及点击确定后会出现的提示信息显示区域。下方为倒计时、开始/重置按钮、历史纪录按钮,倒计时由timer控件控制,在点击开始/重置按钮后会运行/重置,在倒计时结束后会触发事件提示时间到;点击历史纪录按钮则会弹出相应历史信息
四、项目重要代码(完整代码在GitHub上,这里只列出重要部分的代码)
1.生成题目代码
char* chuti(int a)
{
double nums[100];
srand((unsigned)time(NULL));
char str[100];
char chuti[3000];
int ii=0;
int flag, q = 1;
int pos1 = -1, ///pos1,pos2为括号位置
pos2 = -1;
if(a==1)
{
int dd,ee,ff,gg;
str[0] = '+' ;
str[1] = '-';
str[2] = '*';
str[3] = '/';
flag = rand() % 5 + 2;
int aa;
aa=0;
int bb;
bb=rand()%flag-1;
int cc=-1;
for(int i = 0; i < flag; i++)
{
nums[i] =