(1)前言
本阶段三次题目集涵盖了从基础编程概念到较复杂算法设计等多个知识点。题量适中,难度呈梯度上升,从简单的数据结构与算法实现到复杂的问题求解,逐步挑战学生的编程能力。
第一次题目集主要考察基本语法、数据类型和简单的控制结构;第二次题目集则增加了数组、链表等数据结构的应用;到了第三次题目集,题目则涉及到了正则表达式的实现以及动态规划。整体而言,题目难度逐次递增,既考察了学生对基础知识的掌握,也检验了他们的分析和解决问题的能力。
(2)设计与分析
一、第一次题目集共有五道题,前四道题比较基础主要考察类的设计、类和对象的使用、类、数组的基本运用、关联类。最后一题是答题判题程序-1综合了前四道题的技巧。
就最后一题而言:
我首先仔细读题,考虑到出入格式是严格按照顺序的(第一行是n;后面n行是question,再下一行是answer,最后一行是end)。
我就一切从简,先用nextLine读n,再用nextLine读n行question,接着用next读到空格前的answer并用每读一个答案就循环给第i个题判断答案是否正确。最后读到end的时候就要输出了。
输出则是先打印n行题目与答案,最后一行打印true 或false。
1、读题功能我写在Question类当中。将"N:|Q:|A:"都替换成空,再用"#"分割成三个部分,分别是id, Content, StandardAnswer。
点击查看代码
public Question(String input) {
String tmp = input.replaceAll("N:|Q:|A:","");
String[] a = tmp.trim().split("#");
a[1] = a[1].trim();
this.id = Integer.parseInt(a[1]);
this.Content = a[2].trim();
this.StandardAnswer = a[3].trim();
}
点击查看代码
if(a.equals("end")) {
for (int i = 1; i <= n; i++) {
for(int j = 0; j < n; j++) {
if(question[j].getID() == i)
question[j].printInfo();
}
}
for (int i = 1; i <= n; i++) {
for(int j = 0; j < n; j++) {
if(question[j].getID() == i)
question[j].isTrue();
}
if(i != n) System.out.print(" ");
}
}
二、第二次题目集共有四道题,前三道题比较基础主要考察前一个题目级的内容,以及排序查找更深层次的类与对象。最后一题是答题判题程序-2综合了前三道题的技巧。
就最后一题而言:
答题判题程序-2比之答题判题程序-1,新增了试卷信息,并且存在乱序输入,Question与Answer(AnswerSheet)与Paper(TestPaper)可能穿插输入,以及一些试卷的设计是否有100分、答卷分数的统计、问卷中是否答题。
1、考虑到新增了个试卷信息,对于答题判题程序-1的类的设计明显不够用,我就对Question、Answer、Paper三个不同的信息都采取了设计。Answer中使用了Map和Paper中使用了List。
点击查看代码
class Question {//题目
private int id;
private String content;
private String answer;
Question() {
}
Question(int id, String content, String answer) {
this.id = id;
this.content = content;
this.answer = answer;
}
}
class TestPaper {//问卷
int id;
Map<Integer, Integer> scores;//题号对应的标准答案
TestPaper(int id) {
this.id = id;
this.scores = new LinkedHashMap<>();
}
}
class AnswerSheet {//答卷
int id;
List<String> answers;//答题者的答案
AnswerSheet(int id) {
this.id = id;
this.answers = new ArrayList<>();
}
}
2、考虑到存在乱序输入的可能,我学习到了startsWith(),通过判断一行的前三个字符,来储存相应的信息,如果是"#N:",则存到questions(题目信息)(LinkedHashMap)中。如果是"#T:",则存到testPapers(问卷信息)(ArrayList)中。如果是"#S:",则存到answerSheets(答卷信息)(ArrayList)中,如果是end,则输出结果。
该功能我写到了processInput()中。
点击查看代码
public void processInput() {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.equals("end")) {
break;
}
if (line.startsWith("#N:")) {
String[] parts = line.split("#");
int id = Integer.parseInt(parts[1].trim().split(":")[1]);
String content = parts[2].trim().split(":")[1];
String answer = parts[3].trim().split(":")[1];
addQuestion(id, content, answer);
} else if (line.startsWith("#T:")) {
String[] parts = line.split(" ", 2);
int id = Integer.parseInt(parts[0].trim().split(":")[1]);
String questionsScores = parts[1];
addTestPaper(id, questionsScores);
} else if (line.startsWith("#S:")) {
String[] parts = line.split("#");
int id = Integer.parseInt(parts[1].trim().split(":")[1]);
String answers = line.substring(line.indexOf("#A:"));
addAnswerSheet(id, answers);
}
}
}
3、输出部分:
先按照Paper顺序,判断是否满分为100。
再按照Answer顺序,在List中从i=0开始,取第i个answerSheets。再从List中从n=0中,取第n个testPapers。如果两者的id(编号)相等,则说明试卷号有效,再从testPaper中的scores与questions中的answer和answerSheets中的answers(List)做比较,判断对错并记分。
该功能在printResults()中实现:
点击查看代码
public void printResults() {
for (TestPaper testPaper : testPapers) {
if (testPaper.getTotalScore() != 100) {
System.out.println("alert: full score of test paper" + testPaper.id + " is not 100 points");
}
}
for (int i = 0; i < answerSheets.size(); i++) {
boolean flag = false;
AnswerSheet answerSheet = answerSheets.get(i);
for(int n = 0; n < testPapers.size(); n++) {
TestPaper testPaper = testPapers.get(n);
if(testPaper.getID() == answerSheet.getID()) {
flag = true;
Integer count = 0;
for (Map.Entry<Integer, Integer> entry : testPaper.scores.entrySet()) {
count ++;
int questionId = entry.getKey();
int score = entry.getValue();
if(answerSheet.answers.size() >= count) {
String answer = answerSheet.answers.get(count - 1);
boolean correct = checkAnswer(questionId, answer);
System.out.println(questions.get(questionId).getContent() + "~" + answer + "~" + (correct ? "true" : "false"));
} else {
System.out.println("answer is null");
}
}
List<Integer> scoresList = new ArrayList<>();
for (int j = 0; j < testPaper.scores.size(); j++) {
int questionId = testPaper.scores.keySet().stream().toArray(Integer[]::new)[j];
String answer = answerSheet.answers.size() > j ? answerSheet.answers.get(j) : "answer is null";
int score = checkAnswer(questionId, answer) ? testPaper.scores.get(questionId) : 0;
scoresList.add(score);
}
System.out.println(scoresList.stream().map(Object::toString).collect(Collectors.joining(" ")) + "~" + scoresList.stream().mapToInt(Integer::intValue).sum());
}
}
if (flag == false) {
System.out.println("The test paper number does not exist");
}
}
}
三、第三次题目集共有三道题,前二道题比较基础主要考察前两个题目级的内容,以及面向对象编程的封装性以及类的基本使用。最后一题是答题判题程序-3综合了前两道题的技巧。
就最后一题而言:
答题判题程序-3比之答题判题程序-2,新增了学生信息、删除题目信息,并且需要实现格式错误提示信息,被删除的题目提示信息、题目引用错误提示信息、试卷号引用错误提示输出、学号引用错误提示信息。比前两个答题判题程序更加复杂。
1、类的设计:
Question中新增了个isexist属性,判断题目是否被删除。AnswerSheet类新增了String Sid(学生id),以及answers从List
并且新增了Student类。
点击查看代码
class Student {//学生
String Sid;
String name;
Student(String Sid, String name) {
this.Sid = Sid;
this.name = name;
}
String getSID() {
return Sid;
}
String getName() {
return name;
}
}
2、输入信息的获取:
startsWith()的使用新增了判断"#X:"和"#D:",前者是获取学生信息,后者是删除题目信息。
点击查看代码
else if (line.startsWith("#X:")) {
String parts = line.split(":")[1];
String[] stus = parts.split("-");
for (int i = 0; i < stus.length; i++) {
String Sid = stus[i].trim().split(" ")[0];
String name = stus[i].trim().split(" ")[1];
Student student = new Student(Sid, name);
students.put(Sid, student);
}
} else if (line.startsWith("#D:")) {
String parts = line.split("-")[1];
int questionId = Integer.parseInt(parts.trim());
questions.get(questionId).setisExist(false);
}
此外使用了正则表达式判断了信息输入格式是否正确
点击查看代码
if (line.startsWith("#N:")) {
Pattern pattern = Pattern.compile("(#N:(\\w+) (#Q:(.+))) (#A:(\\w+))");
Matcher matcher = pattern.matcher(line);
if(matcher.find()) {
String[] parts = line.split("#");
int id = Integer.parseInt(parts[1].trim().split(":")[1]);
String content = parts[2].trim().split(":")[1];
String answer = parts[3].trim().split(":")[1];
boolean isexist = true;
addQuestion(id, content, answer, isexist);
} else {
System.out.println("wrong format:" + line);
}
}
3、输出格式:
先按照Paper顺序,判断是否满分为100。
再按照Answer顺序,在List中从i=0开始,取第i个answerSheets。再从List中从n=0中,取第n个testPapers。如果两者的id(编号)相等,则说明试卷号有效,再从testPaper中的scores中的key(题号)和answerSheets中的answers(Map)做比较,如果questions(题目)中不存在则输出"non-existent question~0",判为0分;如果answerSheet.answers中有这一题则判断是否被删除,如果被删除则输出"the question " + questionId + " invalid~0",判为0分,否则判断对错并记分;其他情况则说明未作答,输出"answer is null"。
该功能在printResults()中实现:
点击查看代码
public void printResults() {
for (TestPaper testPaper : testPapers) {
if (testPaper.getTotalScore() != 100) {
System.out.println("alert: full score of test paper" + testPaper.id + " is not 100 points");
}
}
for (int i = 0; i < answerSheets.size(); i++) {
boolean flag = false;
AnswerSheet answerSheet = answerSheets.get(i);
for(int n = 0; n < testPapers.size(); n++) {
TestPaper testPaper = testPapers.get(n);
if(testPaper.getID() == answerSheet.getID()) {
flag = true;
List<Integer> scoresList = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : testPaper.scores.entrySet()) {
int questionId = entry.getKey();
int score = entry.getValue();
if(!questions.containsKey(questionId)) {
System.out.println("non-existent question~0");
scoresList.add(0);
} else if(answerSheet.answers.containsKey(questionId)) {//答卷中是否答题
if(questions.get(questionId).getisExist() == true) {//题目存在
String answer = answerSheet.answers.get(questionId);
boolean correct = checkAnswer(questionId, answer);
System.out.println(questions.get(questionId).getContent() + "~" + answer + "~" + (correct ? "true" : "false"));
if(correct == true) {
scoresList.add(score);
} else {
scoresList.add(0);
}
} else {//题目被删除
System.out.println("the question " + questionId + " invalid~0");
scoresList.add(0);
}
} else {//否则answer is null
System.out.println("answer is null");
scoresList.add(0);
}
}
if(!students.containsKey(answerSheet.getSID())) {
System.out.println(answerSheet.getSID() + " not found");
} else {
Student student = students.get(answerSheet.getSID());
System.out.println(student.getSID() + " " + student.getName() + ": " + scoresList.stream().map(Object::toString).collect(Collectors.joining(" ")) + "~" + scoresList.stream().mapToInt(Integer::intValue).sum());
}
}
}
if (flag == false) {
System.out.println("The test paper number does not exist");
}
}
}
在分析过程中,我发现自己在实现算法时过于注重细节而忽略了整体架构的设计,导致代码结构不够清晰。此外,对于一些边界条件的处理也不够完善,这需要在今后的编程实践中加以改进。
(3)采坑心得
在源码提交过程中,我遇到了几个常见问题。首先是语法错误,这通常是由于对编程语言规则理解不透彻或粗心大意导致的。为了避免这类错误,我加强了对语法规则的学习,并在编写代码时更加细心。
其次是逻辑错误,这类错误往往更难发现和修复。为了解决这个问题,我加强了测试用例的设计和验证,确保代码在各种情况下都能正确运行。
此外,我还发现自己在时间管理和代码复用方面存在不足。为了提高效率,我学会了使用版本控制工具来管理代码,并尝试将重复的代码封装成函数或类进行复用。
(4)改进建议
针对上述分析和采坑心得,我提出以下改进建议:
加强基础知识的学习和理解,尤其是对语法规则和常用数据结构的掌握;
提高问题分析和解决能力,多做一些综合性题目来锻炼自己的思维;
注重代码质量和可读性,遵循良好的编程规范,避免过于复杂的代码结构;
加强测试和验证工作,确保代码的正确性和稳定性;
学会使用工具来提高编程效率和质量,如版本控制工具、代码分析工具等。
(5)总结
通过本阶段三次题目集的练习,我收获颇丰。我不仅巩固了基础知识,还提高了编程能力和问题解决能力。同时,我也认识到自己在编程实践中还存在许多不足之处,需要继续努力学习和提高。
对于教师、课程、作业等方面的建议,我认为可以增加一些综合性题目的比重,以更好地检验学生的综合能力。此外,还可以组织一些线上或线下的讨论会,让学生分享自己的编程经验和心得,促进相互学习和交流。Blog就是一个很好的交流渠道,同学们通过阅读他人的Blog来学习他人的方法,减少自己可能遇到的错误。
总之,本阶段的题目集对于我的编程能力提升起到了很大的帮助作用。我将继续努力学习和实践,争取在下一阶段取得更好的成绩。
标签:Java,String,答题,int,split,判题,answer,题目,id From: https://www.cnblogs.com/2052083792qq/p/18147536