1.Github项目地址
https://github.com/baiyexing/myapp.git
2.功能要求
题目:实现一个自动生成小学四则运算题目的命令行程序
功能(已全部实现)
- 使用 -n 参数控制生成题目的个数
- 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围
- 生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1 − e2的子表达式,那么e1 ≥ e2
- 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数
- 每道题目中出现的运算符个数不超过3个
- 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目
- 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt
- 程序应能支持一万道题目的生成
- 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,统计结果输出到文件Grade.txt
3.解题思路
大致思路为,随机生成操作符数目,调用方法递归生成式子,同时表示成二叉树,同时规范化二叉树(好查重)。数字,运算符都用方法随机生成。
4.设计实现过程
(1)Question类:生成式子,包括获得随机数,获得随机运算符,计算算式结果,将结果化简,规范化二叉树等方法。
(2)Parameter类:处理结果,包括获取命令行参数,查重,写入文件,判断答案等方法。
5.代码说明
只说明部分重要和难点代码
(1)生成式子的主要方法,采用递归方式,随机生成式子,存为二叉树形式,保存在字典中。
1 def expression2(self,count):#生成式子 2 if count == 1: 3 figure = self.getnumber() 4 return{ 5 'expression_array': figure['figure'], 6 'expression': figure['figure_char'], 7 'answer': figure['figure_array'] 8 } 9 else : 10 leftcount = self.getrandom(count -1) 11 rightcount = count - leftcount 12 13 left = self.expression2(leftcount) 14 right = self.expression2(rightcount) 15 16 operate = self.getrandom(4) 17 18 if operate == 4 and right['answer'][0] == 0: 19 t = left 20 left = right 21 right = t 22 answer = self.Calculation(left['answer'],right['answer'],operate) 23 if answer[0] < 0: 24 t = left 25 left = right 26 right = t 27 answer = self.Calculation(left['answer'],right['answer'],operate) 28 29 leftvalue = left['answer'][0]/left['answer'][1] 30 rightvalue = right['answer'][0]/right['answer'][1] 31 expression_array = [left['expression_array'],operate,right['expression_array']]
(2)规范化二叉树,按左右子树为数数,数树,树树来判定规范。
if type(left['expression_array'])!=list and type(right['expression_array'])!=list: #两个子树都为值 if (operate == 1 or operate == 3) and leftvalue < rightvalue: expression_array = [right['expression_array'],operate,left['expression_array']] elif type(left['expression_array'])==list and type(right['expression_array'])==list:# 两个子树都为树 if operate == 1 or operate == 3: if leftvalue == rightvalue and left['expression_array'][1] < right['expression_array'][1]:#树的值相等时,运算符优先级高的在左边 expression_array = [right['expression_array'],operate,left['expression_array']] elif leftvalue < rightvalue : expression_array = [right['expression_array'],operate,left['expression_array']] if operate in [3,4] : if left['expression_array'][1] in [1,2]: left['expression'] = '(' + left['expression'] + ')' if right['expression_array'][1] in [1,2]: right['expression'] = '(' + right['expression'] + ')' else:#一边的子树为树 if operate == 1 or operate == 3: if type(right['expression_array']) == list: expression_array = [right['expression_array'],operate,left['expression_array']] if operate in [3,4] : if type(left['expression_array']) == list and left['expression_array'][1] in [1,2] : left['expression'] = '(' + left['expression'] + ')' if type(right['expression_array']) == list and right['expression_array'][1] in[1,2]: right['expression'] = '(' + right['expression'] + ')'
(3)生成算式列表,判重。
def getexpression_list(self, expression_count, number_range, count, probability) :# 算式 List = [] i = 0 while i < expression_count: expression = Question(number_range,count,probability) while self.check(expression,List): expression = Question(number_range,count,probability) List.append({ 'expression_array': expression.__dict__['expression_array'],#二叉树表示 'expression': expression.__dict__['expression'],#算式表达形式 'answer': expression.__dict__['answer'],#答案 'answer_char': expression.__dict__['answer_char']#答案表达形式 }) i += 1 return List def check(self,expression,List):#查重方法 expressionarray = expression.__dict__['expression_array'] for i in List: if expressionarray == i['expression_array']: return True return False
6.测试运行
·全部功能
·-n,支持生成10000道题目
·-r 为100时
·答案文件
·答案判定
7.PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
50 |
40 |
· Estimate |
· 估计这个任务需要多少时间 |
50 |
40 |
Development |
开发 |
1215 |
1300 |
· Analysis |
· 需求分析 (包括学习新技术) |
80 |
85 |
· Design Spec |
· 生成设计文档 |
60 |
40 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
50 |
45 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
35 |
30 |
· Design |
· 具体设计 |
70 |
60 |
· Coding |
· 具体编码 |
800 |
820 |
· Code Review |
· 代码复审 |
55 |
50 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
65 |
70 |
Reporting |
报告 |
105 |
110 |
· Test Report |
· 测试报告 |
30 |
35 |
· Size Measurement |
· 计算工作量 |
25 |
30 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
50 |
45 |
合计 |
|
1370 |
1480 |
8.项目小结
这次的题目比上次的难得多,但收获也多得的多。我终于懂得结构化代码的重要性,不然代码过长乱成一团自己也看不懂。同时也学到了python语言许多新的知识。最重要的,这次是结对编程,第一次接触到这种编程方式,两个人坐在一起,一个人主要编写,另一个人在旁提意见,映像最深的一个好处就是嘉帆同学总是能很快的发现代码中的小错误小bug,别小看这些,有时候自己经常因为这些容易忽视的小错误,跑不了代码,而自己始终找不到bug而导致浪费许多时间。这时候队友常常可以轻而易举的指出错误,大大节省了时间。而且两个人一起讨论常常会有不一样的思路,讨论验证的过程能更好的增加我们对相关知识的理解。