四至六次大作業總結

王昱祺發表於2024-11-22

一、前言

1. 7-3 答題判題程式-4

1.1 知識點

1.1.1 類設計和封裝:

  • 題目類:增加選擇題和填空題的設計,新增題目型別這個屬性,需要完成多答案解析與比對,增加答案部分正確性的判斷方法。
  • 試卷類:允許多試卷資訊的輸入,需要試卷總分校驗方法,允許動態調整分值規則。
  • 答卷類:新增處理多選題和填空題答案的方法,支援對部分正確答案的評分規則,增加按學號和試卷號排序功能。

1.1.2 輸入解析:

  • 選擇題解析:新增解析包含多答案的選擇題格式,正確答案以空格分隔,支援多個同學、多張試卷的答卷處理,按學號和試卷號優先順序輸出。
  • 填空題解析:新增解析答案包含多個可接受文字的填空題格式。
  • 動態解析順序:需要確認輸入資訊順序無關,允許亂序輸入試卷、題目、答題等資訊,統一歸類解析。
  • 刪除題目解析:需要能正確處理題目刪除指令,動態調整對應的輸出內容。

1.1.3 判題邏輯:

  • 單選與填空題:按答案匹配。
  • 多選題判分:區分完全正確、部分正確和錯誤情況,按規則計分。
  • 題目狀態檢測:對於引用錯誤、題目刪除或答案缺失的情況優先輸出提示資訊。

1.2 題量

  • 1.2.1 基本題量:需要有單選題、多選題、填空題以及傳統題目的解析與判題邏輯。
  • 1.2.2 實現內容:實現多種題型的解析、多答案比對、輸出排序以及異常處理。

1.3 難度

  • 很複雜和困難:需要靈活實現複雜輸入解析和多場景判題邏輯,涵蓋異常處理與多型別資料整合輸出。

2. 家居強電電路模擬程式設計-1

2.1 知識點

2.1.1 類設計與封裝:

  • 裝置類設計:針對不同型別的電路裝置(如開關、調速器、燈具和風扇等),需要設計相應的類來封裝每個裝置的狀態與行為。每個裝置類應包含輸入和輸出電壓,以及透過控制訊號調整裝置狀態的方法。
  • 電路連線類:連線類應支援解析輸入的連線資訊並根據裝置間的關係更新裝置狀態。
  • 電路管理類:此類負責電路中各個裝置的狀態管理與更新。根據裝置的連線資訊,計算電壓、電流等電路引數,並根據控制指令實時更新電路狀態。

2.1.2 輸入解析:

  • 裝置與引腳輸入解析:輸入資訊中包含裝置的連線資訊和引腳的連線方式,需要透過解析裝置識別符號和引腳編號,建立裝置之間的連線關係。
  • 控制指令解析:需要解析裝置控制指令,根據指令改變裝置的狀態。開關類的控制指令用於改變開關的狀態;調速器類的控制指令用於調整調速器的檔位;燈具和風扇的控制則根據電壓差進行計算和更新。

2.1.3 判定邏輯:

  • 開關控制邏輯:開關的開/關狀態直接決定電路是否通電,影響其他裝置的電壓輸入。需要根據開關的狀態判斷電路是否閉合,並相應更新電路中其他裝置的輸入電壓。
  • 調速器控制邏輯:調速器的檔位決定輸出電壓的比例。根據檔位的調整,調速器的輸出電壓應按照預定的規則進行調整,並傳遞給下游裝置。需要考慮到調速器輸入端的電壓與檔位的關係,精確計算輸出電壓。
  • 裝置響應邏輯:根據電壓變化來計算燈具的亮度、風扇的轉速等裝置的狀態。不同裝置對電壓的響應不同,例如白熾燈的亮度隨電壓差成比例變化,而風扇的轉速也與電壓差成正比。在輸出時,需根據裝置的輸入電壓來計算其響應結果。

2.2 題量

  • 2.2.1 基本題量:本題包含多個裝置和連線方式,涉及控制裝置與受控裝置的互動。題目要求實現對電路連線、裝置狀態變化以及控制指令的處理。設計時要考慮裝置型別、裝置編號、連線規則等因素,確保電路模型的正確性。
  • 2.2.2 實現內容:本題需要實現裝置與電路連線的管理、裝置控制指令的解析、裝置狀態更新等功能。要保證程式能夠正確處理輸入格式,準確類比電路行為,並根據裝置的電壓和控制指令輸出相應的狀態。

