第二次Blog
- 一、前言
- 第四次大作业的答题判题程序-4相对于上一次的迭代难度其实并不大,但是有几个测试点难以想到,在这些测试点上花费了一些时间。
- 第五次大作业的家居强电电路模拟程序-1是新一轮的迭代,正所谓万事开头难,这次的大作业在类的设计以及电路的工作上花费了不少时间去思考,但也并不是很难。
- 第六次大作业的家居强电电路模拟程序-2在1的基础上加入了新的用电器、电流、电阻以及并联电路,也不是很难,但是在一些细节上没有处理好、也没有认真读题,导致虽然设计完了代码但还是debug了很久。
- 二、设计与分析
- 答题判题程序-4的类的设计
![]()
首先根据试题类型的增加,我将Text定义为了父类,有子类单选题Ntext、多选题Ztext、填空题Ktext。其他的类和上一次相比并没有很大改变。 - 家居强电电路模拟程序-1的类的设计
![]()
各种设备类的设计没什么好说的,由于第一次的电路比较比较简单,所以抽象父类device的属性也只有类型type、设备名name和设备的电压voltage。主要是在读取设备时要防止设备的重复创建上思考了一番,老师用的TreeMap我实在理解不了,所以我用了LinkedHashMap键存放设备的名字、值存放设备。通过LinkedHashMap键不重复的特性去掉了重复创建出来的设备。在输出设备的时候先把Map里的值拿出来放在List里,然后通过Comparator接口来实现按顺序输出。
Collection<Device> device=devices.getDecices().values();
List<Device> deviceList=new LinkedList<>(device);
Comparator<Device> deviceComparator = new Comparator<Device>() {
@Override
public int compare(Device device1, Device device2) {
int typeCompare=getTypeOrder(device1.getType())-getTypeOrder(device2.getType());
if (typeCompare != 0) {
return typeCompare;
} else {
return device1.getName().compareTo(device2.getName());
}
}
};
Collections.sort(deviceList, deviceComparator);
for (Device i : deviceList) {
i.show();
}
下面是getTypeOrder()方法的实现
private static int getTypeOrder(char type) {
switch (type) {
case 'K':
return 0;
case 'F':
return 1;
case 'L':
return 2;
case 'B':
return 3;
case 'R':
return 4;
default:
return 5;
}
- 家居强电电路模拟程序-2的类的设计
![]()
相比于家居强电电路模拟程序-1新加的用电器的设计非常简单,但这次涉及到了串并联要考虑到用电器的电流和电阻,所以在Device类中还新加了电阻resistance、电流intensity和该用电器是否连通status。还新加入了一个并联电路MLine。在家居强电电路模拟程序-1中用电器的show()方法实际上是先让用电器work后再让用电器show出来。而家居强电电路模拟程序-2则是将show()方法分为了work()方法和show()方法。串联电路通过work()方法给每个串联电路里的用电器赋上电流然后再让用电器work;而并联电路通过work()方法给每个处于连通的用电器赋上电压(没连通的电压赋为0)然后再让用电器work;
- 三、踩坑心得
- 前面也说到过答题判题程序-4其实比较简单但是就是有几个测试点比较难想到,比如说填空题的学生答案末尾带空格但是标准答案不带空格可是最后程序的输出要输出带空格的学生答案。不过想到了这一点困难也自然迎刃而解。
- 家居强电电路模拟程序-1写的其实挺顺的,只不过是再show的时候忘记了先获取一下设备的状态,导致输出的为最初给设备赋的初值。
- 家居强电电路模拟程序-2难度提升了一点点。刚开始设计完代码后就自信的提交了,结果只拿了10分,就连给出的第二个测试点也没有通过,原本电流相同D2、D3的输出也应该是相同的,但我D3的输出是正确的而D2的输出却小的离谱。这个问题困扰了我一个晚上,于是乎我在第二天早早的就爬起床来debug,最后终于发现,我在每次给设备赋电流或电压值之后都会重新计算一遍用电器的电阻,然后根据电阻值和电流或电压值计算电压或电流。但是我却忘记每次调用getResistance()时候应该将电阻的值初始化。导致电阻的值在每一次调用之后都变大,最后影响到输出。其次我还在考虑将创建用电器方法的两个for循环放在一起
public void setDevices() {
for(String i:list) {
Pattern pat=Pattern.compile("#(\\S+):");
Matcher mat=pat.matcher(i);
if(mat.find()) {
createDevice(mat.group(1));
if(mat.group(1).charAt(0)=='T') {
Pattern pat1=Pattern.compile("\\[(\\S+?)(-(\\S+))? (\\S+?)(-(\\S+))?\\]");
Matcher mat1=pat1.matcher(i);
while(mat1.find()) {
if(!mat1.group(1).equals("VCC")&&!mat1.group(1).equals("IN")) {
createDevice(mat1.group(1));
//((Line) device.get(mat.group(1))).add(device.get(mat1.group(1)));
}
if(!mat1.group(4).equals("GND")&&!mat1.group(4).equals("OUT")) {
createDevice(mat1.group(4));
//((Line) device.get(mat.group(1))).add(device.get(mat1.group(4)));
}
if(mat1.group(1).equals("VCC")) {
mainList=mat.group(1);
}
}
}
// if(mat.group(1).charAt(0)=='M') {
// Pattern pat2=Pattern.compile("\\[(\\S+( \\S+)*)\\]");
// Matcher mat2=pat2.matcher(i);
// if(mat2.find()) {
// String matchedGroup=mat2.group(1);
// String[] parts=matchedGroup.split(" ");
// for (String part:parts) {
// createDevice(part);
// //((Line) device.get(mat.group(1))).add(device.get(part));
// }
// }
// }
}
}
for(String i:list) {
Pattern pat=Pattern.compile("#(\\S+):");
Matcher mat=pat.matcher(i);
if(mat.find()) {
if(mat.group(1).charAt(0)=='T') {
Pattern pat1=Pattern.compile("\\[(\\S+?)(-(\\S+))? (\\S+?)(-(\\S+))?\\]");
Matcher mat1=pat1.matcher(i);
while(mat1.find()) {
if(!mat1.group(1).equals("VCC")&&!mat1.group(1).equals("IN")) {
((Line) device.get(mat.group(1))).add(device.get(mat1.group(1)));
}
if(!mat1.group(4).equals("GND")&&!mat1.group(4).equals("OUT")) {
((Line) device.get(mat.group(1))).add(device.get(mat1.group(4)));
}
}
}
if(mat.group(1).charAt(0)=='M') {
Pattern pat2=Pattern.compile("\\[(\\S+( \\S+)*)\\]");
Matcher mat2=pat2.matcher(i);
if(mat2.find()) {
String matchedGroup=mat2.group(1);
String[] parts=matchedGroup.split(" ");
for (String part:parts) {
((Line) device.get(mat.group(1))).add(device.get(part));
}
}
}
}
}
}
public void setDevices() {
for(String i:list) {
Pattern pat=Pattern.compile("#(\\S+):");
Matcher mat=pat.matcher(i);
if(mat.find()) {
createDevice(mat.group(1));
if(mat.group(1).charAt(0)=='T') {
Pattern pat1=Pattern.compile("\\[(\\S+?)(-(\\S+))? (\\S+?)(-(\\S+))?\\]");
Matcher mat1=pat1.matcher(i);
while(mat1.find()) {
if(!mat1.group(1).equals("VCC")&&!mat1.group(1).equals("IN")) {
createDevice(mat1.group(1));
((Line) device.get(mat.group(1))).add(device.get(mat1.group(1)));
}
if(!mat1.group(4).equals("GND")&&!mat1.group(4).equals("OUT")) {
createDevice(mat1.group(4));
((Line) device.get(mat.group(1))).add(device.get(mat1.group(4)));
}
if(mat1.group(1).equals("VCC")) {
mainList=mat.group(1);
}
}
}
if(mat.group(1).charAt(0)=='M') {
Pattern pat2=Pattern.compile("\\[(\\S+( \\S+)*)\\]");
Matcher mat2=pat2.matcher(i);
if(mat2.find()) {
String matchedGroup=mat2.group(1);
String[] parts=matchedGroup.split(" ");
for (String part:parts) {
createDevice(part);
((Line) device.get(mat.group(1))).add(device.get(part));
}
}
}
}
}
理论上看起来好像是可行的,但代码跑起来却不行。我思考了很久,最后发现我是通过LinkedHashMap的键不会重复来去掉多new出来的对象,但那些对象是实实在在被new出来了的,最后也会添加进串并联电路中。而后面新new出来的串并联电路也会将之前重名的串并联电路覆盖掉,最后导致串并联电路里面没有用电器。
- 四、改进建议
- 对于答题判题程序-4,由于最后有几个测试点没有通过所以一直在思考可能的输入情况,后来发现多选题如果学生答案是空的话,学生依旧是部分正确拿到了一半的分,虽然老师没有将它作为测试点,但我觉得依旧是改进的方向。
- 对于家居强电电路模拟程序-1,其实设计的还是挺好的,在迭代第二次的时候源码基本上没有什么修改,都是在原有基础上添加类。然后在迭代第二次的时候,我将输出的排序放在了CreateDevice类中写成了showDevices()方法,减少了main()方法的内容,使得main()方法更加简洁。
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
ArrayList<String> list=new ArrayList<>();
String str=sc.nextLine();
while(!str.equals("end")) {
list.add(str);
str=sc.nextLine();
}
CreateDevice devices=new CreateDevice(list);
Device mainDevice=devices.getMainDevice();
double voltage=220;
for(Map.Entry<String, Device> entry : devices.getDevices().entrySet()) {
String key = entry.getKey();
Device value = entry.getValue();
if(key.charAt(0)=='F'||key.charAt(0)=='L') {
value.setVoltage(voltage);
voltage=((Governor) value).changeVoltage();
continue;
}
}
mainDevice.setVoltage(voltage);
mainDevice.work();
devices.showDevices();
}
- 对于家居强电电路模拟程序-2,我最开始不清楚要如何设计管脚,管脚里面该存放什么东西,然后在一番思考下发现其实好像也用不到管脚,但在下一次的迭代里会出先互斥开关,而且开关上的管脚还存在内阻,虽然很苦恼下次迭代可能要对代码进行大改,但是这也提醒了我该如何设计管脚,下次对于管脚的设计也会方便下下次输出管脚的输入电压和输出电压。
- 五、总结
- 注意细枝末节:在家居强电电路模拟程序-2中,就是因为每次调用getResistance()方法前没有将电阻值赋0,导致我花了2到3小时的时间在debug上,还让我辗转反侧了一夜思考问题到底出在了哪里。
- 多学习一些Java的集合:这次大作业虽然不用TreeMap也能写出来,但是创建设备并且在串并联电路中增加设备我就用了两个大的for循环,然后在输出的时候还要用一个接口和方法来实现输出。多学一些Java集合的特性和方法可以方便以后对代码的设计,选择更加合适的方法来简化代码。
- 设计代码高于写代码:在家居强电电路模拟程序-1中,刚拿到题目其实看了很久还是没有想好用电器之间的连接与通电工作究竟如何实现,还没有完全想明白就先开始设计类,中间写代码写到一半又发现这样写好像不太合适,前前后后修改了很多次,如果在最开始设计代码的时候就想清楚再开始写代码,那后面写代码应该还会轻松很多。




浙公网安备 33010602011771号