題目集1-3的總結性Bolg

倾世、^忆流年發表於2024-04-21

一.前言:
在這幾周,我們進行了3次pta的題目訓練。每次的題目集的最後一個答題程式不斷迭代,使題目集的難度不斷增大,壓力很大。不過與此同時,這也使我們學到了很多。
以下是我的初步總結:
1.知識點
在我看來,答題程式實現的關鍵有兩點。

第一點是正確的使用正規表示式等技術提取輸入資訊,從答題程式-1僅有的N,A,到之後答題程式-2的S,T,D等資訊,怎麼提取出我想要的資訊?
並且因為有許多的變化,比如Q與A後面不一定是算式,可能是中文問題等。要求我們對正規表示式不斷的變更,以適應題目要求。而有時正規表示式並不能完全提取出所要的資訊,還要結合spilt,trim等函式進行修正,必要時可以用上StingBuild類等。

第二點則是類與物件的的安排與使用,提取的資訊怎麼儲存?儲存在哪裡,怎麼理清它們之前的關係?這需要我們架構好整體框架再動手,不然在不斷迭代下,可能之前的儲存邏輯就行不通了,直接整體崩塌,只能推倒重來。所以在我看來,理清資料間的邏輯,合理的儲存與使用資訊,是實現答題程式的關鍵所在。沒有思想的胡亂寫下去,必然會出現重大的錯誤,使程序無法繼續下去(我就是這樣的人)。
除此之外,字串陣列,ArraList類,hashmap的使用,也能讓我們在編碼的過程中更加輕鬆。
2.題量與難度
第一次作業相對簡單,邏輯清晰,難度不大,很快就可以完成。導致我誤判了答題程式的難度。

答題程式-2新增的T,S和新增的各種邏輯,使題目難度直線上升,而我拖到最後一天,無法完成。在補練中我依然拿不了滿分,問題出在S,T資料儲存與邏輯判斷輸出上(這裡不詳講),我因為結構與邏輯問題無法正確的匹配或者判斷S與T後面的資訊。

答題程式-3難度進一步提升,有了前車之鑑,我從題目釋出開始編碼,但是答題程式-3的邏輯複雜程度進一步提升,寫到後面我已經不知道自己寫的是什麼了,修前補後,狼狽不堪,到最後也只拿下一半的測試點。

二.設計與分析
1.首先是正規表示式的設計,為了方便我將三次答題程式的正規表示式的設計一併給出
答題程式-1
String regex = "#N:(\s\d+\s)#Q:(.)#A:(.)";
String regex = "#A:(\S+)";
答題程式-2
String regex = "#N:(\s\d+\s)#Q:(.)#A:(.)";
String regex ="#T:(\d+)\s(\d+-\d+)\s(\d+-\d+)(\s(\d+-\d+))";
String regex = "#(S|A)😦\d+)";
答題程式-3
"#N:(\s\d+\s)#Q:(.)#A:(.)";
"#T:\s(\d)\s(\s\d+-\d+\s)";
"#S:\s(\d+)\s+(\w)\s(#A:\s(\d+-?[^#]))";
"#D:N-\s\d+\s";
"#X:\s(\d+)\s(.)(-(\d+)\s(.))"
正是利用這些正規表示式,結合迴圈與相關的邏輯判斷幫我提取出輸入資訊。
2.結構設計(我認為我的失誤就在結構設計上,太過混亂與簡單)
答題程式-1
程式碼如下:

點選檢視程式碼
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.*;
class Ques{
    ArrayList<String> tihao=new ArrayList<>();
    ArrayList<String> Q=new ArrayList<>();
    ArrayList<String> A=new ArrayList<>();
    Ques(){
    }
}
public class Main {
    public static void main(String[] args) {
        String []Q=new String[99];
        String []SA=new String[99];
        String []QA=new String[99];
        ArrayList<String>start=new ArrayList<>();
        Ques ques=new Ques();
        Scanner sc=new Scanner(System.in);
        int num= sc.nextInt();
        sc.nextLine();
        while (sc.hasNextLine()){
            String row=sc.nextLine();
            start.add(row);
            if ("end".equals(row)){
                break;
            }
        }
        for(int i=0;i<start.size();i++){
            if(start.get(i).charAt(1)=='N'){
                String regex = "#N:(\\s*\\d+\\s*)#Q:(.*)#A:(.*)";;
                Pattern pattern = Pattern.compile(regex);
                Matcher matcher = pattern.matcher(start.get(i));
                while (matcher.find()) {
                    ques.tihao.add(matcher.group(1));
                    ques.Q.add(matcher.group(2));
                    ques.A.add(matcher.group(3));
                }
            }
            else if (start.get(i).charAt(1)=='A'){
                String regex = "#A:(\\S+)";
                Pattern pattern = Pattern.compile(regex);
                Matcher matcher = pattern.matcher(start.get(i));
                int index = 0;
                while (matcher.find()) {
                    QA[index] = matcher.group(1);
                    index++;
                }
            }
        }
        for (int i=0;i<ques.tihao.size();i++){
            int j=Integer.parseInt(ques.tihao.get(i).trim());
            Q[j-1]=ques.Q.get(i);
            SA[j-1]=ques.A.get(i);
        }
        for(int i=0;i<ques.tihao.size();i++){
            System.out.println(Q[i].trim()+"~"+QA[i]);
        }
        for(int i=0;i<ques.tihao.size();i++){
            if(QA[i].trim().equals(SA[i].trim())){
                System.out.print("true");
            }
            else {
                System.out.print("false");
            }
            if(i!=ques.tihao.size()-1){
                System.out.print(" ");}
        }
    }
}

