天天看點

建構之法--界面化的簡單四則運算

要求位址:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2213

github位址:https://github.com/GVictory/MakeOutQuestionsWithInterface

前言:

  據課上要求,需要實作一個帶頁面的四則運算,并實作一定的擴充功能,本程式或許不能稱之為一個程式,因為其使用java web技術,是一個運作于浏覽器的網頁,但又可稱之為單機,因為隻要有浏覽器和電腦,均能運作此網頁。

題目要求:

  • 自動生成題目,單個題目最多不能超過4個運算符,操作數小于100。
  • 使用者可以輸入答案。
  • 若使用者輸入答案正确,則提示正确;若答案錯誤,則提示錯誤,并要提示正确答案是多少。

實作擴充要求:

  • 使用者答題結束以後,程式可以顯示使用者答題所用的時間。
  • 程式可以設定答題時間,時間設定為整數,機關為秒,最大不能超過120秒,若超過了答題時間未答題,則提示:時間已到,不能答題。
  • 程式可以設定皮膚功能,可以改變界面的顔色即可。
  • 使用者可以選擇出題的個數(最多不能超過5個題目),答題結束可以顯示使用者答錯的題目個數和答對的題目個數。

所用版本:

  作業系統:windows10

  開發環境:intellij IDEA 2016.4

  開發語言:java,html,css,javascript,spring

結對組隊:

  •  姓名:李志成 學号:201606110064  部落格園位址:https://www.cnblogs.com/97lzc/
  •  姓名:郭木凱 學号:201606110066  部落格園位址:https://www.cnblogs.com/GMUK/
  •  李志成: 題目和答案生成,前台題目和答案的渲染。
  •  郭木凱: 前台設計,換膚,計時。
建構之法--界面化的簡單四則運算

實作思路:

  由于本次作業使用的是java web技術,是以實作思路可分為如下:

  • 前端:使用flex布局搭起整體的布局,并ajax異步請求後端獲得随機生成的JSON格式的題目和答案,通過vue.js架構将資料綁定到元件中。元件的事件則通過jquery微架構編寫。
  • 後端:使用springboot搭起後端,controller調用計算類根據前端傳來的題目數生成相應的題目和答案并傳回給前端。

個人軟體過程耗時估計與統計表:

Personal Software Process Stages Time Senior Student Time
計劃 0.5h
估計這個任務需要多少時間 8h 10h
開發 4h 5h
需求分析 (包括學習新技術)
生成設計文檔
設計複審 0h
代碼規範
具體設計
具體編碼
代碼複審
測試(自我測試,修改代碼,送出修改)
報告
測試報告
計算工作量 2h
并提出過程改進計劃 1h

實作代碼:

  首先是前端頁面的實作,通過html,css,JavaScript,jQuery,vue.js編寫

