22207320-王攀-Blog2

天意不可违123發表於2024-11-23

題目集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> connections = new HashMap<>();

// 新增裝置到電路中
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> connections = new HashMap<>();

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,我在程式設計技能和問題解決能力方面取得了顯著的進步。以下是我在整個學習過程中的幾點體會和收穫:

基礎知識的重要性:無論是資料處理還是電路模擬,紮實的基礎知識都是解決問題的關鍵。在遇到難題時,迴歸基礎往往能找到突破口。
程式碼的可維護性:編寫可維護的程式碼不僅有助於自己未來的開發工作,也能方便他人理解和修改。透過模組化和複用性設計,可以使程式碼更加清晰和高效。
除錯技巧:除錯是程式設計中不可或缺的一部分。學會使用除錯工具和編寫測試用例,可以大大提高開發效率,減少錯誤的發生。
團隊合作:在學習過程中,與其他同學交流和合作是非常重要的。透過討論和分享,可以互相啟發,共同進步。
持續學習:技術是不斷髮展的,只有保持持續學習的態度,才能跟上時代的步伐。無論是閱讀最新的技術文章,還是參加線上課程,都是提升自己的有效途徑。
五、對教師和課程的建議
增加實際案例:在課程中增加更多實際案例的講解,幫助學生更好地將理論知識應用於實踐中。實際案例可以來自真實世界的問題,也可以是經典的程式設計挑戰。
定期舉辦程式設計比賽:透過舉辦程式設計比賽或專案展示活動,激發學生的學習興趣,促進同學間的交流和合作。比賽可以設定不同的難度級別,適合不同水平的學生參與。
提供更多資源:提供更多的學習資源,如參考書籍、線上教程和開源專案,幫助學生在課後繼續學習和探索。
鼓勵創新思維:在教學過程中,鼓勵學生髮揮創新思維,提出獨特的解決方案。可以透過小組討論、頭腦風暴等方式,培養學生的創造力和批判性思維。
透過以上總結和建議,希望未來的學習和教學能夠更加高效和有趣。。可以透過小組討論、頭腦風暴等方式,培養學生的創造力和批判性思維。

相關文章