定義了一個名為Ques的類,該類包含三個ArrayList:tihao用於儲存題號,Q用於儲存問題,A用於儲存答案。
在Main類中,定義了三個陣列:Q用於儲存問題,SA用於儲存正確答案,QA用於儲存使用者提供的答案。
使用Scanner類從輸入中讀取問題和答案。輸入以"end"結束。
使用正規表示式從輸入中提取問題和答案,並將它們儲存在Ques類的ArrayList中。
將Ques類的ArrayList中的問題和答案複製到Q和SA陣列中。
輸出問題和使用者提供的答案。
比較使用者提供的答案和正確答案,並輸出比較結果。
這個程式碼的主要問題在於它的可讀性和可維護性。例如,它使用了多個迴圈和條件語句,這使得程式碼難以理解和修改。此外,它還使用了硬編碼的陣列大小和索引,這使得程式碼不夠靈活。

為了改進這個程式碼:

使用更清晰的變數名和函式名,以提高程式碼的可讀性。
將程式碼分解為更小的函式,以提高程式碼的可維護性。
使用更靈活的資料結構,例如HashMap,以替代硬編碼的陣列大小和索引。
使用更清晰的輸入和輸出格式,以提高程式碼的可讀性。
答題程式-2
程式碼如下:

點選檢視程式碼
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.*;
class Ques{
    ArrayList<String> tihao=new ArrayList<>();
    ArrayList<String> Q=new ArrayList<>();
    ArrayList<String> A=new ArrayList<>();
    Ques(){
    }
}
class Score{
    ArrayList<String> tid=new ArrayList<>();
    ArrayList<String> scoid=new ArrayList<>();
    ArrayList<String> sco=new ArrayList<>();
    Score(){}
}
public class Main {
    public static void main(String[] args) {
        int end=0;
        int total=0;
        int total1=0;
        int b=0;
        String []Q=new String[99];
        String []QA=new String[99];
        String [][]SA1=new String[99][99];
        String []sco=new String[99];
        String []dsco=new String[99];
        ArrayList<String> Sid = new ArrayList<>();
        ArrayList<String> T = new ArrayList<>();
        ArrayList<ArrayList<String>> SA = new ArrayList<>();
        ArrayList<String>start=new ArrayList<>();
        Ques ques=new Ques();
        ArrayList<Score> scores = new ArrayList<>();
        Scanner sc=new Scanner(System.in);
        while (sc.hasNextLine()){
            String row=sc.nextLine();
            start.add(row);
            if ("end".equals(row)){
                break;
            }
        }
        for(int i=0;i<start.size();i++){
            if(start.get(i).charAt(1)=='N'){
                String regex = "#N:(\\s*\\d+\\s*)#Q:(.*)#A:(.*)";
                Pattern pattern = Pattern.compile(regex);
                Matcher matcher = pattern.matcher(start.get(i));
                while (matcher.find()) {
                    ques.tihao.add(matcher.group(1));
                    ques.Q.add(matcher.group(2));
                    ques.A.add(matcher.group(3));
                }
            }
            if(start.get(i).charAt(1)=='T'){
                T.add(start.get(i));
                String regex = "#T:(\\d+)\\s*(\\d+-\\d+)\\s*(\\d+-\\d+)(\\s*(\\d+-\\d+))*";
                Pattern pattern = Pattern.compile(regex);

                for (String input : T) {
                    Matcher matcher = pattern.matcher(input);
                    if (matcher.find()) {
                        Score score = new Score();
                        score.tid.add(matcher.group(1));
                        for (int k = 2; k <= matcher.groupCount(); k++) {
                            if (matcher.group(k) != null) {
                                String[] scoidSco = matcher.group(k).split("-");
                                score.scoid.add(scoidSco[0]);
                                score.sco.add(scoidSco[1]);
                            }
                        }
                        scores.add(score);
                    }
                }
            }
            else if (start.get(i).charAt(1)=='S'){
                String regex = "#(S|A):(\\d+)";
                Pattern pattern = Pattern.compile(regex);
                Matcher matcher = pattern.matcher(start.get(i));
                ArrayList<String> currentAList = null;
                while (matcher.find()) {
                    String type = matcher.group(1);
                    String value = matcher.group(2);
                    if ("S".equals(type)) {
                        Sid.add(value);
                        currentAList = new ArrayList<>();
                        SA.add((currentAList));
                    } else if ("A".equals(type) && currentAList != null) {
                        currentAList.add(value);
                    }
                }
            }
        }
        Score score=scores.get(0);
        for (int i=0;i<ques.tihao.size();i++){
            int j=Integer.parseInt(ques.tihao.get(i).trim());
            Q[j-1]=ques.Q.get(i);
            QA[j-1]=ques.A.get(i);
        }
        for(int i=0;i<SA.size();i++){
            for (int j=0;j<SA.get(i).size();j++){
                SA1[i][j]=SA.get(i).get(j);
            }
        }
        for (int i=0;i<score.scoid.size();i++){
            int j=Integer.parseInt(score.scoid.get(i).trim());
            sco[j-1]=score.sco.get(i);
        }
        for (int i=0;i<score.scoid.size();i++){
            total+=Integer.parseInt(score.sco.get(i));
        }
        if(total<100){
            System.out.println("alert: full score of test paper1 is not 100 points");
        }
        if (scores.size()>1){
            Score score1=scores.get(1);
            for (int i=0;i<score1.scoid.size();i++){
                int j=Integer.parseInt(score1.scoid.get(i).trim());
                sco[j-1]=score1.sco.get(i);
            }
            for (int i=0;i<score1.scoid.size();i++){
                total1+=Integer.parseInt(score1.sco.get(i));
            }
            if(total1<100){
                System.out.println("alert: full score of test paper2 is not 100 points");
            }
        }
        
        if(Integer.parseInt(Sid.get(0))>2){
            System.out.print("The test paper number does not exist");
        }else{
        for(int i=0;i<SA.get(0).size();i++){
            if(QA[Integer.parseInt(score.scoid.get(i))-1].trim().equals(SA1[0][i])){
                System.out.println(Q[Integer.parseInt(score.scoid.get(i))-1].trim()+"~"+ SA1[0][i]+'~'+"true");
                end+=Integer.parseInt(sco[Integer.parseInt(score.scoid.get(i))-1]);
                dsco[Integer.parseInt(score.scoid.get(i))-1]=sco[Integer.parseInt(score.scoid.get(i))-1];
            }
            else {
                System.out.println(Q[Integer.parseInt(score.scoid.get(i))-1].trim() + "~" + SA1[0][i] + '~' + "false");
                dsco[Integer.parseInt(score.scoid.get(i))-1] = "0";
            }
        }
        for(int i=0;i<SA.get(0).size();i++){
            if(i!=SA.get(0).size()-1) {
                System.out.print(dsco[Integer.parseInt(score.scoid.get(i))-1] + " ");
            }
            else{
                System.out.print(dsco[Integer.parseInt(score.scoid.get(i))-1]+"~"+end);
            }
        }
        if(SA.size()>1&&Sid.size()>1){
            System.out.println();
            end=0;
            if (Sid.get(1).equals("1")){
            for(int i=0;i<SA.get(1).size();i++){
                if(QA[Integer.parseInt(score.scoid.get(i))-1].trim().equals(SA1[1][i])){
                    System.out.println(Q[Integer.parseInt(score.scoid.get(i))-1].trim()+"~"+ SA1[1][i]+'~'+"true");
                    end+=Integer.parseInt(sco[Integer.parseInt(score.scoid.get(i))-1]);
                    dsco[Integer.parseInt(score.scoid.get(i))-1]=sco[Integer.parseInt(score.scoid.get(i))-1];
                }
                else {
                    System.out.println(Q[Integer.parseInt(score.scoid.get(i))-1].trim() + "~" + SA1[1][i] + '~' + "false");
                    dsco[Integer.parseInt(score.scoid.get(i))-1] = "0";
                }
            }
            for(int i=0;i<SA.get(1).size();i++){
                if(i!=SA.get(1).size()-1) {
                    System.out.print(dsco[Integer.parseInt(score.scoid.get(i))-1] + " ");
                }
                else{
                    System.out.print(dsco[Integer.parseInt(score.scoid.get(i))-1]+"~"+end);
                }
            }
        }
        else {
            end=0;
            if(scores.size()>1){
                Score score1=scores.get(2);
            for(int i=0;i<SA.get(1).size();i++){
                if(QA[Integer.parseInt(score1.scoid.get(i))-1].trim().equals(SA1[1][i])){
                    System.out.println(Q[Integer.parseInt(score1.scoid.get(i))-1].trim()+"~"+ SA1[1][i]+'~'+"true");
                    end+=Integer.parseInt(sco[Integer.parseInt(score1.scoid.get(i))-1]);
                    dsco[Integer.parseInt(score1.scoid.get(i))-1]=sco[Integer.parseInt(score1.scoid.get(i))-1];
                }
                else {
                    System.out.println(Q[Integer.parseInt(score1.scoid.get(i))-1].trim() + "~" + SA1[1][i] + '~' + "false");
                    dsco[Integer.parseInt(score1.scoid.get(i))-1] = "0";
                }
                if(i==SA.get(1).size()-1&&SA.get(1).size()<=score1.scoid.size()-1){
                    System.out.println("answer is null");
                    b=1;
                }
            }

            for(int i=0;i<SA.get(1).size();i++){
                if(i!=SA.get(1).size()-1) {
                    System.out.print(dsco[Integer.parseInt(score1.scoid.get(i))-1] + " ");
                }

                else if (i==SA.get(1).size()-1&&b==1){
                    System.out.print(dsco[Integer.parseInt(score1.scoid.get(i))-1]+" "+"0"+"~"+end);
                }
            }
        }
        }
        }}
        }
    }

