1.Github项目地址 : https://github.com/hebaowei/test
2.PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(小时) | 实际耗时(小时) |
Planning | 计划 | 0.5 | 0.5 |
Estimate | 估计这个任务需要多少时间 | 5 | 6 |
Development | 开发 | 20 | 24 |
Analysis | 需求分析 (包括学习新技术) | 1 | 2 |
Design Spec | 生成设计文档 | 0.5 | 0.5 |
Design Review | 设计复审 (和同事审核设计文档) | 1 | 1 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 1 | 1 |
Design | 具体设计 | 10 | 15 |
Coding | 具体编码 | 5 | 6 |
Code Review | 代码复审 | 2 | 2 |
Test | 测试(自我测试,修改代码,提交修改) | 1 | 1 |
Reporting | 报告 | 0.5 | 0.5 |
Test Report | 测试报告 | 0.5 | 0.5 |
Size Measurement | 计算工作量 | 0.5 | 0.5 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 0.5 | 1 |
合计 | >40 | >>50 |
3.解题思路:
基于python编程
我最先的想法是先把软件的四个基本功能先用代码实现,然后在基本功能实现的情况下,将附加功能一个一个加上去,最终得到一个完整的“软件”。
基本功能:
1.参与运算的操作数(operands)除了100以内的整数以外,还要支持真分数的四则运算,例如:1/6 + 1/8 = 7/24。操作数必须随机生成。
2.运算符(operators)为 +, −, ×, ÷ (如运算符个数固定,则不得小于3)运算符的种类和顺序必须随机生成。
3.要求能处理用户的输入,并判断对错,打分统计正确率。
4.使用 -n 参数控制生成题目的个数,或通过用户交互过程确定题目个数,例如执行下面命令将生成5个题目。
对于基本功能1,操作数可以使用函数random.randiant(1,9)实现,而分数可以使用Fraction函数,最终得到一个真分数;
对于基本功能2,运算符可以用random函数来在在字符数组中任意选取;
对于基本功能3,将题目答案实先存在数组中,将用户输入的答案与正确答案比较,使用if语句来判断用户的输入答案是否正确,并且计算得分;
对于基本功能4,可以在最开始就设定好题目的个数n。
附加功能:
1.运算符个数随机生成(考虑小学生运算复杂度,范围在1~10)。
2.设计并实现一种合理的根据题目难度分配不同分值的方案。
3.设计并实现一种计时机制,能够实现超时停止答题,或者根据答题用时调整分数。
4.防止随机生成的题目发生重复。
对于附加功能1,首先用random函数随机产生一个9以内的整数,代表参与运算符的个数,有多少个符号就有多少个数字+1个;
对于附加功能2,用参与运算的数字个数来代表运算难度;
对于附加功能3,给每道题设定60s的作答时间,超过时间则自动显示下一题;
对于附加功能4,可以先定义一个题目字符串数组,将每次产生的题目字符串与之前的进行比较,若不相同,则打印出来并存储在数组中。
4.设计实现过程
我的想法是最先打印出n让用户输入题目数量,然后可以开始显示题目和分数,最终输出总得分。
在主函数中调用出产生题目的函数;
在产生题目函数中首先生成题目(将新生成题目与题目数组进行比对,查看是否重复),并且打印在屏幕上。同时调用计算答案的函数用于得到新生成题目的答案;同时设定计时功能,统计分数功能,再提示让用户输入答案,将用户所输入的答案与真实答案进行比较,输出结果;
个人觉得最困难的部分是计算答案的函数,大致思路是将算术表达式的运算符号通过遍历,按优先级进行计算(程序中没有括号)。
5.主要代码说明
#得到一道题目 返回这道题的得分,有时间限制
def one_question():
opers = ['+', '-', '*', '÷']
timu = [] #存放每一题
oper_count = random.randint(1, 9) #参与操作的数字个数
timu.append(Fraction(random.randint(1, 9), 1))
for i in range(oper_count):
timu.append(opers[random.randint(0, 3)])
ch=random.randint(1,5) #有20%的机会产生分数,80%的机会产生整数
if ch==1:
a=random.randint(1,9)
b=random.randint(1,9)
if a>=b:
c=Fraction(b,a)
timu.append(Fraction(c))
else:
c=Fraction(a,b)
timu.append(Fraction(c))
else:
timu.append(Fraction (random.randint(1,9),1))
timu_str = toString(timu)
if timu_str in list_timu:
return one_question()
list_timu.append(timu_str)
print('题目: %s' % timu_str)
print('分值: %d分' % oper_count)
res= getResult(timu)
context['data'] = '超时'
t = threading.Thread(target=input_func, args=(context, ))
t.start() #计时功能
t.join(60) # 等待60秒
if str(res) == context['data']:
print('回答正确,加%d分' % oper_count)
return oper_count
else:
if context['data'] == '超时':
print('超时')
return 0
else:
print("回答错误,正确答案是: %s" % str(res))
return 0
#计算题目的结果,利用栈计算表达式的值。
def getResult(timu):
res = []
res.append(timu[0])
for i in range(1, len(timu), 2): #遍历所有操作符
if timu[i] == '+' or timu[i] == '-':#将操作符的优先级进行比较从而堆栈
res.append(timu[i])
res.append(timu[i+1])
elif timu[i] == '*':
res[len(res)-1] = res[len(res)-1] * timu[i+1]
elif timu[i] == '÷':
res[len(res)-1] = res[len(res)-1] / timu[i+1]
sum = res[0]
for i in range(1, len(res), 2):
if res[i] == '+':
sum = sum + res[i+1]
elif res[i] == '-':
sum = sum - res[i+1]
elif res[i] == '*':
sum = sum * res[i+1]
elif res[i] == '÷':
sum = sum / res[i+1]
return sum
6.测试运行
答案正确,答案错误,超时三种情况都出现了。就能够过多次测试,程序可行。
7.项目小结
由于对编程基础学习掌握不牢,需要花费很多时间去重新学习,但是在期末备考的情况下,各种答疑和课程把课表安排得比较满,没有得到充分的一大块时间去好好编程,往往都是利用零碎时间去完成作业,交作业前的最后几天,都是中午没睡觉和晚上加班在进行代码编写和调试,最终完成的作业也算是勉强完成。
我想,这很大一部分原因是因为自己没有把全部精力放在这门课上,因为在本学期课程安排的很满的情况下,导师也会安排比较多的实验任务,很难完全放开投入到一门非专业课上面去;还有一部分原因是因为自己担任队内的足球队队长,由于要负责组织训练等活动,每天的自由时间都会被占用一大半,所以基本都是利用晚上零散的时间来进行学习;最后一个原因是因为最近安排了三门公共基础课的考试,备战期末的人物比较繁重,时间上我也进行了一定的安排,所以每天来完成作业的时间不够。
回到我这个程序的功能,题目要求的功能基本全部实现,但是我个人感觉最大的问题在于分数对于每道题的分配方面,本人的程序并没有做到总分在100分的前提下生成n道题,然后对每道题根据难度进行分数的分配,而是直接根据参与运算的数字个数来分配分数;第二个问题就是没有能对括号()进行优先级运算比较。
经过这次比较漫长的作业,我个人感觉最大的收获就是算是开始对python学习上手了,虽然花费在上面的时间占据了我其他学科的时间,但我相信有付出也会有回报。虽然花费了很多时间在编程上面,但最终程序能够调试出来,也是比较满意的。
关于时间分配这方面,我也和导师商量过,他说你就利用好这点时间好好把python学一学,将来对专业课也有一定作用。所以下一步我也打算好好学习利用python,在完成专业课学习的基础上更大可能地拓展自己的全面性。