- 前言:
- 設計與分析:
- opp-4-答題判題程式-4
- opp-5-家居強電電路模擬程式-1
- opp-6-家居強電電路模擬程式-2
- 踩坑心得:
- opp-4-答題判題程式-4踩坑和心得:
- opp-5-家居強電電路模擬程式-1踩坑和心得:
- opp-6-家居強電電路模擬程式-2踩坑和心得:
- 改進建議:
- 總結:
前言:
難度(1-10):
opp-4:6
opp-5:4
opp-6:6
知識點:
(1)類與物件:Java物件導向程式設計的核心,透過定義類和建立物件,實現大作業中的基本且必要操作。
(2)字串與陣列:處理輸入資訊的關鍵,字元陣列儲存char型別資料,支援資訊訪問、宣告、初始化、對比和轉換。
(3)正規表示式:高效處理輸入資訊,匹配特定字元和擷取字串,結合字串轉換,在大作業中發揮重要作用。
(4)ArrayList應用:資料儲存與呼叫的便捷選擇,避免類陣列越界問題,提升資料儲存安全性與便利性。
(5)抽象與繼承:資料類定義時採用繼承,最佳化類整理與操作,統一處理各類電器時僅需呼叫父類方法。
設計與分析:
opp-4-答題判題程式-4
- 該題繼第三次大作業增加了繼承的使用,將原來的問題類寫成父類,新增了它的子類填空題類(BlankQuestion),多選題類(MultipleChoiceQuestion),普通題目類(CommonQuestion)。
- 本次內容和上次相比無太大改動,主要不同點再對答案的判斷上,本次大作業答案的判斷放在了問題類的judje(String answer)方法裡,輸入回答的答案,返回判定結果,其他過程與前一次一致。
程式碼SourceMontor的生成報表內容:
opp-5-家居強電電路模擬程式-1
類圖:
- 本次是新一輪迭代的第一次作業,該次的類有父類(Electronic),以及它的子類:開關類(Switch)、兩種燈類(FluorescentLamp,IncandescentLamp)、兩種調速器類(BinningGovernor,ContinuousGovernor)、吊扇類(CeilingFan),還有一個代理類(Agent),該類負責處理輸入資訊。
- 每一個類裡面都有屬性Electronic frontElectronic;Electronic behindElectronic;用於每個電子元件知道前後連線的是誰,方便電壓的傳遞,因為不瞭解下一次的大作業的形式,所有該次本來打算將Electronic frontElectronic;Electronic behindElectronic;改為Electronic[] frontElectronic;Electronic[] behindElectronic;的形式應對並聯,不過最後沒用上。
- 大體執行思路:Agent裡有一個Electronic head;屬性,即開頭的電子元件,設該電子元件傳入電壓220v,傳出看情況,用behindElectronic傳入下一個,一直到最後。輸出是根據各自的傳入電壓輸出對應的工作狀態。
- 具體細節看類圖。
程式碼SourceMontor的生成報表內容:
opp-6-家居強電電路模擬程式-2
類圖:
- 相比於上一次大作業的看完題直接寫程式碼,這次大作業花費在設計的時間更多,刪除了上次的Electronic frontElectronic;Electronic behindElectronic;屬性,本次電子元件的前後關聯依靠ArrayList。
- 本次大作業新增了串聯類(Tandem)、並聯類(Parallel)、落地扇類(FloorFan),這三都是電子元件類(Electronic)的子類。還增加了一個上次打算寫但偷懶沒寫的排序類(SortPrint)。落地扇類與吊扇、白熾燈類差不多這裡不多做說明。串聯類和並聯類都有一個ArrayList連結串列。並聯類的ArrayList連結串列的引數化型別是Tandem,存放串聯物件。串聯類的的ArrayList連結串列的引數化型別是Electronic,可新增所有電子元件的子類(包括並聯類的物件,在這裡並聯類物件看成一個電子元件)。
- 和上一次電壓傳入傳出不同,因為迭代新增了電阻,本次電子元件傳入的資訊為電流,刪除了傳出。大體計算思路為(在接收全部輸入資訊後):計算電路總電阻->用220v電壓(如果有調速器按調後電壓計算)除總電阻得總電流->電子元件透過傳入的總電流計算其所分到的電壓->依照該電壓輸出對應的工作狀態。
- 具體細節看類圖。
程式碼SourceMontor的生成報表內容:
踩坑心得:
opp-4-答題判題程式-4踩坑和心得:
未考慮多選題輸入答案亂序
未改前程式碼:
public String judje(String answer) {
boolean flag=true;
StringTokenizer st = new StringTokenizer(answer," ");
while(st.hasMoreElements()&&flag)
{
if(standardAnswer.contains(st.nextToken()))
flag=true;
else
{
flag=false;
break;
}
}
if(answer.equals(standardAnswer))
return "true";
else if(answer.equals(""))
return "false";
else if(flag)
return "partially correct";
else
return "false";
}
該處理方法在答案為ABCD情況下,如果輸入為ABDC或AABCD,返回partially correct。
改後程式碼:
public String judje(String answer) {
if(answer==null)
return "false";
boolean flag=true;
answer=answer.trim();
StringTokenizer St = new StringTokenizer(standardAnswer," ");
int n=0;
while(St.hasMoreElements())
{
St.nextToken();
n++;
}
int m=0;
String[] ch=new String[10];
StringTokenizer st = new StringTokenizer(answer," ");
while(st.hasMoreElements()&&flag)
{
ch[m]=st.nextToken();
if(standardAnswer.contains(ch[m]))
{
flag=true;
m++;
}
else
{
flag=false;
break;
}
}
int M=0;
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
if(i!=j&&(ch[i].equals(ch[j])))
M++;
m=m-M/2;
if(!flag)
return "false";
else if(answer.equals(standardAnswer)||m==n)
return "true";
else
return "partially correct";
}
opp-5-家居強電電路模擬程式-1踩坑和心得:
1,基本沒有設計階段,因為本次題目簡單,直接邊敲程式碼邊想,多次刪改程式碼,邏輯混亂。所以在寫程式碼前還是要先設計好,這樣才能事半功倍。
2,忽略部分情況,比如開關在後面斷開,開關後的電器電壓全為零,但開關前的電器電壓未清零。解決方法便是新增一個TestFlow()方法判斷電路是否為通路,在進行Flow()。
3.物件為空的情況,因為本次用了Electronic behindElectronic,這種類似C語言連結串列的形式的方法,在處理資訊時有behindElectronic或者frontElectronic為空導致錯誤。我的解決方法是重頭理一遍,還是設計的問題,一開始沒想好怎麼寫就直接動手。
4,截尾輸出出現問題,不應該使用String.format("%.0f",n),應直接用(int)強制型別轉換後輸出。
opp-6-家居強電電路模擬程式-2踩坑和心得:
本次作業在完成時主要出現一些細節錯誤。
1,未接收全部資訊就計算線路電阻。在計算電阻的setR()方法裡有條件判斷(即Test Flow()方法),而如開關在未接受資訊#K時電路為斷路,並聯裡該串聯線路的電阻不加入計算,如果在串聯主線直接全不算,輸入電流直接全為零,因此造成結果出錯。改正方法便是在接收全部資訊後才計算線路電阻。
2,電阻值敲錯了。因為部分類長得差不多,直接複製過來不需要改多少,但有些該改的地方沒改造成錯誤,寫程式碼的時候還是得細心點。
3,精度誤差。並聯電阻的計算原採用方法為:1/R=1/R1+1/R2+1R3.....結果有誤差,兩個點過不去。改為R=R1*R2/(R1+R2)這種方法才能全過。
改進建議:
對於opp-4-答題判題程式-4:
1.新增更多的註釋方便程式碼閱讀。
2.類的劃分不夠細緻,並不是很符合單一職責原則。
對於opp-5-家居強電電路模擬程式-1:
(1) 建議增加排序類,本次透過投機取巧解決輸出順序問題:
ele=agent.getHead();
while(true)
{
ele.flow();
if(ele.getName().contains("K"))
ele.display();
if(ele.getnext()==null)
break;
ele=ele.getnext();
}
ele=agent.getHead();
while(true)
{
if(ele.getName().contains("K"));
else
ele.display();
if(ele.getnext()==null)
break;
ele=ele.getnext();
}
因為要輸出的內容少,需要排序的就那幾個,所有投機取巧先輸入開關再輸入其他就可以解決排序問題,不過後面還是得加上。
(2)
double m=(v-10)*5.0/7.0+50.0;
int n=(int)m;
System.out.println(n);
太麻煩
改成
System.out.println(String。format("%d",(int)((v-10)*5.0/7.0+50.0));
(3)刪除無關緊要的類,如本次的Vcc,除了令開始電壓為220v外沒其他作用。
對於opp-6-家居強電電路模擬程式-2:
- 排序類太過複雜,可以用介面(comparable或compatator)。
`
> public void Sortdisplay7() {
> String[] ch=new String[10];
> int L=0;
> for(FloorFan s:floorFans)
> {
> ch[L]=s.getName();
> L++;
> }
> for(int i=0;i<L-1;i++)
> for(int j=0;j<L-1-i;j++)
> {
> if(ch[j].compareTo(ch[j+1])>0)
> {
> String t=ch[j];
> ch[j]=ch[j+1];
> ch[j+1]=t;
> }
> }
> for(int i=0;i<L;i++)
> {
> for(FloorFan s:floorFans)
> {
> if(s.getName().equals(ch[i]))
> {
> s.display();
> break;
> }
> }
> }
> }
該程式碼差不多的內容寫了七次,一個排序類差不多三百行,佔了總程式碼行數的三分之一,雖然寫起來一直複製貼上花不了多少功夫,但是不夠精簡,查錯和改起來麻煩。
總結:
第四次大作業除了了繼承的使用無太多新東西。新一輪迭代的第五次和第六次大作業讓我更好的認識到了設計和註釋的重要性,好的設計可以讓你事半功倍,至於註釋,雖然第五次大作業缺少設計但有大量註釋,極大的方便了第六次大作業的書寫,不需要向第一輪迭代時一樣每次花時間讀懂上一次作業的程式碼。另外就是在遇到有些無法想通的問題時多和其他人討論,如本人第六次的計算精度問題,有些靠自己一人很難發現並解決,與他人討論不僅可以節省時間也能瞭解他人想法,拓寬自己的思路。