一、前言
第六次题目集中有一道题,题目有一定的难度,是课程成绩统计系统-1,他对于各个类之间的嵌套关系以及ArrayList等数据的储存和利用有一定的涉及。
第七次题目集的难度有一定的减少,因为一共有四道题,第一二和四题较简单,第三题就是课程统计系统-2,对于我们有一点点不友好,它是在课程成绩统计系统-1的基础上加上其他功能并进行改进,类与类的关系复杂程度加深。而另外三题主要考察我们对于容器-HashMap的检索与排序,题目要求较为基础,内容较简单。(相比于课程成绩统计系统来说已经是简单很多了······)
第八次的题目集的难度某些题更上一步,共有五道题,有对于ArrayList的排序以及其他锻炼我们编程能力的接口与覆盖的练习,当然少不了最难的课程成绩统计系统-3·······。
二、设计与分析
(题目集一中的题目较为简单,可分析部分较少,但做题需注意题目的要求与一开始的初始条件,可能结果与正确答案就差一行代码)
*这里主要分析课程成绩统计系统
题目要求(图片)
该题代码:
import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String[] args) { int count = 0; Scanner sc = new Scanner(System.in); ArrayList<Course> courses = new ArrayList<>(); ArrayList<Student> students = new ArrayList<>(); // while (true) { // String[] data = sc.nextLine().split(" "); // if (data[0].equals("end")) { // break; // } // Course course = new Course(data[0], data[1], data[2]); // courses.add(course); // } while (true) { String[] data = sc.nextLine().split(" "); if (data[0].equals("end")) { break; } Student student = new Student(data[0], data[1]); for (Course course : courses) { if (course.getName().equals(data[2])) { if (course.getType().equals("必修") && course.getExam().equals(data[3])) { student.addGrade(new Grade(course, Integer.parseInt(data[4]))); } else if (course.getType().equals("选修") && course.getExam().equals(data[3])) { student.addGrade(new Grade(course, Integer.parseInt(data[4]))); } else { System.out.println(student.getID() + " " + student.getName() + " : access mode mismatch"); continue; } } } students.add(student); } for (Student student : students) { int totalScore = 0, totalCredit = 0; for (Course course : courses) { int score = student.getGrade(course); if (score == -1) { continue; } else if (score == -2) { System.out.println(student.getID() + " " + student.getName() + " did not take " + course.getName()); continue; } totalScore += score * course.getCredit(); totalCredit += course.getCredit(); } if (totalCredit == 0) { if(count < 2){ System.out.println(student.getID() + " " + /* student.getName() + */"has no grades yet"); count++; } else System.out.print(student.getID() + " " + /* student.getName() + */"has no grades yet"); } else { double gpa = 1.0 * totalScore / totalCredit; System.out.printf("%s %s %.0f\n", student.getID(), student.getName(), gpa); for (Course course : courses) { int score = student.getGrade(course); if (score == -1) { System.out.println(course.getName() + " has no grades yet"); } else if (score == -2) { System.out.println(course.getName() + " has no records"); } else { System.out.printf("%s %d ", course.getName(), score); } } System.out.println(); System.out.printf("%s %.0f\n", student.getID().substring(0, 6), gpa); } } } } class Course { private String name; private String type; private String exam; private int credit; public Course(String name, String type, String exam) { this.name = name; this.type = type; this.exam = exam; this.credit = 2; } public String getName() { return name; } public String getType() { return type; } public String getExam() { return exam; } public int getCredit() { return credit; } } class Grade { private Course course; private int score; public Grade(Course course, int score) { this.course = course; this.score = score; } public Course getCourse() { return course; } public int getScore() { return score; } } class Student { private String id; private String name; private ArrayList<Grade> grades; public Student(String id, String name) { this.id = id; this.name = name; this.grades = new ArrayList<>(); } public String getID() { return id; } public String getName() { return name; } public void addGrade(Grade grade) { grades.add(grade); } public int getGrade(Course course) { boolean hasRecord = false; for (Grade grade : grades) { if (grade.getCourse().getName().equals(course.getName())) { hasRecord = true; return grade.getScore(); } } if (!hasRecord) { return -1; } else { return -2; } } }
分析:课程成绩统计程序-1虽说相比前面的题目对于我们而言是一个大挑战,但是不断熟悉类与类之间的关系与调用,凭借我们之前的基础,还是能加把劲赶出来的。
课程成绩统计程序-2
分析:该程序相比与课程统计-1增加了实验的功能,模板还是套用课程统计-1,但因有了这功能输入的情况也变得随之不一样了,课程的数量也不一样。一开始我认为,可能并不太难,因为我们有了第一次的经验,相较于之前的代码,我最初的思路是增加addCourse()与但最后调试时发现我的操作与数据一直无法相对应,它们之间毫无关联,这时才意识到可能没有这么简单,后来我通过再次深入了解静态变量与静态方法,数组大小的原因等,解决了该问题。
部分代码:
ArrayList<Course> courses = new ArrayList<>(); ArrayList<Student> students = new ArrayList<>(); // while (true) { // String[] data = sc.nextLine().split(" "); // if (data[0].equals("end")) { // break; // } // Course course = new Course(data[0], data[1], data[2]); // courses.add(course); // } while (true) { String[] data = sc.nextLine().split(" "); if (data[0].equals("end")) { break; } Student student = new Student(data[0], data[1]); for (Course course : courses) { if (course.getName().equals(data[2])) { if (course.getType().equals("必修") && course.getExam().equals(data[3])) { student.addGrade(new Grade(course, Integer.parseInt(data[4]))); } else if (course.getType().equals("选修") && course.getExam().equals(data[3])) { student.addGrade(new Grade(course, Integer.parseInt(data[4]))); } else { System.out.println(student.getID() + " " + student.getName() + " : access mode mismatch"); continue; } } } students.add(student); }
课程成绩统计程序-3
题目增加的部分要求:
分析:课程成绩统计程序-3新加了计算总成绩等信息,组合关系等。第三次程序对于前面来说,虽说是延续着先前的模板,但难度还是一下子增幅太大了,不仅对于功能的增加过多,同时需要思考运用的灵活性,某方面来说要更改部分先前的逻辑,增添新的东西,使该闭环更加的复杂。
但部分测试点还是出错,课程成绩统计程序-3的难度还是对我来说较大,无法顺利完成,类与类之间的关系过于复杂。
7-1 容器-ArrayList-排序
代码:
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); ArrayList<Student> list = new ArrayList<>(); while (true) { String str = sc.nextLine(); if ("end".equals(str)) { break; } String[] strs = str.split(" "); int id = Integer.parseInt(strs[0]); String name = strs[1]; int math = Integer.parseInt(strs[2]); int physics = Integer.parseInt(strs[3]); Student s = new Student(id, name, math, physics); list.add(s); } Collections.sort(list, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { int sum1 = o1.getMath() + o1.getPhysics(); int sum2 = o2.getMath() + o2.getPhysics(); if (sum1 != sum2) { return sum2 - sum1; } else { return list.indexOf(o1) - list.indexOf(o2); } } }); for (Student student : list) { System.out.println(student.toString()); } } } class Student { private int id; private String name; private int math; private int physics; public Student(int id, String name, int math, int physics) { this.id = id; this.name = name; this.math = math; this.physics = physics; } public int getId() { return id; } public String getName() { return name; } public int getMath() { return math; } public int getPhysics() { return physics; } public int getSum() { return math + physics; } @Override public String toString() { return id + " " + name + " " + getSum(); } }
7-3 jmu-Java-02基本语法-03-身份证排序
分析:这些题目的难度都不大,但是需要有耐心进行一次次的测试。
三、踩坑心得
1、非零返回:
编写课程成绩统计程序的代码时,测试点经常由于非零返回出错,实际上就是程序的语法在中间就出现了异常,或者是没有结束的方法,导致程序可能返回null,判断的逻辑出错了,无法进行到该方法最后的return,因此出现了非零返回的状态。
2、运行超时:
在编写“容器-ArrayList-排序”以及“课程成绩统计程序”等题目时,也都出现了该情况,最初我使用嵌套循环的方法,结果严重超时,代码的复杂度太高了,因此一次两个测试点都错了,我重复修改了很多次但仍然没有很好的改善,因此去网上查阅方法查资料,学会了字符流输入,动态的将其的大量计算给省去了。
四、主要困难以及改进建议
1、主要困难:
a.我认为初学Java的我们,第一次的题目集对于我们来说可能比较友好,因为有了C语言的基础,但是对于后面编写的困难,难就难在我们对于Java很多与C语言不同的语法,以及类的用法不一样,我们没有办法直接像逻辑关系等直接套用,我们需要花时间慢慢去了解,因此一上来做类似菜单计价程序这样的题对于我们来说负担过大时间过短。
b.对于我们来说运用一门新的编程语言,我们要做到对而且得知道哪里错了,而PTA中测试点的模糊描述,让我们不知所以然,很难第一时间就了解自己的问题出现在哪里,只能不断的花时间去思索考虑并调试修正;同时在提交题目后不论对错,我们也没有答案可以参考,这样我认为不利于我们的提升,对于我们编写题目是一种困难。
c.题目难度的跳跃有点大,菜单计价程序若是通过慢慢添加一两个功能,我认为我们还能接受,但看到后面那十多二十来个的测试点,不禁会有想要放弃的念头,没有了继续编写的激情。
2、改进建议:
我认为PTA网站的测试点应该描述的更加详细,能够让我们提交之后更加清晰的了解到到底错了哪里;同时希望题目集时间截至时间过去了之后能够给我们参考答案,我认为这能让我们的提升更快,也能让我们每次写题目集都有连续的想法。我认为我们应该多去参考一些别人的代码来看看自己的代码究竟是哪里出了问题,请教他人请教老师;可以运用报表图等来辅助自己撰写代码,也方便让自己进行添加删改,同时对于代码进行注释,保证自己在做完其他题目之后还能回忆先前自己编写的内容。
五、总结
对于该三次的题目集,我认为对于我自己来说是一个很大的提升,PTA和这次的博客对我们来说都是很重要的提升自己的机会,也能够让我们回过头来给自己的成果予以反思、总结。虽然说过程有点艰难,但自己写出代码并看到它能成功运行时,心里有一种油然而生的成就感。我认为给我们更多的时间,让题目量可以增多但难度适当降低一些,能够增加我们的积极性,让我们对于Java的学习更加有动力。