yangjiaobaoza

博客园 首页 新随笔 联系 订阅 管理
  3 随笔 :: 0 文章 :: 0 评论 :: 201 阅读

第三次博客作业

一、前言

第一次作业

第一次作业有一道题,即在前一次家居电路模拟程序的基础上进行迭代。添加了一种受控窗帘,线路中包含多个串联起来的并联电路,难度较大。

第二次作业

第二次作业有一道题,即在前一次家居电路模拟程序的基础上进行更进一步的迭代。添加了二极管元件,增加了管脚电压的显示、电流限制和短路检测,线路中包含多个串联起来的并联电路,并联电路中也可以包含并联,难度极大。

二、设计与分析

第一次作业

SourceMontor报表

image
image
image
12.9% 的代码行包含注释,没有特别指出类和接口的注释比例。

平均每个类有 3.67 个方法,每个方法平均有 6.03 条语句,方法的平均复杂度目标没有特别指出。最大块深度为 7(指代码块嵌套的层数);平均块深度为 2.85;平均复杂度为 1.82(指方法中不同路径的数量,较高的复杂度可能意味着方法难以测试和维护)表明代码的复杂度控制得相对较好。

最复杂的方法是 Circuit.calculateVoltages(),位于第 210 行。这可能表明 Circuit.calculateVoltages() 方法过于复杂,需要进一步的分解或重构或者需要拆分;其复杂度为 9,包含 16 条语句,最大深度为 7,调用了 14 次方法调用。这表明 Circuit.calculateVoltages() 方法可能需要进一步的优化。

类图

image
ControlDevice 类:
包含两个成员变量 id、inputVoltage 和 outputVoltage,表示控制设备的标识符、输入电压和输出电压。
包含一个构造方法,用于初始化控制设备的标识符。
包含一个抽象方法 updateOutputVoltage,用于更新设备的输出电压。
包含一个抽象方法 getStatus,用于获取设备的当前状态。

Switch 类:
包含一个成员变量 isClosed,表示开关的当前状态。
包含一个构造方法,用于初始化开关的标识符。
包含一个方法 toggle,用于切换开关的状态。
继承并实现 updateOutputVoltage 方法,根据开关状态更新输出电压。
继承并实现 getStatus 方法,返回开关的当前状态。

StepSpeedController 类:
包含一个成员变量 level,表示分档调速器的当前档位。
包含一个构造方法,用于初始化调速器的标识符。
包含两个方法 incrementLevel 和 decrementLevel,用于调整档位。
继承并实现 updateOutputVoltage 方法,根据档位更新输出电压。
继承并实现 getStatus 方法,返回调速器的当前档位。

ContinuousSpeedController 类:
包含一个成员变量 position,表示连续调速器的当前位置参数。
包含一个构造方法,用于初始化调速器的标识符。
包含一个方法 setPosition,用于设置调速器的位置参数。
继承并实现 updateOutputVoltage 方法,根据位置参数更新输出电压。
继承并实现 getStatus 方法,返回调速器的当前位置参数。

ControlledDevice 类:
包含两个成员变量 id、inputVoltage 和 outputVoltage,表示受控设备的标识符、输入电压和输出电压。
包含一个构造方法,用于初始化受控设备的标识符。
包含一个抽象方法 updateOutputVoltage,用于更新设备的输出电压。
包含一个抽象方法 getStatus,用于获取设备的当前状态。

IncandescentLamp 类:
包含一个构造方法,用于初始化白炽灯的标识符。
包含一个方法 calculateBrightness,用于计算灯具的亮度。
继承并实现 updateOutputVoltage 方法,白炽灯不需要更新输出电压。
继承并实现 getStatus 方法,返回灯具的亮度。

FluorescentLamp 类:
包含一个构造方法,用于初始化日光灯的标识符。
包含一个方法 calculateBrightness,用于计算灯具的亮度。
继承并实现 updateOutputVoltage 方法,日光灯不需要更新输出电压。
继承并实现 getStatus 方法,返回灯具的亮度。

CeilingFan 类:
包含一个构造方法,用于初始化吊扇的标识符。
包含一个方法 calculateSpeed,用于计算风扇的转速。
继承并实现 updateOutputVoltage 方法,吊扇不需要更新输出电压。
继承并实现 getStatus 方法,返回风扇的转速。

Circuit 类:
包含三个成员变量 controlDevices、controlledDevices 和 connections,分别存储控制设备、受控设备和设备间的连接关系。
包含三个方法 addControlDevice、addControlledDevice 和 connectDevices,用于添加控制设备、受控设备和连接设备。
包含一个方法 processCommand,用于处理控制命令。
包含一个方法 calculateVoltages,用于计算电路中所有设备的电压。
包含一个方法 outputStates,用于输出所有设备的状态。

Main 类:
包含 main 方法,是程序的入口点,负责读取输入并模拟电路系统的操作。
在 main 方法中,使用 Circuit 对象来管理电路中的所有设备和连接。
处理输入数据,创建相应的设备对象,连接设备,并处理控制命令。
最后,计算电路中的电压并输出所有设备的状态。

第二次作业

SourceMontor报表

image
image
image
13.1% 的代码行包含注释,没有特别指出类和接口的注释比例。

平均每个类有 4.78 个方法,每个方法平均有 5.42 条语句,方法的平均复杂度目标没有特别指出。最大块深度为 7(指代码块嵌套的层数);平均块深度为 2.23;平均复杂度为 1.57(指方法中不同路径的数量,较高的复杂度可能意味着方法难以测试和维护)表明代码的复杂度控制得相对较好。

最复杂的方法是 Circuit.processCommand(),位于第 282 行。这可能表明 Circuit.processCommand() 方法过于复杂,需要进一步的分解或重构或者需要拆分;其复杂度为 9,包含 23 条语句,最大深度为 4,调用了 19 次方法调用。这表明 Circuit.processCommand() 方法可能需要进一步的优化。

类图

image
ControlDevice 类:
包含三个成员变量:设备标识符 id,输入电压 inputVoltage,输出电压 outputVoltage。
包含一个构造方法,用于初始化设备标识符。
包含两个抽象方法:updateOutputVoltage 用于更新设备的输出电压,getStatus 用于获取设备的当前状态。

点击查看代码
// 控制设备的父类
abstract class ControlDevice {
    String id; // 设备标识符
    double inputVoltage = 0; // 输入电压
    double outputVoltage = 0; // 输出电压

    ControlDevice(String id) {
        this.id = id;
    }

    // 更新输出电压的抽象方法,具体实现由子类完成
    abstract void updateOutputVoltage();

    // 获取设备状态的抽象方法,具体实现由子类完成
    abstract String getStatus();
}

Switch 类:
包含一个成员变量 isClosed,表示开关的开闭状态。
包含一个构造方法,用于初始化开关的标识符。
包含一个方法 toggle,用于切换开关的状态。
重写 updateOutputVoltage 方法,根据开关状态更新输出电压。
重写 getStatus 方法,返回开关的当前状态。

点击查看代码
// 开关类,继承自 ControlDevice
class Switch extends ControlDevice {
    boolean isClosed = false; // 初始状态为打开

    Switch(String id) {
        super(id);
    }

    // 切换开关状态
    void toggle() {
        isClosed = !isClosed;
    }

    @Override
    void updateOutputVoltage() {
        // 开关闭合时输出电压等于输入电压,否则为0
        outputVoltage = isClosed ? inputVoltage : 0;
    }

    @Override
    String getStatus() {
        return "@" + id + ":" + (isClosed ? "closed" : "turned on");
    }
}

StepSpeedController 类:
包含一个成员变量 level,表示分档调速器的档位。
包含一个构造方法,用于初始化调速器的标识符。
包含两个方法 incrementLevel 和 decrementLevel,用于调整档位。
重写 updateOutputVoltage 方法,根据档位更新输出电压。
重写 getStatus 方法,返回调速器的当前档位。

点击查看代码
// 分档调速器类,继承自 ControlDevice
class StepSpeedController extends ControlDevice {
    int level = 0; // 初始档位为0

    StepSpeedController(String id) {
        super(id);
    }

    // 增加档位
    void incrementLevel() {
        if (level < 3) level++;
    }

    // 减少档位
    void decrementLevel() {
        if (level > 0) level--;
    }

    @Override
    void updateOutputVoltage() {
        // 根据档位调整输出电压
        double[] factors = {0, 0.3, 0.6, 0.9};
        outputVoltage = inputVoltage * factors[level];
    }

    @Override
    String getStatus() {
        return "@" + id + ":" + level;
    }
}

ContinuousSpeedController 类:
包含一个成员变量 position,表示连续调速器的位置参数。
包含一个构造方法,用于初始化调速器的标识符。
包含一个方法 setPosition,用于设置调速器的位置参数。
重写 updateOutputVoltage 方法,根据位置参数更新输出电压。
重写 getStatus 方法,返回调速器的当前位置参数。

