题目地址:http://www.cnblogs.com/HQL0301/p/7502315.html
1.需求分析:
(1) 按照用户输入来控制题目生成个数以及随机数的值域;
(2)生成题目与答案的TXT文件;
(3)提供作答核对功能;
(4)表达式生成与处理:
2.功能设计:
(1) 根据用户输入生成相应表达式:
根据题目要求,表达式中操作符个数不少于3个。故生成一个随机数,根据随机数先确定本次生成的表达式的操作符个数。按照不同操作符个数分别处理,按照输入的数值范围生成随机数,使用了一个随机变量控制了分数生成的概率。对操作符÷进行特殊处理,保证了÷后的数值不为0,将生成的数字与操作符进行拼接得到中缀表达式, 对于括号的添加同样用随机数控制。(对二元运算不进行添加括号的判定)。对得到的表达式用String.split()以" "为标识符进行分割,得到一个字符串数组方便进行后续的中缀表达式转换为后缀表达式。
(2)表达式查重:
由生成的中缀表达式转换成后缀表达式(见代码中Tohouzhui类),并根据后缀表达式建立二叉树。
一开始自己想的查重方法是将表达式的答案存入数组,在新生成表达式时,将答案进行对比,只要答案不相同就一定不重复。后来发现这种查重局限性很大。当生成题目较少而数值范围大时,可以使用且查重效率高。但是当生成题目较多而数值范围较小时,这种方法导致生成题目的效率变得缓慢(已生成较多表达式时,同答案的不同表达式仍会被放弃),且后期查重的效率较低。
也想过通过层次遍历表达式二叉树的方法来查重,因为实现起来比较复杂,效率也不够高的原因还是放弃。按照模版里的那种方法,通过一定的规则生成二叉树,将*和+可能出现的通过有限次交换导致重复的情况避免。具体规则如下:若生成节点的对象是*或者+
1.左右子树的值不同,则值大的作为左子树
2.左右子树的值相同时,判断子树的运算符优先级大小,优先级大的作为左子树
3.运算符优先级相同,判断子树下的左子树值得大小,值大的作为左子树
4.若为子树为一个为数字,一个为运算符,则运算符作为左子树
5.若左右子树都为数字,则值大的作为左子树
根据这个规则,基本上包含了交换律可能出现的情况,将可以有交换律变换得到的表达式都转为一个统一的表达式。从而可以直接比对二叉树后序遍历得到的后缀表达式来实现查重。
(3)将表达式及答案输出至文件:
通过后缀表达式能较轻松的计算出表达式的值,只是对分数需要进行特殊处理。
(4)对用户作答进行批改
限制了作答规范,比对时只要逐行验证字符串是否相同即可;
重要代码展示:
太多了,感觉都很重要,还是看coding里的吧
程序运行截图:
上图为生成10000道题值域为100的测试,表达式下方是后缀表达式。
生成的题目和答案txt文件
答案核对测试:
从新生成5道题
答案如下
在do.txt中进行回答
比对结果:
项目估算: