目录

前言

PTA第四次大作业总结

PTA第五次大作业总结

PTA第六次大作业总结

设计与分析

PTA第四次大作业的设计与分析

PTA第五次大作业的设计与分析

PTA第六次大作业的设计与分析

采坑心得

改进建议

总结

前言
第四次大作业相较于第三次大作业,并没有新增较多的内容,按照之前的设计就能较为轻松地做出来;而在第二次迭代--家庭电路中,涉及到继承和接口的使用,所以我们需要进行更加精细的设计,以便于能够更加轻松地进行后续功能的扩展,接下来是我对这几次大作业的总结。

PTA第四次大作业总结

1.该题目所涉及到的知识点:
正则表达式的使用、HashMap与LinkedList及其API的使用、继承与多态。

2.总结:
相较于第三次大作业,第四次大作业除了增加了两种新题型外,还会输入多张试卷信息并且需要我们按照学号顺序输出结果。总体来说,输入和输出流程整体上和第三次大作业基本类似,我们只需在上次大作业的框架中,进行一些修改即可,所以整体来说比较简单。

PTA第五次大作业总结

1.题目所涉及到的知识点:
正则表达式的使用、HashMap与LinkedList及其API的使用、继承与多态、抽象类与接口以及设计模式。

2.总结:
第五次大作业作为一个新迭代的开始,要求我们设计一个家庭强电电路的模拟程序,其中包括许多生活中常见的设备对象比如开关与白炽灯以及各种串并联电路等,我们要合理根据题目的要求,设计好类和接口,为后续几次迭代的拓展作准备。由于是第一次迭代,所以基础内容较为简单,我的大部分时间都花在了整体类和框架的设计上面。

PTA第六次大作业总结

1.题目所涉及到的知识点:和上次大作业类似,涉及到了正则表达式的使用、HashMap与LinkedList及其API的使用、继承与多态、抽象类与接口以及设计模式。除此之外,我们还需要掌握串并联电路的特性。

2.总结:
第六次大作业相较于上次大作业,改变了输入的格式,增加了并联电路以及落地扇设备斌且设备也有了电阻属性。由于设备是更具电阻来判断分压,我发现上次使用的根据引脚的电位计算电压的方式无法奏效,于是我设计的新的根据电流计算电压的算法。本次大作业相较上次,难度有所提升。

PTA第四次大作业的设计与分析

1、题目分析与类的设计

本程序旨在模拟一个小型测试系统,支持题目信息、试卷信息、学生信息、答题信息及删除题目信息的输入处理,并能根据输入的题目信息中的标准答案自动判断答题结果,输出详细的判题和评分信息。相较于上次迭代,这次大作业添加了许多内容:(1)增加了新题型的输入:增加了两种题型,填空和多选题,并且该类题型可以出现回答部分正确的情况,部分正确时,可以得到一半的分数。(2)输入顺序的变化:只要是正确格式的信息,可以以任意的先后顺序输入各类不同的信息。比如试卷可以出现在题目之前,删除题目的信息可以出现在题目之前等。(3)题目会输入多张试卷信息,输出时先按照学号再按照试卷号排序。根据题目信息,我们可以在上次大作业的基础上加上两个类:多选题类和填空题类,这两个类继承题目类,并且在类中实现判断正确性的方法。

2、类图

如图,我在第三次大作业的基础上加上了多选和填空类继承题目类。

3、部分流程分析

输入流程

如图,我们先一行一行地接收信息,通过正则表达式判断是否为正确输入格式,如果不是,就进入错误处理的函数中,如果输入为正确格式,则获取对应的信息,通过匹配#后面的字母,判断是试卷、答卷还是学生信息,并进入对应的处理中。

输出流程

如图,在输出过程中,我们首先遍历试卷集合,判断出总分是否为100分,若没有100分,则输出"alert: full score of test paper"+试卷号+" is not 100 points";之后在对答卷进行排序后对答卷集合进行遍历:首先通过"testpapers.containsKey(ASid)"判断试卷集合中是否有对应的答卷id,若没有则输出"The test paper number does not exist";若有则我们根据id取出对应的试卷,对试卷中的题目进行遍历:先通过题目id判断对应答卷中是否有对应的答案,再判断题目是否存在,最后判断题目是否被删除,若没有出现这三种错误的情况,则进行算分操作;最后判断学生是否存在,若存在,就按照格式输出对应信息。

PTA第二次大作业的设计与分析

