一、項目源碼
Github的倉庫主頁鏈接地址:https://github.com/LilyFuEnLi/Arithmetic_SE.git
二、項目報告
1. 需求分析
(1)由計算機從題庫文件中隨機選擇20道加減乘除混合算式,用戶輸入算式答案,程序檢查答案是否正確,每道題正確計5分,錯誤不計分,20道題測試結束后給出測試總分;
(2)題庫文件可采用實驗二(詳細內容請查看上一篇博客)的方式自動生成,文本格式如圖1所示;
圖 1 圖 2
(3)程序為用戶提供三種進階四則運算練習功能選擇:百以內整數算式、帶括號算式、真分數算式練習;
(4)程序允許用戶進行多輪測試,提供用戶多輪測試分數柱狀圖,如圖2所示;
(5)程序記錄用戶答題結果,當程序退出再啟動的時候,可為用戶顯示最后一次測試的結果,並詢問用戶可否進行新一輪的測試;
(6)測試有計時功能,測試時動態顯示用戶開始答題后的消耗時間;
(7)程序人機交互界面是GUI界面(WEB頁面、APP頁面都可),界面支持中文簡體/中文繁體/英語,用戶可以進行語種選擇。
2. 軟件設計
(1)程序設計圖如下所示:
(2)類圖如下圖所示:
(1)Main( )類:主函數類,彈出登錄窗口界面;
(2)Start( )類:產生答題窗口類,利用按鈕監聽器接口,存儲學生答案,顯示結果,進行對比分析等操作。
(3)Calculate_SE()類:運算式產生類,結合上次作業,產生整數運算式、分數運算式文件。
(4)Timer()類:包含內部類Timer.CountingThread()類,產生計時窗口。
(5)Chart_H( )類:繪制成績柱狀圖。
3. 核心功能代碼展示
(1) 答題界面的監聽器方法部分代碼

1 //---------------------------------------整數------------------------- 2 JRadioButton buttonInteger=new JRadioButton("整數");//JRadioButton 3 buttonInteger.addItemListener(new ItemListener() { 4 public void itemStateChanged(ItemEvent arg0) { 5 frame2.pack(); 6 frame2.setVisible(true); 7 try { 8 CA.calaulate_AE(40); 9 } catch (IOException e) { 10 e.printStackTrace(); 11 } 12 String shizi = CA.IntegerQ.get(number); 13 NUM++; 14 label1.setText(shizi); 15 } 16 }); 17 //--------------------------------分數--------------------------------- 18 JRadioButton buttonFenshu = new JRadioButton("分數"); 19 buttonFenshu.addItemListener(new ItemListener() { 20 public void itemStateChanged(ItemEvent arg0) { 21 frame2.pack(); 22 frame2.setVisible(true); 23 try { 24 CA.fenshu(); 25 } catch (IOException e) { 26 e.printStackTrace(); 27 } 28 String shizi = CA.FractionQ.get(number); 29 NUM++; 30 label1.setText(shizi); 31 } 32 }); 33 //-------------------------------------下一題答案按鈕的設定------------------------------------------------------- 34 JButton buttonNext=new JButton("下一題"); 35 buttonNext.addActionListener(new ActionListener() {//定義時間監聽器 36 public void actionPerformed(ActionEvent e) { 37 if(buttonInteger.isSelected()) 38 { 39 String question=label1.getText(); 40 String result=text.getText(); 41 String ifRight=""; 42 if((CA.IntegerA.get(number)).equals(result)) 43 { 44 ifRight="正確"; 45 rightSum++; 46 } 47 else 48 { 49 ifRight="錯誤"; 50 } 51 String message=question+", "+"你的答案:"+result+", "+"正確答案: "+CA.IntegerA.get(number)+", 狀態: "+ifRight; 52 list.add(message); 53 text.setText(""); 54 number++; 55 String shizi=CA.IntegerQ.get(number); 56 NUM++; 57 label1.setText(shizi); 58 if(NUM==20) 59 { 60 JOptionPane.showMessageDialog(null, "本題為第20道題,答題結束,請提交答案。", "答題結束", JOptionPane.INFORMATION_MESSAGE); 61 text.setText(result); 62 } 63 } 64 if(buttonFenshu.isSelected()) 65 { 66 String question=label1.getText(); 67 String result=text.getText(); 68 String ifRight=""; 69 if(CA.FractionA.get(number).equals(result)) 70 { 71 ifRight="正確"; 72 rightSum++; 73 } 74 else 75 { 76 ifRight="錯誤"; 77 } 78 String message=question+", "+"你的答案:"+result+", "+"正確答案: "+CA.FractionA.get(number)+", 狀態: "+ifRight; 79 list.add(message); 80 text.setText(""); 81 number++; 82 String shizi=CA.FractionQ.get(number); 83 NUM++; 84 label1.setText(shizi); 85 if(NUM==20) 86 { 87 JOptionPane.showMessageDialog(null, "本題為第20道題,答題結束,請提交答案。", "答題結束", JOptionPane.INFORMATION_MESSAGE); 88 text.setText(result); 89 } 90 } 91 } 92 });
(2)計時器部分代碼

