題目集4~6的總結性Blog
一、前言
經過題目集4至6的練習,我對Java程式設計的理解和實踐能力都有了顯著的提升。題目集4主要考察了繼承與正規表示式的知識點,題目集5引入了家庭電路的模擬,題目集6則在前者的基礎上增加了並聯電路的處理。三次題目集的題量逐步增加,難度也有所提升,特別是題目集6,只有一題,但涉及的知識點較為複雜,需要深入理解電路原理以及Java中複雜的類與介面的設計。1
二、設計與分析
題目集4:資料處理與判題程式
在這個題目集中,我們實現了一個能夠處理多選題和填空題的判題程式。主要功能包括題目的管理、學生的答題管理、評分和輸出結果。以下是主要類和方法的介紹:
Question 類
封裝了題目的基本屬性,如編號、內容、標準答案等。
方法 matchAnswer 用於判斷學生的答案是否正確。
方法 isPartiallyCorrect 用於判斷學生的答案是否部分正確。
MultipleChoiceQuestion 類 和 FillInTheBlankQuestion 類
分別繼承自 Question 類,用於處理多選題和填空題的特殊需求。
TestPaper 類
用於管理試卷,包括題目的集合和每題的分值。
方法 checkTotalScore 檢查試卷總分是否為100分。
方法 checkQuestionExistence 檢查試卷中是否存在指定的題目。
AnswerPaper 類
表示學生的答卷,包含了學生資訊、試卷資訊和答案列表。
Judge 類
負責評分和輸出結果,透過呼叫不同的評估方法來處理不同型別題目的評分。
InputHandler 類
處理輸入資料,將其解析為程式可以處理的物件。
主要程式碼示例:
class Question {
private int number;
private String content;
private String answer;
private boolean isValid = true;
private boolean isMultipleChoice;
public Question(int number, String content, String answer, boolean isMultipleChoice) {
this.number = number;
this.content = content;
this.answer = answer;
this.isMultipleChoice = isMultipleChoice;
}
public int getNumber() {
return number;
}
public String getContent() {
return content;
}
public String getAnswer() {
return answer;
}
public void invalidate() {
isValid = false;
}
public boolean isValid() {
return isValid;
}
public boolean isMultipleChoice() {
return isMultipleChoice;
}
public boolean matchAnswer(String studentAnswer) {
return answer.equalsIgnoreCase(studentAnswer);
}
public boolean isPartiallyCorrect(String studentAnswer) {
if (isMultipleChoice) {
Set<String> correctSet = new HashSet<>(Arrays.asList(answer.split(" ")));
Set<String> studentSet = new HashSet<>(Arrays.asList(studentAnswer.split(" ")));
if (correctSet.equals(studentSet)) {
return false; // 完全正確
}
if (Collections.disjoint(correctSet, studentSet)) {
return false; // 完全錯誤
}
return correctSet.containsAll(studentSet) && studentSet.size() < correctSet.size();
} else {
return answer.contains(studentAnswer) && !studentAnswer.equals(answer);
}
}
}
class TestPaper {
private int number;
private Map<Integer, Integer> questionScores = new HashMap<>();
public TestPaper(int number) {
this.number = number;
}
public void addQuestion(int questionNumber, int score) {
questionScores.put(questionNumber, score);
}
public boolean checkTotalScore() {
int totalScore = questionScores.values().stream().mapToInt(Integer::intValue).sum();
if (totalScore != 100) {
System.out.println("alert: full score of test paper " + number + " is not 100 points");
return false;
}
return true;
}
public boolean checkQuestionExistence(Map<Integer, Question> questions) {
for (int qNumber : questionScores.keySet()) {
if (!questions.containsKey(qNumber)) {
return false;
}
}
return true;
}
public int getNumber() {
return number;
}
public Map<Integer, Integer> getQuestionScores() {
return questionScores;
}
}
class Answer {
private int paperNumber;
private String studentId;
private Map<Integer, String> answers = new HashMap<>();
public Answer(int paperNumber, String studentId) {
this.paperNumber = paperNumber;
this.studentId = studentId;
}
public void addAnswer(int questionNumber, String answer) {
answers.put(questionNumber, answer);
}
public String getStudentId() {
return studentId;
}
public int getPaperNumber() {
return paperNumber;
}
public Map<Integer, String> getAnswers() {
return answers;
}
}
設計類圖:
順序圖:
題目集五:家居電路模擬
為了實現智慧家居強電電路模擬系統,我設計了以下幾個類和方法:
Device:抽象類,表示一個裝置,包含裝置的基本屬性和方法。
Switch:繼承自Device,表示一個開關。
Fan:繼承自Device,表示一個風扇。
Bulb:繼承自Device,表示一個燈具。
Circuit:表示一個電路,包含裝置和連線關係的管理。
Main:主類,負責讀取輸入命令並呼叫Circuit類的方法進行處理。
2. 關鍵類和方法解析
Device 類
abstract class Device {
String id; // 裝置識別符號
double resistance; // 電阻值
int voltageDifference; // 引腳間的電壓差
// 建構函式,初始化裝置ID和電阻
Device(String id, double resistance) {
this.id = id;
this.resistance = resistance;
this.voltageDifference = 0; // 預設電壓差為0
}
// 更新裝置狀態的方法,由子類實現
abstract void updateState(String command);
// 獲取裝置當前狀態的方法,子類重寫來根據裝置的實際狀態返回資訊
abstract String getStatus();
// 設定電壓差
void setVoltageDifference(int voltage) {
this.voltageDifference = voltage;
}
}
Switch 類
class Switch extends Device {
boolean isClosed; // 開關狀態(關閉時為true)
// 建構函式初始化開關狀態
Switch(String id) {
super(id, 0); // 開關的電阻是0
this.isClosed = false; // 預設狀態為“開啟”
}
@Override
void updateState(String command) {
isClosed = !isClosed; // 每次切換開關狀態
}
@Override
String getStatus() {
// 根據開關狀態返回相應的狀態文字
return isClosed ? "closed" : "turned on";
}
}
Fan 類
class Fan extends Device {
int minVoltage, maxVoltage; // 風扇工作電壓範圍
int minSpeed, maxSpeed; // 風扇轉速範圍
// 建構函式初始化風扇引數
Fan(String id, double resistance, int minVoltage, int maxVoltage, int minSpeed, int maxSpeed) {
super(id, resistance);
this.minVoltage = minVoltage;
this.maxVoltage = maxVoltage;
this.minSpeed = minSpeed;
this.maxSpeed = maxSpeed;
}
@Override
void updateState(String command) {
// 風扇的狀態是由電壓差來決定的,不需要在這裡手動更新
}
@Override
String getStatus() {
if (voltageDifference < minVoltage) return "0"; // 停止
if (voltageDifference > maxVoltage) return String.valueOf(maxSpeed); // 達到最大轉速
// 計算轉速比例
double speed = minSpeed + (double) (voltageDifference - minVoltage) / (maxVoltage - minVoltage) * (maxSpeed - minSpeed);
return String.valueOf((int) speed); // 返回整數值
}
}
Bulb 類
class Bulb extends Device {
int maxBrightness; // 最大亮度
// 建構函式初始化燈具引數
Bulb(String id, double resistance, int maxBrightness) {
super(id, resistance);
this.maxBrightness = maxBrightness;
}
@Override
void updateState(String command) {
// 燈具的狀態由電壓差來決定,不需要手動更新
}
@Override
String getStatus() {
if (voltageDifference == 0) return "0"; // 燈滅
double brightness = (double) voltageDifference / 220 * maxBrightness;
return String.valueOf((int) brightness); // 亮度按比例計算
}
}
Circuit 類
class Circuit {
Map<String, Device> devices = new LinkedHashMap<>();
Map<String, List
// 新增裝置到電路中
void addDevice(Device device) {
devices.put(device.id, device);
}
// 連線裝置的引腳
void addConnection(String pin1, String pin2) {
connections.computeIfAbsent(pin1, k -> new ArrayList<>()).add(pin2);
connections.computeIfAbsent(pin2, k -> new ArrayList<>()).add(pin1);
}
// 根據命令更新裝置的狀態
void updateDevice(String command) {
String id = command.substring(1, 3); // 提取裝置ID
Device device = devices.get(id);
if (device != null) {
device.updateState(command);
}
}
// 類比電路的工作
void simulate() {
// 假設電源電壓為220V
for (Device device : devices.values()) {
device.setVoltageDifference(220); // 給所有裝置設定電壓差為220V
}
}
// 輸出所有裝置的狀態
void outputStatus() {
for (Device device : devices.values()) {
System.out.println("@" + device.id + ":" + device.getStatus());
}
}
}
Main 類
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Circuit circuit = new Circuit();
// 讀取輸入並進行處理
while (scanner.hasNextLine()) {
String input = scanner.nextLine().trim();
if (input.equals("end")) break; // 結束輸入
if (input.startsWith("#")) {
// 處理控制命令,如#K1,#F1+等
circuit.updateDevice(input);
} else if (input.startsWith("[")) {
// 處理連線資訊,如:[K1-1 K2-2]
String[] pins = input.substring(1, input.length() - 1).split(" ");
circuit.addConnection(pins[0], pins[1]);
} else if (input.contains(":")) {
// 處理裝置定義,如:K1:0
String[] parts = input.split(":");
if (parts[0].startsWith("K")) {
circuit.addDevice(new Switch(parts[0]));
} else if (parts[0].startsWith("D")) {
circuit.addDevice(new Bulb(parts[0], 10, 200)); // 示例:白熾燈
} else if (parts[0].startsWith("A")) {
circuit.addDevice(new Fan(parts[0], 20, 80, 150, 80, 360)); // 示例:吊扇
}
}
}
// 類比電路並輸出裝置狀態
circuit.simulate();
circuit.outputStatus();
}
}
設計類圖:
順序圖:
題目集6:複雜電路模擬
在這個題目集中,我們在題目集5的基礎上增加了並聯電路的處理。系統的主要功能包括處理複雜的電路連線關係、更精細的裝置操作邏輯、電路分析相關功能的強化等。以下是主要類和方法的介紹:
Device 類
抽象類,表示電路中的基本裝置。
包含裝置ID、電阻值和電壓差屬性。
抽象方法 updateState 和 getStatus 由子類實現。
Switch 類
繼承自 Device,表示開關裝置。
屬性 isClosed 表示開關狀態(關閉時為 true)。
方法 updateState 切換開關狀態。
方法 getStatus 返回開關的當前狀態。
Fan 類
繼承自 Device,表示風扇裝置。
屬性 minVoltage, maxVoltage, minSpeed, maxSpeed 表示風扇的工作電壓範圍和轉速範圍。
方法 updateState 不需要手動更新狀態。
方法 getStatus 根據電壓差計算風扇的轉速並返回。
Bulb 類
繼承自 Device,表示燈具裝置。
屬性 maxBrightness 表示最大亮度。
方法 updateState 不需要手動更新狀態。
方法 getStatus 根據電壓差計算燈具的亮度並返回。
Circuit 類
管理裝置和連線資訊,提供方法來更新裝置狀態和類比電路。
方法 addDevice 新增裝置到電路中。
方法 addConnection 連線裝置的引腳。
方法 updateDevice 根據命令更新裝置的狀態。
方法 simulate 類比電路的工作。
方法 outputStatus 輸出所有裝置的狀態。
主要程式碼示例:
abstract class Device {
String id; // 裝置識別符號
double resistance; // 電阻值
int voltageDifference; // 引腳間的電壓差
Device(String id, double resistance) {
this.id = id;
this.resistance = resistance;
this.voltageDifference = 0; // 預設電壓差為0
}
abstract void updateState(String command);
abstract String getStatus();
void setVoltageDifference(int voltage) {
this.voltageDifference = voltage;
}
}
class Switch extends Device {
boolean isClosed; // 開關狀態(關閉時為true)
Switch(String id) {
super(id, 0); // 開關的電阻是0
this.isClosed = false; // 預設狀態為“開啟”
}
@Override
void updateState(String command) {
isClosed = !isClosed; // 每次切換開關狀態
}
@Override
String getStatus() {
return isClosed ? "closed" : "turned on";
}
}
class Fan extends Device {
int minVoltage, maxVoltage; // 風扇工作電壓範圍
int minSpeed, maxSpeed; // 風扇轉速範圍
Fan(String id, double resistance, int minVoltage, int maxVoltage, int minSpeed, int maxSpeed) {
super(id, resistance);
this.minVoltage = minVoltage;
this.maxVoltage = maxVoltage;
this.minSpeed = minSpeed;
this.maxSpeed = maxSpeed;
}
@Override
void updateState(String command) {
// 風扇的狀態是由電壓差來決定的,不需要在這裡手動更新
}
@Override
String getStatus() {
if (voltageDifference < minVoltage) return "0"; // 停止
if (voltageDifference > maxVoltage) return String.valueOf(maxSpeed); // 達到最大轉速
double speed = minSpeed + (double) (voltageDifference - minVoltage) / (maxVoltage - minVoltage) * (maxSpeed - minSpeed);
return String.valueOf((int) speed); // 返回整數值
}
}
class Bulb extends Device {
int maxBrightness; // 最大亮度
Bulb(String id, double resistance, int maxBrightness) {
super(id, resistance);
this.maxBrightness = maxBrightness;
}
@Override
void updateState(String command) {
// 燈具的狀態由電壓差來決定,不需要手動更新
}
@Override
String getStatus() {
if (voltageDifference == 0) return "0"; // 燈滅
double brightness = (double) voltageDifference / 220 * maxBrightness;
return String.valueOf((int) brightness); // 亮度按比例計算
}
}
class Circuit {
Map<String, Device> devices = new LinkedHashMap<>();
Map<String, List
void addDevice(Device device) {
devices.put(device.id, device);
}
void addConnection(String pin1, String pin2) {
connections.computeIfAbsent(pin1, k -> new ArrayList<>()).add(pin2);
connections.computeIfAbsent(pin2, k -> new ArrayList<>()).add(pin1);
}
void updateDevice(String command) {
String id = command.substring(1, 3); // 提取裝置ID
Device device = devices.get(id);
if (device != null) {
device.updateState(command);
}
}
void simulate() {
for (Device device : devices.values()) {
device.setVoltageDifference(220); // 給所有裝置設定電壓差為220V
}
}
void outputStatus() {
for (Device device : devices.values()) {
System.out.println("@" + device.id + ":" + device.getStatus());
}
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Circuit circuit = new Circuit();
while (scanner.hasNextLine()) {
String input = scanner.nextLine().trim();
if (input.equals("end")) break; // 結束輸入
if (input.startsWith("#")) {
circuit.updateDevice(input);
} else if (input.startsWith("[")) {
String[] pins = input.substring(1, input.length() - 1).split(" ");
circuit.addConnection(pins[0], pins[1]);
} else if (input.contains(":")) {
String[] parts = input.split(":");
if (parts[0].startsWith("K")) {
circuit.addDevice(new Switch(parts[0]));
} else if (parts[0].startsWith("D")) {
circuit.addDevice(new Bulb(parts[0], 10, 200)); // 示例:白熾燈
} else if (parts[0].startsWith("A")) {
circuit.addDevice(new Fan(parts[0], 20, 80, 150, 80, 360)); // 示例:吊扇
}
}
}
circuit.simulate();
circuit.outputStatus();
}
}
設計類圖:
順序圖:
三、踩坑心得
在完成題目集4至6的過程中,我積累了豐富的經驗和教訓,這些經驗教訓不僅幫助我順利完成了任務,也為我後續的學習和工作打下了堅實的基礎。
題目集4
正規表示式的複雜性與可維護性
在處理輸入資料時,我最初嘗試使用非常複雜的正規表示式來確保輸入的格式正確。然而,這種做法很快就暴露出了問題。複雜的正規表示式不僅難以編寫,而且一旦出現錯誤,除錯起來也非常困難。為了解決這個問題,我採取了以下措施:
簡化正規表示式:將複雜的正規表示式拆分成多個簡單的表示式,每個表示式只處理一部分輸入格式。這樣做不僅使程式碼更易讀,也更容易除錯和維護。
增加條件判斷:在正規表示式匹配的基礎上,增加了更多的條件判斷,以確保輸入資料的合法性。例如,檢查輸入的數字是否在合理範圍內,檢查字串是否符合預期的格式等。
輸入資料的錯誤處理
在處理使用者輸入時,經常會遇到各種意外情況,如格式錯誤、缺失欄位等。為了提高程式的健壯性,我採用了以下策略:
異常處理:使用 try-catch 塊來捕獲和處理輸入中的異常情況。這樣可以避免程式因輸入錯誤而崩潰,同時也能給使用者提供明確的錯誤提示。
錯誤資訊記錄:使用 StringBuilder 來收集和記錄所有的錯誤資訊,最後一次性輸出給使用者。這樣做不僅提高了使用者體驗,也方便了除錯。
題目集5和6
電路原理的理解
在進行電路模擬時,我最初對電路原理的理解不夠深入,導致在計算電壓傳遞和電流分配時出現了很多錯誤。為了解決這個問題,我採取了以下措施:
查閱資料:透過查閱電路原理相關的書籍和線上資源,加深了對電路基礎知識的理解。
反覆試驗:透過編寫測試用例,反覆試驗不同的電路配置,逐步修正演算法中的錯誤。
程式碼重構:在理解電路原理的基礎上,對程式碼進行了重構,使其更加清晰和高效。例如,將電壓傳遞和電流分配的計算邏輯分離出來,放在獨立的方法中,便於管理和維護。
異常處理
在處理複雜的電路網路時,輸入錯誤和未知裝置型別是常見的問題。為了優雅地處理這些問題,我採用了以下策略:
輸入驗證:在接收使用者輸入時,首先進行嚴格的格式驗證,確保輸入資料的合法性。
裝置型別檢查:在建立裝置物件時,檢查裝置型別是否合法。如果裝置型別未知,則丟擲異常並給出明確的錯誤提示。
異常捕獲:在關鍵的計算邏輯中,使用 try-catch 塊來捕獲可能發生的異常,確保程式不會因為某個錯誤而完全停止執行。
四、總結
透過完成題目集4至6,我在程式設計技能和問題解決能力方面取得了顯著的進步。以下是我在整個學習過程中的幾點體會和收穫:
基礎知識的重要性:無論是資料處理還是電路模擬,紮實的基礎知識都是解決問題的關鍵。在遇到難題時,迴歸基礎往往能找到突破口。
程式碼的可維護性:編寫可維護的程式碼不僅有助於自己未來的開發工作,也能方便他人理解和修改。透過模組化和複用性設計,可以使程式碼更加清晰和高效。
除錯技巧:除錯是程式設計中不可或缺的一部分。學會使用除錯工具和編寫測試用例,可以大大提高開發效率,減少錯誤的發生。
團隊合作:在學習過程中,與其他同學交流和合作是非常重要的。透過討論和分享,可以互相啟發,共同進步。
持續學習:技術是不斷髮展的,只有保持持續學習的態度,才能跟上時代的步伐。無論是閱讀最新的技術文章,還是參加線上課程,都是提升自己的有效途徑。
五、對教師和課程的建議
增加實際案例:在課程中增加更多實際案例的講解,幫助學生更好地將理論知識應用於實踐中。實際案例可以來自真實世界的問題,也可以是經典的程式設計挑戰。
定期舉辦程式設計比賽:透過舉辦程式設計比賽或專案展示活動,激發學生的學習興趣,促進同學間的交流和合作。比賽可以設定不同的難度級別,適合不同水平的學生參與。
提供更多資源:提供更多的學習資源,如參考書籍、線上教程和開源專案,幫助學生在課後繼續學習和探索。
鼓勵創新思維:在教學過程中,鼓勵學生髮揮創新思維,提出獨特的解決方案。可以透過小組討論、頭腦風暴等方式,培養學生的創造力和批判性思維。
透過以上總結和建議,希望未來的學習和教學能夠更加高效和有趣。。可以透過小組討論、頭腦風暴等方式,培養學生的創造力和批判性思維。