2.3 難度

  • 比較難:題目要求實現一個家居電路的模擬程式,涉及裝置的控制邏輯、電路的連線與電壓計算。儘管題目相對基礎,只有串聯電路,但涉及的裝置種類較多,控制邏輯複雜,需要編寫合理的判定和計算邏輯。

3. 家居強電電路模擬程式-2

1.1 知識點

1.1.1 類設計與封裝:

  • 電路類:包括了多種電路裝置(如開關、分壓器、連續調節器等)的管理與狀態更新功能。透過多層次的封裝設計,支援電路裝置的增刪、串聯電路與並聯電路的計算與管理。
  • 電路裝置類:每個電路裝置都是一個類(如 SwitchDividerGovernorContinuousGovernor 等),擁有各自的屬性與方法,封裝了裝置的狀態、控制指令與電壓、電流的計算邏輯。
  • 電路連線管理:透過串聯電路(seriesCircuits)與並聯電路(parallelCircuits)的組織方式,模擬了電路裝置間複雜的連線關係,實現了串聯與並聯電路的計算邏輯。
  • 控制指令處理:設計了控制資訊解析與裝置控制的功能,允許使用者透過輸入不同的控制指令(如開關、調節器設定等)對裝置進行狀態修改。

1.1.2 輸入解析與動態調整:

  • 控制指令解析:對不同型別的控制指令(如開關操作、分壓器調節等)進行解析,處理控制命令對電路裝置的影響,支援動態的控制指令輸入。
  • 電路裝置連線解析:支援串聯和並聯電路裝置的輸入解析,處理不同型別的電路裝置間的連線關係,確保電路狀態的準確更新。
  • 異常處理與裝置狀態檢測:對於電路裝置中的異常(如開關未閉合、分壓器設定為零等),能夠進行錯誤檢測並適時輸出提示資訊。對電路中的短路、斷路等情況也進行了相應的處理與判斷。

1.1.3 電路計算與判定:

  • 電阻計算:設計了並聯電路與串聯電路的電阻計算方法,能夠根據電路裝置的狀態和連線關係動態計算電阻,並更新電流、電壓等電路狀態。
  • 電流與電壓分配:根據總電壓(如220V)和各個電路裝置的電阻,計算整個電路的電流,並根據電壓降和電阻情況,更新各個裝置的電壓狀態。
  • 電路狀態檢測:透過 updateDevices 方法更新所有電路裝置的狀態,動態調整電路的工作狀態,並且輸出每個裝置的當前狀態。

1.2 題量

1.2.1 基本題量:需要實現電路中多種裝置的模擬與多電路連線關係的計算。每種裝置的設計需要滿足類比電路中複雜的操作與控制功能。

1.2.2 實現內容:透過對多種裝置的模擬、電路狀態的動態調整、輸入指令的解析與電路計算等功能的實現,構建了一個較為完整的電路系統模擬器。電路的計算涉及串聯與並聯電路的電阻計算、電流分配、電壓變化等內容,並能根據使用者輸入控制電路裝置的開關與調節。

1.3 難度

非常難:該專案增加了並聯電路處理,難度直線上升。

二、設計與分析

7-3 答題判題程式-4

1.1 類圖設計

1.2 SourceMonitor 報表分析

  • 專案目錄D:\Desktop\PTA4CODE\
  • 專案名稱:PTA4
  • 檢查點名稱:Baseline
  • 檔名稱PTA4code.java
  • 程式碼行數:286 行
  • 語句數:244 個語句
  • 分支語句百分比:19.7%,表示程式碼中分支語句(如 ifswitch 等)佔總語句的比例。
  • 方法呼叫語句:132 個方法呼叫語句。
  • 程式碼註釋百分比:0.3%,表示程式碼中註釋行佔總行數的比例。
  • 類和介面數:10,表示該檔案中定義了 10 個類或介面。
  • 每類方法數:2.50,表示平均每個類中定義了 2.50 個方法。
  • 每方法平均語句數:7.20,表示平均每個方法包含 7.20 個語句。
  • 最複雜方法的行號:185 行,表示 ExamSystem.parseInput() 方法是最複雜的方法。
  • 最大複雜度:10,表示程式碼中方法的最大複雜度為 10。
  • 最深程式碼塊的行號:123 行,表示最深程式碼塊的行號。
  • 最大程式碼塊深度:4,表示程式碼塊的最大巢狀深度。
  • 平均程式碼塊深度:1.98,表示平均程式碼塊深度。
  • 平均複雜度:2.74,表示所有方法的平均複雜度。
  • 方法分佈:最複雜方法在 1 個類中。

