NCHU-PTA三次大作业总结
目录
前言
设计与分析
踩坑心得
改进建议
总结
(1) 前言
第一次大作业
知识点:类与对象基础,java数组的基础使用,java输入输出等基础内容。
题量:入门级别
难度:易
第二次大作业
知识点:类与对象,数组,动态数组(列表),接口,正则表达式。
题量:中等
难度:中等
第三次大作业
知识点:类与对象,正则表达式,哈希表,动态数组。
题量:中等偏多
难度:难
关于前三次PTA大作业,整体题目量都集中在最后一道题,都是对“答题判题”问题进行解决,难度是依次迭代,加入了新的格式要求和判题要求。第一次大作业由于给定了题目总数num,确定了Question的长度,只需要用到Array数组的知识点即可解决。而第二次大作业由于不确定Questiond的数目,便只好用ArrayList列表的知识点来进行解决。而第三次大作业由于问题的进一步复杂化,我进行了HashMap和ArrayList结合的方式来解决问题,以便快速确定位置和信息对应。需要注意的是三次作业都需要通过强大的工具---正则表达式来进行对输入的信息进行处理,拆分并包装。就题目量和难度来说,题目集一最后一题代码量在100行左右;第二次则在200行左右;第三次在400行左右。对于个人来说我觉得还是偏难了一点。也正是这几次作业让我明白编程之路漫漫其修远兮,若还是秉持之前得过且过的他态度对待专业学习,一定是不行的。
(2) 设计与分析
以下是三次作业最后一题的分析
对于三次作业,其实设计上都应履行单一职责原则和模块化,降低圈复杂度的同时可以使我们的代码复用性和可维护性提高。但可惜我的代码似乎并没有特别显示出这样的特性,虽然每个类都有自己的属性和方法,但似乎还是大量采用了面向过程的思维,没有面向对象的思维,导致代码的复用性和可维护性特别糟糕。特别是到了第三次大作业开始,题目要求添加学生信息,删除信息和不符合格式要求输出:“wrong format”,即要修改大量的代码的时候,这个缺点就特别显著了,有一种“改不动”的情况,无法基于前一次作业再修改,要想做好导致只能重新推翻了重来。但时间有限,我也只能硬着头皮改了,结果可想而知。
第一次大作业涉及的类:
题目类(Question):
private int num;//题号
private String content;//题目内容
private String answer;//标准答案
public boolean judge(String answer,String a);//判题方法
试卷类 (Paper) :
private Question[] list;//题目清单
private int num;//试卷号
public boolean judge(int n,String a) //判题方法
public void save(int n,Question a) //存放问题
答卷类 (Answer) :
private Paper paper;//存放的试卷
private String[] list1;//提交的答案清单
private boolean[] list2;//判题清单
第二次大作业涉及的类:
题目类(Question):
private int num;//题号
private String content;//题目内容
private String answer;//标准答案
public boolean judge(String answer,String a);//判题方法
试卷类 (Paper) :
private ArrayList<Question> list;//问题清单
private ArrayList<Integer> number;//题号清单
private ArrayList<Integer> score;//分数清单
private int num;//试卷号
public void check()//检查试卷总分是否为100分
答卷类 (Answer):
private int num;//试卷号
private ArrayList<String> list;//考生答案
private ArrayList<Integer> score;//得分
public int sum()//计算考生最后得分总分
第三次大作业涉及的类:
题目类(Question):
private int num;//题号
private String content;//内容
private String answer;//标准答案
private boolean valid=true;//是否合法
public boolean judge(String answer,String a)//判题方法
试卷类 (Paper) :
private ArrayList<Question> list;//问题清单
private ArrayList<Integer> number;//题号清单
private HashMap<Integer,Question> paper=new HashMap<>();//题号-问题哈希表
private HashMap<Integer,Integer> score;//题号-分数哈希表
private int num;//试卷号
public void check()//判断是否为100分满分
答卷类 (Answer) :
private int num;//试卷号
private String id;//学号
private String name;//姓名
private HashMap<Integer,String> answerpaper;//题号,答案
private HashMap<Integer,Question> questions;
private HashMap<Integer,Integer> score=new HashMap<Integer, Integer>();//得分
private HashMap<Integer,Wrong> wrong=new HashMap<Integer, Wrong>();//错误的题目
public int sum()//考生总分
学生类 (student):
private String id;//学号
private String name;//id
错误信息类 (wrong):
private int num;
private String wrongstring;//错误信息
public void check();//错误输出
第一题的思路是先接收一个总数num,然后进行num次循环接收问题,再通过正则表达式进行拆分和包装,再最后进行判题,得出答卷的结果,总体来说比较简单。
第二题的思路是一直接收多种类型(问题啊,试卷啊,答卷啊等等)字符串直到接收到"end"停止,再把所有信息通过正则表达式分类存入已经定义好的多种类型的ArrayList中,最后通过试卷对答卷的方法进行判题输出,只要花了足够的时间不难拿到满分。
第三题的思路和第二题类似,只不过要用到HASHMAP进行更快速的信息确认,还有错误格式的判断和输出。
以下分别是三次作业最后一题的source monitor分析:
可以看到我的Max Complexity(最大圈复杂度)从第一次的9直接爆到第二,三次作业的27。这也对应了我上文提到的我没有用好单一职责原则和面向对象职责,导致失去了很多分数(痛心......)
(3)踩坑心得
以上分别是我第一次,第二次,第三次PTA提交代码的测试结果
第一次的坑估计就是格式问题,含多余的空格我当时无法确认怎么处理,后来发现java中字符串提供的trim方法好像能完美解决这个问题,但是不知道为什么我对接收题号的字符串再进行trim方法后进行强制类型转化为integer后系统一直不通过,我想是不是题号根本就不要用int类型来定义会好一点,统一用String来处理。
第二次的坑其实我觉得还好,虽然PTA第一次发布的时候由于时间问题耽搁了一会没提交上,但我在截止后的两天内还是完成了并将源码复制提交在补练拿到了满分,其坑就是对答卷和试卷的不同判断,比如答卷为空,试卷不存在,但也可能是我用了面向过程的方法,导致侥幸拿到了分,就比如PTA2我最后判题输出是用了一个嵌套多层循环的方法进行(如下)。
for(Answer i:a) {
int num=i.getNum();
int flag=0;
for(Paper j:p) {
if(j.getNum()==num) {
flag=1;
for(int z=0;z<i.getList().size();z++) {
if(i.getList().get(z).equals(j.getList().get(z).getAnswer())) {
i.setScore(j.getScore(z));
System.out.println(j.getList().get(z).getContent()+"~"+i.getList().get(z)+"~true");
}
else {
i.setScore(0);
System.out.println(j.getList().get(z).getContent()+"~"+i.getList().get(z)+"~false");
}
}
if(i.getList().size()<j.getList().size()) {
for(int l=0;l<j.getList().size()-i.getList().size();l++) {
i.setScore(0);
System.out.println("answer is null");
}
}
for(int u=0;u<i.getScore().size();u++) {
if(u==i.getScore().size()-1) {
System.out.println(i.getScore().get(u)+"~"+i.sum());
}
else {
System.out.print(i.getScore().get(u)+" ");
}
}
}
}
if(flag==0) {
System.out.println("The test paper number does not exist");
}
}
但到了第三次就处处是问题了,一个是大量的非零返回(答案乱序输入,空白卷,错误的格式信息,答案为空等等),这些坑其实都是我在之前做题目的时候自己给自己挖好的,踩到其实也是罪有应得。应该对每个类再添加多些方法,并多创几个比如判题类,确定输入信息的合法性等等。
(4)改进建议
第一次大作业
没有处理好多个类的职责问题
代码在main方法中过于冗长,不好进行多次的修改,可复用性太差了,可以在类中多添加几个方法
只能进行有限的题目数量处理
采用的是单一的java数组,必须在已知的长度范围内才能处理,无法添加更多的题目信息,用ArrayList处理更好
第二次大作业
类的职能太差了
还是延续第一次大作业只用了三个类,问题,试卷,答卷,导致单一职责性很差,应该多添加几个类,比如问题试卷,答卷试卷等类,并多添加几个方法。
main方法太长了
main方法写了100余行,包括信息的输入,问题试卷答卷的处理和包装,字符串的匹配,判题的输出等等。应该重新分配职能
嵌套循环太多
即圈复杂度太高,逻辑一丝一缕扭在一起,非常难修改,可复用性太差。应该重新分配职能
第三次大作业
嵌套循环太多
依旧是作业二的毛病,判断的循环一层套一层,可迭代性和可复用性太差,应该重新分配类和方法
很多功能无法实现
很多迭代的功能难以添加上去,很多时候判断格式错误又会影响前面的问题,试卷,答卷处理,相互缠绕难以修改,应总结这些错误,大改代码
(5)总结
学到了什么
(1)首先那必然是强大的工具--正则表达式。通过正则表达式,我们在解决之前用c语言来写的一些问题时候就是降维打击(比如第三次大作业的第二题,通过正则表达式和localdate,只用了50行左右的代码就可以完成:闰年的判断,日期合法性,以及相差的年份,月份和天数),以及每一次的最后一题我们都离不开用正则表达式来处理问题,试卷,答卷,删除信息,学生信息等。
(2)ArrayList,也是动态数组,它实现了List接口,可以动态地增加或减少其大小。ArrayList允许存储重复的元素,并且可以按照插入顺序来访问这些元素。ArrayList的主要操作包括添加、获取、删除和包含某个元素的操作。它提供了常数时间复杂度的性能(O(1))。在第二次,第三次大作业最后一题中有重要作用。
(3)HashMap,它实现了Map接口,并且基于哈希表来存储键值对。HashMap允许存储null键和null值。哈希表是一个强大的数组,他可以自己定义下标,其可以是多种类型的,不拘泥于一种单一的整型下标。查找内容起来也十分快得心应手和快捷。HashMap的主要操作包括插入、获取、删除和包含某个键的操作。它提供了常数时间复杂度的性能(O(1))。在第三次大作业最后一题里发挥了很大的作用。
进一步学习
(1)面向对象编程(OOP)的概念和实践: Java是一种面向对象的编程语言,深入理解OOP的原则和概念对于掌握Java至关重要。学习如何创建类、对象、继承、封装和多态等概念,并将其应用到实际的编程项目中。
(2)核心Java类库的深入了解: Java拥有丰富的类库,包括java.lang、java.util、java.io等。深入了解这些类库的常用类和方法,掌握它们的用法对于编写高效的Java程序至关重要。
(3)编码规范和最佳实践: 学习编写清晰、可读性强、符合标准的Java代码是很重要的。阅读并遵循Java编码规范,以及学习其他Java程序员的最佳实践是提高自己编程技能的好方法。
(4)常用开发工具和框架: 学习如何使用常见的开发工具如Eclipse、IntelliJ IDEA等,以及流行的框架如Spring、Hibernate等,这些工具和框架可以提高我的开发效率并且使你的代码更加模块化和可维护。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~