软件工程(2019)第五次作业
四则运算生成器
ProjectAddress(含有可执行文件)
小学四则运算自动生成程序,要求:
- 能够自动生成四则运算练习题
- 可以定制题目数量
- 用户可以选择运算符
- 用户设置最大数(如十以内、百以内等)
- 用户选择是否有括号、是否有小数
- 用户选择输出方式(如输出到文件、打印机等)
- 最好能提供图形用户界面(根据自己能力选做,以完成上述功能为主)
任务分工
- 驾驶员:张家铭(负责代码的编写)
- 领航员:张天翊(负责调试以及测试)
项目结果
这里率先给出成品结果图。
如下图所示,展示了界面的功能分布。
如下图所示,这里运行了一个样例。
- 数值范围 :0~100
- 需要生成所有算符,包括小数
- 产生10道题
- 需要生成题目和答案文件
- 每个算式数字个数为2
如下图所示,表示了习题样例。
如下图所示,表示了答案样例。
算法细节
0.项目结构
- 如何计算表达式
使用Python内置的eval(),其用来执行一个字符串表达式,并返回表达式的值。
2.算法流程图
绘制的算法流程图如下:
3.函数模块
- Moulde List
- returnDotNumber()
- check()
- generateEquationDueToBracket()
- generateEquation()
- draw()
- returnDotNumber()
该函数完成的功能是生成整数或者按照一定概率生成小数。
def returnDotNumber():
global percentOfDot
percentOfDot = round(random.uniform(0, 1), 2)
# percentOfDot = 1
if typeString[-1] == '1':
n = int(percentOfDot * 100)
l = n * "0"
l += (100 - n) * '1'
s = list(l)
random.shuffle(s)
s = ''.join(s)
if s[random.randint(0, 99)] == '1':
return 1
else:
return 0
else:
return 1
- checkI()
该函数完成的功能是判断值是否小于零以及是否有除以零的错误。
def check(string, KEY):
"""
:param string:
:return:
"""
global answerOfquestion, indexOfQuestion
try:
answerOfEval = eval(string)
if answerOfEval < 0:
return False
if KEY == 1:
answerOfquestion += "{0:>5s}{1:<.2f}\n".format(str(
indexOfQuestion) + '. ', round(eval(string), 2))
indexOfQuestion += 1
# print('answerOfquestion:',answerOfquestion)
return True
if KEY == 2:
return True
except ZeroDivisionError:
return False
- generateEquation()
该函数是按照要求生成表达式。
def generateEquation():
"""
:return:
"""
global questionString, theNumberOfquestion, rawEquation
specialFunctionList = []
if typeString[0] == '1':
specialFunctionList.append('+')
if typeString[1] == '1':
specialFunctionList.append('-')
if typeString[2] == '1':
specialFunctionList.append('*')
if typeString[3] == '1':
specialFunctionList.append('/')
if typeString[4] == '1':
specialFunctionList.append('()')
if typeString[5] == '1':
specialFunctionList.append('.')
# print('specialFunctionList:', specialFunctionList)
i = 0
key = 0
while i < theNumberOfquestion + key:
equationStirng = ''
if returnDotNumber() == 1:
equationStirng += str(random.randint(MINMUM, MAXMUM))
else:
dotNum = random.uniform(MINMUM, MAXMUM)
dotNum = round(dotNum, 2)
equationStirng += str(dotNum)
j = 0
tempKey = 0
while j < numberOfTerms - 1 + tempKey:
tempString = random.choice(['+', '-', '*', '/', '.', '()'])
if tempString in specialFunctionList:
if tempString == "()":
specialList_copy = copy.deepcopy(specialFunctionList)
if '()' in specialFunctionList:
specialList_copy.remove('()')
if '.' in specialFunctionList:
specialList_copy.remove('.')
equationStirng_temp = random.choice(
specialList_copy)
equationStirng += equationStirng_temp
equationStirng += '('
equationStirng += generateEquationDueToBracket(
specialFunctionList,random.randint(2,numberOfTerms))
equationStirng += ')'
elif tempString == '+':
equationStirng += '+'
equationStirng += str(random.randint(MINMUM, MAXMUM))
elif tempString == '-':
equationStirng += '-'
equationStirng += str(random.randint(MINMUM, MAXMUM))
elif tempString == '*':
equationStirng += '*'
equationStirng += str(random.randint(MINMUM, MAXMUM))
elif tempString == '/':
equationStirng += '/'
equationStirng_temp = str(random.randint(MINMUM, MAXMUM))
if equationStirng_temp == '0':
tempList = [i for i in range(MINMUM, MAXMUM)]
tempList.remove(0)
equationStirng += str(random.choice(tempList))
else:
equationStirng += equationStirng_temp
elif tempString == '.':
if returnDotNumber() == 1:
specialFunctionList_copy = copy.deepcopy(
specialFunctionList)
if '()' in specialFunctionList_copy:
specialFunctionList_copy.remove('()')
if '.' in specialFunctionList_copy:
specialFunctionList_copy.remove('.')
equationStirng_temp = random.choice(
specialFunctionList_copy)
if equationStirng_temp == '/':
equationStirng += '/'
equationStirng_temp = str(
random.randint(MINMUM, MAXMUM))
if equationStirng_temp == '0':
tempList = [i for i in range(MINMUM, MAXMUM)]
tempList.remove(0)
equationStirng += str(random.choice(tempList))
else:
equationStirng += equationStirng_temp
else:
equationStirng += equationStirng_temp
equationStirng += str(
round(random.randint(MINMUM, MAXMUM)))
else:
specialFunctionList_copy = copy.deepcopy(
specialFunctionList)
if '()' in specialFunctionList_copy:
specialFunctionList_copy.remove('()')
if '.' in specialFunctionList_copy:
specialFunctionList_copy.remove('.')
equationStirng_temp = random.choice(
specialFunctionList_copy)
if equationStirng_temp == '/':
equationStirng += '/'
equationNum_temp = round(random.uniform(
MINMUM, MAXMUM), 2)
if equationNum_temp == 0:
tempList = [i for i in range(MINMUM, MAXMUM)]
tempList.remove(0)
equationStirng += str(random.choice(tempList))
else:
equationStirng += str(equationNum_temp)
else:
equationStirng += equationStirng_temp
equationStirng += str(
round(random.uniform(MINMUM, MAXMUM), 2))
else:
tempKey += 1
j += 1
if check(equationStirng, 1) == False:
key += 1
else:
rawEquation += "#" + str(indexOfQuestion - 1) + '. '
equationStirng += '=\n'
rawEquation += equationStirng
i += 1
questionString = rawEquation
# print(questionString)
4.总结
整个项目下来,用了三个晚上就把基本功能都实现了出来,这首先要依靠自己对于工具的熟悉程度,其次还要感谢软件工程带给自己的编辑软件的思想,诸如驼峰式变量名称,基于测试的开发方法等等,也是由于软件工程课程的学习,让我渐渐明白了了测试框架的重要性。总之,在做自己喜欢的事情的时候,真的是可以干得又快又满足。
先来说说自己对于这次项目的感悟以及收获。1.Python很强大。这门语言可以快速地实现你想要的功能,让你能够全身心地投入到结构与逻辑设计中,就比如这次需要使用到字符串表达式,使用Python提供的内置函数eval()可以很方便地计算,这使得工作负担一下子就减轻了。2.界面的设计。这次使用tkinter设计界面,用到了复合选项,带有滚动条的文本框和按钮不可见等以前没有用到的新功能,之所以有了以前的基础,这次才能够很快速的开发出demo。3.关于括号的处理。关于括号,这是一个当时没有一个很好解决办法的需求,足足在第二个版本中才添加上,但是目前觉得自己的解决办法也不是很完美,自己单独列写了一个几乎和gengerate()一样的函数,当需要在括号中生成算式时,就调用新写的函数即可,这未尝不是一种处理办法,但是不够优雅!
再来说所自己的领航员。作为领航员这个角色,他的目的是为了辅助驾驶员完成编码工作,并且进行代码测试以及样例覆盖。由于天翊才学Python编程不久,所以,在一起合作时并没有充分感觉到结对编程的快乐,通常需要一边编写代码,一边给他讲述我在干什么,导致效率发生了下降。但是,他还是很耐心地在一步步跟着我做,最后也能出色地完成代码的测试工作,做好领航员的角色。
5.彩蛋
就在我把软件打包完毕后,发送给家里当老师的小舅妈看的时候,运行时报了错误,说是操作系统位数出了问题,我才发现,原来电脑本身是32位的WIN7系统,而我的打包文件是64位的,32位机不支持64位应用,结果,我又在同学的电脑上配置好了32位python环境,然后再次打包,最终才好使。
下面这个是我的设计草稿:
6.合作过程



