PTA題目集7、8的總結

cyzzl發表於2024-06-30

**前言**

1.第七次題目集的7-1在家居強電電路模擬程式-2的基礎上新增了一些內容,控制裝置增加了一個互斥開關,比較麻煩的是互斥開關不同的引腳相接其電阻並不相同,而且要從輸入資訊中讀取互斥開關的狀態也有點難度,與其他裝置不同的是,互斥開關可以出現在一個或兩個串聯電路中,更加考驗我們的演算法設計能力以解決準確讀取互斥開關狀態的問題。另外,本次迭代還加入了新的受控裝置———窗簾,有意思的是窗簾的開啟程度與電路中所有發光裝置的總亮度有光,需要記錄電路中的總亮度。這次題目的輸入格式更加複雜,因為本次迭代考慮多個並聯電路串聯在一起的情況和一條串聯電路中包含其他串聯電路的情況,很好的考察了我們對於資訊的處理能力、對字串和陣列相關知識點的掌握還有使用物件導向方法程式設計的熟練度。此外,相比於前面兩題,這次題目的要求更加***鑽和細緻,非常考驗我們當前對於Java語言的熟練度以及較強的邏輯思維和演算法設計能力。這次題目的工作量相對較大,對我來說操作難度比較大,需要花費很長的時間來完成。

2.第八次題目集的7-1家居強電電路模擬程式-3是一道非常有難度的題目,題幹非常的長,看完容易使人望而生畏。這就很考驗我們的資訊閱讀和資訊提取的能力,需要從長篇大論中總結出與我們編寫Java程式有關的資料和條件加以整合,還是比較麻煩的。本次作業用到了Java中繼承、多型的知識,讓我對涉及到的Java知識點更加熟悉,同時還用到了電路相關的基礎知識,綜合性非常強。本次迭代增加了新的電路裝置————二極體,讓題目的內容變得更加豐富。另外,在本題中,並聯電路M中的串聯電路可以包含別的並聯電路。最誇張的是增加管腳電壓的顯示,在輸出每個電器的狀態資訊後,再依次輸出該電器每個管腳的電壓。讓我花費了大量的時間來設計正確輸出該電器每個管腳的電壓的演算法,非常有難度啊,寫的時候感覺要崩潰了,因為水平確實有限啊。相比於上次題目,本次迭代對我們讀取所有電路裝置有了更加精確和完整的要求,不能模糊化處理任何電路裝置,每個電路裝置的所有屬性都要準確地得到,非常考驗整體思維。

**設計與分析**

1.第七次題目集7-1首先根據題目要求建立好所有的類,再根據細節對類的屬性和方法等進行補充。UML類圖如下:

本題的重點在於透過讀取控制裝置的狀態獲得電路的總電壓,再根據總電壓求出各受控裝置的亮度或速度。容易被忽略的是,本題中的控制裝置——開關可以重複出現,而連續調速器和分檔調速器最多隻能出現其一併且不能同時出現,而且只能直接連VCC。假如電路中有連續調速器或者分檔調速器,根據輸入資訊讀取level,再計算出電路電壓,最後判斷開關是否全部開啟;假如電路中既沒有分檔調速器,也沒有連續調速器,只需要判斷開關是否全部開啟(如果電路中存在開關的話),若全部開啟電壓為220V,否則為0V。得到電路的總電壓後就可以根據受控裝置的條件求出相應的亮度(或轉速)。 互斥開關的引腳可以重複出現,要準確獲取它的連線情況。窗簾主要在於求出電路中的總亮度,獲取它的開啟程度。

我設計的互斥開關類的程式碼如下:

 1 class MutexSwitch extends ControlDevice {
 2     boolean on;
 3 
 4     public MutexSwitch(double voltage, String name, double level, String input) {
 5         super(voltage, name, level, input);
 6         this.on = true;
 7     }
 8 
 9     public void changeOn() {
10         if (!on) {
11             on = true;
12         } else {
13             on = false;
14         }
15     }
16 
17     public double getR() {
18         if (on) {
19             return 5;
20         } else {
21             return 10;
22         }
23     }
24 
25     public void output() {
26         if (!on){
27             System.out.println("@" + getName() + ":turned on");
28         } else {
29             System.out.println("@" + getName() + ":closed");
30         }
31     }
32 }