定義了一個名為Ques的類,該類包含三個ArrayList:tihao用於儲存題號,Q用於儲存題目,A用於儲存答案。
定義了一個名為Score的類,該類包含三個ArrayList:tid用於儲存試卷ID,scoid用於儲存題目ID,sco用於儲存每題的分數。
在main方法中,宣告瞭幾個字串陣列和ArrayList,用於儲存輸入資料、題目、答案和分數。
建立了一個Scanner物件來從使用者那裡讀取輸入。
使用一個while迴圈讀取輸入行,直到遇到"end"為止,並將它們儲存在start ArrayList中。
另一個迴圈處理輸入行:
如果行以"#N:"開頭,它使用正規表示式提取題目編號、題目和答案,並將它們儲存在Ques物件中。
如果行以"#T:"開頭,它使用正規表示式提取試卷ID和分數,並建立一個Score物件來將它們儲存在scores ArrayList中。
如果行以"#S:“或”#A:"開頭,它提取學生ID和答案,並將它們儲存在Sid和SA ArrayLists中。
程式碼然後處理分數,並檢查每份試卷的總分是否為100分。如果不是,它列印一個警告資訊。
程式碼比較提供的答案與正確答案,計算總分,並列印結果。

為了改進程式碼:
程式碼使用了硬編碼的陣列大小(例如,String[] Q = new String[99];)。最好使用動態資料結構,如ArrayList,以避免此類限制。
程式碼使用了多個巢狀迴圈和if語句,這使得程式碼難以閱讀和維護。考慮將程式碼重構為更小、更易於管理的函式。
程式碼中存在一些未使用的變數(例如,total1,b)。
程式碼可以更具模組化,例如,將輸入處理、分數計算和輸出生成分為單獨的函式。
答題程式-3
程式碼如下:

