GitHub項目地址:https://github.com/Juneflyfire/jisuan2git
a. 需求分析:github
設計開發一個小學生四則運算練習軟件,使之具備如下功能:編程
(1)由計算機從題庫文件中隨機選擇20道加減乘除混合算式,用戶輸入算式答案,程序檢查答案是否正確,每道題正確計5分,錯誤不計分,20道題測試結束後給出測試總分;數組
(2)題庫文件可採用實驗二的方式自動生成,也能夠手工編輯生成less
(3)程序爲用戶提供三種進階四則運算練習功能選擇:百之內整數算式(必作)、帶括號算式、真分數算式練習;ide
(4)程序容許用戶進行多輪測試,提供用戶多輪測試分數柱狀圖;學習
(5)程序記錄用戶答題結果,當程序退出再啓動的時候,可爲用戶顯示最後一次測試的結果,並詢問用戶能否進行新一輪的測試; 測試
(6)測試有計時功能,測試時動態顯示用戶開始答題後的消耗時間。this
(7)程序人機交互界面是GUI界面(WEB頁面、APP頁面均可),界面支持中文簡體(必作)/中文繁體/英語,用戶能夠進行語種選擇。編碼
b. 軟件設計:使用類圖
c. 核心功能代碼展現:展現核心功能代碼。
(1)語言切換
如下爲語言的切換功能,採用的方式是設置三個按鈕,分別爲「簡體中文」、「繁體中文」和「英文」,將窗體上全部的文字設置爲一個變量,當任意一個按鈕按下時,切換成該按鈕對應的語言。
if(input.equals("S5"))//簡體中文 { La1="得分"; La2="計時"; La4="下一輪"; La5="提交答案"; La6="測評"; La7="簡體中文"; La8="繁體中文"; La9="英文"; La10="整數運算"; La11="分數運算"; l1.setText(La1); BT4.setText(La6); BT2.setText(La5); BT5.setText(La7); BT6.setText(La8); BT7.setText(La9); BT8.setText(La2); BT9.setText(La10); BT10.setText(La11); } if(input.equals("S6"))//繁體中文 { La1="得分"; La2="計時"; La4="下一輪"; La5="提交答案"; La6="測評"; La7="簡體中文"; La8="繁體中文"; La9="英文"; La10="整數運算"; La11="分數運算"; l1.setText(La1); BT4.setText(La6); BT2.setText(La5); BT5.setText(La7); BT6.setText(La8); BT7.setText(La9); BT8.setText(La2); BT9.setText(La10); BT10.setText(La11); } if(input.equals("S7")) { La1="Grade"; La2="Time"; La4="Next Turn"; La5="Submit"; La6="Measurement"; La7="Simplified Chinese"; La8="Traditional Chinese"; La9="English"; La10="Integer arithmetic"; La11="Fraction arithmetic"; l1.setText(La1); BT4.setText(La6); BT2.setText(La5); BT5.setText(La7); BT6.setText(La8); BT7.setText(La9); BT8.setText(La2); BT9.setText(La10); BT10.setText(La11); }
(2)統計得分
對「提交答案」按鈕進行監聽,獲取全部輸入的答案,於文本文檔result1中的答案進行比較,每對一題得五分,在得分後的文本框中顯示得分。
if(input.equals("S2"))//提交答案 { String []res = new String[20]; //獲取結果數組 try { int i = 1; BufferedReader br = new BufferedReader(new FileReader("result1.txt")); String nString = br.readLine(); res[0] = nString; while (nString != null) { nString=br.readLine(); res[i]= nString; i++; } br.close(); } catch (Exception e) { } int sum = 0; //獲取答案內容 if(a1.getText().equals(res[0])) { sum += 5; } if(a2.getText().equals(res[1])) sum += 5; if(a3.getText().equals(res[2])) sum += 5; if(a4.getText().equals(res[3])) sum += 5; if(a5.getText().equals(res[4])) sum += 5; if(a6.getText().equals(res[5])) sum += 5; if(a7.getText().equals(res[6])) sum += 5; if(a8.getText().equals(res[7])) sum += 5; if(a9.getText().equals(res[8])) sum += 5; if(a10.getText().equals(res[9])) sum += 5; if(a11.getText().equals(res[10])) sum += 5; if(a12.getText().equals(res[11])) sum += 5; if(a13.getText().equals(res[12])) sum += 5; if(a14.getText().equals(res[13])) sum += 5; if(a15.getText().equals(res[14])) sum += 5; if(a16.getText().equals(res[15])) sum += 5; if(a17.getText().equals(res[16])) sum += 5; if(a18.getText().equals(res[17])) sum += 5; if(a19.getText().equals(res[18])) sum += 5; if(a20.getText().equals(res[19])) sum += 5; String sco = sum + ""; l2.setText(sco); Grade.add(sco); }
(3)計時
public class Time extends JFrame { private static final long serialVersionUID = 1L; private static final String INITIAL_LABEL_TEXT = "00:00:00 000"; // 計數線程 private CountingThread thread = new CountingThread(); // 記錄程序開始時間 private long programStart = System.currentTimeMillis(); // 程序一開始就是暫停的 private long pauseStart = programStart; // 程序暫停的總時間 private long pauseCount = 0; private JLabel label = new JLabel(INITIAL_LABEL_TEXT); private JButton startPauseButton = new JButton("開始"); private JButton resetButton = new JButton("清零"); String time; private ActionListener startPauseButtonListener = new ActionListener() { public void actionPerformed(ActionEvent e) { if (thread.stopped) { pauseCount += (System.currentTimeMillis() - pauseStart); thread.stopped = false; startPauseButton.setText("暫停"); } else { pauseStart = System.currentTimeMillis(); thread.stopped = true; startPauseButton.setText("繼續"); } } }; private ActionListener resetButtonListener = new ActionListener() { public void actionPerformed(ActionEvent e) { pauseStart = programStart; pauseCount = 0; thread.stopped = true; label.setText(INITIAL_LABEL_TEXT); startPauseButton.setText("開始"); } }; public Time(String title) throws HeadlessException { super(title); setDefaultCloseOperation(EXIT_ON_CLOSE); setLocation(300, 300); setResizable(false); setupBorder(); setupLabel(); setupButtonsPanel(); startPauseButton.addActionListener(startPauseButtonListener); resetButton.addActionListener(resetButtonListener); thread.start(); // 計數線程一直就運行着 } // 爲窗體面板添加邊框 private void setupBorder() { JPanel contentPane = new JPanel(new BorderLayout()); contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); this.setContentPane(contentPane); } // 配置按鈕 private void setupButtonsPanel() { JPanel panel = new JPanel(new FlowLayout()); panel.add(startPauseButton); panel.add(resetButton); add(panel, BorderLayout.SOUTH); } // 配置標籤 private void setupLabel() { label.setHorizontalAlignment(SwingConstants.CENTER); label.setFont(new Font(label.getFont().getName(), label.getFont().getStyle(), 40)); this.add(label, BorderLayout.CENTER); } private class CountingThread extends Thread { public boolean stopped = true; private CountingThread() { setDaemon(true); } @Override public void run() { while (true) { if (!stopped) { long elapsed = System.currentTimeMillis() - programStart - pauseCount; label.setText(format(elapsed)); time=label.getText(); File f=new File("time.txt"); BufferedWriter bw; try { bw = new BufferedWriter(new FileWriter(f)); bw.write(time); bw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } try { sleep(1); // 1毫秒更新一次顯示 } catch (InterruptedException e) { e.printStackTrace(); System.exit(1); } } } // 將毫秒數格式化 private String format(long elapsed) { int hour, minute, second, milli; milli = (int) (elapsed % 1000); elapsed = elapsed / 1000; second = (int) (elapsed % 60); elapsed = elapsed / 60; minute = (int) (elapsed % 60); elapsed = elapsed / 60; hour = (int) (elapsed % 60); return String.format("%02d:%02d:%02d:%03d", hour, minute, second, milli); } } }
(4)柱狀圖
public class BarGraph extends JPanel { private int x; private static int length ; int i=0; public int[] count; ArrayList<JLabel> label = new ArrayList<JLabel>(); public BarGraph(final ArrayList<String> summer) { length = summer.size(); count = new int[length]; System.out.print(length); this.setLayout(null); for(int i=0;i<summer.size();i++) { count[i] = Integer.parseInt(summer.get(i)); } for(int i=1;i<summer.size();i=i+2) { JLabel Label = new JLabel("柱狀圖",JLabel.LEFT); Label.setFont(new Font("SansSerif", Font.BOLD + Font.ITALIC, 18)); Label.setBounds(30+(i-1)*30, 610, 60,50); JLabel Label2 = new JLabel(count[i]+"",JLabel.CENTER); Label2.setFont(new Font("SansSerif", Font.BOLD + Font.ITALIC, 18)); Label2.setBounds(25+(i-1)*30, 555-6*count[i], 60,50); label.add(Label); label.add(Label2); this.add(label.get(i-1)); this.add(label.get(i)); } } protected void paintComponent(Graphics g) { int x=10; g.setColor(Color.red); for (int i = 0; i < count.length; i++) { g.fillRect(x, 600-6*count[i], 30,6*count[i] ); x += 30; } } }
d. 程序運行:程序運行時每一個功能界面截圖。
(1)語言的切換
(2)點擊「整數運算」按鈕之後,隨機產生20個算式,而且存在result文本文檔中,同時將單獨的計算結果存在result1文檔中。以下圖所示:
‘’
(3)計時。點擊「計時」按鈕,開始計時,當答案輸入完畢時,提交答案,顯示得分。計時器具備清零、暫停等按鈕。
(4)柱狀圖
第一輪計算
第二輪, 再次點擊「整數運算」按鈕,將上一輪的文本框清空,進行再一輪運算。
將以上兩輪的得分存在一個ArrayList數組中,做爲繪製柱狀圖的參數
e.描述結對的過程,提供兩人在討論、細化和編程時的結對照片(非擺拍)。
因爲咱們採用的是分工合做的方法完成項目,彼此不熟悉彼此的代碼風格,兩我的也沒有花時間去討論類與類之間的關係,只是畫了一個初期完成項目的思惟導圖就開始各作個的了,再花一天時間一塊兒完善代碼。在這期間,隊友給我帶來了不少的新思路,但同時呢,也出現過兩我的彼此誤導,在長時間編程之後兩我的都陷入了錯誤之中。兩我的也都在磨合之中,逐漸提升了Java的編程能力。
f.提供這次結對做業的PSP。
PSP2.1 |
任務內容 |
計劃共完成須要的時間(min) |
實際完成須要的時間(min) |
Planning |
計劃 |
8 |
6 |
· Estimate |
· 估計這個任務須要多少時間,並規劃大體工做步驟 |
8 |
6 |
Development |
開發 |
600 |
1800 |
·· Analysis |
需求分析 (包括學習新技術) |
6 |
10 |
· Design Spec |
· 生成設計文檔 |
5 |
6 |
· Design Review |
· 設計複審 (和同事審覈設計文檔) |
4 |
6 |
· Coding Standard |
代碼規範 (爲目前的開發制定合適的規範) |
3 |
3 |
· Design |
具體設計 |
10 |
12 |
· Coding |
具體編碼 |
36 |
1693 |
· Code Review |
· 代碼複審 |
7 |
10 |
· Test |
· 測試(自我測試,修改代碼,提交修改) |
13 |
60 |
Reporting |
報告 |
9 |
6 |
·· Test Report |
· 測試報告 |
3 |
2 |
· Size Measurement |
計算工做量 |
2 |
1 |
· Postmortem & Process Improvement Plan |
· 過後總結 ,並提出過程改進計劃 |
3 |
3 |
g. 請使用漢堡評價法給你的小夥伴一些點評。
隊友是個好隊友,思路很清晰,效率也很高。在兩我的的思想碰撞中,能夠很好的表達本身,而且讓我很好的接受她的建議。但願在將來還有機會能夠一塊兒合做。
h. 結對編程真的可以帶來1+1>2的效果嗎?經過此次結對編程,請談談你的感覺和體會。
結對編程能夠帶來1+1>2的效果,由於本身在編寫代碼的時候,很容易陷入錯誤的思路之中,此時隊友就能夠在一旁點醒本身。兩我的編程能夠取長補短,相互補充不知道的知識,同時也由於分工合做的緣由,不自覺地會將代碼規範,認真地將本身寫的代碼部分註釋好意思,而且給隊友講解,在這個過程當中,本身對本身的要求高了,知識記憶也加深了。固然了,凡事都要兩面性,在與隊友的磨合時,花費了很長的時間,也面臨了與隊友的時間衝突問題,但這些都是能夠一一克服的。
不少書中都批判過中國人的合做,《醜陋的中國人》中將這個問題延伸到了「窩裏鬥」,三個和尚沒水喝的故事也成了合做界的笑話。可是在本次項目中,我切身體會到了「三個臭皮匠勝過諸葛亮」的道理。在信息大爆炸的今天,只有合做,才能讓思想之花綻開的燦爛,中國的互聯網飛速發展,你們都在提倡團隊合做,咱們不再是像曾經書中寫的那樣了。
至於本身在寫代碼的過程當中,最大的感悟就是前期的分析工做是相當重要的,因爲沒有提早設計好項目思路,在寫項目尤爲是在寫界面的時候,反覆改寫界面,類寫了又刪,刪了又寫,並且對於用戶的需求分析不足,只關注到了老師留的任務的個數,想着將任務所有完成,卻忽視了小學生是多數用戶,在寫的時候犯下了致命錯誤,就是沒有控制百內的整數運算。雖然功能基本完成,可是倒是很失敗的。其次就是,條條大路通羅馬,在編寫代碼的過程當中,會遇到一個方法行不通,而後又想着能夠存在文檔裏,再行不通的話又會想出另外一個辦法,實現同一個功能,會有不少不少的方法去達到它,這大概也是它的迷人之處吧,讓編程者在思考的海洋中不斷遨遊。最後就是,少壯不努力,老大徒傷悲呀,大一Java沒學好,如今每次項目前,都須要把代碼涉及到的知識點都現學一遍,所幸的是,如今的本身,已經能夠靜下心來花很長的時間去寫一個代碼,所幸的是,如今也不晚。