1.3 程式碼分析

1.3.1 類職責分工

  • Main 類:程式的入口,初始化 ExamSystem 例項,並透過控制檯輸入讀取測試資料,輸出結果。
  • Question 類:抽象類,所有題目的基類,封裝題目基本資訊(題號、內容、答案等),並定義子類需要實現的題目格式化和得分方法。
  • SingleChoiceQuestion 類:繼承自 Question 類,表示單選題,提供題目格式化和得分的實現。
  • MultipleChoiceQuestion 類:繼承自 Question 類,表示多選題,提供題目格式化和得分的實現,支援部分正確的得分計算。
  • FillInBlankQuestion 類:繼承自 Question 類,表示填空題,提供題目格式化和得分的實現,支援部分正確的得分計算。
  • QuestionFactory 類:用於根據輸入字串建立對應的題目物件,支援單選題、多選題和填空題的建立。
  • TestPaper 類:表示試卷物件,管理試卷中的題目及其分值,提供驗證試卷總分是否為 100 分的功能。
  • Student 類:表示學生物件,包含學生的 ID 和姓名。
  • AnswerSheet 類:表示學生的答卷,包含學生的答案資料。
  • ExamSystem 類:核心類,負責處理整個考試系統的流程,包括解析輸入、管理試卷和答卷、評分和輸出結果。

