自動生成中小學數學題目的控制台小程序


前段時間寫了一個自動生成中小學數學題目的控制台小程序

下面簡要介紹一下我這次的一個開發過程

 

需求:

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+²38 ,哈哈。對於這一點我的處理方法是檢測式子中的 ² 符號,如果檢測到這個字符且他下一位是一個數字,就交換兩個字符的位置,然后繼續向后比較,就可以很輕松的把式子調整為 14+38² 。(但是這會並不是調整的最佳時機,稍后會提到)

 

進階+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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM