南昌航空大學 22207209-侯智慧-第二次blog作業

TeFuir1發表於2024-11-23

一、前言
在過去的一個月中,我全身心地投入到了Javapta課程的學習中,尤其是三次極具挑戰性的大作業。這些作業不僅是對我Java程式設計技能的考驗,也是我在電腦科學領域不斷探索和成長的重要里程碑。
最近的一次大作業是關於家庭電路管理系統的開發。最初接觸這個專案時,我感到有些不知所措。這個專案要求我們運用不同的Java特性,從基本的物件導向程式設計到複雜的資料結構和演算法最佳化,以實現一個能夠模擬和管理家庭電路的應用程式。
在這個專案中,我需要設計一個系統來模擬家庭電路的各種元件,比如開關、插座、燈泡等,並實現它們之間的互動。面對這些挑戰,我逐漸意識到,學習程式設計不僅僅是掌握語法和工具,更是培養一種解決問題的思維方式。
在專案進行過程中,我不斷遇到各種技術難題和邏輯陷阱。有時候,一個小小的錯誤可能會花費數小時甚至數天去除錯和修復。然而,正是在這些反覆試錯和不斷迭代的過程中,我的程式設計能力得到了顯著提升。我學會了如何更有效地除錯程式碼,如何最佳化演算法以提高程式效率,以及如何在團隊協作中利用版本控制工具來管理專案。
此外,這個作業也讓我深刻體會到理論與實踐相結合的重要性。在課堂上學到的概念,只有透過實際編碼和專案應用,才能真正內化為自己的技能。每次成功解決一個棘手的問題,或者在專案中實現一個新功能,都會讓我感受到極大的成就感和滿足感。
在這篇部落格中,我將詳細分享這個家庭電路專案的背景、我所採用的解決方案,以及在過程中積累的經驗和教訓。我希望這些分享不僅能幫助其他正在學習Java的同學,也能為那些對程式設計充滿好奇和熱情的人提供一些有用的啟示。程式設計之路漫漫,但每一步的努力和探索都值得我們珍惜和回味。讓我們一起繼續這段充滿挑戰的學習旅程吧!
二、設計與分析
1.第四次作業7-3 答題判題程式-4
(1)難度分析:
這道題目涉及多種型別的題目處理,包括選擇題和填空題,每種題目型別都有其特定的評分規則。此外,題目還要求處理多張試卷和多名學生的答卷資訊,並根據學號和試卷號進行排序輸出。

  • 題目解析與輸入處理:
    需要解析不同格式的輸入資訊,包括選擇題、填空題、試卷資訊、學生資訊等。每種輸入格式都有其特定的識別符號(如#Z:、#K:、#T:等),需要正確識別並解析。
    輸入資訊可能無序,因此需要在解析時做好資訊的儲存和關聯。
  • 評分規則的實現:
    選擇題和填空題有各自不同的評分規則,尤其是在處理多選題和部分正確的答案時,需要仔細判斷學生答卷與標準答案的匹配程度。
    需要考慮部分正確答案的得分計算,並處理得分截尾的問題。
  • 多張試卷和多名學生的處理:
    需要正確關聯試卷資訊和學生答卷,並根據試卷的題目分值進行評分。
    在輸出時,需要根據學號和試卷號進行排序,這涉及到對資料結構的選擇和排序演算法的實現。
  • 輸出格式的要求:
    輸出不僅包括每道題目的評分結果,還需要計算每名學生在每張試卷上的總分。
    需要檢測試卷的總分是否為100分,並在不滿足時輸出相應的警告資訊。

(2)知識點分析:

  • 物件導向程式設計(OOP):
    抽象類和繼承:Question類是一個抽象類,定義了所有題目的基本屬性和方法。SingleChoiceQuestion、MultipleChoiceQuestion、FillInTheBlankQuestion繼承自Question,並實現了抽象方法evaluateAnswer。
    封裝:類中的屬性通常是私有的,透過公共方法(getter和setter)訪問,以保護資料的完整性。
    多型:透過使用抽象類和介面,允許不同的題目型別實現自己的答案評估方法。
  • 集合框架:
    List和Set:使用ArrayList來儲存題目、試卷、學生和答卷資訊。HashSet用於處理多選題和填空題的答案匹配。
    Map:HashMap用於在答卷中儲存題號和學生答案的對應關係。
  • 字串處理:
    使用String.split()方法對輸入字串進行分割,以提取相關資訊。
    使用trim()方法去除字串首尾的空格,確保資料的準確性。
    使用正規表示式對輸入格式進行驗證和匹配。
    (3)類圖和順序圖設計


    (4)踩坑心得
  • 填空題缺少情況

N:1 #Q:1+1= #A:2

K:2 #Q:古琴在古代被稱為: #A:瑤琴或七絃琴

T:1 1-5 2-10

X:20201103 Tom

S:1 20201103 #A:1-5 #A:2-七絃琴或瑤琴

end
當答案變換順序,也應該是滿分
Set correctAnswers = new HashSet<>(Arrays.asList(trimmedAnswer.split("或")));
Set studentAnswers = new HashSet<>(Arrays.asList(trimmedStudentAnswer.split("或")));
用或字分隔可以將正確答案匹配出來,無論什麼順序都可以匹配成功。

  • 填空題缺少情況

N:1 #Q:1+1= #A:2

K:2 #Q:古琴在古代被稱為: #A:瑤琴或七絃琴

T:1 1-5 2-10

X:20201103 Tom

S:1 20201103 #A:1-5 #A:2-瑤琴或古琴

end
當有一個答案是錯誤的應該0分
for (String studentAns : studentAnswers) {
for (char c : studentAns.toCharArray()) {
if (!trimmedAnswer.contains(String.valueOf(c))) {
return getContent() + "~" + studentAnswer + "~false";
}
}
}
檢查學生答案中是否有錯誤字元,有錯誤字元該題就為0分
*格式錯誤

N:1 #Q:1+1= #A:2

Z:2 #Q:黨十八大報告提出要加強()建設。A 政務誠信 B 商務誠信 C社會誠信 D司法公信 #A:A B C D

T:1 1-5 2-9

X:20201103 Tom

S:1 20201103 #A:1-5 #A:2-A C

end

S:1 20201103 #A:1-5 #A:2-A C 這個輸入無論後面有多少的空格,只需要刪除答案後面的一個空格就可以

// 判斷答案是否為空格,如果是,則刪除
if (answer.endsWith(" ")) {
answer = answer.substring(0, answer.length() - 1); // 刪除最後一個空格
}
2.第五次作業7-1 家居強電電路模擬程式-1
(1)難度分析:

  • 電路模擬的複雜性
    裝置多樣性:題目要求模擬多種裝置,包括開關、分檔調速器、連續調速器、白熾燈、日光燈和吊扇。每種裝置都有不同的工作特性和狀態引數,需要分別進行建模和模擬。
    電路連線:需要處理裝置之間的連線資訊,確保按照正確的電路連線順序進行模擬。尤其是在處理串聯和並聯電路時,需要確保連線的正確性和完整性。
    電壓和狀態計算:裝置的輸出狀態或引數(如亮度、轉速)依賴於輸入電壓或電位差,需要根據裝置的特性進行正確的計算和模擬。
  • 輸入解析的複雜性
    多種輸入格式:輸入資訊包括裝置資訊、連線資訊、控制裝置調節資訊等,格式各異,需要設計靈活的解析器來處理不同型別的輸入。
    輸入約束:需要驗證輸入的合法性,例如確保連線資訊按照電路順序輸入,調速器的輸入端只接VCC等。
  • 輸出要求的複雜性
    格式化輸出:根據裝置的型別和狀態,輸出格式需要符合特定的要求,如開關的狀態顯示、連續調速器的檔位保留兩位小數等。
    排序輸出:需要按裝置型別和編號順序輸出裝置狀態,這要求在輸出階段進行排序處理。
  • 物件導向設計的複雜性
    類設計:需要設計合理的類結構來表示各種裝置、電路連線、輸入解析和輸出處理。類之間的關係、繼承、介面設計等都需要仔細考慮。
    多型和封裝:利用物件導向的多型和封裝特性,設計裝置的行為介面,以便在模擬過程中靈活呼叫不同裝置的特定行為。
  • 演算法和邏輯的複雜性
    狀態更新和模擬:在接收到調節資訊後,需要實時更新裝置的狀態,並重新計算受控裝置的輸出狀態。
    電路模擬:在後續迭代中,隨著電路結構的複雜化(如並聯電路、巢狀電路等),需要設計更復雜的演算法來類比電路行為。
    (2)知識點分析:
  • 抽象類與繼承
    CircuitEquipment: 作為所有電路裝置的基類,包含裝置的基本屬性和方法,如裝置ID和輸出電壓。
    ControlledDevice和ControlDevice: 分別繼承自CircuitEquipment,用於表示受控裝置和控制裝置,進一步擴充套件了裝置的特性,如亮度、速度和狀態。
  • 多型與介面實現
    各種裝置類如Switch、Dimmer、ContinuousDimmer、WhiteBulb、DaylightBulb、HairDryer等,繼承自CircuitEquipment或其子類,實現了各自的calculateOutPut方法,體現了多型的應用。
  • 狀態管理
    開關和調速器: 透過狀態變數(如state、level、speedRatio)和相應的方法(如toggle、increaseLevel、decreaseLevel、setSpeedRatio)來管理裝置的狀態。
  • 輸入輸出處理
    InPut類: 負責解析使用者輸入,建立裝置例項並新增到電路中,並根據控制指令調整裝置狀態。
    OutPut類: 負責輸出裝置的當前狀態,按裝置ID排序後輸出各裝置的狀態資訊。
  • 集合與排序
    使用ArrayList儲存裝置,利用Collections.sort對裝置按ID排序,便於輸出時的有序處理。
  • 使用者輸入解析
    字串處理: 透過解析輸入字串來識別裝置連線資訊和控制命令,使用split、substring等方法提取資訊。
  • 邏輯控制
    使用條件語句(如if、switch)來實現對裝置狀態的判斷和相應的輸出電壓或亮度、速度的計算。
  • 物件導向設計
    程式碼透過物件導向的方式設計,具有良好的可擴充套件性和模組化,便於後續新增新的裝置型別或功能。
    (3)類圖和順序圖設計


    (4)踩坑心得及改進建議
  • 開關在後面的情況


    這段程式碼中實現了開關在任何地方都可以實現完整的功能
    關鍵實現細節:
  • 裝置連線和狀態更新:
    SeriesCircuit類中有一個List devices用於儲存電路中的所有裝置。
    裝置可以按任意順序新增到電路中,並不要求開關必須在前面。
  • 輸出電壓計算:
    在calculateOutputs方法中,首先遍歷所有裝置,計算控制裝置(如開關、調光器)的輸出電壓。
    透過Math.min函式找到所有控制裝置中的最小輸出電壓,這個最小值用於設定受控裝置(如燈泡、風扇)的電壓。
    這種設計允許開關和其他控制裝置在電路中的任意位置,只要它們的狀態發生變化,就會影響到整個電路的輸出。
  • 裝置狀態更新:
    在InPut類中,使用者輸入的控制命令(如#K1)會觸發相應裝置的狀態更新。
    呼叫toggle()方法改變開關狀態後,立即呼叫calculateOutPut()來更新輸出電壓。
    緊接著,circuit.calculateOutputs()會重新計算整個電路的輸出,確保所有裝置的狀態根據最新的控制裝置狀態進行更新。
    3.第六次作業7-1 家居強電電路模擬程式-2
    (1)難度分析
  • 程式碼結構與設計
    物件導向設計:程式碼採用了物件導向的設計,定義了多個抽象類和具體類來表示不同的電路裝置。這種設計提高了程式碼的可擴充套件性和可維護性,但也增加了理解和實現的複雜性。
    繼承與多型:使用繼承和多型來實現不同裝置的行為,這要求開發者對這些概念有深入的理解,尤其是在處理複雜的電路邏輯時。
  • 功能實現
    多種裝置型別:支援多種控制裝置(開關、分檔調速器、連續調速器)和受控裝置(白熾燈、日光燈、吊扇、落地扇),每種裝置都有不同的特性和行為。這需要為每種裝置單獨實現邏輯,並確保它們能夠正確互動。
    電阻和電壓計算:引入了電阻的概念,並實現了電壓的分配和計算。需要根據電路的拓撲結構計算總電阻,並根據電阻比例分配電壓,這涉及到電路分析的基本原理。
  • 演算法複雜性
    電路模擬演算法:實現了串聯和並聯電路的模擬,包括電阻計算和電壓分配。這需要設計高效的演算法來處理電路的複雜拓撲結構。
    輸入解析:解析複雜的輸入格式,包括裝置標識、連線資訊、控制資訊、串聯和並聯電路資訊。需要設計一個穩健的解析器來處理潛在的輸入錯誤。
  • 邊緣情況
    電路異常情況:需要考慮電路中可能出現的異常情況,如短路、開路等,並確保程式能夠正確處理這些情況。
    輸入錯誤處理:需要設計程式來處理可能的輸入錯誤或異常情況,如格式錯誤、不合法的連線資訊等。
    (2)知識點分析
  • 抽象類與繼承:
    CircuitEquipment 是一個抽象類,定義了電路裝置的基本特徵(如 ID、輸出電壓、電阻等)。
    ControlledDevice 和 ControlDevice 繼承自 CircuitEquipment,分別代表受控裝置和控制裝置,擴充套件了特定的屬性和方法。
    具體裝置類(如 Switch、Dimmer、WhiteBulb 等)繼承自上述抽象類,實現了具體的行為。
  • 多型性:
    抽象方法 calculateOutPut 在不同裝置類中有不同實現,體現了多型性。
    透過多型性,可以在不修改程式碼的情況下擴充套件新的裝置型別。
  • 封裝與資訊隱藏:
    各個類透過私有屬性和公共方法封裝內部狀態,提供對外的介面。
    透過方法(如 toggle、handleControl)來操作裝置狀態,隱藏了內部實現細節。
  • 電路設計:
    使用 SeriesCircuit 和 ParallelCircuit 類模擬串聯和並聯電路,包含裝置的連線和電阻、電壓的計算。
    透過裝置的組合,實現複雜電路的模擬。
  • 面向介面程式設計:
    裝置的控制和狀態更新透過介面(如 calculateOutPut)進行,而不是直接操作物件,增強了程式碼的靈活性和可擴充套件性。
  • 集合與資料結構:
    使用 List 儲存裝置,Map 儲存裝置和電路對映,Set 用於去重和狀態跟蹤。
    這些集合類的使用提高了資料管理效率和程式碼的可讀性。
    (3)類圖和順序圖設計


    (4)踩坑心得及改進建議
  • 計算串聯電路和並聯電路的電阻

    在計算串聯電阻的時候需要考慮電路里面是否有開關,如果開關是斷開狀態,則整個電路的電阻設定為0,不可以設定為無窮大,這樣會導致並聯電路的電阻計算錯誤。

    在計算並聯電路的電阻時,當兩個開關都時閉合狀態而且都是閉合,就會導致短路的情況。
    三、總結
    在過去的幾個月中,深入學習Java程式設計的過程中,我經歷了從基礎到複雜的多個專案挑戰。這些專案不僅讓我掌握了Java的語法和特性,還培養了我解決問題的能力和程式設計思維。
    透過第一次作業,我鞏固了物件導向程式設計的基礎知識,理解了類的定義、構造方法、資料封裝、常量定義和方法重寫的重要性。這為我在後續專案中設計和實現複雜的類結構奠定了基礎。
    隨著作業難度的增加,我開始接觸到集合操作、字串處理和輸入輸出等中級知識點。這些技能在第二次作業中得到了充分的應用。我學會了如何有效地解析和處理輸入資料,特別是在應對格式複雜的輸入時,如何利用正規表示式和字串操作來提取有用的資訊。
    第三次作業則是對我程式設計能力的全面考驗。面對多種輸入型別、複雜的資料結構設計和多樣的錯誤處理,我逐步提高了程式碼的健壯性和可維護性。我認識到,良好的程式碼結構和清晰的邏輯是解決複雜問題的關鍵。
    在整個學習過程中,我也積累了許多經驗和教訓。比如,正確處理輸入中的空格和格式問題,確保程式的輸出與預期一致;在設計資料結構時,保持資料之間的關聯性和一致性;在處理錯誤時,優先處理那些對程式影響最大的錯誤。
    這些專案不僅提高了我的程式設計技術,也讓我更加理解理論與實踐相結合的重要性。每次解決一個難題或實現一個新功能,都會帶給我極大的成就感和滿足感。程式設計之路充滿挑戰,但每一次努力和探索都值得珍惜。未來,我將繼續這段充滿挑戰的學習旅程,不斷提升自己的技能和知識水平。

相關文章