在讀取輸入資訊時獲取互斥開關的基礎狀態,程式碼如下:

 1 case 'H':
 2     int index = 0;
 3     for (int j = 0; j < h.size(); j++) {
 4       index = input.indexOf("[H", index + 2);
 5       int index1 = input.indexOf('-', index);
 6       int index2 = input.lastIndexOf(']', index);
 7       char p = input.charAt(index1 + 1);
 8       char q = input.charAt(index2 - 1);
 9       if (p == '2' || q == '2') {
10            r0 += 5;
11        } else {
12            r0 += 10;
13        }
14        break;
15     }

使用String類的indexOf()方法得到‘H’在字串中的下標,再透過下標使用charAt()方法判斷引腳的數字是‘2’還是‘3’,從而得到接入電路中的是互斥開關的哪一部分,同時得到其正確的的電阻。

我設計的窗簾類的程式碼如下:

 1 class Curtain extends ControlledDevice {
 2     double light;
 3     int openScale;
 4 
 5     public Curtain(double voltage, String name, String input) {
 6         super(voltage, name, input);
 7     }
 8 
 9     public void setLight(double light) {
10         this.light = light;
11     }
12 
13     public void output() {
14         System.out.println("@" + getName() + ":" + openScale + "%");
15     }
16 }

本次迭代只需在上次題目的基礎上增加一些新的內容,如果寫出了上次的題目的話,這次的題目應該也能做出來。

3.第六次題目集7-1在第五次的基礎上增加了一些要求。UML類圖如下:

增加了並聯電路中的並聯電路,要考慮受控裝置的電阻,讓電路變得更加複雜,所要考慮的東西也更多了。 以串聯電路類為主體,從單個的串聯電路開始分析。 該方法讀取一條串聯電路中的所有電路裝置,放在ArrayList陣列裡,同時得到裝置的名字。 該方法用於判斷一條串聯電路是否處於通路狀態(是返回true,否返回false)。 該方法用於返回處於通路狀態下的一條串聯電路上所有受控裝置的總電阻。 大概的思路如下: 讀取輸入資訊,根據輸入資訊建立相應的串聯電路類和並聯電路類物件 讀取輸入資訊中所有開關的操作情況 根據所有控制裝置的狀態求出主電路的電壓 求出各並聯電路的電阻進而求出整個電路(主電路)的總電阻 計算求出每個串聯電路(除主電路外)的分壓 根據受控裝置的分壓求出每個受控裝置的亮度(或轉速) 根據題目要求排序輸出所有電路裝置的工作狀態。與上次迭代相比,這次的題目要求對所有電路裝置的屬性都有精確的輸出。最麻煩的就是需要獲取每個電路裝置兩個管腳的電壓,演算法設計起來還是比較複雜的,感覺同一個串聯電路中相鄰的電路裝置的管腳電壓的求法有點類似於遞迴,最重要的就是得到每個串聯電路最左端的電壓。有了最左端的電壓以後,就可以根據每個電路裝置的電壓求出它們的倆個管腳的電壓。程式碼實現如下:

  1 for (int i = 1; i < cd.getC().size(); i++) {
  2             for (int j = 0; j < b.size(); j++) {
  3                 if (cd.getC().get(i).name.equals(b.get(j).name)) {
  4                     b.get(j).setLeftV(cd.getC().get(i - 1).getRightV());
  5                     b.get(j).setRightV(b.get(j).getLeftV() - (int)b.get(j).voltage);
  6                     cd.getC().get(i).setLeftV(b.get(j).getLeftV());
  7                     cd.getC().get(i).setRightV(b.get(j).getRightV());
  8                 }
  9             }
 10             for (int j = 0; j < r.size(); j++) {
 11                 if (cd.getC().get(i).name.equals(r.get(j).name)) {
 12                     r.get(j).setLeftV(cd.getC().get(i - 1).getRightV());
 13                     r.get(j).setRightV(r.get(j).getLeftV() - (int)r.get(j).voltage);
 14                     cd.getC().get(i).setLeftV(r.get(j).getLeftV());
 15                     cd.getC().get(i).setRightV(r.get(j).getRightV());
 16                 }
 17             }
 18             for (int j = 0; j < d.size(); j++) {
 19                 if (cd.getC().get(i).name.equals(d.get(j).name)) {
 20                     d.get(j).setLeftV(cd.getC().get(i - 1).getRightV());
 21                     d.get(j).setRightV(d.get(j).getLeftV() - (int)d.get(j).voltage);
 22                     cd.getC().get(i).setLeftV(d.get(j).getLeftV());
 23                     cd.getC().get(i).setRightV(d.get(j).getRightV());
 24                 }
 25             }
 26             for (int j = 0; j < a.size(); j++) {
 27                 if (cd.getC().get(i).name.equals(a.get(j).name)) {
 28                     a.get(j).setLeftV(cd.getC().get(i - 1).getRightV());
 29                     a.get(j).setRightV(a.get(j).getLeftV() - (int)a.get(j).voltage);
 30                     cd.getC().get(i).setLeftV(a.get(j).getLeftV());
 31                     cd.getC().get(i).setRightV(a.get(j).getRightV());
 32                 }
 33             }
 34             for (int j = 0; j < c.size(); j++) {
 35                 if (cd.getC().get(i).name.equals(c.get(j).name)) {
 36                     c.get(j).setLeftV(cd.getC().get(i - 1).getRightV());
 37                     c.get(j).setRightV(c.get(j).getLeftV() - (int)c.get(j).voltage);
 38                     cd.getC().get(i).setLeftV(c.get(j).getLeftV());
 39                     cd.getC().get(i).setRightV(c.get(j).getRightV());
 40                 }
 41             }
 42             for (int j = 0; j < k.size(); j++) {
 43                 if (cd.getC().get(i).name.equals(k.get(j).name)) {
 44                     k.get(j).setLeftV(cd.getC().get(i - 1).getRightV());
 45                     cd.getC().get(i).setLeftV(k.get(j).getLeftV());
 46                     if (k.get(j).on) {
 47                         k.get(j).setRightV(k.get(j).getLeftV());
 48                     } else {
 49                         k.get(j).setRightV(0);
 50                     }
 51                     cd.getC().get(i).setRightV(k.get(j).getRightV());
 52                 }
 53             }
 54             for (int j = 0; j < h.size(); j++) {
 55                 if (cd.getC().get(i).name.equals(h.get(j).name)) {
 56                     h.get(j).setLeftV(cd.getC().get(i - 1).getRightV());
 57                     cd.getC().get(i).setLeftV(h.get(j).getLeftV());
 58                     if (s.withH) {
 59                         h.get(j).setRightV(0);
 60                         if (h.get(j).on) {
 61                             if (h.get(j).front) {
 62                                 h.get(j).setV1(h.get(j).getLeftV());
 63                             } else {
 64                                 h.get(j).setV3(h.get(j).getLeftV());
 65                             }
 66                         } else {
 67                             if (h.get(j).front) {
 68                                 h.get(j).setV1(h.get(j).getLeftV());
 69                             } else {
 70                                 h.get(j).setV2(h.get(j).getLeftV());
 71                             }
 72                         }
 73                     } else {
 74                         h.get(j).setRightV(h.get(j).getLeftV() - (int)h.get(j).voltage);
 75                         if (h.get(j).on) {
 76                             if (h.get(j).front) {
 77                                 h.get(j).setV1(h.get(j).getLeftV());
 78                                 h.get(j).setV2(h.get(j).getRightV());
 79                             } else {
 80                                 h.get(j).setV1(h.get(j).getRightV());
 81                                 h.get(j).setV2(h.get(j).getLeftV());
 82                             }
 83                         } else {
 84                             if (h.get(j).front) {
 85                                 h.get(j).setV1(h.get(j).getLeftV());
 86                                 h.get(j).setV3(h.get(j).getRightV());
 87                             } else {
 88                                 h.get(j).setV1(h.get(j).getRightV());
 89                                 h.get(j).setV3(h.get(j).getLeftV());
 90                             }
 91                         }
 92                     }
 93                     cd.getC().get(i).setRightV(h.get(j).getRightV());
 94                 }
 95             }
 96             for (int j = 0; j < e.size(); j++) {
 97                 if (cd.getC().get(i).name.equals(e.get(j).name)) {
 98                     if (e.get(j).isOn()) {
 99                         e.get(j).setLeftV(cd.getC().get(i - 1).getRightV());
100                         e.get(j).setRightV(e.get(j).getLeftV());
101                         cd.getC().get(i).setLeftV(e.get(j).getLeftV());
102                         cd.getC().get(i).setRightV(e.get(j).getRightV());
103                     } else {
104                         e.get(j).setLeftV(0);
105                         e.get(j).setRightV(cd.getC().get(i - 1).getRightV());
106                         cd.getC().get(i).setLeftV(e.get(j).getRightV());
107                         cd.getC().get(i).setRightV(e.get(j).getLeftV());
108                     }
109                 }
110             }
111             for (int j = 0; j < m.size(); j++) {
112                 if (cd.getC().get(i).name.equals(m.get(j).name)) {
113                     m.get(j).setLeftV(cd.getC().get(i - 1).getRightV());
114                     m.get(j).setRightV(m.get(j).getLeftV() - (int) m.get(j).voltage);
115                     cd.getC().get(i).setLeftV(m.get(j).getLeftV());
116                     cd.getC().get(i).setRightV(m.get(j).getRightV());
117                 }
118             }
119             for (int j = 0; j < t.size(); j++) {
120                 if (cd.getC().get(i).name.equals(t.get(j).name)) {
121                     t.get(j).setLeftV(cd.getC().get(i - 1).getRightV());
122                     t.get(j).setRightV(m.get(j).getLeftV() - (int) t.get(j).voltage);
123                     cd.getC().get(i).setLeftV(t.get(j).getLeftV());
124                     cd.getC().get(i).setRightV(t.get(j).getRightV());
125                 }
126             }
127         }

