(1)前言
- 這三次題目集的知識點,主要分佈在OOP的封裝、正規表示式、字串的合理使用、Java中的集合類的合理選擇和使用、對於使用者錯誤輸入的控制。
- 對於題量和難度的話,其實算適中,主要是由於我剛剛學習Java語言,思維方式還沒有完全從程序導向轉到物件導向,在有些方面上還是始終用程序導向的思維去解決我們的pta大作業,程式設計方面,我一直都沒有相通怎麼樣才算物件導向,而且再加上上學期c語言本身就沒有怎麼過關的我,這也導致我剛開始寫pta的時候確實有些吃力。
(2)設計與分析
-題目集1
原始碼:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 這裡是讀取題目數目
int numQuestions = scanner.nextInt();
// 這裡是讀取題目
TestPaper testPaper = new TestPaper();
testPaper.readQuestions(scanner, numQuestions);
// 這裡是讀取和儲存
AnswerSheet answerSheet = new AnswerSheet();
answerSheet.readAnswers(scanner);
// 獲取題目列表和使用者答案列表
List<Question> questions = testPaper.getQuestions();
List<String> userAnswers = answerSheet.getAnswers();
// 按照題號排序題目和使用者答案
Collections.sort(questions, Comparator.comparingInt(Question::getNumber));
List<String> sortedUserAnswers = new ArrayList<>(Collections.nCopies(numQuestions, ""));
for (int i = 0; i < numQuestions; i++) {
sortedUserAnswers.set(questions.get(i).getNumber() - 1, userAnswers.get(i));
}
// 輸出題目及使用者答案
for (Question question : questions) {
String userAnswer = sortedUserAnswers.get(question.getNumber() - 1); // Adjust index
System.out.println(question.getContent() + "~" + userAnswer);
}
// 評判使用者答案
for (int i = 0; i < numQuestions; i++) {
Question question = questions.get(i);
String userAnswer = sortedUserAnswers.get(question.getNumber() - 1); // Adjust index
boolean result = userAnswer.equals(question.getCorrectAnswer());
System.out.print(result ? "true" : "false");
if (i != numQuestions - 1) {
System.out.print(" ");
}
}
}
}
class Question {
private int number;
private String content;
private String correctAnswer;
public Question(int number, String content, String correctAnswer) {
this.number = number;
this.content = content;
this.correctAnswer = correctAnswer;
}
public int getNumber() {
return number;
}
public String getContent() {
return content;
}
public String getCorrectAnswer() {
return correctAnswer;
}
}
class TestPaper {
private List
public TestPaper() {
questions = new ArrayList<>();
}
public void addQuestion(Question question) {
questions.add(question);
}
public List<Question> getQuestions() {
return questions;
}
public void readQuestions(Scanner scanner, int numQuestions) {
scanner.nextLine(); // Consume newline
for (int i = 0; i < numQuestions; i++) {
String line = scanner.nextLine();
String[] parts = line.split("#N:| #Q:| #A:");
int number = Integer.parseInt(parts[1].trim());
String content = parts[2].trim();
String correctAnswer = parts[3].trim();
addQuestion(new Question(number, content, correctAnswer));
}
}
}
class AnswerSheet {
private List
public AnswerSheet() {
answers = new ArrayList<>();
}
public void addAnswer(String answer) {
answers.add(answer);
}
public List<String> getAnswers() {
return answers;
}
public void readAnswers(Scanner scanner) {
String line;
while (!(line = scanner.nextLine()).equals("end")) {
String[] answers = line.split("#A:| ");
for (String answer : answers) {
if (!answer.equals("")) {
addAnswer(answer);
}
}
}
}
}
由於這道題比較簡單,複雜度上並不是特別大
對於這道題目,現在分析的話,會發現有好多問題
- 依然使用的是程序導向的思路來寫題目的,對類的使用不太靈活,程序導向的思想還是沒有改變過來
- 主函式存在大量程式碼,沒有設計方法來封裝這些程式碼
- public和private使用混亂,類裡面的功能單一,大部分的功能都在主函式中
-題目集2
原始碼:
import java.util.*;
class Question {
String questionNumber;
String questionContent;
String correctAnswer;
public Question(String questionNumber, String questionContent, String correctAnswer) {
this.questionNumber = questionNumber;
this.questionContent = questionContent;
this.correctAnswer = correctAnswer;
}
public String getQuestionNumber() {
return questionNumber;
}
public String getQuestionContent() {
return questionContent;
}
public String getCorrectAnswer() {
return correctAnswer;
}
}
class TestPaper {
String paperNumber;
Map<String, Integer> questionScores;
public TestPaper(String paperNumber) {
this.paperNumber = paperNumber;
this.questionScores = new LinkedHashMap<>();
}
public void addQuestionScore(String questionNumber, int score) {
questionScores.put(questionNumber, score);
}
public String getPaperNumber() {
return paperNumber;
}
public Map<String, Integer> getQuestionScores() {
return questionScores;
}
}
class AnswerSheet {
String paperNumber;
List
public AnswerSheet(String paperNumber) {
this.paperNumber = paperNumber;
this.answers = new ArrayList<>();
}
public void addAnswer(String answer) {
answers.add(answer);
}
public String getPaperNumber() {
return paperNumber;
}
public List<String> getAnswers() {
return answers;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Map<String, Question> questionBank = new LinkedHashMap<>();
Map<String, TestPaper> testPapers = new LinkedHashMap<>();
List
while (scanner.hasNext()) {
String line = scanner.nextLine();
if (line.equals("end")) {
break;
}
if (line.startsWith("#N:")) {
String[] parts = line.split(" ");
String questionNumber = parts[0].substring(3);
String questionContent = parts[1].substring(3);
String correctAnswer = parts[2].substring(3);
questionBank.put(questionNumber, new Question(questionNumber, questionContent, correctAnswer));
} else if (line.startsWith("#T:")) {
String[] parts = line.split(" ");
String paperNumber = parts[0].substring(3);
TestPaper testPaper = new TestPaper(paperNumber);
for (int i = 1; i < parts.length; i++) {
String[] scorePair = parts[i].split("-");
testPaper.addQuestionScore(scorePair[0], Integer.parseInt(scorePair[1]));
}
testPapers.put(paperNumber, testPaper);
} else if (line.startsWith("#S:")) {
String[] parts = line.split(" ");
String paperNumber = parts[0].substring(3);
AnswerSheet answerSheet = new AnswerSheet(paperNumber);
for (int i = 1; i < parts.length; i++) {
answerSheet.addAnswer(parts[i].substring(3));
}
answerSheets.add(answerSheet);
}
}
int flag = 0;
for (AnswerSheet answerSheet : answerSheets) {
TestPaper testPaper = testPapers.get(answerSheet.getPaperNumber());
List<String> answers = answerSheet.getAnswers();
int totalScore = 0;
boolean scoreAlert = false;
int[] scores = new int[testPaper.getQuestionScores().size()];
int allScore = 0;
for (String questionNumber : testPaper.getQuestionScores().keySet()) {
int score = testPaper.getQuestionScores().get(questionNumber);
allScore += score;
}
for (int i = 0; i < answers.size(); i++) {
String questionNumber = (String) testPaper.getQuestionScores().keySet().toArray()[i];
int score = testPaper.getQuestionScores().get(questionNumber);
Question question = questionBank.get(questionNumber);
String userAnswer = answers.get(i);
boolean isCorrect = userAnswer.equals(question.getCorrectAnswer());
if (isCorrect) {
totalScore += score;
scores[i] = score;
} else
scores[i] = 0;
if (allScore != 100 && !scoreAlert && flag == 0) {
if(testPaper.getQuestionScores().size()>answers.size())
flag=0;
else
flag = 1;
System.out.println("alert: full score of test paper " + testPaper.getPaperNumber() + " is not 100 points");
scoreAlert = true;
}
System.out.println(question.getQuestionContent() + "~" + userAnswer + "~" + isCorrect);
}
if(testPaper.getQuestionScores().size()>answers.size())
System.out.printf("answer is null\n");
for (int i = 0; i < testPaper.getQuestionScores().size(); i++) {
System.out.printf("%d", scores[i]);
if (i != testPaper.getQuestionScores().size()- 1) {
System.out.printf(" ");
}
}
System.out.printf("~%d\n", totalScore);
}
}
}
這道題在上上個星期的訓練中,我並沒有拿到好的成績,主要原因還是出現在正規表示式這一知識點和在使用hashmap的時候,並不知道hashmap的執行緒並不安全,不能保證鍵和輸入一一對應。現在重新回過頭來分析的話,會發現暴露出來了好多問題,
- 依舊是使用的程序導向的思路來寫題目的,沒有更加深入地理解程序導向這一思想的深層含義
- 主函式仍存在大量程式碼,沒有設計方法來封裝這些程式碼
- 沒有深入學習正規表示式和Java集合的使用方法,只是一知半解地去胡亂編碼
-題目集3
原始碼:
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
class Question {
int number;//題目編號
String content;//內容
String answer;//標準答案
public void setNumber(int number) {
this.number = number;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
public Question(int number, String content, String answer) {//初始化
this.number = number;
this.content = content;
this.answer = answer;
}
public int getNumber() {
return number;//返回編號
}
}
class TestPaper {//試卷題目類
int paperNumber;//試卷編號
List
public int getPaperNumber() {
return paperNumber;
}
public void setPaperNumber(int paperNumber) {
this.paperNumber = paperNumber;
}
public void setNumberScores(List<NumberScore> numberScores) {
NumberScores = numberScores;
}
public TestPaper(int paperNumber) {
this.paperNumber = paperNumber;
this.NumberScores =new ArrayList<>();
}//初始化和建立map
public void addAumberScore(NumberScore numberScore) {//將題目的序號和對應分數寫入
NumberScores.add(numberScore);
}
public List<NumberScore> getNumberScores() {
return NumberScores;
}
}
class AnswerSheet {//學生答卷
int sheetNumber;//答卷編號
String studentID;//學生學號
Map<Integer, String> answers;//學生答案陣列
public int getSheetNumber() {
return sheetNumber;
}
public void setSheetNumber(int sheetNumber) {
this.sheetNumber = sheetNumber;
}
public void setStudentID(String studentID) {
this.studentID = studentID;
}
public Map<Integer, String> getAnswers() {
return answers;
}
public void setAnswers(Map<Integer, String> answers) {
this.answers = answers;
}
//////寫到這裡
public AnswerSheet(int SheetNumber,String studentID) {
sheetNumber = SheetNumber;//初始化
this.studentID=studentID;
this.answers = new HashMap<>();
}
public void addAnswer(int ordernumber,String answer) {//將每個題目的答案都存進去
answers.put(ordernumber,answer);
}
public String getStudentID()
{ return studentID;
}
}
class NumberScore
{
int number;
int score;
public void setNumber(int number) {
this.number = number;
}
public void setScore(int score) {
this.score = score;
}
public NumberScore(int number, int score) {//初始化
this.number = number;
this.score= score;
}
public int getNumber()
{ return number;
}
public int getScore()
{ return score;
}
}
//正規表示式
class RegexPatterns {
public static final String QUESTION_PATTERN = "^#N:(.) #Q:(.) #A:(.*)\(";
public static final String TEST_PATTERN = "^#T:\\d+ \\d+-\\d+( \\d+-\\d+)*\)";
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List
LinkedHashMap<Integer, TestPaper> testPapers = new LinkedHashMap<>();//試卷編號——試卷
LinkedHashMap<Integer, List
LinkedHashMap<String, String> students = new LinkedHashMap<>();//學號——姓名
List
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (line.equals("end")) {
break;
} else if (line.startsWith("#N:")) {
String regex = RegexPatterns.QUESTION_PATTERN;
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(line);
if(matcher.matches())
{
String[] parts = line.split("#");
String[] parts1 = parts[1].split(":");
String number = parts1[1].trim();
//System.out.println("number = " + number);
String[] parts2 = parts[2].split(":");
String content = parts2[1].replaceAll(" +","");
//System.out.println("content = " + content);
String[] parts3 = parts[3].split(":");
String[] parts4 = parts3[1].trim().split(" ");
String answer = parts4[0];
//System.out.println("answer = " + answer);
Question a=new Question(Integer.parseInt(number), content, answer);
questions.add(a);
}
else
{ System.out.println("wrong format:"+line);
}
} else if (line.startsWith("#T:")) {
Pattern patternTest = Pattern.compile(RegexPatterns.TEST_PATTERN);
Matcher matcherTest= patternTest.matcher(line);
if(matcherTest.find())
{
String[] parts = line.split(":");
String parts1 = parts[1].trim().replaceAll(" +","-");
// System.out.println("parts1 = " + parts1);
String[] parts2 = parts1.split("-+");
int paperNumber = Integer.parseInt(parts2[0]);
TestPaper testPaper = new TestPaper(paperNumber);
//System.out.println("paperNumber = " + paperNumber);
for (int i = 1; i < parts2.length; i+=2) {
int questionNumber = Integer.parseInt(parts2[i]);
// System.out.println("questionNumber = " + questionNumber);
int score = Integer.parseInt(parts2[i+1]);
// System.out.println("score = " + score);
NumberScore numberScore=new NumberScore(questionNumber,score);
testPaper.addAumberScore(numberScore);
}
testPapers.put(paperNumber, testPaper);
}
else
{ System.out.println("wrong format:"+line);
}
} else if (line.startsWith("#S:")) {
String[] parts = line.split("#");
String parts1 = parts[1].substring(2);
String[] parts2 = parts1.split(" ");
int sheetNumber = Integer.parseInt(parts2[0]);
String studentID = parts2[1];
AnswerSheet answerSheet=new AnswerSheet(sheetNumber,studentID);
for (int i = 2; i < parts.length; i++) {
String a = parts[i].substring(2);
String a1 = a.trim();
String[] orderanswer = a1.split("-");
int ordernumber = Integer.parseInt(orderanswer[0]);
String answer = orderanswer.length > 1 ? orderanswer[1] : "";
if (answer == null) {
assert false;
answer= answer.replace("","yes");
} else {
}
answerSheet.addAnswer(ordernumber,answer);
}
if (answerSheets.containsKey(sheetNumber))
{
answerSheets.get(sheetNumber).add(answerSheet);
} else
{
List<AnswerSheet> list = new ArrayList<>();
list.add(answerSheet);
answerSheets.put(sheetNumber,list);
}
}else if (line.startsWith("#X:")) {
String ab=line.substring(3);
String[] parts = ab.split("-");
for (String part : parts) {
String[] IDname = part.split(" ");
students.put(IDname[0], IDname[1]);
}
}else if (line.startsWith("#D:")) {
String line1=line.substring(3);
String[] parts = line1.split(" ");
for (String part : parts) {
String[] number = part.split("-");
deletes.add(Integer.parseInt(number[1]));
}
}else
{
System.out.println("wrong format:"+line);
}
}
//第一次迴圈為了列印是否為滿分卷
for (int paperNumber : testPapers.keySet()) {
int totalScore = 0;//總分
TestPaper testPaper = testPapers.get(paperNumber);//建立遍歷到的當前的試卷
for(NumberScore numberScore :testPaper.getNumberScores())
{
totalScore += numberScore.getScore();//求試卷總分
}
if (totalScore != 100) {
System.out.println("alert: full score of test paper" + paperNumber + " is not 100 points");
}//不是100則輸出
}
for (int paperNumber : answerSheets.keySet()) {
if (!testPapers.containsKey(paperNumber)) {
System.out.println("The test paper number does not exist");
} else {
TestPaper testPaper = testPapers.get(paperNumber);
List<Integer> questionScores = testPaper.getNumberScores().stream()
.map(NumberScore::getScore)
.collect(Collectors.toList());
List<AnswerSheet> AnswerSheets = answerSheets.get(paperNumber);
for (AnswerSheet answerSheet : AnswerSheets) {
List<Question> paperQuestions = new ArrayList<>();
int deletedQuestionNumber = 100;
for (NumberScore numberScore : testPaper.getNumberScores()) {
Question targetQuestion = questions.stream()
.filter(question -> question.getNumber() == numberScore.getNumber())
.findFirst().orElse(null);
if (targetQuestion != null) {
paperQuestions.add(targetQuestion);
} else {
paperQuestions.add(new Question(deletedQuestionNumber, "delete", "delete"));
deletedQuestionNumber++;
}
}
for (int i = 0; i < paperQuestions.size(); i++) {
Question question = paperQuestions.get(i);
String answer = (i < answerSheet.answers.size()) ? answerSheet.answers.get(i + 1): "answer is null";
if (answer.equals("answer is null")) {
System.out.println("answer is null");
} else {
if (!deletes.contains(question.getNumber())) {
if (question.getNumber() >= 100) {
System.out.println("non-existent question~0");
} else {
boolean isCorrect = answer.equals(question.answer);
System.out.println(question.content + "~" + answer + "~" + (isCorrect ? "true" : "false"));
}
} else {
System.out.println("the question " + question.getNumber() + " invalid~0");
}
}
}
String studentName = students.get(answerSheet.getStudentID());
if (studentName != null) {
System.out.print(answerSheet.getStudentID() + " " + studentName + ": ");
int totalPaperScore = 0;
int questionIndex = 0;
for (int i = 0; i < paperQuestions.size(); i++) {
Question question = paperQuestions.get(i);
String answer = (i < answerSheet.answers.size()) ? answerSheet.answers.get(i + 1) : "answer is null";
if (answer.equals(question.answer) && !deletes.contains(question.getNumber())) {
if (question.getNumber() >= 100) {
System.out.print("0" + (questionIndex == paperQuestions.size() - 1 ? "" : " "));
} else {
totalPaperScore += questionScores.get(i);
System.out.print(questionScores.get(i) + (questionIndex == paperQuestions.size() - 1 ? "" : " "));
}
} else {
System.out.print("0" + (questionIndex == paperQuestions.size() - 1 ? "" : " "));
}
questionIndex++;
}
System.out.printf("~%d\n", totalPaperScore);
} else {
System.out.print(answerSheet.getStudentID() + " not found");
}
}
}
}
}
}
由於在編碼過程中,還是用的是程序導向的思路去解決問題,導致圈複雜度比較大
這道題在上個星期的訓練中,我拿了88分,最後這幾個測試點一直都沒有過,主要的原因還是自己對題目的意思有點曲解,我錯誤地以為,題目錯誤輸入,是以第一個輸入結果來儲存(如果輸入2 3 5,我理解為只要儲存2,其他的都是錯誤輸入),導致我一直改我的正規表示式,到最後輸入答卷資訊的時候,我正規表示式一直都寫不出來(因為輸入中的空格的原因),怎麼除錯都無濟於事,我去問同學這個怎麼處理,然後才發現是自己理解錯了題目意思。
下面是我的總結
- 在稀裡糊塗的理解錯誤題目要求的過程中,我重心轉到了如何使用正規表示式的這一層面中,在不斷地除錯中再加上不斷地查詢,我更加深入地瞭解了正規表示式的使用。
- 上個星期,我一直在思考怎樣才算得上程序導向,說實話,之前老師佈置的網課任務,我一直都是沒有認認真真地看,大部分時間都是把網課掛在旁邊,平時上課也是聽得稀裡糊塗的,後面我就去重新開啟了老師佈置的網課任務,重新刷網課,才發現老師講通了好多我所謂的痛點。
(3)踩坑心得
程式碼在提交過程中出現的問題:
- 格式問題,在原始碼提交的過程中,格式問題可坑苦了我,寫第一次大作業的時候,經常就是出現格式錯誤。
- 問題考慮不全面,在依據題幹資訊設計的時候,沒有去認真思考和設計,簡單來說,就是隨便看下題目就盲區地去打程式碼,導致問題一旦出現後,前面寫的東西又要重新改,沒有好好地去設計自己的程式碼
- 在類的設計過程中,思路相當混亂,沒有縷清出各個類所要發揮的職責,就隨便亂打一通,導致效率比較低下,後面又要重新去改,得不償失。
- 正規表示式要認真設計,不要等下又重新回過頭來改邏輯,在完成大作業的過程中,我有好幾次就是因為正規表示式設計的不好就又重新推翻自己原有的邏輯重新打,在這裡花了好多好多時間,在後面的正規表示式的設計的時候,要好好考慮可能出現的情況。
- 資訊的儲存方式,剛開始我是一直以為hashmap是特別好用的,所有我把全部的儲存方式都變成了hashmap,後面在使用的過程中才發現,hashmap並不是我想象中的那麼好用,它並不能保證執行緒的安全,也不能保證它能夠像連結串列一樣儲存,在第二次大作業中,我是真的被這個害苦了,這讓我明白了一件事,就是,以後每學習到一件新事物,都要去系統地學習,而不是一知半解就去隨便使用,並和其他類似的去做對比,得出相對應的使用條件。
- 字串的使用,字串在Java當中,算得上是資料處理的一大利器,它的形式具有多元化,可以幫我們處理好多問題,在第二次大作業當中,我在處理資料的時候,出現好多錯誤,後面發現大部分都是出現在字串的處理上,比如字串的型別轉換,剛開始我甚至不知道Java中的字串是不能更改的,就隨便地去賦值,這讓我摔了個大坑。
- 空指標異常,在處理資料的時候,出現了空指標異常的情況,就是在儲存資料的時候,如果使用者沒有輸出,導致後面的儲存資料處於空指標的狀態下,就需要我們用if來控制空指標異常這一情況
(4)改進建議
現在自己對之前的程式碼總結之後,發現自己程式碼的問題主要出現在對程序導向這一思想還沒有理解,出現了比較大的問題,在類的處理層面,沒用用類去封裝方法,導致在主函式中出現了冗長的程式碼,並且依舊還是用程序導向的思想去編碼,這也是我接下來要去解決的問題。還有就是,在寫題目之前,沒用認真地去設計自己的程式碼,導致邏輯混亂。這倆個方面是我接下來需要改進的方向。
(5)總結
在前一段學習Java的過程當中,說實話,我學的真的不咋地,就是那種學得稀裡糊塗的那種感覺,因為自己也沒有足夠重視,說白了就是沒用花到時間,沉迷於遊戲。現在自己沉下心來思考,才發現了自己在學習方面出現了好大的問題,問題一直都是沒有及時地去解決,導致問題越積越多,學起來也一直感覺力不從心,進而讓自己一直處於一種死迴圈裡。我現在也已經意識到了問題,也準備儘可能地去彌補。還有就是,我一直都沒有把那種物件導向的思維方式從程序導向那裡完全走出來,思考問題方式也是這樣,這是我要解決的!
老師您在授課過程中,我是覺得沒問題的,覺得您講得通俗易懂,不過,老師您能不能在課前稍微說明一下下節課您準備講什麼和我們大致所需要學習的知識點,我們才有所準備,我是有幾次真的聽得一頭霧水,因為我不知道您到底在講哪裡,我需要在課前學習啥和我需要所具備的基礎知識,我感覺這樣我才能夠更好地去吸收您上課所講的知識和後面的複習總結。