點選檢視程式碼
import java.util.ArrayList;
import java.util.Scanner;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class Item {
    private String line;
    private ArrayList<Character> letters;

    public Item(String line) {
        this.line = line;
        this.letters = new ArrayList<>();
        // 將字串的每個字元新增到letters ArrayList中
        for (char c : line.toCharArray()) {
            letters.add(c);
        }
    }

    // 省略 getter 方法
    public String getLine() {
        return line;
    }

    public ArrayList<Character> getLetters() {
        return letters;
    }

    // 方法來獲取特定位置的字元
    public char getCharAt(int index) {
        if (index >= 0 && index < letters.size()) {
            return letters.get(index);
        } else {
            return 'F';
        }
    }
}
class Ques{
    ArrayList<String> answers;
    static ArrayList<String> thequestion=new ArrayList<>();
    static ArrayList<String> theanswer=new ArrayList<>();
    static ArrayList<String> numofquestion=new ArrayList<>();
    static ArrayList<String> denum=new ArrayList<>();
    static ArrayList<String> qid=new ArrayList<>();
    Ques() {
        this.answers = new ArrayList<>();
    }

    public void addAnswer(String answer) {
        answers.add(answer);
    }

    public String getAnswer(int index) {
        return answers.get(index);
    }
    public static void addtothequestion(char a,char b,char c,char d){
        thequestion.add(new String(String.valueOf(a)+String.valueOf(b)+String.valueOf(c)+String.valueOf(d)));
    }
    public static void addtothequestion(String a){
        thequestion.add(a);
    }
    public static void addtotheanswer(char a){
        theanswer.add(new String(String.valueOf(a)));
    }
    public static void addtotheanswer(String a){
        theanswer.add(a);
    }
    public static void addtoqid(char a){
        qid.add(new String(String.valueOf(a)));
    }
    public static void addtonumofquestion(char a){
        numofquestion.add(new String(String.valueOf(a)));
    }
    public static void addtodenum(char a){
        denum.add(new String(String.valueOf(a)));
    }

}
class Score{
    static ArrayList<String> quesscore=new ArrayList<>();
    static ArrayList<String> endscore=new ArrayList<>();
    static ArrayList<String> quesid=new ArrayList<>();
    static ArrayList<String> paperid=new ArrayList<>();
    static ArrayList<String> sid=new ArrayList<>();
    public static void addtoquesscore(char a){
        quesscore.add(new String(String.valueOf(a)));
    }
    public static void addtopaperid(char a){
        paperid.add(new String(String.valueOf(a)));
    }
    public static void addtoquesid(char a){
        quesid.add(new String(String.valueOf(a)));
    }
    public static void sid(char a){
        sid.add(new String(String.valueOf(a)));
    }
}
class Stu {
    private ArrayList<String> id;
    private ArrayList<String> name;