1.3.2 功能分析

  • 輸入讀取:透過 Scanner 類從控制檯讀取輸入,讀取題目、試卷、學生資訊及答卷。輸入格式包括題目型別(#N:, #Z:, #K:)、試卷資訊(#T:)、學生資訊(#X:)以及答卷資訊(#S:)。

  • 解析題目和答案

    • 透過正規表示式解析題目輸入行,分離出題號、題目內容和標準答案。不同型別的題目(單選、多選、填空)使用不同的類進行處理。透過 QuestionFactory 工廠類建立相應的題目物件。
  • 建立試卷物件 TestPaper:試卷透過題目順序和分值來定義,使用 Map 儲存題目的分數和順序。每個試卷物件會繫結一定數量的題目,並透過 TestPaper 類管理。

  • 建立答卷物件 AnswerSheet:答卷儲存學生的答案,並與試卷中的題目順序對應。AnswerSheet 類透過 addAnswer 方法新增學生的每道題答案。

  • 判題

    • 每道題目透過 getFormattedQuestion 方法格式化輸出,顯示學生的答案和判題結果。
    • getScore 方法用來計算學生答案的得分,支援單選題的完全正確、部分正確和錯誤的判定;多選題和填空題也同樣支援部分正確的判定。
  • 結果展示

    • showQuesAndAns:輸出每道題目的內容和學生提供的答案,並判斷答案是否正確。
    • showResults:輸出每道題目的判題結果(如 truepartially correctfalse),並計算學生的總分。
  • 錯誤處理:對輸入格式不正確的情況進行錯誤處理並記錄錯誤日誌,確保系統對不規範輸入具有容錯性。

2. 家居強電電路模擬程式設計

2.1 類圖設計

2.2 程式碼報表分析

  • 專案目錄D:\Desktop\PTA5CODE\
  • 專案名稱:PTA5
  • 檢查點名稱:Baseline
  • 檔名稱PTA5.java
  • 程式碼行數:425 行
  • 語句數:213 個語句
  • 分支語句百分比:21.1%,表示程式碼中分支語句佔總語句的比例。
  • 方法呼叫語句:105 個方法呼叫語句。
  • 程式碼註釋百分比:19.8%,表示程式碼中註釋行佔總行數的比例。
  • 類和介面數:2,表示該檔案中定義了 2 個類或介面。
  • 每類方法數:14.50,表示平均每個類中定義了 14.50 個方法。
  • 每方法平均語句數:6.34,表示平均每個方法包含 6.34 個語句。
  • 最複雜方法的行號:40 行,表示 CircuitManager.parseInput() 方法是最複雜的方法。
  • 最大複雜度:4,表示程式碼中方法的最大複雜度為 4。
  • 最深程式碼塊的行號:43 行,表示最深程式碼塊的行號。
  • 最大程式碼塊深度:4,表示程式碼塊的最大巢狀深度。
  • 平均程式碼塊深度:0.98,表示平均程式碼塊深度。
  • 平均複雜度:2.33,表示所有方法的平均複雜度。

2.3 程式碼分析

2.3.1 類職責分工

  • Main 類:程式入口,負責初始化 CircuitManager 例項並透過控制檯輸入讀取電路連線和控制命令資料,最後呼叫方法執行電路狀態計算和輸出結果。

  • CircuitManager 類:核心類,負責電路的裝置管理與操作。解析輸入的連線資訊,處理裝置間的連線,解析控制命令並處理裝置狀態,同時進行電壓傳播,計算裝置的輸出電壓或狀態(如亮度、轉速等)。

  • circuitEquipment 類:所有電路裝置的基類,包含輸入電壓(IV)和輸出電壓(OV)屬性。所有裝置類都繼承自此類,定義基本的電壓設定和獲取方法。

  • controlEquipment 類:繼承自 circuitEquipment 類,增加了一個 gear 屬性表示裝置的檔位,用於表示控制裝置(如開關、調速器)不同狀態。

  • circuitSwitch 類:繼承自 controlEquipment,表示開關裝置,包含控制開關的狀態(如開啟或關閉)和計算輸出電壓的方法。

  • binningGovernor 類:繼承自 controlEquipment,表示分檔調速器,透過檔位控制輸出電壓,幷包含對檔位的修正功能。

  • continuousGovernor 類:繼承自 controlEquipment,表示連續調速器,透過百分比檔位設定電壓,並計算輸出電壓。

  • controlledEquipment 類:繼承自 circuitEquipment,表示受控裝置(如燈具、風扇),包含具體裝置的操作邏輯(如亮度或轉速的計算)。

  • light 類:繼承自 controlledEquipment,表示燈具,定義了亮度計算方法。

  • incandescentLamp 類fluorescentLamp 類:分別表示白熾燈和日光燈,繼承自 light 類,計算各自的亮度。

  • ceilingFan 類:繼承自 controlledEquipment,表示吊扇,透過電壓計算轉速。

2.3.2 功能分析

  • 輸入解析:透過 Scanner 類讀取控制檯輸入,分離連線資訊(裝置的連線)和控制命令。連線資訊透過 processConnections 方法解析,裝置間的連線關係被提取出來並建立裝置之間的電壓傳遞關係。控制命令透過正規表示式解析,執行裝置狀態的變更(如開關切換、調速器調整等)。

  • 裝置建立與連線:在 processConnections 方法中,透過解析連線資訊,程式根據裝置識別符號(如 KFL 等)建立對應的裝置物件,並根據裝置引腳(如 VCCGND)來初始化電壓源(如輸入電壓或接地)。裝置之間透過連線資訊建立聯絡,並透過 connectDevices 方法將裝置連成電路。

  • 控制命令處理:在 processCommands 方法中,透過正規表示式解析不同型別的控制命令(如 #K 切換開關、#F 調整分檔調速器、#L 設定連續調速器的檔位)。這些命令會觸發裝置狀態的更新,並計算輸出電壓。

  • 電壓傳播與計算propagateVoltage 方法負責電壓的傳播過程。首先會遍歷所有開關裝置,計算每個開關的導通狀態,判斷是否有斷開電路的情況。如果電路斷開,後續裝置的電壓會被設定為 0。如果電路通暢,電壓會從輸入裝置傳播到後續裝置,計算每個裝置的輸出電壓、亮度、轉速等引數。

  • 輸出裝置狀態:透過 outputStatus 方法,程式會按照裝置型別(如開關、燈具、風扇等)和裝置編號順序輸出裝置的狀態。狀態包括開關的開啟/關閉狀態、調速器的檔位、燈具的亮度或風扇的轉速等。

2.3.3 程式碼結構分析

  • 裝置類設計:電路裝置透過類繼承實現多型,每個裝置類根據裝置型別的不同實現自己的特定功能(如計算電壓、亮度或轉速等)。這種設計方式使得程式碼具備高度的可擴充套件性和可維護性,可以方便地新增裝置型別。

  • 控制命令處理:使用正規表示式解析輸入命令,並根據命令型別呼叫相應的方法來處理裝置狀態。這種方式簡潔高效,但需要保證輸入格式的準確性,否則會導致解析失敗。

  • 電壓傳播邏輯:電壓傳播透過遍歷所有裝置,並根據裝置的型別和狀態進行不同的處理。開關裝置的狀態會影響後續裝置的電壓傳遞,確保電路狀態的準確模擬。調速器和燈具的輸出會根據輸入電壓動態計算,確保電壓變化的合理性。

2.3.4 程式最佳化建議

  • 輸入驗證:目前的程式碼假設輸入格式始終正確,應新增更多的輸入校驗邏輯,避免因輸入錯誤導致程式崩潰或行為異常。

  • 效能最佳化:雖然該程式的功能較為簡單,但在裝置數量較多時,遍歷裝置的次數會增加。可以使用更高效的圖結構來表示裝置間的連線關係,從而提高電壓傳播和裝置狀態更新的效率。


3.家居強電電路模擬程式-2

3.1 類圖設計

3.2 SourceMonitor 報表分析

  • 專案目錄D:\Desktop\PTA6CODE\
  • 專案名稱:PTA6
  • 檢查點名稱:Baseline
  • 檔名稱PTA6.java
  • 程式碼行數:800 行
  • 語句數:497 個語句
  • 分支語句百分比:27.6%,表示程式碼中分支語句佔總語句的比例。
  • 方法呼叫語句:171 個方法呼叫語句。
  • 程式碼註釋百分比:10.6%,表示程式碼中註釋行佔總行數的比例。
  • 類和介面數:9,表示該檔案中定義了 9 個類或介面。
  • 每類方法數:5.22,表示平均每個類中定義了 5.22 個方法。
  • 每方法平均語句數:10.43,表示平均每個方法包含 10.43 個語句。
  • 最複雜方法的行號:289 行,表示 Circuit.parallelResistance() 方法是最複雜的方法。
  • 最大複雜度:19,表示程式碼中方法的最大複雜度為 19。
  • 最深程式碼塊的行號:311 行,表示最深程式碼塊的行號。
  • 最大程式碼塊深度:8,表示程式碼塊的最大巢狀深度。
  • 平均程式碼塊深度:2.41,表示平均程式碼塊深度。
  • 平均複雜度:3.45,表示所有方法的平均複雜度。

3.3 程式碼分析

3.3.1 類職責分工

  • Main 類:程式的入口,初始化 CircuitSystem 例項,讀取輸入並展示類比電路的狀態。
  • Device 類:抽象類,所有電路裝置的基類,封裝裝置的基本資訊(如名稱、電壓、電流等)和狀態(開關、分壓等)。定義子類需要實現的裝置控制方法和電路計算方法。
  • Switch 類:繼承自 Device 類,表示開關裝置。控制裝置的開啟與關閉,影響電路的整體狀態。
  • DividerGovernor 類:繼承自 Device 類,表示分壓器。控制電壓的分配,影響電路中的電壓計算。
  • ContinuousGovernor 類:繼承自 Device 類,表示連續調節器。調節電流或電壓,影響電路中的電流和電壓分佈。
  • Circuit 類:管理電路中各個裝置的連線(串聯與並聯),並計算電路的電阻、電流和電壓。
  • CircuitSystem 類:核心類,負責管理電路裝置的建立、連線、更新和計算,控制整個電路系統的模擬流程。
  • InputParser 類:用於解析輸入指令,將使用者輸入的電路裝置、控制指令、連線資訊等轉換為相應的物件或操作。

3.3.2 功能分析

  • 輸入解析

    • 透過 Scanner 類從控制檯讀取輸入,讀取裝置資訊、連線指令、控制指令等。輸入格式包括裝置定義(如 Switch: A)、電路連線(如 Connect: A-B)和控制操作(如 SwitchOn: A)。
  • 裝置管理

    • 透過 InputParser 解析輸入的裝置資訊,建立電路裝置(如開關、分壓器等)。每個裝置都封裝了自己的屬性與狀態。
  • 電路連線

    • 電路連線透過 Circuit 類管理,支援串聯與並聯連線。不同的裝置透過電路連線起來,共享電壓、電流與電阻等計算結果。
  • 裝置控制

    • 電路裝置(如 SwitchDividerGovernor 等)可以透過控制指令進行開啟、關閉或調節,影響電路中的電流和電壓分佈。
  • 電路計算

    • 電路透過 Circuit 類進行電阻、電流與電壓的計算。對於串聯電路,電阻相加;對於並聯電路,電阻的倒數相加。計算時,裝置的開關狀態會影響電流分配。
  • 結果展示

    • 使用 showStatus() 方法輸出每個裝置的當前狀態(如是否開啟、調節的電壓等)。
    • 使用 showCircuitStatus() 輸出整個電路的狀態,包括總電流、電壓分配和各裝置的工作狀態。
  • 錯誤處理

    • 對輸入格式不規範的情況進行錯誤提示,確保系統在出現非法輸入時能夠穩定執行。比如,裝置連線時若裝置不存在或連線錯誤,系統會輸出錯誤資訊並跳過該操作。
  • 電路狀態更新

    • 電路系統能夠動態更新各個裝置的狀態,透過 CircuitSystem.updateDevices() 方法計算電流和電壓分配,並根據電路裝置的控制狀態(開關、調節等)重新計算電路的總電流和電壓。

三、採坑心得

1. 7-3 答題判題程式-4

1.1 題目解析中的正規表示式問題

在實現題目解析時,我初期使用了簡單的 String.split 方法來分割題目內容和答案。但是由於題目和答案中可能包含空格或其他特殊字元,在解析時出現了兩個問題:

  • 問題 1:如果題目內容或答案中包含空格,split 方法會將整個字串分割成多個部分,導致無法正確獲取題目內容或答案。例如,在題目 #N:1 #Q: This is a question #A: correct answer 中,split 會錯誤地分割答案部分,導致資料丟失。
  • 問題 2:題目順序和輸入順序可能不一致,導致在提取題目時,題目的順序沒有按照題號正確排列。

解決方案

為了解決這個問題,我改用了正規表示式來解析題目內容和答案,從而確保能夠準確提取包含空格的題目和答案。具體程式碼如下:

String pattern = "#N:(\\d+) #Q:(.*?) #A:(.*)";
Matcher matcher = Pattern.compile(pattern).matcher(quesInput);
if (matcher.matches()) {
    int qNum = Integer.parseInt(matcher.group(1).trim());
    String qText = matcher.group(2).trim();
    String qAns = matcher.group(3).trim();
    // 建立題目物件
    QuestionItem qItem = new QuestionItem(qNum, qText, qAns);
    paper.addQues(qItem);
}

這裡的正規表示式 #N:(\\d+) #Q:(.*?) #A:(.*) 透過非貪婪匹配 .*? 來避免過多的分割,能夠準確提取題號、題目內容和答案,即使內容中含有空格或其他特殊字元。

題目順序問題:為了解決題目順序問題,我對題目列表進行排序,確保題目按題號順序輸出:

qList.sort(Comparator.comparingInt(QuestionItem::getQNum)); // 按題號排序

這樣可以確保即使輸入的題目順序不正確,最終輸出時依然是按題號排列的。


1.2 答案解析的順序對齊問題

在初始實現中,我直接按照輸入順序對比題目和答案,而沒有考慮題目編號與答案順序可能不一致的問題。這導致在某些測試用例中,答案與題目順序對不上,出現了錯誤。例如,輸入如下:

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

雖然答案順序是按照 #A:10 #A:2 輸入的,但題號應該為 1 的答案是 10,題號為 2 的答案是 2。由於直接按順序對比,程式無法正確匹配題目和答案。

解決方案

為了解決這個問題,我透過題號來對齊題目和答案,而不是依賴輸入順序。我建立了一個 Map<Integer, String> 來對映題號與答案,並確保題號對應正確的答案。具體程式碼如下:

Map<Integer, String> ansMap = new HashMap<>();
List<QuestionItem> qList = paper.getAllQues();
for (int i = 0; i < qList.size(); i++) {
    QuestionItem qItem = qList.get(i);
    int qNum = qItem.getQNum();
    ansMap.put(qNum, ansList.get(i));  // 使用題號作為鍵,答案作為值
}

2. 家居強電電路模擬程式設計-1

2.2 電壓傳播問題

在實現電壓傳播功能時,我遇到了如下問題:

  • 問題 1:裝置之間的電壓傳播順序不一致,導致電壓傳遞的結果並不如預期。例如,如果一個裝置的輸入電壓為 0,但它仍然嘗試對後續裝置進行電壓傳播,結果導致後續裝置的電壓狀態出錯。
  • 問題 2:電路斷開時,後續裝置應該沒有電壓,但如果沒有正確標記電路斷開,可能會出現裝置仍然繼續傳播電壓的錯誤。

解決方案

為了解決這些問題,我設計了電壓傳播的過程時加入了一個標誌位來標記電路是否斷開,並在傳播過程中按正確的順序更新每個裝置的電壓狀態。如果電路斷開,則後續裝置的電壓應為 0。最重要的是,我新增了對開關裝置的檢查,確保在開關處於關閉狀態時電路不會繼續傳播電壓。具體實現如下:

public void propagateVoltage() {
    double voltage = inputVoltage; // 初始電壓為VCC電壓
    boolean circuitOpen = false;  // 標記電路是否斷開

    for (String deviceId : deviceOrder) {
        circuitEquipment device = equipments.get(deviceId);

        if (device instanceof circuitSwitch) {
            circuitSwitch sw = (circuitSwitch) device;
            sw.calOV();

            if (sw.getGear() == 0) {
                circuitOpen = true; // 電路斷開
                break;
            }
        }
    }

    if (circuitOpen) {
        voltage = 0;
    }

    for (String deviceId : deviceOrder) {
        circuitEquipment device = equipments.get(deviceId);

        if (voltage == 0) {
            device.setIV(0);
        } else {
            device.setIV(voltage);
        }

        if (device instanceof circuitSwitch) {
            ((circuitSwitch) device).calOV();
        } else if (device instanceof binningGovernor) {
            ((binningGovernor) device).calOV();
        } else if (device instanceof continuousGovernor) {
            ((continuousGovernor) device).calOV();
        }
        voltage = device.getOV();
    }
}

3. 家居強電電路模擬程式-2

3.1 心得體會

這道題加入了並聯電路處理,直接給我打蒙了,原來寫的電路裝置類設計幾乎都不可用了,原來的類設計用的電壓是輸入電壓和輸出電壓兩個,發現這個電壓適用於控制裝置,但是對於受控裝置,用這個電壓屬性來計算壓降非常困難,但我死守這個設計,一直沒有正確處理並聯電路後跟著的串聯電路的分壓問題,導致大半測試點通不過。一開始沒意識到這個問題,只覺得自己的類設計沒有標號,參考了一下同學的類設計之後就接著開發了,導致後續問題頻發,並造成58分慘案。痛定思痛,決定這周要重寫類設計重做這題!!!


四、改進建議

1. 7-3 答題判題程式-4

1.1 抽象輸入輸出處理為獨立模組

  • 目前情況:當前程式碼中,輸入和輸出的處理邏輯與題目管理邏輯緊密耦合,在題目修改或刪除時,需要同時處理輸入輸出的調整。

  • 改進:可以將輸入輸出處理與題目管理的核心邏輯分離,專門建立一個 InputOutputHandler 類來負責處理所有輸入輸出的相關工作。這樣,題目類與輸入輸出處理類的耦合度降低,程式結構更加清晰,便於後續維護和擴充套件。

  • 改進方法

class InputOutputHandler {
    public String readInput() {
        // 讀取並返回輸入
        return scanner.nextLine();
    }

    public void outputResult(String result) {
        // 輸出結果
        System.out.println(result);
    }
}

透過將輸入輸出單獨封裝在一個類中,程式的職責劃分更加明確,便於管理和擴充套件。

1.1 最佳化題目排序與查詢

  • 目前情況:在當前程式碼中,題目和答案使用簡單的集合結構進行儲存,雖然能滿足基本的功能需求,但在題目數量增多時,查詢、排序和修改效率可能不高,尤其是在需要動態調整題目順序時。

  • 改進:為了提升資料訪問效率,可以使用 TreeMap 來儲存題目,這樣能夠自動按題號排序。

  • 改進

class QuestionManager {
    private Map<Integer, Question> questions = new TreeMap<>();

    public void addQuestion(int number, String text, String answer) {
        questions.put(number, new Question(number, text, answer));
    }

    public Question getQuestion(int number) {
        return questions.get(number);
    }

    public Collection<Question> getAllQuestions() {
        return questions.values();  // 自動按題號排序
    }
}

2. 電路模擬系統改進建議

2.1 抽象裝置建立為獨立工廠類

  • 目前情況:在現有程式碼中,裝置的建立和初始化邏輯被分散在多個地方,如 CircuitManager 類的 processConnections 方法中,導致裝置建立與管理邏輯高度耦合,增加了程式碼的複雜度和維護難度。

  • 改進:可以將裝置的建立邏輯抽象為一個獨立的工廠類 DeviceFactory,該類根據裝置的型別來建立相應的裝置例項。這樣不僅可以減少 CircuitManager 的程式碼複雜度,還能使得裝置的建立更加模組化,便於後續擴充套件和修改。

  • 改進方法

class DeviceFactory {
    public static circuitEquipment createDevice(String identifier) {
        switch (identifier.charAt(0)) {
            case 'K': return new circuitSwitch();
            case 'F': return new binningGovernor();
            case 'L': return new continuousGovernor();
            case 'B': return new incandescentLamp();
            case 'R': return new fluorescentLamp();
            case 'D': return new ceilingFan();
            default: return null;
        }
    }
}

然後在 CircuitManager 中使用該工廠類來建立裝置:

private circuitEquipment createDevice(String identifier) {
    return DeviceFactory.createDevice(identifier);
}

透過將裝置建立邏輯集中到 DeviceFactory 類中,程式結構更加清晰,且如果後續需要新增裝置型別,只需在工廠類中修改,無需更改其他類的程式碼。

2.2 最佳化電壓傳播邏輯

  • 目前情況:在 CircuitManager 中,電壓傳播的邏輯比較集中,主要透過遍歷裝置和檢查每個裝置的狀態來逐步傳播電壓。然而,當前的設計中,對於每個裝置型別,電壓傳播的計算方法都是透過判斷裝置的型別來手動呼叫不同的計算方法,增加了程式碼重複性和複雜度。

  • 改進:可以透過引入策略模式(Strategy Pattern)來最佳化電壓傳播邏輯。每種裝置可以擁有自己的電壓傳播策略介面,具體的電壓計算由不同的裝置類自己實現。這樣不僅提高了程式碼的可擴充套件性,還能避免 CircuitManager 類中的冗餘程式碼。

  • 改進方法

interface VoltagePropagationStrategy {
    void propagateVoltage(circuitEquipment device);
}

class SwitchVoltageStrategy implements VoltagePropagationStrategy {
    public void propagateVoltage(circuitEquipment device) {
        circuitSwitch sw = (circuitSwitch) device;
        sw.calOV();  // 開關計算輸出電壓
    }
}

class LampVoltageStrategy implements VoltagePropagationStrategy {
    public void propagateVoltage(circuitEquipment device) {
        light lamp = (light) device;
        lamp.calBrightness();  // 燈具計算亮度
    }
}

// 在電路裝置中,設定一個策略
class circuitSwitch extends controlEquipment {
    private VoltagePropagationStrategy voltageStrategy = new SwitchVoltageStrategy();

    public void setVoltageStrategy(VoltagePropagationStrategy strategy) {
        this.voltageStrategy = strategy;
    }

    public void applyVoltage() {
        voltageStrategy.propagateVoltage(this);
    }
}

然後,在 CircuitManager 類中,當傳播電壓時,依賴裝置的策略來進行呼叫:

for (String deviceId : deviceOrder) {
    circuitEquipment device = equipments.get(deviceId);
    if (device != null) {
        device.applyVoltage();  // 根據裝置的策略傳播電壓
    }
}

透過這種方式,電壓傳播的邏輯被更清晰地分離到了不同的裝置策略中,每種裝置的行為可以透過調整策略來改變,而無需修改 CircuitManager 中的核心程式碼。

2.3 最佳化裝置狀態輸出邏輯

  • 目前情況:在現有程式碼中,outputStatus 方法每次都需要遍歷不同型別的裝置並列印其狀態。這個方法內部包含了大量的型別判斷和狀態輸出程式碼,導致邏輯重複和程式碼冗餘。

  • 改進:可以使用模板方法模式(Template Method Pattern)來最佳化裝置狀態輸出邏輯。建立一個抽象的 Device 類,定義一個通用的輸出狀態的方法,具體的裝置類只需要實現自己的狀態計算邏輯。這樣可以避免程式碼重複,並使得狀態輸出邏輯更加統一。

  • 改進方法

abstract class Device {
    public abstract String getDeviceStatus();
}

class circuitSwitch extends Device {
    public String getDeviceStatus() {
        return (getGear() == 1 ? "closed" : "turned on");
    }
}

class incandescentLamp extends Device {
    public String getDeviceStatus() {
        return String.format("%d", (int) getBrightness());
    }
}

// 然後在 CircuitManager 中統一呼叫
public void outputStatus() {
    for (String deviceId : deviceOrder) {
        Device device = equipments.get(deviceId);
        if (device != null) {
            System.out.println("@" + deviceId + ":" + device.getDeviceStatus());
        }
    }
}

3. 家居強電電路模擬程式-2

3.1 58分就不提什麼改進建議了

重寫類設計!

五、總結

1. 重視類設計

類設計不寫好,後面方法的實現可能會舉步維艱,所以開始寫程式碼之前一定要分析好後續可能會增加的需求再進行類設計。

2. 需要進一步學習軟體設計模式

在面對複雜的程式設計任務時,應用設計模式可以極大地提高程式碼的可擴充套件性。比如工廠模式和組合模式,能夠幫助我在程式設計專案中更加高效地解決問題。需要更深入的學習這些設計模式。

3. 對課程與教學的改進建議

課程的整體設計很好,我沒有特別好的建議。對我自己而言,我需要繼續多寫程式碼,多學習知識,不斷提升自己的程式設計能力。還有這周要重寫下PTA6。


相關文章