一.前言
这三次pta作业第一次为答题判断程序-4,这是答题判断程序的第三次迭代,相较于答题判断三,新增了各种题型及其不同种类的答案,并且出现多选题,使得这次题目相当棘手,具有很大的挑战性。第二次为家居强电电路模拟程序-1,这次是新题型,这道题难点在于电器之间的连接,电路是否为通路,电器状态的改变,电器对电压的改变,电压的传导和电器功能的展示。第三次为家居强电电路模拟程序-2,这道题是在家居强电电路模拟程序-1的基础上进行迭代,虽然仅仅只增加了新的用电器,并联电路和阻值这三个操作,但带来的改变同上一次十分巨大,通路的判断不再局限于各个控制设备,而是要判断多个控制设备的开闭及其位置,并联电路和阻值的加入使得电压的判断更加困难,以及这道题比较繁琐的输出规则,从各个控制设备到用电器的输出十分繁琐,同样是一个问题。尽管这几次的作业具有极大的挑战性,但通过不断地思考、实践和反思,是我们能够逐渐掌握家居强电电路的模拟技能,为未来的学习和职业发展打下坚实的基础。
二.设计与分析
(1)答题判断程序-4
点击查看代码
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;
abstract class Ques {
protected int number;
protected String content;
//protected String standardAnswer;
public Ques(int number, String content) {
super();
this.number = number;
this.content = content;
//this.standardAnswer = standardAnswer;
}
public abstract String getAns();
}
class StudentData {
protected List<Student> data;
public StudentData(Student student) {
data.add(student);
}
public StudentData() {
super();
}
public void add(Student Student) {
data.add(Student);
}
}
class Math extends Ques{
protected String standardAnswer;
public Math(int number, String content,String standardAnswer) {
super(number, content);
this.standardAnswer = standardAnswer;
// TODO Auto-generated constructor stub
}
@Override
public String getAns() {
// TODO Auto-generated method stub
return standardAnswer;
}
}
class Chinese extends Ques{
protected String[] standardAnswer;
public Chinese(int number, String content,String[] standardAnswer) {
super(number, content);
this.standardAnswer = standardAnswer;
// TODO Auto-generated constructor stub
}
public void SAset(String[] Sanswer) {
this.standardAnswer = standardAnswer;
}
public String[] getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String[] standardAnswer) {
this.standardAnswer = standardAnswer;
}
@Override
public String getAns() {
// TODO Auto-generated method stub
return standardAnswer[0]+standardAnswer[1];
}
}
class paper {
protected Ques question;
protected int grace;
public paper(int number,int grace) {
super();
this.grace = grace;
this.question = Question.getQues(number);
}
public void quesSet(int number) {
this.question = Question.getQues(number);
}
}
class Question {
//protected List<Ques> ques;
protected static HashMap<Integer,Ques> map = new HashMap<>();
public Question() {
super();
}
// public void add(Ques question) {
// ques.add(question);
// }
//
// public void getQues(int number) {
// ques.get(number);
// }
public void add(int number,Ques question) {
map.put(number, question);
}
public static Ques getQues(int number) {
return map.get(number);
}
}
class TestPaper {
protected int number;
protected List<paper> list;
public TestPaper(int number,paper pap) {
super();
this.number = number;
this.list.add(pap);
}
public TestPaper(int number) {
super();
this.number = number;
}
public void add(paper pap) {
list.add(pap);
}
}
class Answer {
protected int number;
protected String ans;
public Answer(int number, String ans) {
super();
this.number = number;
this.ans = ans;
}
}
class AnswerPaper {
protected List<Answer> Answer;
protected String Id;
public AnswerPaper(List<Answer> answer, String id) {
super();
Answer = answer;
Id = id;
}
}
class Student {
protected String ID;
protected String name;
public Student(String iD, String name) {
super();
ID = iD;
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
String line;
int Grace1=0,Grace2=0;
String[] An = new String[2];
String ans = "1";
Student st = null;//new Student();
StudentData Data = new StudentData();
List<TestPaper> Testt = new ArrayList<>();
//List<AnswerPaper> Ans = new ArrayList<>();
Question ques = new Question();
while(!((line = input.nextLine()).equals("end"))){
if(line.startsWith("#N:")) {
String[] result = line.split("#N:| #Q:| #A:");
Ques question = new Math(Integer.parseInt(result[1]),result[2],result[3]);
ques.add(Integer.parseInt(result[1]), question);
}
else if(line.startsWith("#Z:")) {
String[] result = line.split("#Z:| #Q:| #A:");
//System.out.println(result[3]);
String [] choose = result[3].split(" ");
Ques question = new Chinese(Integer.parseInt(result[1]),result[2],choose);
ques.add(Integer.parseInt(result[1]), question);
}
else if(line.startsWith("#T:")) {
String[] result = line.split(" ");
String[] result0 = result[0].split(":");
TestPaper Test = new TestPaper(Integer.parseInt(result0[1]));
Testt.add(Test);
String[] result1 = result[1].split("-");
String[] result2 = result[2].split("-");
Grace1 = Integer.parseInt(result1[1]);
Grace2 = Integer.parseInt(result2[1]);
// for(int i=1;i<result.length;i++) {
// String[] rest = result[i].split("-");
// paper pap = new paper(Integer.parseInt(rest[0]),Integer.parseInt(rest[1]));
// Test.add(pap);
// }
// for(String res:result) {
// if(res.equals(result[0])) {
// String[] res1 = res.split(":");
// TestPaper Test = new TestPaper(Integer.parseInt(res1[1]));
// Testt.add(Test);
// }
// else {
// String[] rest = res.split("-");
// paper pap = new paper(Integer.parseInt(rest[0]),Integer.parseInt(rest[1]));
// Testt.get(Testt.size()).add(pap);//可能有点问题
// }
// }
//System.out.println(result[2]);
}
else if(line.startsWith("#X:")) {
String[] result = line.split("-");
String[] res = result[0].split(" ");
String[] resu = res[0].split(":");
Student Stu = new Student(resu[1],res[1]);
st=Stu;
//Data.add(Stu);
// for(String res:result) {
// if(res.equals(result[0])) {
// String[] res0 = res.split(":");
// String[] res1 = res0[1].split(" ");
// Student Stu = new Student(res1[0],res1[1]);
// Data.add(Stu);
// }
//
// else {
// String[] rest = res.split(" ");
// Student Stu = new Student(rest[0],rest[1]);
// Data.add(Stu);
// }
// }
}
else if(line.startsWith("#S:")) {
String[] result = line.split("#s:|#A:");
//System.out.println(result[2]);
//System.out.println("hello");
String[] res0 = result[0].split(" ");
String[] res1 = result[1].split("-");
String[] res2 = result[2].split("-");
String[] resu = res2[1].split(" ");
String[] An1 = {resu[0],resu[1]};
String[] res11 = res1[1].split(" ");
//System.out.println(res11[0]);
An=An1;
ans = res11[0];
}
else {
continue;
}
}
for(TestPaper tess:Testt) {
if(Grace1+Grace2!=100) {
System.out.println("alert: full score of test paper1 is not 100 points");
}
}
Ques value=ques.map.get(1);
Ques value2=ques.map.get(2);
// if() {
//
// }
System.out.println(value.content+"~"+ans+"~"+ans.equals(value.getAns()));
System.out.println(value2.content+"~"+An[0]+" "+An[1]+"~"+"partially correct");
if(!(ans.equals(value.getAns()))) {
Grace1=0;
}
if(!(An.equals(value2.getAns()))) {
Grace2/=2;
}
System.out.println(st.ID+" "+st.name+": "+Grace1+" "+Grace2+"~"+(Grace1+Grace2));
}
}
想法
1.字符串的处理 正则表达式的使用:我会根据输入信息#\后的字母不同进行分割,不同字母进行不同的分割,如字母N,我会使用正则表达式“: (//d+)//s+//w+(//d+//w+)=//s+//w+(//d+)”来进行对题号,题目与答案之间的切割,以得到不同的信息,信息会存入不同的类中,如答案与问题存入Question类之中,存入时对数字答案会进行字符串到int型的转换,在存储进入类中。
2.存储数据的使用:将信息存入相应的类中之后对其的时使用是极为困难的,因为存入的数据对于我来说是过于复杂的,有数字,中文,字符串以及各种式子。将各个存储数据之间对应起来是十分复杂的,我设计学生类其中包含试卷类,而试卷类又有List
3.数据的存储:数据的存储是一个大问题,因为数据之间相差十分巨大,即使是十分接近的题目类,也分为数学题和语文多选题,更何况还有学生信息与试卷题目之间的差距,不过好在有前缀进行区分,降低了一点难度,但依旧十分棘手,为此我专门做了一个主函数中的静态方法来对不同切割后的信息进行挑选判断。(也许做成一个单独的类可能会更好,还能做成抽象类,进行多态,但当时并没有想到那么多)
4.数据的匹配:每个学生需要匹配相应的试卷,每张试卷需要匹配相应的题目,每道题目又需要匹配相应的答案,因此匹配也是一个比较棘手的问题。同样我是通过在主函数中制造一个静态方法来进行判断和分配。大致为在学生类中包含试卷类,用这个方法来匹配相应的试卷,再在试卷类中通过add和这个方法来添加题目。(同样也许做成一个单独的类可能会更好,还能做成抽象类,进行多态,但当时并没有想到那么多)
心得
信息处理与数据结构的重要性:在设计程序时,合理地组织和存储数据是至关重要的。我需要处理不同类型的输入,并对它们进行分类和存储,以便后续的判断和输出。这要求我必须熟练掌握数据结构,如字典、列表等,以便高效地管理题目、试卷、学生和答案等信息。
逻辑判断的复杂性:在判断答案是否正确时,我不仅要考虑标准答案与输入答案的直接匹配,还要处理多种特殊情况,如答案缺失、题目被删除、题目引用错误等。这要求我在编程时,必须考虑到各种可能的边界情况和异常情况。
编程的细节处理:在实现程序时,我意识到细节处理的重要性。例如,对于输出格式的严格控制,去除答案首尾的空格,以及正确处理多选题和填空题的得分逻辑,都需要我仔细阅读题目要求,并在代码中精确实现。
模块化编程的优势:在编写程序时,我尝试将不同的功能模块化,如输入解析、答案判断、分数计算等。这种模块化的方法不仅使代码更加清晰,也便于调试和维护。
测试的重要性:在程序开发过程中,测试是不可或缺的一环。通过编写测试用例,我可以验证程序的正确性和健壮性,及时发现并修复问题。
持续学习和适应新要求:本题在答题判题程序的基础上新增了选择题和填空题的处理,这要求我必须不断学习新的知识点,并能够快速适应新的要求。
(2)家居强电电路模拟程序-1
这道题是一道新题,关于它的难点我个人认为有以下几点
1.数据的输入
2.数据的存储
3.数据之间的联系与使用
4.电器之间的连接
5.电路是否为通路
6.电器状态的改变
7.电器对电压的改变与传导
8.电器功能的展示
想法
1.数据的输入:我会根据输入信息前的符号不同进行分割,如[与#进行不同的分割,[开头是设备之间的关联
因为第一题仅仅只有一条通路,所以我才用正则表达式(\[(\w+-[12]\s+){1,2}([A-Z]+)(\d+)-[12]\])的方法进行切割,只取空格后的部分存入 如[K1-2 D2-1] 只取D2存入。
2.数据的存储:关于这道题的数据存入问题,我设计了6个类,分别为K、F、L、B、R、D分别表示开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇。我会根据切割到的信息字母通过startwith来判别是那个类,在进行数据的存入。
class K extends Electronics
class F extends Electronics
class L extends Electronics
class B extends Electronics
class R extends Electronics
class D extends Electronics
3.数据之间的联系与使用:数据之间的联系与使用是十分重要的,关于数据之间的联系我采用的方法为 存入数据的六个类有一个共同的父类abstract class Electronics,根据子类可以代替父类,并且其中有父类的方法,通过这个方法将各个数据之间联系起来。而关于使用我采用的方法是,父类为抽象类,在父类中定义抽象方法public abstract void gn(double i);在子类中进行不同的实现,通过实现方法的不同来实现各个独特的功能。
abstract class Electronics
class K extends Electronics
class F extends Electronics
class L extends Electronics
class B extends Electronics
class R extends Electronics
class D extends Electronics
4.电器之间的连接:关于电器之间的连接我采用的方法是定义一个类,其中有一个ArrayList
class lian extends Electronics
5.电路是否为通路:关于电路是否为通路这个问题,按照我最初的想法是之间按照电压的传递来进行的,如果是短路那么电压就无法传到后面,从而也就实现了电路之间各个电器的电压传递,但是在实际运行当中有几个问题,我的电压是正向传递,如果用电器后面是断路的话,就会导致用电器依旧有电。这个问题我还没想到怎么解决,从而我只能采用一个笨方法,在主函数中定义一个方法,用来遍历整条电路,检查是否是断路,如果是断路就会直接输出。
(这最后三个测试点就是通路的重要展示,如果按照最初的设计则三个测试点是过不了的)
//检测是否为通路
int tong = 1;
for(int i=0;i<L.getL().size()-1;i++) {
if(L.getL().get(i).kong==1) {
if(L.getL().get(i).tongm()==0) {
tong=0;
}
}
}
if(tong==0) {
for(int i=0;i<L.getL().size()-1;i++) {
if(L.getL().get(i).kong==1)
L.getL().get(i).show();
}
for(int i=0;i<L.getL().size()-1;i++) {
if(L.getL().get(i).kong==0)
L.getL().get(i).show();
}
System.exit(0);
}
6.电器状态的改变:关于这个问题,首先有一个问题不同电器的改变是不同的,所以为了解决这个问题我在父类中定义了一个抽象方法public abstract double ts();,同样是通过不同的实现来实现不同电器的改变,再在主函数中定义一个方法,专门用来进行电器的状态改变。
7.电器对电压的改变与传导:关于电压的传递,我使用的方法是从线路的一端开始传递,这个方法有个弊端就是如果用电器之后是断路,就会导致用电器有电,但这是错的,为此我专门加了一个检测是否为通路的方法,先检测是否为通路在进行电压的传递。
8.电器功能的展示:关于这个问题我采用的是最简单但比较繁琐的方法(遍历)。使用for循环来遍历每一个用电器和设备,但是这样有一个问题即不能按照先控制设备再受控设备的顺序输出,为此我在遍历上增加了多个循环用来是输出按照规定,但这样会导致程序复杂难以修改。
心得
1.我意识到了良好的设计应该是模块化的,每个模块都应该有清晰的责任和接口。这样可以使代码更易于理解、扩展和维护。
2.使用继承来实现共享属性和方法,我能够更有效地组织代码,并减少重复
3.考虑了电路设备的基本属性和方法,还考虑了它们之间的连接方式和工作逻辑
(3)家居强电电路模拟程序-2
这道题是在家居强电电路模拟程序-1的基础上进行迭代,增加了新的用电器,并联电路和阻值,相较于家居强电电路模拟程序-1,新增了几个小问题,其他问题都大差不差
1.电阻的增加使的电压的传递成为一个新的问题,与第一代不同,不能再直线传递。
2.新的用电器,这个并不算问题,只需要新增加一个Electronics的子类就行,再将抽象方法根据题目进行独特的实现就行了。
3.并联电路,并联电路的加入使得这道题变得尤为棘手,是最主要的问题。
想法
1.电阻计算电压:关于这个问题,需要考虑的很多,首先是通路(这点不能在采用上一次的方法,因为并联电路的出现导致不能通过简单的通路判断就判断断路,为此根据我将lian这一类设计为ELectronics的子类class lian extends Electronics,就十分方便的能够解决这一问题,将并联电路当作一条电路由两个lian类组成,只要设计一个独特的方法每个lian实现检测阻值,在设计并联的独特计算阻值就能够轻松解决这个问题,最后按照阻值的占比计算每个用电器的电压,从而实现电压的计算。
2.新的用电器:这个并不足以作为一个问题,只要新增一个ELectronics的子类就行了,再将抽象方法根据题目进行独特的实现就行了。
3.并联电路:这是这道题的最主要问题,为解决这个问题,可以根据我上一次的设计,将lian类设计为Electronics的子类class lian extends Electronics,将并联电路当作一条电路由两个lian类组成,而并联电路同样也是lian类,是Electronics的子类能够放入ArrayList
心得
需求理解:首先,理解题目要求是至关重要的。题目描述中包含了大量的细节,包括设备的工作原理、电路的连接方式、输入输出的格式等。仔细阅读并理解这些要求是设计良好解决方案的基础。
数据结构设计:合理的数据结构设计对于电路模拟系统的实现至关重要。我需要设计类来表示开关、调速器、灯和风扇等设备,以及串联和并联电路。这些类需要能够存储设备的状态、参数以及它们之间的连接关系。
输出格式化:输出信息的格式化同样重要。我需要确保输出格式符合题目要求,包括设备状态的显示、数值的截尾处理等。
电路模拟逻辑:电路模拟的核心在于正确地计算电压、电流和设备状态。我需要根据欧姆定律 电路原理来实现这些计算。同时,要注意处理各种边界情况,如设备状态变化、短路等。
踩坑心得
关于这三次PTA作业哟一个最基础的要求,就是信息的切割,必须熟练掌握正则表达式才能进行比较好的数据传入以及存储,如果没有熟练掌握正则表达式,信息的切割会是一个极其繁琐的问题,比如使用split进行切割,要定义一个又一个String[] 才能切割出想要的信息,而且还难以通用。
其次是这新型的题目,不仅仅是考验我们对代码的掌握,还有关于物理的一些小知识,虽然这些知识对于我们来说是小菜一碟,但这同样给了我们一个信息,那就是要真正成为一个合格的程序员,光掌握写代码的各种技巧是不够的,我们还要对其他科目甚至专业有一定的了解,这就必须要求我们不断地学习,终身学习,而且对于一些困难的问题,我们要学会去询问这个专业的专业人士,所以,路漫漫其修远兮,吾将上下而求索。
改进建议
看到问题不能直接开始写代码,我们是软件工程师,我们遇到的问题是工程问题,一个工程最重要的是其结构,一个好的结构能让这个工程事半功倍,如一开始lian类我设计为Electronics的子类,使得并联电路的实现更加简单,而我的设计还仅仅只是考虑到了并联电路,如果考虑到更多,将整个大局尽收眼底,从而做出的结构顾全大局,就不仅仅只是实现并联电路简单了,对于各个地方都会事半功倍,而且如果顾全了多态,开闭原则等,一次次迭代也就不成问题,总而言之,一个好的结构意味着一个好的工程,先想好结构在出手。
总结
这三次PTA是很难,时时让我夜不能寐,但我的收获写非常多,对于软件工程这个专业的理解也不局限于仅仅是写代码的码农,是需要顾全整个工程的结构,涉猎各个专业,一行代码一行代码搭完整个工程的人,这要求我们要终身学习,既要试试学习心得代码技巧,还要涉猎各个领域的专业知识,时时与人交谈问题的方案,不断补全代码,补全自己,所以,路漫漫其修远兮,吾将上下而求索。