首页 > 编程语言 >三次答题判题程序练习让你入门Java。

三次答题判题程序练习让你入门Java。

时间:2024-04-21 11:56:24浏览次数:23  
标签:Java String 答题 int split 判题 answer 题目 id

(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();
        
    }
2、输出功能:
点击查看代码
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 改成了Map<Integer, String>。
并且新增了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

相关文章

  • Java设计模式-责任链模式,应用接口多个参数验证,订单多个费用的计算
    Java设计模式-责任链模式,应用接口多个参数验证,订单多个费用的计算1.定义请求和返回对象的上下文对象packagecom.example.core.mydemo.java.filter;importjava.time.LocalDateTime;publicclassOrderReqContext{/***租客会员号*/StringmemNo;......
  • Java面试题:请谈谈对ThreadLocal的理解?
    ThreadLocal是一种特殊的变量存储机制,它提供了一种方式,可以在每个线程中保存数据,而不会受到其他线程的影响。这种机制在多线程编程中非常有用,因为它允许每个线程拥有自己的数据副本,从而避免了数据竞争和线程之间的干扰,以空间换时间。在Java中,ThreadLocal的实现主要涉及到三个类:Th......
  • [转帖]十年拉锯战终结束,Google 赢得 Java API 版权诉讼
    https://www.oschina.net/news/136073/googles-wins-lawsuit Google和Oracle(甲骨文)在法庭上就Android操作系统中Java编程语言的使用问题争吵了十年。美国最高法院在周一以6比2的投票结果裁定,Google对Java代码的使用被归为"合理使用",没有违反联邦版权法......
  • [转帖]Oracle 败了、谷歌赢了:Java API 版权案最终裁决
    https://zhuanlan.zhihu.com/p/362496136 周一,最高法院在Oracle围绕移动操作系统Android中所用软件的一起旷日持久的版权诉讼中判谷歌胜诉。法院的判决为6比2。大法官AmyConeyBarrett没有参与此案。该案涉及谷歌用于构建Android的12000行代码,这些代码是从SunMicrosy......
  • Solon Java 应用开发框架 v2.7.5 发布
    JavaSolon是什么框架?Java“新的”应用开发框架。从零开始构建(非java-ee架构),有灵活的接口规范与开放生态。追求:更快、更小、更简单提倡:克制、简洁、高效、开放、生态有什么特点?更高的计算性价比:并发高2~3倍;内存省50%更快的开发效率:内核小,入门快;调试重启快5......
  • 最新Java面试题带答案【2024中级】
    互联网大厂面试题1:阿里巴巴Java面试题2:阿里云Java面试题-实习生岗3:腾讯Java面试题-高级4:字节跳动Java面试题5:字节跳动Java面试题-大数据方向6:百度Java面试题7:蚂蚁金服Java面试题-中级8:蚂蚁金服Java面试题-高级9:京东Java面试题-中级10:拼多多Java面试题-电商部11:商汤科技......
  • java 异步任务,定时任务,邮件发送
    java异步任务,定时任务,邮件异步任务异步方法注解:@Async主程序开启异步注解功能:@EnableAsync定时任务开启定时功能的注解在main:@EnableSchedulingTaskScheduler:任务调用者TaskExecutor:任务执行者@EnableScheduling开启定时功能的注解@Scheduled固定......
  • Java 安全基础之 Java 反射机制和 ClassLoader 类加载机制
    目录Java反射机制反射java.lang.RuntimeClassLoader类加载机制URLClassLoaderJava反射机制Java反射(Reflection)是Java非常重要的动态特性。在运行状态中,通过Java的反射机制,我们能够判断一个对象所属的类。了解任意一个类的所有属性和方法。能够调用任意一个对象的任意方......
  • java Swagger 使用汇总
    Swagger1.Swagger简介最流行的api框架restfulapi在线自动生成工具:api文档与api定义同步更新直接运行,可以在线测试api接口支持多种语言:java,php2.官网https://swagger.io在项目中使用swagger需要springboxswagger2ui3.SpringBoot集成Swaggerhttps://mvnreposito......
  • Java面试题:为什么HashMap不建议使用对象作为Key?
    HashMap是一种基于哈希表的动态数据结构,它允许使用任意不可变对象作为键(key)来存储和检索数据。然而,在某些情况下,使用对象作为HashMap的键可能会遇到一些问题。 首先,我们需要明确对象作为HashMap的键需要满足一些条件:不可变性:对象的属性不能被修改,因为如果属性被修改,那......