1、题目分析与类的设计
该题目要求我们设计一个智能家居强电电路模拟系统,其中要求我们能够实现:(1)控制设备模拟,可以通过控制开关、分档调速器、连续调速器来控制电路的状态。(2)受控设备模拟,要求我们能够根据电压来计算出受控设备的状态,受控设备包括白炽灯、日光灯、吊扇。(3)设备信息的输入,分别用设备标识符K、F、L、B、R、D分别表示开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇,引脚格式:设备标识-引脚编号,例如:K1-1标识编号为1的开关的输入引脚。根据题目分析,我们可以设计一个device类,是所有设备的父类,其成员有输入电压、输出电压、设备id,定义了两个抽象方法:更新电压updateVoltage(double voltageIn)、获取设备状态getStatus()。设计了受控设备类以及控制设备类,而开关类、调速器类继承控制设备类,日光灯、吊扇和白炽灯继承了受控设备类。通过设计Circuit电路类,来进行电路的控制,电路类中有成员Map<String, Device> devices存储电路中的设备信息;List commands存储控制命令的信息;Map<String, String> links来存储引脚的连接关系。通过Circuit类中的各种方法来完成对电路的管理。

2、类图

如图,我们设计了一个device类,是所有设备的父类,其成员有输入电压、输出电压、设备id,定义了两个抽象方法:更新电压updateVoltage(double voltageIn)、获取设备状态getStatus()。设计了受控设备类以及控制设备类,而开关类、调速器类继承控制设备类,日光灯、吊扇和白炽灯继承了受控设备类。通过设计Circuit电路类,来进行电路的控制,电路类中有成员Map<String, Device> devices存储电路中的设备信息;List commands存储控制命令的信息;Map<String, String> links来存储引脚的连接关系。通过Circuit类中的addDevice()来通过输入添加设备,通过addCommand()来存控制操作,addConnectioins来存储连接;processConnectoins来处理连接,通过processCommanad来处理控制命令,通过updateVoltage来处理更新各个设备的状态和电压。

3、部分流程分析

输入流程