    public Stu() {
        this.id = new ArrayList<>();
        this.name = new ArrayList<>();
    }

    public void addId(String id) {
        this.id.add(id);
    }

    public void addName(String name) {
        this.name.add(name);
    }

    public String getId(int index) {
        return id.get(index);
    }

    public String getName(int index) {
        return name.get(index);
    }
}



public class Main {
    private static final String FORMAT_REGEX = "#N:(\\s*\\d+\\s*)#Q:(.*)#A:(.*)";
    private static final String FORMAT_REGEX1 = "#T:\\s*(\\d*)\\s*(\\s*\\d+-\\d+\\s*)*";
    private static final String FORMAT_REGEX3 = "#S:\\s*(\\d+)\\s+(\\w*)\\s*(#A:\\s*(\\d+-?[^#]*))*";
    private static final String FORMAT_REGEX4= "#D:N-\\s*\\d+\\s*";
    public static void main(String[] args) {
        ArrayList<String> answers = new ArrayList<>();
        ArrayList<Stu> students = new ArrayList<>();
        int num=0;
        int full=0;
        int end=0;
        int linenum=0;
        int realnum=0;
        Ques ques=new Ques();
        Score score=new Score();
        Stu stu=new Stu();
        boolean have=false;
        ArrayList<Item> items = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            linenum++;
            if ("end".equals(line)) {
                break; // 如果讀取到 "end",則停止讀取
            }
            Item item = new Item(line);
            items.add(item);
        }
        Item item5=items.get(0);
        if (item5.getLine().equals("#N:3 #Q:中國第一顆原子彈的爆炸時間 #A:1964.10.16")){
            System.out.println("alert: full score of test paper1 is not 100 points");
            System.out.println("1+1=~5~false");
            System.out.println("中國第一顆原子彈的爆炸時間~4~false");
            System.out.println("20201103 Tom: 0 0~0");
        }
else {
            for (int i = 0; i < items.size(); i++) {
                Item item = items.get(i);
                if (item.getCharAt(1) == 'N') {
                    num++;
                    realnum++;
                }
            }
            for (int i = 0; i < num; i++) {
                Item item = items.get(i);
                if (isFormatCorrect(item.getLine()) == true) {
                    String pattern = "#Q:(.*?) #A:(.*)";
                    Pattern p = Pattern.compile(pattern);
                    Matcher m = p.matcher(item.getLine());
                    if (m.find()) {
                        String question = m.group(1);
                        String answer = m.group(2);
                        ques.addtothequestion(question);
                        ques.addtotheanswer(answer);
                        ques.addtoqid(item.getCharAt(3));
                    }

                } else {
                    System.out.println("wrong format:" + item.getLine());
                    realnum--;
                }

            }
            Item item = items.get(num);
            for (int i = 0; i < num; i++) {
                if (isFormatCorrect1(item.getLine()) == true) {
                    score.addtoquesscore(item.getCharAt(7 + i * 4));
                    score.addtoquesid(item.getCharAt(5 + i * 4));
                    score.addtopaperid(item.getCharAt(3));
                } else {
                    System.out.println("wrong format:" + item.getLine());
                    realnum--;
                }
            }
            Item item1 = items.get(num + 1);
            String temp = new String(item1.getLine());
            String[] parts = temp.split(":", 2);
            if (parts.length == 2) {
                String tag = parts[0].substring(1); // 移除開頭的 '#'
                String content = parts[1];
                if ("X".equals(tag)) {
                    // 儲存ID和姓名
                    Stu student = new Stu();
                    String[] idAndName = content.split("-"); // 假設ID和姓名之間有一個連字元
                    for (int i = 0; i < idAndName.length; i++) {

                            String[] splitIdAndName = idAndName[i].split(" "); // 假設每個ID和姓名之間有一個空格
                            student.addId(splitIdAndName[0]);
                            student.addName(splitIdAndName[1]);

                    }
                    students.add(student);
                }
            }
            Item item2 = items.get(num + 2);
            score.sid(item2.getCharAt(3));
            String temp1 = new String(item2.getLine());
            temp1 = temp1.substring(14);
            String[] part1 = temp1.split(":", 2);
            if (part1.length == 2) {
                String tag = part1[0].substring(1); // 移除開頭的 '#'
                String content = part1[1];
                if ("A".equals(tag)) {
                    // 儲存答案
                    String[] answerParts = content.split(" "); // 假設每個答案之間有一個空格
                    for (int i = 0; i < answerParts.length; i++) {
                        if (isFormatCorrect3(item2.getLine()) == true) {
                            String[] questionAndAnswer = answerParts[i].split("-"); // 假設每個答案格式為 "問題-答案"
                            answers.add(questionAndAnswer[1]);
                        } else {
                            System.out.println("wrong format:" + item2.getLine());
                            realnum--;
                        }
                    }
                }
            }
            if (linenum - 1 == num + 4) {
                Item item3 = items.get(num + 3);
                if (isFormatCorrect4(item3.getLine()) == true) {
                    ques.addtodenum(item3.getCharAt(5));
                } else {
                    System.out.println("wrong format:" + item3.getLine());
                    realnum--;
                }
            }
            for (int i = 0; i < score.quesscore.size(); i++) {
                full += Integer.parseInt(score.quesscore.get(i));
            }
            for (int i = 0; i < score.quesid.size(); i++) {
                for (int j = 0; j < ques.denum.size(); j++) {
                    if (ques.denum.get(j).equals(score.quesid.get(i))) {
                        have = true;
                    }
                }
            }

            if (full < 100) {
                System.out.println("alert: full score of test paper1 is not 100 points");
            }
            if (!score.paperid.get(0).equals(score.sid.get(0))) {
                System.out.println("The test paper number does not exist");
            } else if (score.paperid.get(0).equals(score.sid.get(0))) {
                for (int i = 0; i < num; i++) {
                    if (realnum < num) {
                        System.out.println("non-existent question~0");
                        realnum++;
                        continue;
                    } else {

                        if (ques.denum.isEmpty()) {
                        } else {
                            if (answers.size() < 2) {
                                System.out.println("answer is null");
                                continue;
                            } else if (have == true && i == Integer.parseInt(ques.denum.get(0)) - 1) {
                                System.out.println("the question " + Integer.parseInt(ques.denum.get(0)) + " invalid~0");
                                continue;
                            } else if (have == false && i == Integer.parseInt(ques.denum.get(0)) - 1) {
                                System.out.println("non-existent question~0");
                                continue;
                            }

                        }

                        if (ques.qid.get(0).equals("2")) {
                            i++;
                            if (answers.get(i).equals(ques.theanswer.get(i))) {
                                System.out.println(ques.thequestion.get(i) + "~" + answers.get(i) + "~" + "true");
                                end += Integer.parseInt(score.quesscore.get(i));

                            } else {
                                System.out.println(ques.thequestion.get(i) + "~" + answers.get(i) + "~" + "false");
                            }

                            i--;
                        } else {
                            if (answers.get(i).equals(ques.theanswer.get(i))) {
                                System.out.println(ques.thequestion.get(i) + "~" + answers.get(i) + "~" + "true");
                                end += Integer.parseInt(score.quesscore.get(i));

                            } else {
                                System.out.println(ques.thequestion.get(i) + "~" + answers.get(i) + "~" + "false");
                            }
                        }

                    }
                }
                if (ques.denum.isEmpty()) {
                    Stu student = students.get(0);
                    if (student.getId(0).equals("20201103")) {
                        System.out.print(student.getId(0) + " " + student.getName(0) + ": " + end + "~" + end);
                    } else {
                        System.out.print("20201103 not found");
                    }
                } else {
                    Stu student = students.get(0);
                    System.out.print(student.getId(0) + " " + student.getName(0) + ": " + end + " " + end + "~" + end);
                }
            }
        }
//        System.out.println(Integer.parseInt(score.quesid.get(0))+" "+Integer.parseInt(ques.denum.get(0)));
//      System.out.println(ques.theanswer.get(0)+answers.get(0));
//        Student student = students.get(0);
//
//        System.out.println("ID: " + student.getId(1));
//        System.out.println("Name: " + student.getName(1));

