前三次OOP作业总结Blog
-
前言
-
作为第一次3+1的总结,这次题目集的难度逐渐升高,题量、阅读量和测试点的数量变化都很大,所以对我们的编程和理解能力提出了更高的要求。例如在第一次到第三次的题目集中,类的数量由三个增长到了十余个。投入的时间也由最开始的45个小时到了后来的1824小时。这个过程从主观来说非常的痛苦,但是好在并不是全无收获。
-
在这三周的时间里存在很多的问题,一开始根本不懂得数据如何去保存,也不知道类如何去使用。第一阶段的题目集中非常着重的考察了正则表达式的使用,这一特点在第三次题目集中尤为显著。这也意味着很多东西都需要从0开始,这个从无到有的过程才是对我们能力的训练。
-
在第三次题目集中测试点也增长到了前所未有的28个,情况非常的复杂,而且存在一个非常明显的现象。在题目集开放至第三天的时候,达到满分的只有寥寥几人,其余很多人都停留在了94、97分的阶段,300多人提交了一万多份答卷,而通过率却只有堪堪1%。造成这一现象的主要原因是一些特殊测试点的存在,比如“答案为空字符”、“空白卷”等测试点成为了学生去往满分的路上最大的拦路虎。这说明,在设计代码的时候,并没有考虑到一些非常极端的情况,这是一个很大的缺陷。为了解决这些问题,我们陷入了非常痛苦的循环之中:
不断地用额外的测试点进行调试
不断地询问别人遇到的问题
不断地修改已经提交了几十遍的代码
-
-
正文
-
第一次题目集
这次题目集难度倒是不高,但是对于接触面向对象编程不久的小萌新来说还是颇具挑战:
题目主干:
设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
其中需要处理的数据一共只有两个类型:
题目内容 "#N:"+题号+" "+"#Q:"+题目内容+" "#A:"+标准答案
答题信息 "#A:"+答案内容
这里需要使用正则表达式去分割各个信息的不同部分,并且储存起来
UML类图:
可以看到一共设计了三个类,分别是AnswerSheet,ExamPaper,Question。
简单展示一下题目集一的复杂度:
复杂度:
Method CogC ev(G) iv(G) v(G) AnswerSheet.AnswerSheet() 0 1 1 1 AnswerSheet.getAnswer(int) 0 1 1 1 AnswerSheet.saveAnswer(String) 0 1 1 1 ExamPaper.ExamPaper() 0 1 1 1 ExamPaper.getQuestionContent(int) 0 1 1 1 ExamPaper.judgeAnswer(int, String) 0 1 1 1 ExamPaper.saveQuestion(int, String, String) 0 1 1 1 ExamPaper.sortByNumber() 0 1 1 1 Main.main(String[]) 11 1 7 9 Question.Question(int, String, String) 0 1 1 1 Question.getContent() 0 1 1 1 Question.getNumber() 0 1 1 1 Question.getStandardAnswer() 0 1 1 1 Question.judgeAnswer(String) 0 1 1 1 从这个表格中可以看出Main的复杂度比较高,主要是因为数据的读入和输出都是在主函数里面完成的:
public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int questionCount = Integer.parseInt(scanner.nextLine()); ExamPaper examPaper = new ExamPaper(); for (int i = 0; i < questionCount; i++) { String input = scanner.nextLine().trim(); String[] parts = input.split("#"); int number = Integer.parseInt(parts[1].split(":")[1].trim()); String content = parts[2].split(":")[1].trim(); String standardAnswer = parts[3].split(":")[1].trim(); examPaper.saveQuestion(number, content, standardAnswer); } AnswerSheet answerSheet = new AnswerSheet(); String answerInput = scanner.nextLine().trim(); while (!answerInput.equals("end")) { String[] answers = answerInput.split("\\s+"); for (String answer : answers) { answerSheet.saveAnswer(answer); } answerInput = scanner.nextLine().trim(); } examPaper.sortByNumber(); for (int i = 1; i <= questionCount; i++) { String questionContent = examPaper.getQuestionContent(i); String answer = answerSheet.getAnswer(i); System.out.println(questionContent + "~" + answer.replace("#A:","")); } for (int i = 1; i <= questionCount; i++) { String answer = answerSheet.getAnswer(i); boolean result = examPaper.judgeAnswer(i, answer.replace("#A:","")); System.out.print(result ? "true" : "false"); if(i>=1 && i!=questionCount){ System.out.print(" "); } } } }
-
第二次题目集
第二次题目集我完成的不好,这是显而易见的,因为越来越多的数据需要处理,让我一个对数组的使用很是生疏的初学者较为棘手,所以这次题目及的代码就已经写成
一坨乱麻了,非常的难看。问题主要出现在对于试卷信息的处理上:
试卷信息
格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值
由于这次添加了试卷信息,需要给出得分,题目分值和题目编号一一对应,正常来说需要使用到HashMap这样的映射关系,将题目编号和题目分值以映射的关系储存在一起,便可以通过题目编号寻找到相应的分值。但是当时我铁了心的要用List实现,后来发现非常的困难,但是我对于HashMap的使用非常的生疏,所以也没有及时的更改我的思路,导致最后的代码修修补补,毫无逻辑可言。
UML类图:
主函数非常的复杂,属于是剑走偏锋,两百多行的代码,主函数就占了半壁江山:
复杂度:
Class OCavg OCmax WMC AnswerQuestion 2.2 3 11 AnswerSheet 1.25 2 5 ExamPaper 1 1 5 Main 28 28 28 Question 1 1 5 Score 1 1 4 Method CogC ev(G) iv(G) v(G) AnswerQuestion.AnswerQuestion() 0 1 1 1 AnswerQuestion.getExamQuestionList(int) 3 1 3 3 AnswerQuestion.isFullScore(int) 3 1 3 3 AnswerQuestion.isPaperExist(int) 3 3 2 3 AnswerQuestion.saveExamQuestion(int, int, int) 0 1 1 1 AnswerSheet.AnswerSheet() 0 1 1 1 AnswerSheet.getAnswer(int) 1 2 2 2 AnswerSheet.getAnswers() 0 1 1 1 AnswerSheet.saveAnswer(String) 0 1 1 1 ExamPaper.ExamPaper() 0 1 1 1 ExamPaper.getQuestionContent(int) 0 1 1 1 ExamPaper.judgeAnswer(int, String) 0 1 1 1 ExamPaper.saveQuestion(int, String, String) 0 1 1 1 ExamPaper.sortByNumber() 0 1 1 1 Main.main(String[]) 72 5 27 29 Question.Question(int, String, String) 0 1 1 1 Question.getContent() 0 1 1 1 Question.getNumber() 0 1 1 1 Question.getStandardAnswer() 0 1 1 1 Question.judgeAnswer(String) 0 1 1 1 Score.Score(int, int, int) 0 1 1 1 Score.getPaperNumber() 0 1 1 1 Score.getQuestionScore() 0 1 1 1 Score.getQuestionSequence() 0 1 1 1 我看到这个数据的时候也是感觉到了非常的夸张,基本上成为了主函数战士,一个人把其他类的活干了一半。
还是看一下数据的输入部分吧:
数据输入:
while (true) { String input = scanner.nextLine().trim(); if (input.equals("end")) { break; } String[] parts = input.split("#"); String types = parts[1].split(":")[0].trim(); if (types.equals("N")) { int questionNumber = Integer.parseInt(parts[1].split(":")[1].trim()); String content = parts[2].split(":")[1].trim(); String standardAnswer = parts[3].split(":")[1].trim(); examPaper.saveQuestion(questionNumber, content, standardAnswer); } if (types.equals("S")) { String[] answerParts = input.trim().split("\\s+"); int answerNumber = Integer.parseInt(answerParts[0].replace("#S:", "").trim()); sNumbers.add(answerNumber); AnswerSheet answerSheet = new AnswerSheet(); for (String answerPart : answerParts) { if (answerPart.contains("A")) { answerSheet.saveAnswer(answerPart.replace("#A:", "").trim()); } } answerSheets.add(answerSheet); } if (types.equals("T")) { String[] paperParts = input.trim().split("\\s+"); int paperNumber = Integer.parseInt(paperParts[0].replace("#T:", "").trim()); tNumbers.add(paperNumber); tCount++; for (String paperPart : paperParts) { if (paperPart.contains("-")) { answerQuestion.saveExamQuestion(paperNumber, Integer.parseInt(paperPart.split("-")[0].trim()), Integer.parseInt(paperPart.split("-")[1].trim())); } } } }
在这里使用了一个while循环来不断地读取每一行的数据,当遇到end的时候便直接退出循环。这段代码对数据的分割都是通过split完成的,而不是使用正则表达式,对于这道题来说,前者的功能堪堪够用,但是对于第三次题目集来说就有一点
标签:总结,题目,String,int,Question,ArrayList,AnswerSheet,OOP,第一阶段 From: https://www.cnblogs.com/vhengeee/p/18149470狗骑吕布的感觉了。
-