一、前言
对于这几周开始的Java答题判题程序的编写对我压力有点大,因为我对编程感觉总是慢半拍。虽然痛苦但也学习到了一些知识,过程艰辛但也有些许收获,让我对Java编程了解到了更多
这三次题目集的难度是逐渐向上攀升的,第一次题目集作业除了最后一题大作业都是入门级Java编程题让我们体会Java的编程理念,非常详细的帮助我们建立类,教导我们进行Java入门,构造一个无参构造方法,一个有参构造方法,还有一些get()与set()方法来对类里面的值进行使用。帮助我进行有关类与对象的应用。
对于大作业题目集1~3的最后一题每次都是难度进行飙升(起码对我来说)导致我每次画长时间在编写最后一天大作业,对我感觉最难的点在于对Java接触时间短,对于很对函数和方法运用不熟练,但继续学习下去会感觉到Java对很多方法进行直接封装了不需要写一些底层逻辑比如链表直接用import java.util.ArrayList;类包里面进行 ArrayList
感觉题量上感觉还是还可以,就是最后一次比较费时间,还有就是最后一题大作业占分很高,如果最后一题没时间完成直接影响整体。
二、设计与分析
7-1设计一个风扇类(class Fan)
我认为本次实验主要是学习到了构造方法
1.一个无参构造方法Fan();
2。一个有参构造方法 public Fan(int fanSpeed,boolean fanOn,double fanRadius,String fanColor) { ... },
3.toString()的方法返回描述风扇的字符串。
7-2类和对象的使用
与以上相同
先构造无参方法public Student()
再构造有参方法Student(String name,String sex,String studentID,int age,String major)
再toString()的方法返回描述风扇的字符串。
7-3成绩计算-1-类、数组的基本运用
这个程序在7-2上修改,最大收获是对浮点数保留小数
利用String.format("%.2f",average)来对average保留两位小数(四舍五入)
7-4成绩计算-2-关联类
与7-3相类似进一步对保留小数进行理解
7-5答题判题程序-1
输入格式:
程序输入信息分三部分:
对于第一次大作业的输入要求主要分为三个方面:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
2、题目内容
一行为一道题,可以输入多行数据。
格式:"#N:"+题号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
3、答题信息
答题信息按行输入,每一行为一组答案,每组答案包含第2部分所有题目的解题答案,答案的顺序号与题目题号相对应。
格式:"#A:"+答案内容
格式约束:答案数量与第2部分题目的数量相同,答案之间以英文空格分隔。
答题信息以一行"end"标记结束,"end"之后的信息忽略。
很清晰的可以创建三个类,对于我创建的三个类
class Quest
主要是存储题目信息主要包括
public Quest(int id, String content, String standardAnswer) {
this.id = id;//题目id号
this.content = content;/题目内容
this.standardAnswer = standardAnswer;//题目答案}
以及一个判断答案对错
public boolean judgeAnswer(String answer) {
return standardAnswer.equals(answer.trim());}
还有就是一些set()以及get()函数便于对题目信息的取值与储存就不一一展示了。
class Paper
主要就是为了用于封装整套题目的信息,通过class Quest创建的问题进行存储以及处理
采用 List<Quest> questions = new LinkedList<>()一个链表对题目信息进行封装
public void addQuestion(Quest question)
这个方法主要是对保存的问题进行添加到question链表中保存
public boolean checkAnswer(int num, String answer)
这个方法来对对应编号的题目答案进行判断,并将结果返回保存起来方便后续进行验证,
public Quest getQuestionById(int num)
这个方法主要用来判断获取题目编号方便进行对题目的判断,如果该题目不存在则会将该位置赋值null,后续程序将会对改题目不同赋值进行相应的处理
public int getMaxQuestionNumber()
该函数主要来返回链表中存储的问题个数,方便对循环次数以及一些处理进行约束,以便对输出处理不会因为漏算还是多算。
class AnswerSheet
用于封装答题信息,输出相应结果
private Paper paper;
对封装好的试卷类进行引用
private List<String> answers = new LinkedList<>();
答案链表对题目标准答案进行保存以便对学生答案进行判断
private List<Boolean> results = new LinkedList<>();
题目答案和标准答案比对完后将true或者false保存在results链表中
public AnswerSheet(Paper paper)
对试卷的导入
public void saveAnswer(int num, String answer)
对相应题目编号答案进行保存
public void print()
对题目完成比对后进行对答案的输出以及相应的提示最后的得分等结果。
对于main函数部分我采用
int questionCount = Integer.parseInt(scanner.nextLine());
通过scanner.nextLine()获取有多少题目输入,再将其转化成int类型的数据保存起来
在通过questionCount的值new Question()将题目存储
后续再利用scanner.hasNextLine()对后续的输入进行处理
while (scanner.hasNextLine()) {
String answerInput = scanner.nextLine();
if ("end".equalsIgnoreCase(answerInput)) {
break;}
通过scanner.hasNextLine()进行判断将一次输入一行在进行处理
通过每一行输出的是startsWith("N:")还是startsWith("Q:") 还是startsWith("A:")进行相应的处理
判断到这是问题信息首先进行分割字符split(":")等,new Question(id,content,answer)进行存储
String[] answers = new String[parts.length];来存储答案
再创建AnswerSheet answerSheet = new AnswerSheet(paper);
然后保存答案信息 answerSheet.saveAnswer(questionNumber, answer);
最后输出answerSheet.print();
下面是这次大作业的类图以及顺序图
第二次大作业最后一题(小题就不加以赘述了)相对于第一次大作业最后一题增加了试卷信息将#T 题目编号应与题目信息中的编号对应。一行信息中可有多项题目编号与分值。而且输入顺序也会发生改变,答卷信息也需要增加相应的题目分数,对输出要求进一步增加,对答卷总分也要求输出,并且增加了对代码健壮性的要求,要求如果输入的答案信息少于试卷的题目数量,没有答案信息的题目输"answer is null",如果答卷分值不足100分也要进行输出提示,alert: full score of test paper1 is not 100 points,而且可能一次输入两张试卷信息,完成答题,要有更多的方法对输入进行处理,第二次大作业在第一次大作业基础上增加一部分
但在question类部分没有改变。
在paper部分增加了变量score与totalScore便于存储分数
为了便于查询增加了
private Map<Integer, Question> questionMap = new LinkedHashMap<>();
private Map<Integer, Integer> questionScores = new LinkedHashMap<>();
一个用来保存问题,一个用来保存得分情况
public void setPaperID(int paperID) {
this.paperID = paperID; }
增加paperID便于处理多张答题的情况,以便处理相对应的paper。
Anwers部分增加了更多对答案的判断,尤其是对分数还有题目的结果输出
results.add(output);
resultScores.add(score);
totalScore += score;等等
本次的类图以及顺序图
第三次大作业最后一题(小题就不加以赘述了)相对于第二次难度更大多增加了格式的检测,这就要求对正则表达式的使用要更加熟练。由于前两次没有自己设计类图,而且仅仅凭着题目的建议和自己的感觉硬写,导致写到后期思路很乱,各个类之间的关系不明了,也没做到单一职责,这导致后期代码量上来以后,每次开始写自己代码前还要浪费很多时间去回想这些代码的作用。最后到处缝缝补补导致自己越来越胡乱,代码越来越不清晰,最后完成效果也不怎么样。
第三次大作业增加删除题目信息和学生信息
学生信息只输入一行,一行中包括所有学生的信息,每个学生的信息包括学号和姓名,格式如下。
格式:"#X:"+学号+" "+姓名+"-"+学号+" "+姓名....+"-"+学号+" "+姓名
删除题目信息为独行输入,每一行为一条删除信息,多条删除信息可分多行输入。该信息用于删除一道题目信息,题目被删除之后,引用该题目的试卷依然有效,但被删除的题目将以0分计,同时在输出答案时,题目内容与答案改为一条失效提示,例如:”the question 2 invalid~0”
对于检测到line.startsWith("#D:N-")需要删除题目是,我是通过对Question类里面的id进行赋值为-1;进而使其标记为删除的题目,分数进行为0处理。
最后一题加入了一个学生类Student,
为了更好的处理这些信息我创建了更多链表以及HashMap来对问题的信息、答卷信息、学生信息和警告信息等等处理,以及对警告信息的存储以方便后续进行处理,方便输出相应的警告,集中处理。
Map<Integer, Paper> papers = new HashMap<>();
Map<String, AnswerSheet> answerSheets = new HashMap<>();
Map<Integer, Question> questionBank = new HashMap<>();
List
List
Map<String, Student> students = new HashMap<>();
为了集中处理信息,输入也需要集中输入一次性输入所有信息将其保存在List
// 读取所有输入
while (!(input = scanner.nextLine()).equals("end")) {
inputs.add(input);}
下面是第三次大作业的类图以及顺序图
三、采坑心得
1.读题要仔细
这是我做大作业首要的收获,读题仔细能减少不必要的麻烦,对题目的输入需要敏感一点,就像第二次大作业的最后一题,他#S答案对应的是输入顺序,而不是第一个答案对应第一题,第二个答案对应第二题,如果输入的时候采用的是乱序输入那就会导致不同的题目对应的标准答案出错,导致得不到对应的输出。但需要注意的是,第三次大作业最后一题的#S的答案又有了对应的题目标号,需要进行索引,这就导致第三题不能直接复用第二题的基础,需要进行修改逻辑以及代码。还有类似很多,我就因为读题不仔细,导致有时候需要画长时间进行对代码改错,时间长了对自己逻辑以及编程有直接影响,会导致逻辑不是那么清晰,又需要进行逻辑梳理,这将导致进行恶性循环,也会打击一点自信心。
2.写代码需要多写注释
由于我对Java编程能力没有那么强,每次完成大作业的最后一题都要花费长时间,通常不能够一次完成作业,都需要花费好几天,这个过程写注释就非常需要了,通常调侃说:不写注释的代码只有自己本人和上帝看得懂。但只要三天后就只有上帝看到的懂了。这句话虽然有点玄学,但确实是编程人的实际情况,每次我写写代码把战线拉长的时候,一旦忘了写注释就一朝回到解放前,又要重新开始捋捋思路。也会浪费长时间,导致代码不连贯,最好还是能够一口气将代码完成。写注释的时候最好的是能将每一个变量的作用,每一个方法的作用,每一个代码块的作用都要给出注释,因为当代码量大起来后,你可以通过注释去了解过去的自己写这些代码的目的,而不用去逐条逐条的看代码,逐条逐条看代码是非常恐怖了。所以写代码加注释是非常重要的。
3.画一下顺序图与类图的必要性
画顺序图能帮助我们更好理清思路,你写代码的时候可以先构造一个大概的框架,然后在这个框架的基础上进行画顺序图,通过画顺序图的过程能够发现很多自己欠缺 考虑的方面,能让自己对框架逐渐完善。然后再通过顺序图完成相应的类图,最后进行编写代码。虽然画顺序图和类图会比较花费时间,但如果时间充足的话,能对自己写代码有很好的帮助。
4.要勇于学习新知识
我对于未知的新东西就会有一点畏惧,对Java里面很多方法都没有好好认真学进去,只是那种陌生感让人感觉不太自信,就比如正则表达式,我就觉得学起来很烦,能不用正则表达式我就会不用,总觉得自己学不会,但看了同学的代码发现如果使用正则表达式就会简单很多,我也慢慢强迫自己去学正则表达式,虽然学的比较慢,但总算学到了一点。要 跳出舒适圈,勇于学习新知识。
四、改进建议:对相应题目的编码改进给出自己的见解,做到可持续改进
对编程的类的封装很重要,最好对类分的细致一点,这样能在下一次大作业的时候能更好的复用,就比如一个类最好就只完成一件事,输入就输入,输出就输出,越简单后面就能越能复用,就能减轻下一次代码的代码量,我写代码能力没那么强就设置了四个类,函数也写的不多,导致我每次大作业都对代码有长时间的修改。
五、总结
在本阶段三次题目集的学习过程中,我获得了许多宝贵的经验和技术提升。从基础的Java语法到类的设计,再到面向对象编程思想的理解,每一步都让我对Java有了更深的认识。通过这些练习,我不仅掌握了构造方法、toString方法的使用,还学会了如何处理数据格式,比如对浮点数的精确控制。还学习到很多新方法类似与Java里面的链表,hashmap还有正则表达式等等,提升了我的程序设计能力。同时,我也深刻认识到了代码注释的重要性,良好的注释不仅能帮助他人理解代码逻辑,也能在未来自我回顾时提供极大的便利。我也越来越深刻体会到了类与对象的使用。此外,还增强了我的自主学习能力。面对不熟悉的正则表达式,我学会了如何有效地查找资料并解决问题。
在建议方面,我认为目前的课程安排对我们学生来说是一个不小的挑战。虽然每次作业给予了一周的时间来完成,但是实际上,由于大三课程安排紧密,我们可用于Java编程的时间十分有限。如果把所有课余时间都投入到Java的学习中,恐怕也无法按时完成所有的任务,因为我们还需要兼顾其他科目的作业。
而对于线上线下课堂的改进方面,我认为上课过程中和学生的互动是很有必要的,对于一些抽象难懂的知识,如果通过简单代码例子的方式实现,我们可能理解得更快。