点击查看代码
// 连续调速器类,继承自 ControlDevice
class ContinuousSpeedController extends ControlDevice {
    double position = 0.00; // 初始档位参数为0.00

    ContinuousSpeedController(String id) {
        super(id);
    }

    // 设置档位参数
    void setPosition(double position) {
        this.position = position;
    }

    @Override
    void updateOutputVoltage() {
        outputVoltage = inputVoltage * position;
    }

    @Override
    String getStatus() {
        return String.format("@%s:%.2f", id, position);
    }
}

ControlledDevice 类:
包含三个成员变量:设备标识符 id,输入电压 inputVoltage,输出电压 outputVoltage。
包含一个构造方法,用于初始化设备标识符。
包含两个抽象方法:updateOutputVoltage 用于更新设备的输出电压,getStatus 用于获取设备的当前状态。

点击查看代码
// 受控设备父类
abstract class ControlledDevice {
    String id; // 设备标识符
    double inputVoltage = 0; // 输入电压
    double outputVoltage = 0; // 输出电压

    ControlledDevice(String id) {
        this.id = id;
    }

    // 更新输出电压的方法,具体实现由子类完成
    abstract void updateOutputVoltage();

    // 获取设备状态的方法,具体实现由子类完成
    abstract String getStatus();
}

IncandescentLamp 类:
包含一个构造方法,用于初始化白炽灯的标识符。
包含一个方法 calculateBrightness,用于计算灯具的亮度。
重写 updateOutputVoltage 方法,白炽灯不需要更新输出电压。
重写 getStatus 方法,返回灯具的亮度。

点击查看代码
// 白炽灯类,继承自 ControlledDevice
class IncandescentLamp extends ControlledDevice {
    IncandescentLamp(String id) {
        super(id);
    }

    // 计算亮度
    int calculateBrightness(double voltageDifference) {
		//略
    }

    @Override
    void updateOutputVoltage() {
        // 灯具不需要更新输出电压,依赖电压差
    }

    @Override
    String getStatus() {
        double voltageDifference = Math.abs(inputVoltage - outputVoltage);
        return "@" + id + ":" + calculateBrightness(voltageDifference);
    }
}

FluorescentLamp 类:
包含一个构造方法,用于初始化日光灯的标识符。
包含一个方法 calculateBrightness,用于计算灯具的亮度。
重写 updateOutputVoltage 方法,日光灯不需要更新输出电压。
重写 getStatus 方法,返回灯具的亮度。

点击查看代码
// 日光灯类,继承自 ControlledDevice
class FluorescentLamp extends ControlledDevice {
    FluorescentLamp(String id) {
        super(id);
    }

    // 计算亮度
    int calculateBrightness(double voltageDifference) {
		//略
    }

    @Override
    void updateOutputVoltage() {
        // 灯具不需要更新输出电压,依赖电压差
    }

    @Override
    String getStatus() {
        double voltageDifference = Math.abs(inputVoltage - outputVoltage);
        return "@" + id + ":" + calculateBrightness(voltageDifference);
    }
}

CeilingFan 类:
包含一个构造方法,用于初始化吊扇的标识符。
包含一个方法 calculateSpeed,用于计算风扇的转速。
重写 updateOutputVoltage 方法,吊扇不需要更新输出电压。
重写 getStatus 方法,返回风扇的转速。

点击查看代码
// 吊扇类,继承自 ControlledDevice
class CeilingFan extends ControlledDevice {
    CeilingFan(String id) {
        super(id);
    }

    // 计算转速
    int calculateSpeed(double voltageDifference) {
		//略
    }

    @Override
    void updateOutputVoltage() {
        // 风扇不需要更新输出电压,依赖电压差
    }

    @Override
    String getStatus() {
        double voltageDifference = Math.abs(inputVoltage - outputVoltage);
        return "@" + id + ":" + calculateSpeed(voltageDifference);
    }
}

FloorFan 类:
包含一个构造方法,用于初始化落地扇的标识符。
包含一个方法 calculateSpeed,用于计算风扇的转速。
重写 updateOutputVoltage 方法,落地扇不需要更新输出电压。
重写 getStatus 方法,返回风扇的转速。

点击查看代码
// 落地扇类,继承自 ControlledDevice
class FloorFan extends ControlledDevice  {
    FloorFan(String id) {
        super(id);
    }

    // 计算转速
    int calculateSpeed(double voltageDifference) {
		//略
    }

    @Override
    void updateOutputVoltage() {
        // 落地扇不需要更新输出电压,依赖电压差
    }

