自动生成中小学数学题目的控制台小程序

2018-10-19 06:30:11来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

前段时间写了一个自动生成中小学数学题目的控制台小程序

下面简要介绍一下我这次的一个开发过程

 

需求:

1、命令行输入用户名和密码,如果用户名和密码都正确,提示输入小学、初中和高中三个选项中的一个,否则提示“请输入正确的用户名、密码”;

2、命令行输入小学、初中和高中的选项之一,输入项不符合要求时,程序控制台提示“请输入小学、初中和高中三个选项中的一个”;

3、程序读取输入正确的小学、初中和高中三个选项中一个后,控制台提示,“准备生成XX数学题目”(xx为输入的小学、初中和高中三个中的一个)。同时提示“请输入生成题目数量”;

4、题目数量的有效输入范围是“10-30”(含10,30),程序根据输入的题目数量生成符合小学、初中和高中难度的题目的卷子。同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复;

5、生成的题目将以“年-月-日-时-分-秒.txt”的形式保存。每道题目有题号,每题之间空一行;

 

实现思路:

首先这个项目的核心部分也是最有挑战性的部分就是出题的部分了,其他的登录和难度选择只需要普通的选择循环就可以搞定。所以我选择主攻这里

随机一道题需要什么呢?

一道最简单的算式是这样的:3x5+4=19

抛开后面的答案来看,一道算式的组成由3个数字和两个运算符组成,那么我就可以先随机产生这道题一共有几个数字,假设有n个数字,那么就会有n-1个运算符,我可以随机生成这些数字和字符。

好了,如果把一道题看成一道菜的话,那么我的材料已经准备好了!然后开始做菜,将这些数字和字母按照数字——字母——数字的顺序去拼接起来。这时,一个最简单的算式就这样生成了。

 

进阶!

可以看到需求中我们还要对难度进行划分,需要加入平方,开方,三角函数等运算符,怎么加入呢?最开始我的想法和和之前一样,去随机数字以后随机运算符,但是这是会碰到一个问题,如果还是按照之前的方法,就会产生这样的算式:14sin5cos3 ,很显然这个式子是有问题的。我也与同学进行了讨论,我的观念中是存在 14sin5 这样的式子的,但是我忽略了一点很重要的就是我们平常算题的时候经常会省略乘号,如果很正式的写法的话是不能忽略的。退一步来讲,就算 14sin5 成立,如果按照这种方法出题,根本不会出现 14+sin5 这样的式子,所以我需要改变我的出题方法,于是我对随机方法进行了一次处理,如果随机的到特殊运算符,那我就给他前面补充随机一个普通运算符,这样就很好的完成了出题的式子,很开心的看到类似这样的式子 14+sin5-cos3 。

此时你是否感觉已经大功告成了?不,这会还有一个很重要的问题没有处理掉,仔细想想,有没有这样第一个很神奇的运算符,他叫做平方,他不出现在数字前面,而是在数字后面,实践一下,会出现这样的式子:14+238 ,哈哈。对于这一点我的处理方法是检测式子中的 2 符号,如果检测到这个字符且他下一位是一个数字,就交换两个字符的位置,然后继续向后比较,就可以很轻松的把式子调整为 14+382 。(但是这会并不是调整的最佳时机,稍后会提到)

 

进阶+1!

普通的式子已经可以很完美的生成了。但是括号我们还没有加进去,这一点困扰了我很久,怎么加括号比较好,我开始想到了逆波兰表达式(又称后缀表达式,我们平常使用的是中缀表达式),考虑到学习的时间成本的问题(其实我就是想偷懒QwQ,但是后来项目二次改进的时候我还是重新学了一遍后缀表达式),后来我又按照之前的思路思考,一个算式写好后,最多可以插入几组括号呢?写一个式子看看咯,首先 2+2=4 这个式子不需要括号。那么三个数字的呢?2+3+5=10 这个可以插入一组括号,以此类推,不难发现括号组数是数字个数n-2。那就好办了啊。我随机 n-2 次然后随机判断每次是否插入。然后开始插入,插入 (  的时候只能插入到数字前面,插入 ) 的时候只能插入到数字后面,这一点是肯定的。其次,要先插入(  ,然后标记插入( 的位置 。)只能插在这之后。整体这么插下来以后基本还算好吧。但是会出现括号包含整个算式的情况(没必要),两组括号甚至多组括号重叠的情况(就像这样((()))  需要去重),还有只包围一个数字的情况(没必要)。这时我没有从插入括号的机制上去进行判断,感觉工作量会很大,我这会对出来的式子进行了一次清洗工作,如果碰到这三种式子就直接扔掉重新生成。

好了!算式搞定了!这会我们要写入到试卷中了。

直接写入就好了呀,然后写入完存到文件里,文件的命名很简单,但是要注意每个用户的试卷要分开存放,便于提取其中的内容,这里我才用的做法是在一个papers的文件夹下给每个用户都有一个独立的文件夹去存储试卷。然后出题的时候读取这个用户之前所有的题目进行一个查重工作,防止重复。

 

最后的就是整个系统的流程控制,流程控制这里我最开始想的是利用循环和选择来进行,后来发现循环写多了以后会很乱,可能会出现6-7层while循环嵌套的情况。不利于阅读与后续的维护。这会我采用了函数的方式去处理了这个问题。

下面展示一下函数表

Demo.main(String[])  //主函数
Demo.menu()  //主菜单
Demo.login()  //登录界面
menu2(String, String)  //二级菜单
selectlevel(String, String)  //难度选择
paper_generate(String, int, String)  //试卷生成
problem_generate(String)  //题目生成
brackets(String)  //加括号
isRight(String)  //合理性检测
itemIsExist(String, String)  //存在性检测

 

大致就是函数直接互相调用来解决了多层循环嵌套的问题吧。感觉会更好一些,对于开发和后期维护来说,思路上更清晰一些,很多东西找起来也更快一些。同时功能模块的复用性很好,在二次改进的项目中我又直接调用了这次写好的函数模块。

然后这个程序我写了一个简单的用户类,其实并没有起到什么作用,只是开始的时候觉得面对对象编程需要这样一个对象吧。后来证明很需要这个用户类,在下一篇博客中会提到。

最后展示一下程序使用还有源码吧。

 

实现效果:

 

 

 源码:https://github.com/yinvoke/Math_Paper

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:RecyclerView的Item的单击事件

下一篇:Java GC机制详解