如图,我一行一行地读取输入的数据知道读到“end”,当读入数据是以“[”开头时,表示输入的是连接关系,所以调用addConnections的方法来添加设备和连接;如果不是以“[”开头,说明输入的是对控制设备进行的操作,所以调用addCommand方法进行处理。

处理连接流程
代码如下

点击查看代码
public void processConnections() {
        for (String[] connection : connections) {
            if(connection[0].equals("VCC"))
            {
                links.put(connection[0], connection[1]);
                String deviceId = connection[1].split("-")[0];
                if(!devices.containsKey(deviceId))
                {
                    addDevice(deviceId);
                }
            }
            else if (connection[1].equals("GND"))
            {
                links.put(connection[0], connection[1]);
                String deviceId = connection[0].split("-")[0];
                if(!devices.containsKey(deviceId))
                {
                    addDevice(deviceId);
                }
            }
            else
            {
                links.put(connection[0], connection[1]);
                String device1Id = connection[0].split("-")[0];
                String device2Id = connection[1].split("-")[0];
                if(!devices.containsKey(device1Id))
                {
                    addDevice(device1Id);
                }
                if(!devices.containsKey(device2Id))
                {
                    addDevice(device2Id);
                }
            }
        }
    }

首先我们遍历连接的集合,当遍历到VCC和GND时,我们不做操作,当遍历到没有添加到设备集合的新设备时,我们就将其加入到设备集合。

计算电压流程
代码如下

点击查看代码
public void UpdateVoltage()
    {
        for(String key : links.keySet())
        {
            if(key.equals("VCC"))
            {
                String str = links.get(key);
                String id = str.split("-")[0];
                String pin = str.split("-")[1];
                if(pin.equals("1"))
                {
                    devices.get(id).updateVoltage(220);
                }
            }
            else if(links.get(key).equals("GND"))
            {
                String id = key.split("-")[0];
                String pin = key.split("-")[1];
                if(pin.equals("2"))
                {
                    devices.get(id).setVoltageOut(0);
                }
            }
            else
            {
                String d1 = key;
                String d2 = links.get(key);
                String id1 = d1.split("-")[0];
                String id2 = d2.split("-")[0];
                String pin1 = d1.split("-")[1];
                String pin2 = d2.split("-")[1];
                if(pin1.equals("1"))
                {
                    devices.get(id1).updateVoltage(devices.get(id2).getVoltageOut());
                }
                else if(pin2.equals("1"))
                {
                    devices.get(id2).updateVoltage(devices.get(id1).getVoltageOut());
                }
            }
        }
    }
我们遍历连接集合,当遍历到VCC时,我们将220v作为与VCC相连设备的输入电压;当遍历到GND时,我们将GND作为相连设备的输出电压;当遍历到设备与设备相连时,我们把前一个设备的输出电压作为后一个设备的输入电压,通过计算设备的输入电压和输出电压的电压差作为设备的电压。

输出流程

输出流程较为简单,当我们处理完连接和命令后,更新设备电压,之后再对设备按照设备号进行排序,最后再遍历设备集合调用设备的printStatus的方法,输出设备的状态。

PTA第六次大作业的设计与分析

1、题目分析与类的设计

相较于上一次大作业,这次大作业添加了许多内容:(1)受控设备有了电阻的属性,我们要通过电阻的分压关系来判断受控设备的电压值。(2)输入的改变,输入的信息可以分为三种:串联电路信息、并联电路信息和对控制设备的操作。(3)添加了新的设备落地扇。 虽然看上去没有新添很多内容,但是由于会出现并联电路和串联电路的组合,所以用之前的通过电位差来计算电压的方法并不适用,所以我更改了设计,我决定通过电阻和电流来计算电压。除此之外,我还优化了之前类的设计,我首先在Device类中增加了新的成员电阻和电流,在控制设备类中新增了一个抽象方法Control()用于对控制设备的操控;设计了串联电路SeriesCircuit继承Device类,其中成员有存储连接关系的Map<String, String> connections和存储设备的Map<String, Device> devices,通过方法total_resistance()来计算串联电路的总阻值;设计了并联电路类ParallelCircuit继承Device类,其中成员有存储串联电路的List circuits,也有计算电压和总电阻的方法。

2、类图

如图,和上次大作业相比在Device类中增加了新的成员电阻和电流,在控制设备类中新增了一个抽象方法Control()用于对控制设备的操控;设计了串联电路SeriesCircuit继承Device类,其中成员有存储连接关系的Map<String, String> connections和存储设备的Map<String, Device> devices,通过方法total_resistance()来计算串联电路的总阻值;设计了并联电路类ParallelCircuit继承Device类,其中成员有存储串联电路的List circuits,也有计算电压和总电阻的方法。

3、部分流程分析
由于输入和输出的流程和上一次大作业类似,我就不再展示了。

计算电压
为了更好的理解,我先解释一下我是如何存储连接关系的,假如输入为:#T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT M2-IN] [M2-OUT OUT] ;则存储的连接关系为:IN->K1-1,K1-1->IN,K1-2->T2-IN,T2-1->K1-2,T2-2->M2-IN,M2-1->T2-OUT,M2-2->OUT,OUT->M2-OUT。(并联电路也作为设备存储进了设备表中)

如图为计算设备电压的详细流程。

踩坑心得

1.第五次大作业中,要考虑开关放在受控设备后的情况,我在处理连接关系时,只考虑到开关放在受控设备之前的情况,导致无法通过一些测试点。

2.第六次大作业中,在读取串联电路的输入设备时,要将并联电路看作一个设备存入串联电路的设备集合中。

3.第六次大作业中,分档调速器可以有第四档,而之前只有三档,要记得修改判断条件。

4.第六次大作业中,当开关闭合时,电阻为应该设置为0,当开关断开时,电阻应该设置为无限大而不是0。

5.在第六此大作业中,要注意浮点数的精度问题,之前一直有两个测试点过不了,最后提高电阻的精度之后就能通过。

改进建议

1.要养成多谢注释的习惯,在写此次博客的时候我回顾了这几次大作业的代码,发现注释寥寥无几,导致我阅读代码有些困难。

2.代码中变量命名要规范,我吸取了第四次大作业的教训,在之后的大作业中尽量规范命名,之后发现读代码时会更加流畅。

3.可以将一些抽象函数替换为接口,提高程序的可拓展性和维护性。比如我的Controller类中的Control抽象方法,可以换成接口,后续的类就不用继承Controller类了,直接实现该接口即可。

4.要注意类的单一职责原则,我在有些类中放了冗余的方法,这一点需要修改。

5.减少if-else语句的使用,尽量用其他办法来替代,比如用switch-case语句替代。

总结

通过这三次大作业的练习,我深刻地认识到了在java中进行设计的重要性,也体会到了设计合理的类结构和继承、封装、多态的使用对于代码的迭代能提供多大的便利。我发现自己在进行类的设计时还存在许多不足之处,比如无法遵循单一职责、继承关系设计不合理等,在之后的大作业中应该要避免;除此之外,我应该多对于老师上课将的模式设计进行实践,比如在第五和第六次大作业中,我就可以使用组合模式的设计,这样可以提高代码的可拓展性。总体而言,通过这三次大作业,我收获了许多相关的知识,比如类的继承与多态、Map的相关API的使用等,在之后的学习中,我将继续精进自己,争取能够取得更大的进步。