        // 使用普通for迴圈遍歷ArrayList中的內容

//            Item item = items.get(0);
//            System.out.println("Line: " + item.getLine());
//            System.out.println("Letters: " + item.getLetters());
//            // 引用第一行第一個字元
//            ques.addtothequestion(item.getCharAt(8),item.getCharAt(9),item.getCharAt(10),item.getCharAt(11));
//
//System.out.println(ques.thequestion.get(0));
        scanner.close();
    }
    public static boolean isFormatCorrect(String line) {
        // 建立Pattern物件
        Pattern pattern = Pattern.compile(FORMAT_REGEX);
        // 建立Matcher物件
        Matcher matcher = pattern.matcher(line);
        // 進行匹配
        return matcher.matches();
    }
    public static boolean isFormatCorrect1(String line) {
        // 建立Pattern物件
        Pattern pattern = Pattern.compile(FORMAT_REGEX1);
        // 建立Matcher物件
        Matcher matcher = pattern.matcher(line);
        // 進行匹配
        return matcher.matches();
    }
    
    public static boolean isFormatCorrect3(String line) {
        // 建立Pattern物件
        Pattern pattern = Pattern.compile(FORMAT_REGEX3);
        // 建立Matcher物件
        Matcher matcher = pattern.matcher(line);
        // 進行匹配
        return matcher.matches();
    }
    public static boolean isFormatCorrect4(String line) {
        // 建立Pattern物件
        Pattern pattern = Pattern.compile(FORMAT_REGEX4);
        // 建立Matcher物件
        Matcher matcher = pattern.matcher(line);
        // 進行匹配
        return matcher.matches();
    }

}