    @Override
    String getStatus() {
        double voltageDifference = Math.abs(inputVoltage - outputVoltage);
        return "@" + id + ":" + calculateSpeed(voltageDifference);
    }
}

SeriesCircuit 类:
包含两个成员变量:电路标识符 id 和连接列表 connections。
包含一个构造方法,用于初始化电路标识符。
包含一个方法 addConnection,用于添加电路连接。

点击查看代码
// 串联电路类
class SeriesCircuit {
    String id;
    List<String[]> connections = new ArrayList<>();

    SeriesCircuit(String id) {
        this.id = id;
    }

    void addConnection(String[] connection) {
        connections.add(connection);
    }
}

ParallelCircuit 类:
包含两个成员变量:电路标识符 id 和串联电路列表 seriesCircuits。
包含一个构造方法,用于初始化电路标识符。
包含一个方法 addSeriesCircuit,用于添加串联电路。

点击查看代码
// 并联电路类
class ParallelCircuit {
    String id;
    List<SeriesCircuit> seriesCircuits = new ArrayList<>();

    ParallelCircuit(String id) {
        this.id = id;
    }

    void addSeriesCircuit(SeriesCircuit seriesCircuit) {
        seriesCircuits.add(seriesCircuit);
    }
}

Circuit 类:
包含四个成员变量:控制设备映射 controlDevices,受控设备映射 controlledDevices,串联电路映射 seriesCircuits,和并联电路映射 parallelCircuits。
包含四个方法:addControlDevice 添加控制设备,addControlledDevice 添加受控设备,addSeriesCircuit 添加串联电路,addParallelCircuit 添加并联电路。
包含两个方法:processSeriesCircuit 处理串联电路,processParallelCircuit 处理并联电路。
包含一个方法 processCommand,用于处理控制命令。
包含一个方法 calculateVoltages,用于计算电路中所有设备的电压。
包含一个方法 outputStates,用于输出所有设备的状态。

点击查看代码
// 电路类,管理所有设备及连接
class Circuit {
    //添加设备,电路

	//处理命令
    void processSeriesCircuit(String line) {
		//略
    }

    // 计算电压
    void calculateVoltages() {
		//略
    }

    // 输出设备状态
    void outputStates() {
		//略
    }

    // 获取设备类型的排序优先级
    private int getOrder(ControlDevice device) {
		//略
    }
}

Main 类:
包含 main 方法,是程序的入口点,负责读取输入并模拟电路系统的操作。
在 main 方法中,使用 Circuit 对象来管理电路中的所有设备和连接。
处理输入数据,创建相应的设备对象,连接设备,并处理控制命令。
最后,计算电路中的电压并输出所有设备的状态。

三、踩坑与心得

开发过程中,电路的串并联设计是核心部分,它直接关系到整个系统的稳定性和准确性。电路中的串并联不仅涉及到基本的电路理论,还涉及到复杂的逻辑处理和算法实现。在模拟系统中,每个元器件都有最大电流的设置,以防止电器过热和烧坏电路。我首先为每个元器件定义了一个最大电流值,并在电路计算中实时监控电流。当检测到电流超过这个值时,系统会在输出信息中加入“exceeding current limit error”提示。这个功能的实现让我深刻理解了电路保护的重要性,以及如何在软件中模拟这种保护机制。

短路检测是电路模拟中的另一个重要功能。如果电路中出现无穷大的电流,即短路,系统需要能够检测到这种情况并停止所有元器件信息的输出,仅显示“short circuit error”。这个功能的实现需要对电路的连接和电流流向有深入的理解,以及如何快速准确地检测异常情况。我通过模拟电流的流动,检查是否有异常的电流值,从而判断是否发生短路。这个过程需要精确的数学模型和高效的算法支持,以确保系统的响应速度和准确性。

在处理并联电路中包含并联的情况时,我遇到了逻辑上的复杂性。这要求我在设计电路模拟框架时,就需要考虑到电路的多层次结构。并联电路的设计需要考虑到多个电路路径的电流分配和电压分配。在并联电路中,每个分支的电压是相同的,而电流则根据各个分支的电阻进行分配。这种电路结构要求我必须有一个清晰的电路模型,以及能够处理复杂逻辑的编程技巧。

在模拟并联电路中包含并联电路的情况时,我采用了递归算法来处理这种嵌套的并联电路。这种递归算法允许我将复杂的电路结构分解为更小、更易于管理的部分。例如,一个并联电路可以包含多个串联电路,而这些串联电路又可以包含其他的并联电路。通过递归算法,我可以逐层解析这些嵌套的电路结构,计算每个部分的电流和电压,然后将结果合并,以得到整个电路的行为。

