PTA第二階段三次作業總結
前言
第二階段的三次大作業明顯對設計的要求進一步提高了。我三次作業一共得到了196分,答題判斷程序-4有兩個測試點未通過,其他兩次作業均通過所有測試點,但程序仍有許多不足,下面開始逐題分析。
7-1 答題判題程序-4
答題判斷程序-4增加的多選題,填空題,本質是考察了字符串的比較,運用contains,equals函數可以解決這兩類題目的答案比較的問題。這兩種題目類型的類,他們都繼承自同一個父類Question類。在這次作業中,相比之前一次作業,我添加了一些父類,如題目的父類Question類,題目判斷的父類Judge類,使用這些繼承關系讓我對代碼的結構有了更好的設計。
整體思路如下:
首先調用JudgeInput類,判斷輸入是否有誤,有誤則輸出輸入有誤,并將這條有誤的信息保存在信息類Information里,無誤則之間保存在信息類Information里。然后對Information類里的信息進行遍歷,對不同類型的信息進行相應處理,比如題目信息,就new出Question類進行保存,試卷信息,就從已經創造的Questions類中遍歷尋找需要的Question類,找到就放入對應信息,沒找到則保存未找到該題信息。再處理答卷,調用Question內部的判斷函數,讓Question類自行判斷答案是否正確,獲得相應分數。最后進行答卷信息的輸出。
下面簡要分析下Question類:

屬性:
1.屬性type表示類型,該值對應為0,1,2分別表示簡單題,多選題,填空題,-1表示原始類型。
2.屬性order應該為int類型,不知道為什么生成類圖的時候輸入int他自動給我改成int[]類型,特此說明。這個值保存的是該題目的題號,方便后續在題目數組中查找對應題號的題目時能夠找到對應的題號。
3.屬性content保存的是題目的內容,創建這個屬性是為了匹配和輸出題目內容。
4.屬性state是一個Boolean類型的值,它表示這道題目的存在與否,如果該值為true,則這道題目未刪除,存在,若這道題目被刪除,不存在,則該值為false。
5.屬性score保存了這道題目的滿分分數,后續計算題目分數的時候就需要從這里取得該值。
6.屬性standardanswer保存了這道題目的標準答案,這樣可以與后續試卷上的作答用equals進行比較,對題目的正誤進行判斷
這些屬性均設為protected類型,方便在子類中對相應的值進行修改,當然,設置成為private類型也可以,但是想要在子類里修改或者取得這些函數,就得使用對應的setter/getter方法,非常不方便。
方法:
主要包括了一個有參構造方法,一個無參構造方法,屬性的getter/setter方法。
judgement方法:這個方法是用來判斷題目是否正確的方法,需要輸入7個參數,這里的設計是有問題的,應該額外建立一個判斷函數來判斷每道題的正誤,并放在一個答題結果類里。
這個類的設計上還是存在很多問題的,比如出現了不該屬于這個類職責的judgement方法。而且后續對多個該類類型的數據保存也使用了錯誤的方法。后續是使用了一個Questions類,內部保存了一個Question類的數組,對數據進行存儲。實際可以使用List
測試點未通過分析:
上面提到了這次作業有兩個測試點未通過,經過反復查找問題,發現是主函數中有一個判斷的邏輯錯誤導致的。
首先分析主函數中的問題,主函數中沒有做到只有輸入輸出,其中添加了大量正則表達式判斷,分割,輸入數據判斷。這種是錯誤的,應該加入一個Split類進行分割,加入一個Agent類進行輸入數據判斷,在Agent類中再調用判斷類對正則表達式進行判斷,輸入數據的判斷。
最后發現問題是主函數中對沒有數據輸入的時候存在邏輯判斷錯誤。面對這種情況下,我的思路是new出一個簡單題類型,content為none,判斷正誤的時候判斷到none就知道這道題不存在,是一個空題。
7-1 家居強電電路模擬程序-1
這道題是一個全新的模擬場景,模擬一個家居電路。主要的類就是一個父類Electricdevice類,所有的用電器類都繼承自這個類,對于串聯電路,也把它看成一個特殊的用電器,同樣繼承自此類。 對于輸入處理,用一個Information類保存。
整體思路如下:用正則表達式處理輸入,將分割后的信息儲存。由于沒有異常信息輸出,所以沒有對應的異常輸出處理。再從儲存的信息中提取電路電器信息,new出每條信息對應的電器類,再遍歷操作類信息,對電器的狀態進行改變,這樣就保證了整個電路的信息與要求對應。將new出的電器放入一個Electricdevice類型的數組中,用List
對Agent類進行簡要分析:

屬性:
Agent類中只有一個串聯類類型的電路屬性,用來保存電路信息
方法:
Agent類中有一個無參構造方法,有添加電器方法,獲取電路信息方法,打印電路信息方法,和排序方法。
其中這個排序方法我采用的是“暴力排序法”,即對比每個電器的類類型名來進行排序,目前沒有想到更好的方法。
在這個類的設計上,其實可以免去createSystem類,使用getRoad().add()方法即可。
對Electricdevice類進行簡要分析:

屬性:
1.name是電器的名字,后續排序的時候需要使用
2.id是電器輸入的次序,排序也需要使用
3.V1, V2是輸入電壓和輸出電壓,這兩個電壓的差值即為電壓差U,這里設定了V1初始值為220,V2的初始值為0,其實是錯誤的,因為串聯電路未接通時候電壓為0。
方法:
主要就是getter/setter方法,有參構造方法和無參構造方法,還有一個打印信息的方法,無特別之處。
這個類的設計存在缺陷,如缺少一個表示電器狀態的state屬性,這樣在后續的判斷中需要用for循環對電路里的每個電器進行操作,非常不方便,而且浪費資源。
測試點分析

在這個測試點卡了很久,后續改正發現是沒有按照KFLBRD這個字母順序輸出,而且有可能有多個開關,沒有考慮這兩種情況。在寫完多個開關判斷的時候,我就發現了代碼結構的問題,所以在滿分后我又修改了代碼,在Electricdevice類中添加了state這個屬性,來表示這個用電器的狀態,控制類電器的初始值為false,用電器類初始值為ture。然后在串聯電路中添加了一個方法,使得電路可以判斷整條電路的狀態。同時我還添加了電阻,電流兩個方法,這對后續迭代會有幫助
7-1 家居強電電路模擬程序-2
這道題的主體思路與上一道題大致相當,除了多了一個落地扇類,多了一個并聯類,并無本質區別。沿用了上一次的代碼后,我刪除了Agent類,添加了一個輸入處理類,一個并聯電路類,就基本完成了整個設計,這是我第一次幾乎做到了開閉原則,第一次體會到段老師上課說的對擴展開放,對修改關閉的好處。
這里提下一個卡了很久的測試點:
因為排序的代碼我直接引用了上一次的,所以在遇到有落地扇的輸出信息排序時候,全錯了,當時找了好久,最后發現是排序的問題,除此之外都是一遍就過了。所以在寫一道題目的時候,一定要先反復讀題理解題意,就像段老師說的,先要做好需求分析,如果需求分析做不好,那肯定是不行的。就像我這個代碼,其他都沒問題,完全是符合要求的產品,結果因為漏掉一個需求,導致運行結果出錯。
分享一些踩坑心得
1.主函數一定不要寫很多處理輸入輸出信息的代碼在里面,一定要用類跟方法實現處理輸入輸出的功能,主函數只能放輸入和輸出的代碼,其他一概不要放在里面。因為如果大量代碼在主函數里,會導致后續邏輯極度混亂,可能會出現改了一個bug,出來三個bug,而且你還沒法找到。比如答題判斷程序-4,我就是因為有大量處理輸入輸出信息的代碼在主函數里,導致我最后沒找到程序錯在哪里,最后還是在與同學討論,在代碼不同位置插入斷點進行反復調試后才發現的bug——一個本該寫在for循環外面的if/else寫在了for里面,導致沒有判斷輸入為空的情況。究其原因,就是因為在主函數里用了多重循環嵌套處理輸入輸出,最后看錯了這段代碼要放的位置。其實些循環,完全可以放在多個不同的類和方法中進行實現。
2.使用繼承的時候一定要考慮子類是否有某些父類沒有的方法。如果子類有父類沒有的方法,一定要謹慎使用父類數組儲存子類對象。因為可能出現:在父類的數組里,我要調用某個位置上儲存的子類對象的方法,但是父類不能調用子類里有而父類里沒有的某個方法。我在家居強電電路模擬程序中就遇到了這種情況,最后解決的辦法就是在父類中添加一個與要調用的子類方法同名的空方法,把子類中的方法看作是對父類方法的復寫。但是這種解決方案不符合繼承與多態的基本原則,所以后續要考慮修改。
改進建議
我覺得目前我對繼承與多態的運用還不算非常合理,在后續的練習中,我還需要對抽象出的父類的合理性進行優化,可以合理地使用抽象類對父類進行表示,有時候也可以添加一些接口,進行實質上的多繼承。
總結
通過這三次作業,我進一步了解了面向對象程序設計的“設計”二字,在對程序的結構設計中,我提升了自己的設計能力,現在逐步開始能夠遵循開閉原則,單一職責原則,主函數中比較簡潔,只有輸入和輸出,這是我從這三次作業里學到的。后續我也要在代碼中加入接口,抽象類等,學以致用。對于pta的題目,我認為難度非常合理,要是老師能夠對有些較難的測試點進行統一提示就更好。

浙公網安備 33010602011771號