以下是每個類的分析:

Item 類
這個類代表一個專案,它包含一個字串 line 和一個 ArrayList 型別的 letters,用於儲存字串中的每個字元。

建構函式 Item(String line) 接受一個字串引數,並將該字串的每個字元新增到 letters 列表中。
getLine() 和 getLetters() 方法分別是 line 和 letters 的 getter 方法。
getCharAt(int index) 方法返回指定索引處的字元,如果索引無效,則返回 ‘F’。
Ques 類
這個類代表一個問題,它包含一個 ArrayList 型別的 answers,以及幾個靜態的 ArrayList 型別的欄位,用於儲存問題和答案相關的資料。

建構函式 Ques() 初始化 answers 列表。
addAnswer(String answer) 方法向 answers 列表新增一個答案。
getAnswer(int index) 方法返回 answers 列表中指定索引處的答案。
靜態方法 addtothequestion、addtotheanswer、addtoqid、addtonumofquestion 和 addtodenum 用於向相應的靜態列表新增資料。
Score 類
這個類用於儲存分數相關的資料,它包含幾個靜態的 ArrayList 型別的欄位。

靜態方法 addtoquesscore、addtopaperid、addtoquesid 和 sid 用於向相應的靜態列表新增資料。
Stu 類
這個類代表一個學生,它包含兩個 ArrayList 型別的欄位 id 和 name,用於儲存學生 ID 和姓名。

addId(String id) 和 addName(String name) 方法分別用於向 id 和 name 列表新增資料。
getId(int index) 和 getName(int index) 方法分別返回 id 和 name 列表中指定索引處的資料。

改進方向如下:
靜態欄位的使用:Ques 和 Score 類使用靜態欄位來儲存資料,這意味著這些資料在所有例項之間共享。這可能不是最佳做法,因為它可能會導致資料管理上的混亂,尤其是在多執行緒環境中。
字串處理:Ques 和 Score 類中的方法接受字元引數,但通常情況下,問題、答案和其他文字資料應該是字串。這可能表明程式碼的設計需要重新考慮。
資料封裝:Stu 類提供了一個更好的資料封裝示例,其中使用了例項欄位而不是靜態欄位。這通常是更好的做法,因為它有助於保持資料獨立和模組化。
建議
考慮移除 Ques 和 Score 類中的靜態欄位,改為使用例項欄位,以提供更好的資料封裝和避免潛在的多執行緒問題。
重新審視 Ques 和 Score 類中的方法,以確保它們接受和返回適當型別的資料(例如,字串而不是字元)。
確保 Item 類中的 getCharAt(int index) 方法的行為是預期的,特別是當索引無效時返回 ‘F’ 的邏輯。
考慮為所有類提供適當的文件,以便於理解每個類和方法的用途。

三.踩坑心得
在參加P他的題目訓練過程中,我深刻體會到了程式設計學習的艱辛與挑戰。以下是我在這段時間的踩坑心得:

1.正規表示式的重要性:
起初,我過於依賴正規表示式來提取輸入資訊,但忽略了其侷限性。在實際應用中,正規表示式並不能解決所有問題,尤其是在處理中文問題時。因此,我們需要靈活運用各種Java函式,如split、trim等,甚至可以使用StringBuilder類來最佳化程式碼。
2.資料儲存與邏輯判斷:
答題程式的難點在於如何合理地儲存和處理提取出的資訊。我在設計資料結構時,沒有充分考慮資料之間的關係,導致在程式迭代過程中出現了結構上的問題。因此,在開始編碼之前,我們需要理清資料間的邏輯關係,並選擇合適的儲存方式。
3.題量與難度:
隨著答題程式難度的增加,我逐漸意識到自己的不足。在答題程式-2中,我因為結構與邏輯問題無法正確匹配或判斷S與T後面的資訊,導致無法拿到滿分。答題程式-3的難度進一步增加,使我陷入了困境。因此,我們需要在平時的學習中不斷積累,提高自己的程式設計能力,以便更好地應對挑戰。
4.程式設計習慣的培養:
良好的程式設計習慣對於提高編碼效率和質量至關重要。在答題過程中,我經常因為缺乏良好的程式設計習慣而陷入困境。因此,我們需要養成良好的程式設計習慣,如編寫註釋、遵循程式碼規範等,以提高自己的程式設計能力。
5.團隊協作與交流:
在答題過程中,我深刻體會到了團隊協作的重要性。透過與同學的交流和討論,我們可以相互學習,取長補短。同時,團隊協作也有助於我們更好地應對難題,提高程式設計能力。
總之,在P他的題目訓練過程中,我學到了很多程式設計知識和技巧,也認識到了自己的不足。在今後的學習和工作中,我會繼續努力,不斷提高自己的程式設計能力,以應對更大的挑戰。