但是執行之後還是有很多問題,也不知道要怎麼解決,畢竟實力不允許[笑哭]。但是透過這幾次P他的練習,我對Java語言的掌握程度越來越深,也會更敢於去挑戰一些難題。

**踩坑心得**

第七次PTA: 沒有充分理解題目的意思,忽略了一些細節。比如,題目給的輸入樣例裡,互斥開關都是作為連線兩個串聯電路的樞紐,所以一開始做題時沒有考慮到互斥開關只有一個管腳接入電路,也就是另一個管腳沒有用到的情況,但是又沒有發現是這個問題,所以不管怎麼改還是這麼多分,最後經過同學提醒後才醒悟過來沒有考慮到這種情況,浪費了很多時間,追悔莫及。 沒有養成良好的編寫程式碼的習慣。寫程式碼時常常忽略用private將成員變數私有化,對有些Java知識點的概念比較模糊,還有很大的進步空間。 寫程式碼的時候容易寫著寫著腦子就亂了,邏輯混亂,需要多寫多練多思考加強程式設計能力。 寫出來的程式碼比較冗長且可讀性不是很強,還需要最佳化自己寫的程式碼,讓它變得更加簡練高效並且邏輯清晰。

第八次PTA:透過第八次PTA我發現第七次PTA提交的程式碼有很多不足的地方,對於那些沒有要求輸出資訊的裝置,都是採取模糊處理的方法,所以第八次PTA在對所有電路裝置有了更加精確的要求之後,之前寫的程式碼基本作廢了,需要進行大量的修改和重寫。感覺這次演算法設計的很糟糕,導致主函式的程式碼寫起來非常麻煩,寫到後面都寫不下去了。所以以後一定要根據題目要求更加合理地設計類的屬性和方法,從而讓自己的程式碼更加簡潔和高效。

透過這兩次題目集的磨練,我不僅鞏固了Java基礎語法,還應用了物件導向程式設計(OOP)的原則,如封裝、繼承和多型性,使我對Java的應用有了更廣泛的瞭解。 透過家居強電電路模擬程式的開發,我學習到了如何用Java實現複雜邏輯的建模,以及如何將實際問題轉化為程式可解決的方式。 儘管在知識掌握上取得了一定的進步,但也存在一些不足之處。例如,對於複雜的電路模擬,我發現我的演算法設計能力還有待提高,程式最佳化方面也缺乏經驗。 針對上述不足,我計劃採取以下措施進行改進: 加強演算法學習:透過學習電腦科學中的高階演算法和資料結構,提高問題解決的效率和質量。 實踐專案最佳化:透過效能分析和調優,提升程式執行效率,增強程式碼的可維護性和可擴充套件性。 學習設計模式:深入理解並實踐常見的設計模式,提高軟體設計的合理性和程式碼的複用性。 跨學科應用:由於家居強電電路涉及電子學知識,我需要補充相關領域的知識,以更好地理解和類比電路的行為。在完成作業的過程中,我遇到了許多挑戰,比如理解複雜的題目和除錯程式碼錯誤。這些挑戰讓我學會了耐心和堅持,我會將這些經歷視為寶貴的學習機會,幫助我在未來的學習和工作中保持積極的心態。透過這兩次題目集的訓練,我不僅提升了自己的程式設計技能,還學會了如何將程式設計知識應用於實際問題解決中。接下來的重點是提高自己在演算法設計、程式最佳化和跨學科應用方面的能力,以適應更復雜和挑戰性的程式設計任務。此外,我深刻認識到學習Java語言理論知識與實踐操作相結合的重要性。在未來的學習中,我將更加註重實踐,透過動手操作來鞏固和深化理解。