1 <!DOCTYPE html>
  2 <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
  3 <head>
  4     <meta charset="UTF-8">
  5     <title>志成出題</title>
  6     <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
  7     <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  8 </head>
  9 <body style="height: 100%;background-color: #F5f5f5;">
 10 <div style="display: flex;justify-content: center;align-content: center">
 11     <div id="boss" style="display:flex;width: 600px;height: 450px;border: 1px dashed gray;background-color: white">
 12         <div style="width: 100px;border-right: 1px solid #bbbbbb;height: 100%;display:flex;align-content: center;justify-content: center">
 13             <div style="font-size: 30px;width: 30px;margin-top: 20px">志成出題</div>
 14         </div>
 15         <div style="width: 100%;height: 100%;display: flex;flex-direction: column">
 16             <div style="width: 100%;height: 90px;display: flex;align-items: flex-end;flex-direction: row;align-items:center;justify-content: space-between">
 17                 <div>
 18                     <div id="selectCount"
 19                          style="display: flex;flex-direction: column;align-items: center;margin-left: 20px">
 20                         <select id="select"
 21                                 style="background-color:#fafdfe;height:28px;  width:90px;  line-height:28px;  border:1px solid #9bc0dd;  -moz-border-radius:2px;  -webkit-border-radius:2px;  border-radius:2px; ">
 22                             <option value="1">1</option>
 23                             <option value="2">2</option>
 24                             <option value="3">3</option>
 25                             <option value="4">4</option>
 26                             <option value="5" selected>5</option>
 27                         </select>
 28                         <button id="countButton" onclick="getArithmetic()"
 29                                 style="margin-top:10px;border:none;height: 30px;width:60px;background-color: rgba(37,155,36,100);color: white;border-radius: 15%;font-size: 9px">
 30                             确定
 31                         </button>
 32                     </div>
 33                 </div>
 34                 <div>
 35                     <div style="display: flex;align-items: flex-start;width: 150px;margin-bottom: 5px">
 36                         <span>所用時間:</span><span id="useTime">0</span><span>秒</span>
 37                     </div>
 38                     <div style="display: flex;align-items: flex-start;width: 150px;margin-top: 5px">
 39                         <span>答題時間:</span><span>120秒</span>
 40                     </div>
 41                 </div>
 42 
 43             </div>
 44             <div id="test"
 45                  style="width: 100%;height: 270px;border-top: 1px solid #bbbbbb;border-bottom:1px solid #bbbbbb;display: flex;flex-direction: column;padding: 30px;box-sizing:border-box">
 46                 <div id="body">
 47                     <div style="margin-bottom: 10px;display: flex;" v-for="(ari,index) in arithmetic">
 48                         <div style="width: 90px">{{ari.question}}</div>
 49                         <span> = </span>
 50                         <input v-bind:id="index" style="border:none;border-bottom: 1px solid #bbbbbb;width: 70px"/>
 51                         <i name="answers" style="margin-right: 25px;margin-left: 25px" v-bind:id="index+10">X</i>
 52                         <div name="answers">
 53                             <span>正确答案:</span>
 54                             <span>{{ari.answer}}</span>
 55                         </div>
 56                     </div>
 57                 </div>
 58             </div>
 59             <div id="result"
 60                  style="width: 100%;height:85px;display: flex;flex-direction: row;justify-content: space-between;align-items: center;padding: 20px;box-sizing: border-box">
 61                 <div>
 62                     <div id="text">
 63                         <span>您答對了<span id="right">3</span>道題,答錯了<span id="error">2</span>道題</span><br/>
 64                         <span>答題正确率為<span id="rate">60%</span></span>
 65                     </div>
 66                 </div>
 67                 <div style="display: flex;align-items: flex-end" id="commit">
 68                     <button onclick="commitAnswer()"
 69                             style="border:none;height: 45px;width:100px;background-color: rgba(37,155,36,100);color: white;border-radius: 12px;font-size: 17px;margin-right: 5px">
 70                         送出
 71                     </button>
 72                     <button id="skin" onclick="changeSkin()"
 73                             style="border:none;height: 30px;width:40px;background-color: rgba(37,155,36,100);color: white;border-radius: 15%;font-size: 9px">
 74                         換膚
 75                     </button>
 76                 </div>
 77             </div>
 78         </div>
 79     </div>
 80 </div>
 81 </body>
 82 <script>
 83     var questions = new Array();
 84     var vue;
 85     var t;
 86 
 87     function getArithmetic() {
 88         var option = $("#select option:selected").text();
 89         $.ajax({
 90             type: 'GET',
 91             url: "/hello?count=" + option,
 92             success: function (data) {
 93                 var jsonData = JSON.stringify(data);
 94                 var obj = JSON.parse(jsonData);
 95                 array = obj;
 96                 for (var p in obj) {//周遊json對象的每個key/value對,p為key
 97                     var ob = {"question": p.toString(), "answer": obj[p]}
 98                     questions.push(ob);
 99                 }
100                 vue = new Vue({
101                     el: '#test',
102                     data: {
103                         arithmetic: questions
104                     }
105                 })
106                 $("#body").show()
107                 $("#selectCount").hide();
108                 $("#commit").show();
109                 $("#text").hide();
110                 $("[name='answers']").hide();
111                 var num = 0;
112                 t = setInterval(function () {
113                     num++;
114                     $("#useTime").text(num)
115                     if (num == 120) {
116                         clearInterval(t);
117                         alert("時間已到,答題結束")
118                         commitAnswer();
119                     }
120                 }, 1000);
121 
122             }
123         });
124     }
125 
126     $(function () {
127         $("#body").hide();
128         $("#commit").hide();
129         $("#text").hide()
130     })
131 
132     function changeSkin() {
133         $("#boss").css("background-color", "#2b2b2b");
134         $("#boss").addClass("changeSkin");
135     }
136 
137     function commitAnswer() {
138         var rightCount = 0;
139         var errorCount = 0;
140         for (var i in questions) {
141             $("#" + i).attr("disabled", "disabled");
142             if (questions[i].answer == $("#" + i).val()) {
143                 var num = parseInt(i) + 10;
144                 $("#" + num.toString()).text("√");
145                 rightCount++;
146             } else {
147                 errorCount++;
148             }
149         }
150         clearInterval(t);
151         $("[name='answers']").show();
152         $("#commit").hide();
153         $("#text").show();
154         $("#right").text(rightCount);
155         $("#error").text(errorCount);
156         $("#rate").text((rightCount / (rightCount + errorCount) * 100) + "%")
157     }
158 </script>
159 <style>
160     .changeSkin {
161         color: #f5a528;
162     }
163 </style>
164 </html>      

  其次是後端控制器代碼,如下:

1 public class testContraller {
2   @GetMapping("/getArithmetic") 
3   public HashMap<String, Integer> getArithmetic(@RequestParam Integer count) throws JSONException { 
4     return new Arithmetic().getArithmetic(count); 
5  } 
6 }      

  最後是解題函數(此處展示重要部分):

1     private static String getQuestion(Integer operatorNumber,Integer numberRange){      
2         char[] operator = new char[]{'+', '-', '*', '/'};
 3         Random random = new Random();
 4         StringBuilder stringBuilder = new StringBuilder();
 5         for (int operatorIndex = 0; operatorIndex < operatorNumber; operatorIndex++) {
 6             stringBuilder.append(random.nextInt(numberRange+1));
 7             stringBuilder.append(operator[random.nextInt(4)]);
 8         }
 9         stringBuilder.append(random.nextInt(numberRange+1));
10         return stringBuilder.toString();
11     }
12 
13     private static Float getAnswer(String question){
14         Stack<Character> operatorStack=new Stack<Character>();
15         Stack<Float> numberStack=new Stack<Float>();
16         char operatorTemp;
17         StringBuilder numberTemp=new StringBuilder();
18         for (int questionIndex=0;questionIndex<question.length();questionIndex++){
19             char singleChar=question.charAt(questionIndex);
20             if (Character.isDigit(singleChar)){
21                 numberTemp.append(singleChar);
22             }else {
23                 if (!operatorStack.isEmpty()&&operatorStack.getTop()=='*'){
24                     operatorStack.pop();
25                     numberStack.push(numberStack.pop()*Float.valueOf(numberTemp.toString()));
26                 }else if (!operatorStack.isEmpty()&&operatorStack.getTop()=='/'){
27                     operatorStack.pop();
28                     numberStack.push(numberStack.pop()/Float.valueOf(numberTemp.toString()));
29                 }else if(!operatorStack.isEmpty()&&operatorStack.getTop()=='-'){
30                     numberStack.push(-Float.valueOf(numberTemp.toString()));
31                 }else {
32                     numberStack.push(Float.valueOf(numberTemp.toString()));
33                 }
34                 operatorStack.push(singleChar);
35                 numberTemp.delete(0,numberTemp.length());
36             }
37         }
38         if (!operatorStack.isEmpty()&&operatorStack.getTop()=='*'){
39             numberStack.push(numberStack.pop()*Float.valueOf(numberTemp.toString()));
40             operatorStack.pop();
41         }else if (!operatorStack.isEmpty()&&operatorStack.getTop()=='/'){
42             numberStack.push(numberStack.pop()/Float.valueOf(numberTemp.toString()));
43             operatorStack.pop();
44         }else if(!operatorStack.isEmpty()&&operatorStack.getTop()=='-'){
45             numberStack.push(-Float.valueOf(numberTemp.toString()));
46         }else {
47             numberStack.push(Float.valueOf(numberTemp.toString()));
48         }
49         while (!operatorStack.isEmpty()){
50             operatorStack.pop();
51                 numberStack.push(numberStack.pop()+numberStack.pop());
52         }
53         return numberStack.pop();
54     }      

運作結果:

  一進來網頁時,網頁的模樣如下圖,主要由五大部分組成,分别是選題數,時間計時,題目,換膚,答題情況,一開始進來時由于題目數未選擇,是以時間計時是靜止的,題目部分不存在。

  PS:題數隻能選擇1-5。

建構之法--界面化的簡單四則運算

   當選好題數并單擊按鈕時,選題數部分消失,時間開始計時,題目出現,并且使用者可以輸入題目的答案并送出。

建構之法--界面化的簡單四則運算

   其次網頁還具有換膚功能,當點選換膚時,會改變文字和背景色。

建構之法--界面化的簡單四則運算

   當點選送出時,答題情況部分出現,時間靜止,考試結束。

建構之法--界面化的簡單四則運算

   當超過時間時,彈出提醒,并且輸入框此時無法輸入,進行與送出一樣的操作。

建構之法--界面化的簡單四則運算

 總結:

  由于此前已有計算類的實作,是以該作業的難度在于頁面的互動以及邏輯的處理,與隊友一路做下來,發現所花的時間甚多,特别是調試和測試上,一改再改,與計劃的時間相差甚遠,至此有感,技術決定效率,效率決定未來。