大家好,我是老貓。今天和大家分享一下程式員日常的繪圖思路,以及一些老貓日常使用的繪圖工具。 為什麼要畫圖? 我們在進行系統設計的時候,為了更加具象地呈現系統的輪廓以及各個組件或者系統之間的關係和邊界以及工作流程。我們就會畫邏輯架構圖,模塊圖、流程圖、時序圖等等。 在日常開發中,軟體設計圖是一種非常好 ...
前言:
這是我第一次寫oop的設計作業,其中不乏踩坑,亂設計,瞎設計,但三次題目都能很好的提高個人能力,這是我跨入面向對象的第一步,只有第一步走踏實了,後面的課中,才能走的更快更穩,更穩更遠。
- 寫前三次作業的過程中,每個題目都要求合理正確設計各種類,要求實現類的封裝性,合理設計類間關係,符合類的單一職責原則,熟悉正則表達式。
第一次題目集較為簡單,需要設計的類較少,即可完成題目。
第二次題目集前三題仍然比較簡單,第四題在第一次題目集最後一題的基礎上進行迭代,增加類的數量,題目難度較第一次加大,總體來說,不算太難。
第三次題目集共三題,前兩題題目內容較少,稍花時間設計即可順利完成,最後一題依舊在前倆次題目的基礎上進行進一步迭代,難度中等。
設計與分析:
- 對於第一次作業最後一題:
點擊查看代碼
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Question {
private int number;
private String content;
private String standardAnswer;
public Question(int number, String content, String standardAnswer) {
this.number = number;
this.content = content;
this.standardAnswer = standardAnswer;
}
public int getNumber() {
return number;
}
public String getContent() {
return content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public boolean checkAnswer(String answer) {
return answer.equals(standardAnswer);
}
}
class Paper {
private List<Question> questions = new ArrayList<>();
public void addQuestion(Question question) {
questions.add(question);
}
public Question getQuestion_Number(int number) {
for (Question question : questions) {
if (question.getNumber() == number) {
return question;
}
}
return null;
}
}
class Answer {
private Paper paper;
private ArrayList<String> answers = new ArrayList<>();
private ArrayList<Boolean> results = new ArrayList<>();
public Answer(Paper paper) {
this.paper = paper;
}
public void saveOne_Your_answer(String answer) {
answers.add(answer);
}
public void saveAnswers() {
for (int i = 0; i < answers.size(); i++) {
Question question = paper.getQuestion_Number(i + 1);
if (question != null) {
results.add(question.checkAnswer(answers.get(i)));
}
}
}
public void outputResults() {
for (int i = 0; i < answers.size(); i++) {
Question question = paper.getQuestion_Number(i + 1);
if (question != null) {
System.out.println(question.getContent() + "~" + answers.get(i));
}
}
int i=0;
for (boolean result : results) {
if(i!=0){
System.out.print(" " + result);
} else {
System.out.print(result);
}
i++;
}
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int questionNumber = sc.nextInt();
sc.nextLine();
Paper paper = new Paper();
Answer answerSheet = new Answer(paper);
for(int i=0;i<questionNumber;i++){
String line = sc.nextLine();
Matcher matcher = Pattern.compile("#N:(\\s+)?(\\S+)(\\s+)?#Q:(\\s+)?(.+)#A:(\\s+)?(.+)").matcher(line);
if (matcher.find()) {
int number = Integer.parseInt(matcher.group(2));
String content = matcher.group(5);
content=content.trim();
String standardAnswer = matcher.group(7);
paper.addQuestion(new Question(number, content, standardAnswer));
}
}
while(true){
String line = sc.nextLine();
if (line.equals("end")) {
break;
}
String regex = "#A:(\\s+)?(\\S+)";
Matcher matcher = Pattern.compile(regex).matcher(line);
int matchCount = 0;
while (matcher.find()) {
matchCount++;
String your_answer = matcher.group(2);
answerSheet.saveOne_Your_answer(your_answer);
}
}
answerSheet.saveAnswers();
answerSheet.outputResults();
}
}
- 定義瞭如下的幾個類:
Question 類:定義了問題的編號、內容以及標準答案,並提供了檢查答案的方法。
Paper 類:包含了一個問題的列表,並提供添加問題和通過編號獲取問題的方法。
Answer 類:包含了一個試卷的引用,存儲了用戶的答案和每個答案的檢查結果。 - 代碼邏輯:
主類 Main 的 main 方法開始執行時,
讀取問題數量,然後根據題目數量迴圈使用正則表達式讀取每個問題的編號、內容和標準答案,並添加到試卷中。
保存答案,並檢查每個答案的正確性。
第一次類圖
-
代碼分析:
-
輸入處理:代碼使用正則表達式解析輸入行,這是處理此類問題的有效方法。
-
錯誤處理:代碼中沒有對於輸入內容的錯誤處理機制。如果輸入格式不正確,程式可能會崩潰。
-
代碼可讀性:正則表達式較為複雜,不易於理解。另外,一些變數和方法命名可以更具描述性。
-
代碼效率:在 Answer 類的 saveAnswers 方法中,每次迴圈都調用 paper.getQuestion_Number(i + 1),這並不高效的,因為可以事先獲取所有問題,再保存試卷中,可以有效提高效率
-
對於第二次作業最後一題:
點擊查看代碼
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Question {
private int number;
private String content;
private String standardAnswer;
public Question(int number, String content, String standardAnswer) {
this.number = number;
this.content = content;
this.standardAnswer = standardAnswer;
}
public int getNumber() {
return number;
}
public String getContent() {
return content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public boolean checkAnswer(String answer) {
return answer.equals(standardAnswer);
}
}
class Paper {
private List<Question> questions = new ArrayList<>();
public void addQuestion(Question question) {
questions.add(question);
}
public Question getQuestion_Number(int number) {
for (Question question : questions) {
if (question.getNumber() == number) {
return question;
}
}
return null;
}
}
class Answer {
private Paper paper;
private ArrayList<String> answers = new ArrayList<>();
private ArrayList<Boolean> results = new ArrayList<>();
public Answer(Paper paper) {
this.paper = paper;
}
public void saveOne_Your_answer(String answer) {
answers.add(answer);
}
public void saveAnswers() {
for (int i = 0; i < answers.size(); i++) {
Question question = paper.getQuestion_Number(i + 1);
if (question != null) {
results.add(question.checkAnswer(answers.get(i)));
}
}
}
public void outputResults() {
for (int i = 0; i < answers.size(); i++) {
Question question = paper.getQuestion_Number(i + 1);
if (question != null) {
System.out.println(question.getContent() + "~" + answers.get(i));
}
}
int i=0;
for (boolean result : results) {
if(i!=0){
System.out.print(" " + result);
} else {
System.out.print(result);
}
i++;
}
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int questionNumber = sc.nextInt();
sc.nextLine();
Paper paper = new Paper();
Answer answerSheet = new Answer(paper);
for(int i=0;i<questionNumber;i++){
String line = sc.nextLine();
Matcher matcher = Pattern.compile("#N:(\\s+)?(\\S+)(\\s+)?#Q:(\\s+)?(.+)#A:(\\s+)?(.+)").matcher(line);
if (matcher.find()) {
int number = Integer.parseInt(matcher.group(2));
String content = matcher.group(5);
content=content.trim();
String standardAnswer = matcher.group(7);
paper.addQuestion(new Question(number, content, standardAnswer));
}
}
while(true){
String line = sc.nextLine();
if (line.equals("end")) {
break;
}
String regex = "#A:(\\s+)?(\\S+)";
Matcher matcher = Pattern.compile(regex).matcher(line);
int matchCount = 0;
while (matcher.find()) {
matchCount++;
String your_answer = matcher.group(2);
answerSheet.saveOne_Your_answer(your_answer);
}
}
answerSheet.saveAnswers();
answerSheet.outputResults();
}
}
- 對於第三次作業最後一題:
點擊查看代碼
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Question{
private int question_num;
private String question_content;
private String question_standardAnswer;
private boolean if_effective = true;
public Question() {
}
public Question(int question_num, String question_content, String question_standardAnswer) {
this.question_num = question_num;
this.question_content = question_content;
this.question_standardAnswer = question_standardAnswer;
}
public int getQuestion_num() {
return question_num;
}
public String getQuestion_content() {
return question_content;
}
public String getQuestion_standardAnswer() {
return question_standardAnswer;
}
public boolean isIf_effective() {
return if_effective;
}
public void setIf_effective(boolean if_effective) {
this.if_effective = if_effective;
}
public boolean judge_right_or_wrong(String answer){
return answer.equals(question_standardAnswer);
}
}
class Question_Set{
HashMap<Integer, Question> question_set = new HashMap<>();
public Question_Set() {
}
public void addQuestion_set(Integer question_num, Question question){
question_set.put(question_num,question);
}
public Question getQuestion_of_set(Integer paper_question_number){
return question_set.get(paper_question_number);
}
public boolean containsKey(int remove_number) {
return question_set.containsKey(remove_number);
}
}
class Paper{
ArrayList<Question> questions = new ArrayList<>();
HashMap<Integer,Integer> questions_score = new HashMap<>();
ArrayList<Integer> answer_order = new ArrayList<>();
Question new_question = new Question(0,"0","0");
public Paper() {
questions.add(new_question);
}
public void addQuestion(Question question){
questions.add(question);
}
public void addQuestion_score(int question_number,int score){
questions_score.put(question_number,score);
}
public void addAnswer_order(int order_num){
answer_order.add(order_num);
}//答題順序
}
class Answersheet{
private int total_answer_number = 0;
// Answer new_answer = new Answer();
// ArrayList<Answer> answers = new ArrayList<>();
HashMap<Integer,Answer> answers = new HashMap<>();
// public Answersheet() {answers.add(new_answer);
// }
public int getTotal_answer_number() {
return total_answer_number;
}
public void add_your_answer(int order_num,Answer answer){
answers.put(order_num,answer);
this.total_answer_number++;
}
}
class Answer{
int order_num;
String your_answer;
public Answer(int order_num, String your_answer) {
this.order_num = order_num;
this.your_answer = your_answer;
}
public String getYour_answer() {
return your_answer;
}
}
class Student{
private String id;
private String name;
HashMap<String,Answersheet> students_to_answersheet = new HashMap<>();//id->答卷卷子
public Student() {
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
class Output{
HashMap<String,Integer> id_for_answer = new HashMap<>();
ArrayList<String> student_order = new ArrayList<>();
ArrayList<Student> students = new ArrayList<>();
HashMap<Integer,Paper> papers = new HashMap<>();
Question_Set question_set = new Question_Set();
ArrayList <Integer> un_question_set = new ArrayList<>();
public Output() {
}
public void save_paper_set(Integer paper_num,Paper paper){
papers.put(paper_num,paper);
}
public void save_student_answer(String id,Integer paper_num){
id_for_answer.put(id,paper_num);
student_order.add(id);
}
public void output_question_and_result(){
for(String student : student_order){//確定答題學生
int []score = new int[105];
Arrays.fill(score, 0);
int count_answer_question = 0;
for(Student new_student : students){//尋找該學生
if(new_student.getId().equals(student)){
int answer_paper_num = id_for_answer.get(student);//尋找所答試卷編號
Paper paper = papers.get(answer_paper_num);
if(paper!=null){
for(Integer answer_num : paper.answer_order){//找所答題目 T
for(Question question : paper.questions){//2 N
if(question!=null) {
if(question.getQuestion_num()==0){
continue;
}
// System.out.println(question.getQuestion_num());
if (question.getQuestion_num() == answer_num) {
if (question.isIf_effective() && !question.getQuestion_content().equals("null_content")) {//題目有效
System.out.print(question.getQuestion_content() + "~");//輸出題目內容
String your_answer = new_student.students_to_answersheet.get(student).answers.get(count_answer_question+1).getYour_answer();//你的答案
System.out.println(your_answer + "~" + question.judge_right_or_wrong(your_answer));//結果
if (question.judge_right_or_wrong(your_answer)) {//題目正確
score[count_answer_question] = paper.questions_score.get(question.getQuestion_num());
}
} else {//題目無效
if (answer_num > new_student.students_to_answersheet.get(student).getTotal_answer_number()) {
System.out.println("answer is null");
} else {
// int Num = new_student.students.get(student).answers.get(answer_num).getOrder_num();
// System.out.println(Num);
// System.out.print("*");System.out.println(answer_num);
if (question.getQuestion_content().equals("null_content")||question.getQuestion_standardAnswer().equals("null_answer")) {
System.out.println("non-existent question~0");
} else {
System.out.print("the question ");
System.out.print(question.getQuestion_num());
System.out.println(" invalid~0");
}
}
}
count_answer_question++;
break;
} else{
for(Integer a : un_question_set){
if(Objects.equals(a, answer_num)){
System.out.println("non-existent question~0");
count_answer_question++;
break;
}
}
}
}
}
}
System.out.print(new_student.getId() + " " + new_student.getName() + ":");
int sum_score = 0;
for(int i=0;i<count_answer_question;i++){
System.out.print(" ");System.out.print(score[i]);
sum_score += score[i];
}
System.out.print("~");System.out.println(sum_score);
} else {
System.out.println("The test paper number does not exist");
}
}
}
}
}
}
class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Output output = new Output();
while(true){
String line = sc.nextLine();
Matcher matcher_question = Pattern.compile("#N:(\\d+)(\\s)#Q:(.+)#A:(.+)").matcher(line);
Matcher matcher_score = Pattern.compile("(\\d+)(-)(\\d+)").matcher(line);//paper
Matcher matcherT = Pattern.compile("#T:(\\s+)?(\\d+)(\\s+)?").matcher(line);
Matcher matcher_your_answer = Pattern.compile("#A:(\\d+)-(\\S+)").matcher(line);//your answer
Matcher matcherS = Pattern.compile("#S:(\\d+)(\\s+)?(\\d+)").matcher(line);
Matcher matcherX = Pattern.compile("#X:").matcher(line);
Matcher matcher_student = Pattern.compile("(\\d+)(\\s)([a-zA-Z]+)").matcher(line);
Matcher matcherD = Pattern.compile("#D:").matcher(line);
Matcher matcher_remove_question = Pattern.compile("N-(\\d+)").matcher(line);
Matcher matcherN = Pattern.compile("#N:").matcher(line);
Matcher matcher_num = Pattern.compile("#N:(\\s+)?(\\d+)").matcher(line);
if(line.equals("end")){
continue;
}
String regex="#N: *(\\d+) *#Q:(.*)#A:(.*)";
Matcher format=Pattern.compile(regex).matcher(str);
if(!format.find()){
System.out.println("wrong format:"+str);
break;
}
if(matcherN.find()){
if (matcher_question.find()) {
int number = Integer.parseInt(matcher_question.group(1));
String content = matcher_question.group(3);
content = content.trim();
String standardAnswer = matcher_question.group(4);
standardAnswer = standardAnswer.trim();
Question question = new Question(number, content, standardAnswer);
output.question_set.addQuestion_set(number,question);
}
}
String regex="^#T: *\\d+ *((\\d+ *- *\\d+ *)+)$";
Matcher format=Pattern.compile(regex).matcher(str);
if(!format.find()){
System.out.println("wrong format:"+str);
continue;
}
if(matcherT.find()){
int paper_num =Integer.parseInt(matcherT.group(2));
Paper paper = new Paper();
int sum = 0;
while(matcher_score.find()){
int paper_question_number = Integer.parseInt(matcher_score.group(1));
paper.addQuestion(output.question_set.getQuestion_of_set(paper_question_number));
if(output.question_set.getQuestion_of_set(paper_question_number)!=null){
paper.addQuestion_score(paper_question_number,Integer.parseInt(matcher_score.group(3)));
paper.addAnswer_order(paper_question_number);
}
else {
paper.addQuestion_score(paper_question_number,0);
paper.addAnswer_order(paper_question_number);
// Question question = new Question(3,"null_content", "null_answer");
output.un_question_set.add(3);
}
sum+=Integer.parseInt(matcher_score.group(3));
}
output.save_paper_set(paper_num,paper);
if(sum!=100){
System.out.println("alert: full score of test paper1 is not 100 points");
}
}
if(matcherX.find()){
while(matcher_student.find()){
Student student = new Student();
String id = matcher_student.group(1);
String name = matcher_student.group(3);
student.setId(id);
student.setName(name);
output.students.add(student);
}
}
if(matcherS.find()){
int paper_num = Integer.parseInt(matcherS.group(1));
String id_for_answer = matcherS.group(3);//學號
output.save_student_answer(id_for_answer,paper_num);
Answersheet answersheet = new Answersheet();
while(matcher_your_answer.find()){
int order_num = Integer.parseInt(matcher_your_answer.group(1));//順序號
String your_answer = matcher_your_answer.group(2);//答案
Answer answer = new Answer(order_num,your_answer);
answersheet.add_your_answer(order_num,answer);
}
for(Student new_student : output.students) {
if(new_student.getId().equals(id_for_answer)){
new_student.students_to_answersheet.put(id_for_answer,answersheet);
}
}
}
if(matcherD.find()){
while(matcher_remove_question.find()){
int remove_number = Integer.parseInt(matcher_remove_question.group(1));
if(output.question_set.containsKey(remove_number)){
Question new_question = output.question_set.getQuestion_of_set(remove_number);
new_question.setIf_effective(false);
}
}
}
}
}
}
-
代碼邏輯:
主類的Main中的main中,利用while(true)死迴圈迴圈輸入各種題目,試卷,學生信息,經過正則表達式進行匹配後存入各個List對應相應的類中,然後,遍歷學生列表,根據學生答題情況輸出題目內容、學生答案、結果以及得分。 -
代碼分析:
-
數據結構:使用了合適的數據結構來存儲題目、試卷、學生答題情況等信息,HashMap、ArrayList 等。
-
邏輯設計:通過多個類的組合和方法調用,實現了題目、試卷、學生答題等功能。
採坑心得:
-
第一次作業:
1.這道題目需要正確讀入輸入的數據,註意錯誤的格式輸入,例如空白字元等,要運用正則表達式進行匹配正確輸入的字元
2.輸入的題號可能不連續,因此直接使用數組索引可能不合適,需要邏輯映射題號到數組或List索引 -
第二次作業:
1.在使用List儲存類時,容易遇到存儲不當,使得類有可能會出現為null的情況
2.沒有合理設計各個類的作用,使用大量方法在Main類中,代碼冗雜,不易讀
3.拘泥於第一題的模板和格式,沒有新增類用於處理第二題新增的輸入和處理,導致單獨一個類中的方法很冗餘,複雜,在運行第二題時,沒有設計多個類的方式高效簡潔和可復用性,使得下麵的第三題需要重新設計類和結構。(怎麼會這麼愚蠢還只設計三個類TT) -
第三次作業:
1.類間關係設計的很複雜,沒有完全符合類的單一職責原則,有的類中甚至只有屬性和getter setter,和構造方法,沒有盡到這個類中該盡的職責。
2.各個方法之間有重覆代碼,沒有理清題目含義,出現大量無效、低效代碼
3.對於輸入的錯誤格式(如空白字元等),容易遺漏判斷錯誤的格式情況,沒有能正確處理輸入,輸出對應應該輸出的答案。
4.對於遍歷各個列表進行遍歷輸出數據的時候,迴圈過於繁雜,遇到出現null或者輸入的是錯誤格式的代碼時,只會一昧的在迴圈的各個地方加上if判斷,沒有復用性,且不易理解TT
5.對於新增的輸出,學生,需要新建一個Student類,但在設計類時思路出現一點問題,Student應該在答卷類內,而我卻由Student之內儲存答卷,這會使得一些題目輸入的無效格式難以處理,極不方便。
踩坑總結:
- 在寫題時,需要先認真審題,好好釐清題目需求,不能寫一步看一步,要註重整體,對類要物盡其用,充分發揮類的職責,不能把活全交給一個或幾個類裡面去處理,要合理利用類間關係,將輸入的數據整合題目需求,高效簡潔的輸出,同時滿足設計時應滿足的幾個原則(例如:里氏代換,依賴倒轉,單一職責等)。(還得加油TT)
改進建議:
-
第一次作業:
可以單獨設計一個類用於儲存題目到試卷中,防止違反類的單一職責原則,讓類的用途更清晰 -
第二次作業:
題目的需求其實用三個類有點不足,可以設計答案類和試卷題目類,答案類可以用於保存答卷的題目,試卷題目類可以應對輸入中相同一道題目在不同試卷中不同分值的情況,刪除一些在第一次作業中在類中編寫的不必要和重覆的代碼,統一調用在新類的方法,可以使代碼更加高效,更加簡潔,增加可復用性。 -
第三次作業:
這次作業的場景需處理多張試卷,多張答卷,多個學生,新增了學生信息、刪除題目信息以及多種異常輸入的監測。
應該新增試卷題目類(Question_Paper):用於保存試卷中的題目信息。由於試卷中的題目序號與題目本身的題號不一致。且題目在不同試卷中的分值可能不一樣,因此,設計試卷題目類轉門用於處理
其次對於題目可能輸入的各種錯誤輸入,需要在各個對應的類中,專門添加一些類來處理這些信息,將其試卷或者題目或者答卷給定為無效,刪除改進前在Output類中的多層嵌套迴圈,改為調用類的方法內的迴圈,將複雜迴圈簡單化
總結
- 前三次的作業中,答題判題程式題目由淺入深,在題目中,學會了處理以下幾點:
1.學會使用正則表達式處理不同格式的輸入信息,包括題目信息、試卷信息、學生信息、答題信息以及刪除題目信息等,對信息進行解析和分類處理。
2.需要設計合適的數據結構來存儲題目信息、試卷信息、學生信息以及答題信息,以方便後續的操作和管理。
3.需要設計邏輯來判斷答題的正確性、計算得分,處理刪除題目信息等情況,要考慮各種可能的異常情況並給出合適的處理方式。
4.需要合理設計類間關係
5.需要考慮各種可能的異常情況,如格式錯誤、題目引用錯誤、學號引用錯誤等,給出相應的提示信息,保證程式的健壯性。 - 但是,我在這三次作業中,仍然有很多不足,只有第一題在規定時間內,通過了全部測試點,自己的編程,設計能力仍然還需提高,對於老師上課講的基本的類間關係還不太熟悉,處理題目的邏輯也很亂,需要加強對題目的理解能力。
- 在這些題目中我需要加深對於需求不斷的題目的處理問題能力,提高一定編程能力,加深設計能力,以處理之後難度逐漸加大,題目更加複雜的需求。
- 對於老師的授課方式,我覺得很合理,線上線下相結合,對於線下沒有理解的方面,可以線上上反覆觀看。但是對於題目中一些難以理解的一些輸入輸出,可以適當添加一些樣例來輔助理解題目含義,題目內最好不要出現自相矛盾的地方,比如刪除了某些題目的試卷已不再是100分,卻無警告信息輸出,但能通過測試樣例,可以適當增加測試樣例更加符合現實中的對應情況
- 最後我希望後面三次作業能夠彌補前面出現的不足,再接再厲,oop我來辣 ^O^/