1 public void run() { 2 while (true) { 3 if (!stopped) { 4 long elapsed = System.currentTimeMillis() - programStart - pauseCount; 5 label.setText(format(elapsed)); 6 time=label.getText(); 7 File f=new File("time.txt"); 8 BufferedWriter bw; 9 try { 10 bw = new BufferedWriter(new FileWriter(f)); 11 bw.write(time); 12 bw.close(); 13 } catch (IOException e) { 14 // TODO Auto-generated catch block 15 e.printStackTrace(); 16 } 17 } 18 19 try { 20 sleep(1); // 1毫秒更新一次顯示 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 System.exit(1); 24 } 25 } 26 } 27 28 // 將毫秒數格式化 29 private String format(long elapsed) { 30 int hour, minute, second, milli; 31 32 milli = (int) (elapsed % 1000); 33 elapsed = elapsed / 1000; 34 35 second = (int) (elapsed % 60); 36 elapsed = elapsed / 60; 37 38 minute = (int) (elapsed % 60); 39 elapsed = elapsed / 60; 40 41 hour = (int) (elapsed % 60); 42 43 return String.format("%02d:%02d:%02d:%03d", hour, minute, second, milli); 44 } 45 }
(3)成績柱狀圖部分代碼

1 public void paint(Graphics g){ 2 //int number=newList.size()-1; 3 int Width = getWidth(); 4 int Height = getHeight(); 5 int leftMargin = 20;//柱形圖左邊界 6 int topMargin = 50;//柱形圖上邊界 7 Graphics2D g2 = (Graphics2D) g; 8 g2.setColor(Color.WHITE);//繪制白色背景 9 g2.fillRect(0, 0, Width, Height-100);//繪制矩形圖 10 g2.setColor(Color.LIGHT_GRAY); 11 for(int i=0;i<=10;i++) 12 {//繪制灰色橫線和百分比 13 g2.drawString((100-10*i)+"", 5, topMargin+30*i);//寫下百分比 14 g2.drawLine(5, topMargin+30*i, Width, topMargin+30*i);//繪制灰色橫線 15 } 16 g2.setColor(Color.PINK); 17 for(int i=0;i<=number;i++) 18 {//繪制柱形圖 19 if(newList.get(i)!="") 20 { 21 int value =Integer.parseInt(newList.get(i)); 22 int step = (i+1)*40;//設置每隔柱形圖的水平間隔為40 23 //繪制矩形 24 g2.fillRoundRect(leftMargin+step*2-5,(100-value)*3+50, 40, 300-(100-value)*3, 40, 10); 25 //列出測試輪數 26 g2.drawString(newList.get(i), leftMargin+step*2, (100-value)*3+50); 27 g2.drawString("第"+(i+1)+"輪", leftMargin+step*2, 380); 28 } 29 } 30 }
4. 程序運行截圖
(1)運行主函數Main.java文件,進入登錄界面,截圖如下圖所示,輸入姓名,學號后,點擊確認進入答題初始界面,如圖3所示,此時會顯示學生的上次成績,當學生點擊選擇進行分數或者整數時,彈出計時器界面。此時點擊開始,輸入題目的答案,並點擊下一題進行作答即可。
圖 3 答題初始界面
(2)當學生答夠20道題后,彈出提示信息,答題結束,如圖4所示。學生提交答案,計時器窗口關閉,彈出運算結果窗口,顯示學生答題情況(整體分數、答題時間),如圖5所示:
圖 4 答題結束界面
圖 5
在項目后期,我們發現,上圖5的總體信息顯示情況不太良好,我們又進行了優化,利用Java的Table優化了界面,如下圖所示:
(3)得到本輪答題情況后,學生可以點擊答題分析按鈕,查看幾輪測試的柱狀圖,如圖6所示,也可以點擊進行下一輪按鈕再次測試。
圖 6 成績柱狀圖
5. 結對編程過程
首先利用老師給出的需求分析,再做詳細分析,建立基本的整體軟件框架,將項目划分為5個模塊。其次,一塊修改上次作業的運算式產生程序,通過查找資料,加入了分數運算式。然后,寫出窗口的整體布局,詳細布局Start()類,通過監聽器接口調用運算式類編程,這部分主要是我敲代碼,我的小伙伴協助。后來,我的小伙伴主筆編寫計時器,調整各個窗口的布局以及其他屬性。最后,我們一塊加入了柱狀圖部分,審核代碼,做優化。
6. PSP
PSP2.1 | 任務內容 | 計划完成的時間(min) | 實際完成需要的時間(min) |
---|---|---|---|
PLanning | 計划 | 60 | 80 |
Estimate | 估計這個任務需要多少時間,並規划大致工作步驟 | 30 | 40 |
Developmet | 開發 | 480 | 520 |
Analysis | 需求分析(包括學習新技術) | 30 | 40 |
Design Spec | 生成設計文檔 | 10 | 15 |
Design Revie | 設計復審(和同事審核設計文檔) | 20 | 30 |
Coding Standard | 代碼規范 | 30 | 40 |
Design | 具體設計 | 45 | 60 |
Coding | 具體編碼 | 240 | 300 |
Code Review | 代碼復審 | 30 | 30 |
Test | 測試(自我測試,修改代碼,提交修改) | 20 | 30 |
Reporting | 報告 | 30 | 40 |
Test Report | 測試報告 | 20 | 20 |
Size Measurement | 計算工作量 | 5 | 5 |
Postmortem & Process Improvement Plan | 事后總結,並提出過程改機計划 | 20 | 30 |
7. 我的小伙伴
我和我的小伙伴是同宿舍的,馬上就一塊度過了大學的第三個年頭了,彼此都比較了解,她是一個動手能力挺強,很有想法的菇涼。我們倆在對軟件需求分析后,基本達成了一個整體的軟件框架,將項目划分為5個模塊。在接下來的模塊編程中,她給出了好幾點很不錯的建議,尤其是做界面與計時器的過程中。當然,我們倆也會遇到不同想法碰撞的時候,這時,她並不是妥協或者態度比較強硬,我們會對兩種想法做出權衡,達成共識。對於項目中我主導編寫的模塊不理解時,她總會積極詢問,就是這樣的一個菇涼,我們一同協作完成了我們的初衷。但是我的小伙伴在程序設計的模塊划分以及模塊間關系處理上存在一定的問題,尤其是模塊間的相互聯系、調用時,一定要做到數據集的高效共享,希望她可以多練習一下數據結構的內容。
嗯,總的來說呢,很不錯的菇涼,期待我們下次的合作。
8. 結對編程的感受和體會
本次結對項目真心感覺到1+1>2的效果,我的小伙伴動手能力也挺強的,我們在做了分析之后,利用周內的三天課余時間來開發軟件,時間的利用率還蠻高的,不會出現一個人卡殼的現象。結對編程的過程也挺愉快的,正好趕上實驗室的茉莉花開,在淡淡的芳香中,坐下來編幾個小時的程序,順便開發開發大腦,也沒有感覺到枯燥。但是,不得不說結對編程能夠達到雙贏的效果是有前提的,你需要一個負責的伙伴,So,選擇伙伴是挺重要的哦。
本次項目開發過程,其實也是一個“撿起”java的過程,以前上課時學的基礎好的話,現在復習一下,還是挺好掌握它的。我們做的小學生四則運算軟件實現了老師的要求,也做了附加功能,但關於語言的附加功能沒有做到,本來想着做成App的,但是由於我們倆都有考研課且近期參加了編程比賽,時間緊張,就用eclipse做了簡單的界面,不太美觀,希望后期我們可以有所改進。