OOP 后三次作业的发寄史
前言
这篇博文总结了我在 Java 课程中的三次编程作业的经验和心得。这三次作业为我大一生活带来了极大的压力,其中仅有一次顺利完成。为了帮助同学们理解我的解题思路和程序框架,我将详细介绍每次作业的设计和实现过程。
首先,这些作业涉及到多种不同的编程任务和问题解决方法。由于编写代码的方法繁琐,再加上时间的限制,我未能在规定时间内完成所有作业。不过,通过这些作业的实践,我积累了宝贵的经验,对代码的模块化设计和异常处理有了更深的理解。
本文将详细讲解每次作业的题目要求、解决思路以及代码框架,同时分享我在编写这些代码时遇到的挑战和解决方案。希望这些内容能对正在学习 Java 的同学们有所帮助,并为大家在编程过程中提供一些借鉴和参考
第一次pta
这次是上一次的第四次迭代,没在规定时间内完成,但是时间外还是写好了。
主类 Main:
通过 Scanner 从标准输入读取命令。
根据命令类型(常规题、多选题、填空题、试卷、学生信息、答卷、删题)创建相应的对象并进行解析。
对不同类型的问题进行存储,并将其存入对应的列表中。
根据命令处理删除操作。
计算每个学生的答卷分数并输出。
类 Question:
这是一个抽象类,包含了问题的基本信息(id、text、ans、status)和一些基本方法(getRegex、parseInput)。
类 Choice、Completion、Common:
继承自 Question 类,每个类代表一种问题类型(多选题、填空题、常规题)。
包含各自的答案检查逻辑(check 方法)。
类 Paper:
表示试卷,包含试卷号和题目信息。
提供解析试卷的方法(parsePaper)和一些辅助方法(如 check、printIsFull)。
类 StudentInfo:
存储学生的基本信息(学生ID和名字)。
提供解析学生信息的方法(parseStudentInfo)和一些辅助方法(如 getStudentName)。
类 AnswerSheet:
表示学生的答卷,包含试卷号、学生ID和答案信息。
提供解析答卷的方法(parseAnswerSheet)和一些辅助方法(如 getScore、setScore)。
类 DeleteQuestion:
表示删除题目操作,包含题目ID。
提供解析删除命令的方法(parseDeleteQuestion)和删除题目逻辑(deleteQuestion)。
类图(因为不太会导图片,所以直接写了)
Main:
属性:
List
List
List
List
List
StudentInfo studentInfo
List
方法:
public static void main(String[] args)
类 Question(抽象类):
属性:
int id
String text
String ans
int status
方法:
public String getRegex(int choice)
public String[] parseInput(String input, String regex)
类 Common(继承自 Question):
方法:
public Common()
public Common(int id, String text, String ans, int status)
public String check(String ans)
类 Choice(继承自 Question):
方法:
public Choice()
public Choice(int id, String text, String ans, int status)
public String check(String ans)
类 Completion(继承自 Question):
方法:
public Completion()
public Completion(int id, String text, String ans, int status)
public String check(String ans)
类 Paper:
属性:
String paperNumber
TreeMap<String, Integer> questionInfo
boolean isFull
方法:
public Paper()
public Paper(String paperNumber, TreeMap<String, Integer> questionInfo, boolean isFull)
public boolean isFull()
public void setFull(boolean full)
public void check()
public String getPaperNumber()
public TreeMap<String, Integer> getQuestionInfo()
public void printIsFull()
public void setPaperNumber(String paperNumber)
public void setQuestionInfo(TreeMap<String, Integer> questionInfo)
public Integer getScoreByQuestionNumber(String questionNumber)
public static Paper parsePaper(String input)
public int compareTo(Paper otherPaper)
类 StudentInfo:
属性:
List
List
方法:
public StudentInfo()
public StudentInfo(List
public List
public List
public boolean getStudentId(String id)
public String getStudentName(String id)
public static StudentInfo parseStudentInfo(String input)
类 AnswerSheet:
属性:
String examPaperNumber
String studentId
TreeMap<Integer, String> answers
static TreeMap<Integer, Integer> score
方法:
public AnswerSheet()
public AnswerSheet(String examPaperNumber, String studentId, TreeMap<Integer, String> answers)
public Integer getScore(Integer num)
public void setScore(Integer num, Integer goal)
public String getExamPaperNumber()
public String getStudentId()
public TreeMap<Integer, String> getAnswers()
public static AnswerSheet parseAnswerSheet(String input)
public int compareTo(AnswerSheet o)
类 DeleteQuestion:
属性:
int id
方法:
public DeleteQuestion()
public DeleteQuestion(int id)
public static DeleteQuestion parseDeleteQuestion(String input)
public void deleteQuestion(List<? extends Question> questions, int id)
心得与建议
我的代码在第一次编写的时候因为图省事,很多功能都放在了Main函数当中,需要进行模块化处理,将其分划出来,以便于调试。(也就是所谓的“高耦合度”)
另一方面,存在大量重复代码以及没有异常处理,这点纯粹是因为懒得动脑子。。。。。。最后,被某人告诉我说代码中存在很多硬编码问题,但是我听不懂,最后还是把字符串输入改了一下,部分改为了常量。
第二次pta
这次是新的题面,勉强能写。
Device:抽象基类,包含所有设备的共有特性,如标识符、引脚电压和抽象方法。
Switch:继承自Device,实现一个开关设备,具有开闭状态。
MultiSpeedController:继承自Device,实现一个多档位控制器,具有多个档位。
ContinuousController:继承自Device,实现一个连续控制器,档位值在0到1之间。
IncandescentLamp:继承自Device,实现一个白炽灯,输出电压根据电压差计算。
FluorescentLamp:继承自Device,实现一个荧光灯,输出电压根据电压差计算。
CeilingFan:继承自Device,实现一个吊扇,输出电压根据电压差计算。
Main:主类,处理输入、管理设备和连接、更新设备状态、输出结果。
Device
属性:
String identifier
double pin1Voltage
double pin2Voltage
方法:
Device(String identifier)
String getIdentifier()
abstract void updateState()
void setPin1Voltage(double voltage)
void setPin2Voltage(double voltage)
double getPin1Voltage()
double getPin2Voltage()
abstract String output()
Switch
继承:Device
属性:
boolean isClosed
方法:
Switch(String identifier)
void updateState()
String output()
boolean isClosed()
MultiSpeedController
继承:Device
属性:
int currentGear
static final int MAX_GEAR
方法:
MultiSpeedController(String identifier)
void increaseGear()
void decreaseGear()
void updateState()
String output()
int getCurrentGear()
ContinuousController
继承:Device
属性:
double gearValue
方法:
ContinuousController(String identifier)
void setGearValue(double value)
void updateState()
String output()
double getGearValue()
IncandescentLamp
继承:Device
属性:
int outputVoltage
方法:
IncandescentLamp(String identifier)
void updateState()
String output()
FluorescentLamp
继承:Device
属性:
int outputVoltage
方法:
FluorescentLamp(String identifier)
void updateState()
String output()
CeilingFan
继承:Device
属性:
int outputVoltage
方法:
CeilingFan(String identifier)
void updateState()
String output()
Main
属性:
Map<String, Device> devices
Map<String, List
方法:
void processConnection(String connection)
void createDevice(String id)
void processControl(String control)
void updateDevices()
void outputResults()
static void main(String[] args)
心得与建议
重复代码:在Switch, MultiSpeedController, ContinuousController类中,存在重复的电压更新逻辑,可以提取到基类中。
强制类型转换:使用instanceof和强制类型转换,设计不够优雅。可以使用多态来避免这些检查。
电压更新逻辑的统一性:在updateDevices方法中,电压更新逻辑和电压传递逻辑混杂,建议分离。
异常处理:代码中缺少异常处理,例如在解析输入时,可能会遇到格式错误。
代码注释:可以增加更多有意义的注释,特别是在复杂逻辑部分,以便于理解和维护。
设备创建逻辑:createDevice方法中使用字符串前缀判断设备类型,不够灵活。可以考虑使用工厂模式创建设备实例。
系统扩展性:当前设计对新设备的支持不够灵活,如果需要增加新设备,需要修改多处代码,可以考虑使用设计模式提高扩展性。
通过以上改进,可以使代码更加简洁、易维护、易扩展。
第三次pta
这次就是纯思路框架,没写出来。。。。。。
和前一次进行对比
相同点
基本功能相似:两个题目都涉及智能家居强电电路的模拟,包括控制设备和受控设备的管理。
控制设备类型:两者都涉及开关、分档调速器和连续调速器的模拟。
受控设备类型:都有白炽灯、日光灯和吊扇。
设备状态更新:都需要根据控制设备的状态来更新受控设备的状态。
输入输出格式:输入都是设备信息、连接信息和控制设备的调节信息;输出都是设备的当前状态或参数。
不同点
新增设备:第二个题目新增了落地扇设备。
电路类型:第二个题目增加了串联和并联电路的信息输入,复杂度更高。
电阻考虑:第二个题目引入了电阻的概念,不同设备有不同的电阻值。
并联电路:第二个题目需要处理并联电路的信息和计算。
电路结构复杂度:第二个题目中,电路结构的复杂度增加,需要处理多条串联电路和并联电路的情况。
思路
定义设备类:
定义控制设备类和受控设备类。
控制设备包括开关、分档调速器、连续调速器。
受控设备包括白炽灯、日光灯、吊扇和落地扇。
管理电路连接:
解析输入信息,创建设备和连接信息。
处理串联和并联电路的信息。
更新设备状态:
根据控制设备的调节信息更新设备状态。
计算各设备的输出状态,考虑电压、电阻等因素。
输出结果:
按照要求的顺序输出所有设备的状态或参数。
代码框架
`import java.util.*;
abstract class Device {
protected String identifier;
protected double pin1Voltage = 0;
protected double pin2Voltage = 0;
public Device(String identifier) {
this.identifier = identifier;
}
public String getIdentifier() {
return identifier;
}
public void setPin1Voltage(double voltage) {
this.pin1Voltage = voltage;
}
public void setPin2Voltage(double voltage) {
this.pin2Voltage = voltage;
}
public double getPin1Voltage() {
return pin1Voltage;
}
public double getPin2Voltage() {
return pin2Voltage;
}
public abstract void updateState();
public abstract String output();
}
class Switch extends Device {
private boolean isClosed;
public Switch(String identifier) {
super(identifier);
this.isClosed = false;
}
@Override
public void updateState() {
isClosed = !isClosed;
pin2Voltage = isClosed ? pin1Voltage : 0;
}
@Override
public String output() {
return "@" + identifier + ":" + (isClosed ? "closed" : "turned on");
}
}
class MultiSpeedController extends Device {
private int currentGear;
private static final int MAX_GEAR = 3;
public MultiSpeedController(String identifier) {
super(identifier);
this.currentGear = 0;
}
public void increaseGear() {
if (currentGear < MAX_GEAR) {
currentGear++;
}
}
public void decreaseGear() {
if (currentGear > 0) {
currentGear--;
}
}
@Override
public void updateState() {
pin2Voltage = (pin1Voltage * currentGear * 0.3);
}
@Override
public String output() {
return "@" + identifier + ":" + currentGear;
}
}
class ContinuousController extends Device {
private double gearValue;
public ContinuousController(String identifier) {
super(identifier);
this.gearValue = 0.00;
}
public void setGearValue(double value) {
if (value >= 0.00 && value <= 1.00) {
this.gearValue = value;
}
}
@Override
public void updateState() {
pin2Voltage = (pin1Voltage * gearValue);
}
@Override
public String output() {
return "@" + identifier + ":" + String.format("%.2f", gearValue);
}
}
class IncandescentLamp extends Device {
private int outputVoltage;
private final int resistance = 10;
public IncandescentLamp(String identifier) {
super(identifier);
}
@Override
public void updateState() {
double voltageDifference = Math.abs(pin1Voltage - pin2Voltage);
if (voltageDifference > 220) {
outputVoltage = 200;
} else if (voltageDifference >= 10) {
outputVoltage = 50 + (int) ((200.0 - 50) / (220.0 - 10.0) * (voltageDifference - 10));
} else {
outputVoltage = 0;
}
}
@Override
public String output() {
return "@" + identifier + ":" + outputVoltage;
}
}
class FluorescentLamp extends Device {
private int outputVoltage;
private final int resistance = 5;
public FluorescentLamp(String identifier) {
super(identifier);
}
@Override
public void updateState() {
double voltageDifference = Math.abs(pin1Voltage - pin2Voltage);
outputVoltage = voltageDifference > 0 ? 180 : 0;
}
@Override
public String output() {
return "@" + identifier + ":" + outputVoltage;
}
}
class CeilingFan extends Device {
private int outputVoltage;
private final int resistance = 20;
public CeilingFan(String identifier) {
super(identifier);
}
@Override
public void updateState() {
double voltageDifference = Math.abs(pin1Voltage - pin2Voltage);
if (voltageDifference < 80) {
outputVoltage = 0;
} else if (voltageDifference > 150) {
outputVoltage = 360;
} else {
outputVoltage = 80 + (int) (((360.0 - 80) / (150.0 - 80) * (voltageDifference - 80)));
}
}
@Override
public String output() {
return "@" + identifier + ":" + outputVoltage;
}
}
class FloorFan extends Device {
private int outputVoltage;
private final int resistance = 20;
public FloorFan(String identifier) {
super(identifier);
}
@Override
public void updateState() {
double voltageDifference = Math.abs(pin1Voltage - pin2Voltage);
if (voltageDifference < 80) {
outputVoltage = 0;
} else if (voltageDifference >= 80 && voltageDifference < 100) {
outputVoltage = 80;
} else if (voltageDifference >= 100 && voltageDifference < 120) {
outputVoltage = 160;
} else if (voltageDifference >= 120 && voltageDifference < 140) {
outputVoltage = 260;
} else {
outputVoltage = 360;
}
}
@Override
public String output() {
return "@" + identifier + ":" + outputVoltage;
}
}
class SerialCircuit {
private List
public void addDevice(Device device) {
devices.add(device);
}
public void updateDevices() {
for (Device device : devices) {
device.updateState();
}
}
public List<Device> getDevices() {
return devices;
}
}
class ParallelCircuit extends SerialCircuit {
private List
public void addSerialCircuit(SerialCircuit circuit) {
serialCircuits.add(circuit);
}
@Override
public void updateDevices() {
for (SerialCircuit circuit : serialCircuits) {
circuit.updateDevices();
}
}
}
public class Main {
private static Map<String, Device> devices = new LinkedHashMap<>();
private static List
private static List
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Main system = new Main();
boolean firstInput = true;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.equals("end")) {
break;
}
if (line.startsWith("#T")) {
system.processSerialCircuit(line);
} else if (line.startsWith("#M")) {
system.processParallelCircuit(line);
} else if (line.startsWith("#")) {
system.processControl(line);
}
}
system.updateAllCircuits();
system.outputResults();
}
private void processSerialCircuit(String line) {
String[] parts = line.substring(4).split(" ");
SerialCircuit circuit = new SerialCircuit();
for (String part : parts) {
String[] pins = part.substring
`
总结
通过这三次 Java 编程作业,我深刻体会到了编程的复杂性和挑战性。尽管过程中遇到了许多困难,但每次作业都帮助我提升了编程技能和问题解决能力。
第一次 PTA 作业 主要涉及问题的解析和存储、学生答卷的评分等基本操作,尽管时间紧迫,但最终在时间外完成了任务。通过这次作业,我学会了如何使用类和对象来组织代码,并认识到代码模块化和减少耦合的重要性。
第二次 PTA 作业 增加了设备管理和状态更新的复杂度,我在编写代码时遇到了重复代码和异常处理不足的问题。通过这次作业,我学会了如何通过设计模式来改进代码的扩展性和维护性。
第三次 PTA 作业 虽然没有完全实现,但提供了一个复杂的智能家居强电电路模拟的框架。通过对比与前一次作业的不同点,我进一步理解了复杂系统的设计思路和多态性的应用。
在这些作业中,我不仅巩固了 Java 编程的基础知识,还学会了如何应对和解决实际编程中的各种问题。我意识到,编程不仅需要扎实的技术基础,更需要细致的思考和不断的优化。希望通过不断的学习和实践,能够进一步提升自己的编程能力和专业素养