在实现递归算法时,我需要特别注意避免无限递归和循环引用的问题。这些问题可能会导致程序陷入无限循环,从而无法得到结果。为了避免这种情况,我为每个电路元素维护了一个状态,记录它是否已经被计算过。如果一个电路元素已经被计算过,我就不会再对其进行递归计算,而是直接使用之前的结果。

此外,我还需要注意电路的连接方式,确保电路的连接是正确的。在电路模拟中,错误的连接可能会导致电路无法正常工作,或者导致短路。我通过检查电路的连接顺序和连接方式,确保每个电路元素都正确地连接到其他电路元素。这需要我对电路的物理特性和连接规则有深入的理解。

在处理并联电路中的电流限制时,我需要考虑到每个电路元素的最大电流限制。在并联电路中,总电流是各个分支电流的总和。因此,我需要确保每个分支的电流都不会超过其最大限制。如果某个分支的电流超过了其最大限制,我就会在输出信息中加入“exceeding current limit error”提示,并停止该分支的电流流动。

在模拟电路的过程中,我还需要注意电路的动态变化。电路的状态可能会随着时间和其他因素的变化而变化,例如开关的开闭、调速器的档位变化等。我需要实时监控这些变化,并更新电路的电流和电压计算。这要求我有一个高效的事件处理机制,能够快速响应电路状态的变化。

四、改进建议及总结

总的来说,这次智能家居强电电路模拟系统的开发之旅让我学到了很多,不仅是技术上的提升,更重要的是对项目管理和用户体验的深刻理解。这些经验将对我未来的项目开发大有裨益。我不仅提升了我的技术能力,也加深了我对电路模拟和系统设计的理解。这些经历不仅提升了我的技术能力,也加深了我对电路模拟和系统设计的理解。这些经验将对我未来的项目开发大有裨益,尤其是在处理复杂系统和异常情况时。通过这些挑战,我学会了如何在软件中模拟真实的电路行为,包括电流限制和短路保护。我也意识到了在设计系统时需要考虑到各种异常情况,并提前规划好应对策略。此外,对于并联电路中包含并联的复杂情况,我学会了如何通过递归和模块化的设计来简化问题。这些经历不仅提升了我的技术能力,也加深了我对电路模拟和系统设计的理解。

五、学期总结

本学期的收获:

1.基础语言语法和编程思想方面。这是最基础也是最重要的收获。通过大量的编程练习,我逐渐熟悉了JAVA的语法规则,更重要的是,我开始理解并习惯用面向对象的思维方式去分析问题和解决问题。这是一种思维模式的转变,它让我能够更加清晰、高效地构建复杂的软件系统。
2.代码设计方面。两个迭代题目,八次PTA大作业,尤其是第一次对试卷题目的设计,让我深刻体会到了良好代码设计的重要性,有一个较好的类设计以及逻辑设计,在迭代时就会比较轻松;同样第二个题目也是因为中途一次没有做好,往后迭代就更加举步维艰。所以,如何设计合理的类层次结构,如何利用抽象类和接口来实现代码的复用和扩展,都非常重要,这些都是我在实践中不断摸索和学习的。我也意识到,写代码不仅仅是实现功能,更重要的是要考虑代码的可读性、可维护性和可扩展性。
3.调试代码方面。编程过程中难免会遇到各种各样的错误,从语法错误到逻辑错误,每一次的调试过程都是一次宝贵的学习机会。我学会了利用IDEA自带的调试工具来定位问题,学会了分析错误信息来寻找解决方案,也学会了通过查阅文、搜索引擎以及AI来获取帮助。

心里想说的话:

PTA作业真的很难,有时候坐在电脑前三四个下午还是没什么分,或者说收效甚微,一度想摆烂不管,努力终有回报一点也不可信。第一个迭代题目还好,起码能够想到一些案例没有提及的情况,但是第二个题目真的很难,中途一次没写好后面就越来越困难,能够把案例提及的情况包含都谢天谢地了。不过在“浪费”的时间里还是(可能?)有一点点收获的,调试代码时,答案和预计答案不符,我就一点一点步入去检查各个方法、各条语句,虽然很费时间,但是能更进一步了解自己的代码,虽然可能只加了三分,多少还是有一点点成就感的或者是一种踏实感(但还是挫败感更多hhhhh我都好久好久没看到过一整列红色的“答案正确”了hh)不知道以后参加工作了会不会有机会更进一步提升吧。

posted on   羊角包砸  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
点击右上角即可分享
微信分享提示