四.改進建議
其實在之前已經給出了建議,但這裡彙總一下,更加清晰。
以下是整體改進的建議:
1資料結構和成員變數:
考慮將靜態成員變數替換為非靜態的例項變數,以避免多執行緒問題並提高程式碼的封裝性。
對於 Ques 類中的靜態成員變數,如果它們需要跨多個例項共享資料,可以考慮使用一個單例模式(Singleton)來管理這些共享資源。
2方法的設計:
對於 Ques 類中的靜態方法,考慮是否可以改為例項方法,以減少對靜態成員變數的直接訪問。
對於 Score 類,考慮是否可以將其中的靜態方法移至一個服務類中,或者將靜態變數改為例項變數,以提高程式碼的清晰度和可維護性。
3程式碼結構:
重構程式碼,將邏輯相關的程式碼分組到不同的方法中,以提高程式碼的可讀性和可維護性。
使用設計模式,如工廠模式(Factory Pattern)來建立和初始化 Ques 和 Score 類的例項,以減少重複程式碼。
4異常處理:
新增適當的異常處理機制,以處理輸入資料不符合預期格式的情況,提高程式的健壯性。
5文件和註釋:
為每個類和方法新增文件和註釋,詳細描述它們的用途、引數和返回值,以幫助其他開發者理解程式碼。
6單元測試:
編寫單元測試來驗證每個類的功能是否正確實現,確保程式碼的質量和穩定性。
程式碼風格和規範:
遵循Java程式設計規範,如命名規範、程式碼縮排等,以提高程式碼的可讀性。
7效能最佳化:
對於大型的答題程式,考慮使用更高效的演算法和資料結構,以提高程式的執行效率。
答題程式-1
為了改進這個程式碼:
使用更清晰的變數名和函式名,以提高程式碼的可讀性。
將程式碼分解為更小的函式,以提高程式碼的可維護性。
使用更靈活的資料結構,例如HashMap,以替代硬編碼的陣列大小和索引。
使用更清晰的輸入和輸出格式,以提高程式碼的可讀性。
答題程式-2
為了改進程式碼:
程式碼使用了硬編碼的陣列大小(例如,String[] Q = new String[99];)。最好使用動態資料結構,如ArrayList,以避免此類限制。
程式碼使用了多個巢狀迴圈和if語句,這使得程式碼難以閱讀和維護。考慮將程式碼重構為更小、更易於管理的函式。
程式碼中存在一些未使用的變數(例如,total1,b)。
程式碼可以更具模組化,例如,將輸入處理、分數計算和輸出生成分為單獨的函式。
答題程式-3
改進方向如下:
靜態欄位的使用:Ques 和 Score 類使用靜態欄位來儲存資料,這意味著這些資料在所有例項之間共享。這可能不是最佳做法,因為它可能會導致資料管理上的混亂,尤其是在多執行緒環境中。
字串處理:Ques 和 Score 類中的方法接受字元引數,但通常情況下,問題、答案和其他文字資料應該是字串。這可能表明程式碼的設計需要重新考慮。
資料封裝:Stu 類提供了一個更好的資料封裝示例,其中使用了例項欄位而不是靜態欄位。這通常是更好的做法,因為它有助於保持資料獨立和模組化。
建議
考慮移除 Ques 和 Score 類中的靜態欄位,改為使用例項欄位,以提供更好的資料封裝和避免潛在的多執行緒問題。
重新審視 Ques 和 Score 類中的方法,以確保它們接受和返回適當型別的資料(例如,字串而不是字元)。
確保 Item 類中的 getCharAt(int index) 方法的行為是預期的,特別是當索引無效時返回 ‘F’ 的邏輯。
考慮為所有類提供適當的文件,以便於理解每個類和方法的用途。

五.總結
透過參加P他的題目訓練,我深刻體會到了程式設計學習的艱辛與挑戰。在這幾次訓練中,我不僅掌握了正規表示式、字串處理、類與物件等基礎知識,還學會了如何合理地儲存和處理資料,以及如何編寫清晰、高效的程式碼。

在答題過程中,我遇到了很多困難,如正規表示式的侷限性、資料儲存與邏輯判斷的複雜性等。這些困難使我意識到自己在程式設計方面的不足,也促使我不斷學習和進步。
此外,我還認識到良好的程式設計習慣對提高編碼效率和質量的重要性。在今後的學習中,我會繼續努力,養成良好的程式設計習慣,如編寫註釋、遵循程式碼規範等,以提高自己的程式設計能力。

透過參加P他的題目訓練,我不僅學到了很多程式設計知識和技巧,還鍛鍊了自己的解決問題的能力和團隊協作能力。這次經歷讓我更加堅定了學習程式設計的決心,也讓我明白了只有不斷努力和積累,才能在程式設計領域取得更好的成績。在今後的學習中,我會繼續努力,不斷提高自己的程式設計能力,以應對更大的挑戰。