題目集7~8的總結性Blog

Duansiyu發表於2024-06-29

目錄
  • 一 、前言:
    • 總結兩次次題目集的知識點、題量、難度等情況
      • 知識點
      • 題目及題量、難度

        • nchu-software-oop-2024-上-7:
        • nchu-software-oop-2024-上-8:
  • 二、第三次的家居強電電路模擬程式分析
    • 設計與分析
      • 第三次的家居強電電路模擬程式類圖以及SourceMontor的生成報表內容:
    • 踩坑心得
    • 改進建議
  • 三、第四次的家居強電電路模擬程式分析
    • 設計與分析
  • 四、總結:

一 、前言:

總結兩次次題目集的知識點、題量、難度等情況

知識點

這兩次題目集綜合考察了java語言三大特性中的多型,子類與父類的繼承關係、方法重寫,資訊處理、比較,排序輸出,類的物件建立有無引數的不同構造方法、屬性的訪問許可權等知識點,對類的設計要求提高,java中的封裝與繼承,多個類的設計,類與類之間的關係考慮,向下轉型,compare介面的使用,集合介面的例項化,迭代器,資料的查詢、排序,字串處理,正規表示式,型別轉換,類與物件、方法的使用,方法的呼叫與返回,多個類的關係與使用、連結串列或雜湊表、遍歷方法,物件導向的封裝性,類的設計等知識點。集合了前幾次的知識點於一體考察。

題目及題量、難度


nchu-software-oop-2024-上-7:

7-1 家居強電電路模擬程式-3

是之前電路模擬程式的第三次迭代,增加了兩種電器:互斥開關和窗簾,增加了考慮多個並聯電路串聯在一起的情況、一條串聯電路中包含其他串聯電路的情況。難點有很多,比如互斥開關的連線狀態判斷,多並聯電路的互相影響。

nchu-software-oop-2024-上-8:

7-1 家居強電電路模擬程式-4

超級超級難,沒有設計思路。這次迭代增加了很多內容:增加管腳電壓的顯示,最大電流的限制顯示,短路檢測,並聯電路中包含並聯電路,增加了二極體。我對管腳電壓的顯示沒有什麼設計思路,可能是因為之前幾次沒有怎麼考慮過引腳電壓,只考慮過引腳的順序。在增加的部分中短路的檢測和最大電流的限制顯示還是很簡單的,難點在於引腳電壓。

二、第三次的家居強電電路模擬程式分析

設計與分析

第三次的家居強電電路模擬程式類圖以及SourceMontor的生成報表內容:


  這一次的迭代中增加了一種開關(互斥開關H類)和一種受控裝置(窗簾S類)。H類繼承SW類S類繼承Lead類
  對於互斥開關,有三個引腳,輸入該元器件資訊時要注意不同引腳連的不同的對應的電路。互斥開關的切換與開關的切換略有不同,要切換電路接通狀態還有改變電阻。需注意的一點就是輸出互斥開關的狀態時是輸出互斥開關中引腳1和引腳2的接通狀態。
  對於窗簾,窗簾的開啟程度與整個電路中電器發出的亮度有關,所以我寫了一個light方法用於計算整個電路中的光照強度。

  1. H類:用於表示互斥開關。包含了一個無參構造方法和一個有參構造方法,用於初始化互斥開關物件。
    提供了:
    Z方法:用於切換開關。原先是引腳12接通切換後變為引腳13接通且電阻變為10,原先是引腳13接通切換後變為引腳12接通且電阻變為2。
    print方法:用於輸出該互斥開關的引腳12的接通狀態。
  2. S類:用於表示並聯電路,包括光照強度(light)、窗簾的開啟比例(b)。包含了一個無參構造方法和一個有參構造方法,用於初始化窗簾物件。
    提供了:
    light方法:用於計算整個電路中的光照強度。
    U方法:用於計算該窗簾的開啟比例。根據不同的光照強度設定不同的開啟比例。
    print方法:用於輸出該窗簾的開啟比例。
點選檢視程式碼
class H extends SW{//互斥開關
	public H() {}
	public H(int lead1,String name) {
		super(lead1,name);
		switch (lead1) {
		case 1: {
			h=2;
			x=1;
			break;
		}
		case 2: {
			h=2;
			x=1;
			break;
		}
		case 3: {
			h=3;
			x=1;
			break;
		}
		default:
			throw new IllegalArgumentException("Unexpected value: " + lead1);
		}
		k=9;
		R=5;//12連
		hsString=this.name+"-"+"2";
	}
	 public void Z()
	    {
	        if(x==1)
	            {h=3;hsString=this.name+"-"+h;
	            x=0;R=10;}
	        else if (x==0) 
	            {x=1;h=2;hsString=this.name+"-"+h;
	            R=5;}
	    }
    public void print()
    {
        if(x==1)
         System.out.println("@"+name+":closed");
        else 
         System.out.println("@"+name+":turned on");
    }
}

class S extends Lead{//窗簾
	double light=0;
	double b=1;
	public S() {}
	public S(int lead1,String name) {
		super(lead1,name);
		k=10;
		R=15;
	} 
	public double light(Array array) {
		for (int i = 0; i < array.arrayList.size(); ++i) {
				if (array.arrayList.get(i).k==4||array.arrayList.get(i).k==5) 
			//System.out.print(array.arrayList.get(i).name+" "+array.arrayList.get(i).light(array));
				light+=array.arrayList.get(i).light(array);
		}
		return light;
	}
	public void U() {
		if (u<50||light==0) {
			b=1;
		}
		else if(light>=50&&light<100){
			b=0.8;
		}
		else if(light>=100&&light<200) {
			b=0.6;
		}
		else if(light>=200&&light<300) {
			b=0.4;
		}
		else if(light>=300&&light<400) {
			b=0.2;
		}
		else {
			b=0;
		}
		b=b*100;
	}
	public void print() {
		 //System.out.println(light+" "+b);
		 this.U();
		 System.out.println("@"+name+":"+ (int)b+"%");
		
	}
}

踩坑心得

我主要是卡在互斥開關。。。

樣例四卡了很久很久

而我的

  • 在設計互斥開關時,一開始我預設輸入引腳為1時這條電路連的另一個引腳就是2,沒有考慮到引腳輸入順序的問題。還有一個需要注意的點在於互斥開關所連的兩條電路的狀態會受到該互斥開關的連線影響,切換開關時對應的電路狀態也可能隨之變化。一定一定要記得切換開關後重新判斷下電路的狀態!我一開始就漏了修改電路狀態和電路內元器件的狀態、電壓等。
  • 這次的電路資訊變複雜了 ,一條串聯電路中也可以含有其他的串聯電路,一條串聯電路中也可以含有多條並聯電路,我一開始把電路資訊單獨儲存,導致串聯電路中有串聯電路時會找不到,或者不會將串聯電路連入主電路等。所以我改變了電路的資訊的儲存。
  • 窗簾的開啟比例計算!這裡這個比例與整個電路中電器發出的光照強度對應成比例,一定要注意是整個電路,而且要注意計算光照強度應該在所有開關狀態切換完畢、所有電器都完成工作後再計算。計算中要注意題目預設規則:所有資料以double型別儲存,輸出整型(連續調檔器除外),所以在計算光照強度時也是用double型別儲存資料。
  • 電器元件輸出時的順序!沒有考慮按字典序排序啊,導致有幾個測試點沒有透過。我的輸出順序只是對型別排了序,對於同型別的不同電器元件,輸出順序與輸入順序一致,這裡是不對的,型別排完序應該對名字排序即字典序排序。

改進建議

  • 在串聯電路series類中設計了一個方法函式用於判斷互斥開關與該電路是否連通。
點選檢視程式碼
public int h(Lead lead,String s,int num) {
		Pattern pattern=Pattern.compile("(H\\d+)-(\\d+)");//互斥開關名字與連線引腳
		Matcher matcher=pattern.matcher(lead.hsString);//該電路的互斥開關資訊
                Matcher matcher2=pattern.matcher(s);//被比較的互斥開關
			if (matcher.matches()) {
				if (matcher2.matches()) {
					//System.out.println(lead.hsString+"  "+s);
					if (matcher.group(1).equals(matcher2.group(1))) {
						if (matcher.group(2).equals(matcher2.group(2))) {
							return 1;//連通
						}
						else {
							return 0;//斷開
						}
					}
				}
			}
			else {
				return 1;}//連通
		return 1;//連通
	}
  • 在窗簾S類中設計了一個方法函式用於計算整個電路里的光照強度。
點選檢視程式碼
public double light(Array array) {
		for (int i = 0; i < array.arrayList.size(); ++i) {
				if (array.arrayList.get(i).k==4||array.arrayList.get(i).k==5) //會發出光照的電器
			//System.out.print(array.arrayList.get(i).name+" "+array.arrayList.get(i).light(array));
				light+=array.arrayList.get(i).light(array);
		}
		return light;
	}
  • 在電器元件類裡修改了排序介面,增加了對字串的比較。
點選檢視程式碼
public int compareTo(Object o) {
		Lead student=(Lead)(o);
		if (this.k==student.k) {
			return this.name.compareTo(student.name);
		}
		return this.k-student.k;
	}

三、第四次的家居強電電路模擬程式分析

這次的程式碼大作業沒怎麼寫,就拿了十五分,寫了下短路的判斷,沒有什麼思路,就簡單分析下。

設計與分析

這次的大作業增加了很多內容:

  • 管腳電壓的顯示:這個內容我沒太有設計思路,可能是之前偷懶了,在前幾次電路程式的設計時,引腳沒有與電壓相關,只是單純的輸入輸出,也沒有把這個作為連線電路的依據,上次寫互斥開關時才開始考慮引腳。而這次顯示管腳的電壓把我難住了,一開始我認為兩邊的電壓不應該一樣嗎?後來想想物理,好像不太對,兩管腳的電壓差是這個電器元件的電壓,明白了這個後,電路中單電器或電器加電阻為0的多電器的還好,電壓只需要考慮那個電阻不為0的電器元件,但是多元件且電阻都不為0的怎麼辦呢,我沒有什麼思路。
  • 電流限制:每個電器會有最大電流,這個部分我寫了一點,拿窗簾來舉個例吧,我在電器元件Lead類中增加了I屬性用於表示最大電流。在輸出電器元件資訊時進行電流判斷,超過則輸出“exceeding current limit error”。
點選檢視程式碼
class S extends Lead{//窗簾
	double light=0;
	double b=1;
	public S() {}
	public S(int lead1,String name) {
		super(lead1,name);
		k=10;
		R=15;
		I=12;
	} 
	public double light(Array array) {
		for (int i = 0; i < array.arrayList.size(); ++i) {
				if (array.arrayList.get(i).k==4||array.arrayList.get(i).k==5) 
			//System.out.print(array.arrayList.get(i).name+" "+array.arrayList.get(i).light(array));
				light+=array.arrayList.get(i).light(array);
		}
		return light;
	}
	public void U() {
		if (u<50||light==0) {
			b=1;
		}
		else if(light>=50&&light<100){
			b=0.8;
		}
		else if(light>=100&&light<200) {
			b=0.6;
		}
		else if(light>=200&&light<300) {
			b=0.4;
		}
		else if(light>=300&&light<400) {
			b=0.2;
		}
		else {
			b=0;
		}
		b=b*100;
	}
	public void print() {
		 //System.out.println(light+" "+b);
		 this.U();
	        l();
	        if(x==1)
	        {
	        	if (this.i>this.I) {
	        		System.out.println("@"+name+":"+ (int)b+"%"+" "+lead1+"-"+lead2+" exceeding current limit error");
				}
	        	else
	        	 System.out.println("@"+name+":"+ (int)b+"%"+" "+lead1+"-"+lead2);
	        }
	        else if(x==0)
	         System.out.println("@"+name+":"+ (int)b+"%"+" "+lead1+"-"+lead2);		
	}
}
  • 短路檢測:對每個串聯電路進行檢測。所以我直接在操作方法中增加對串聯電路的判斷,一旦發現就結束整個程式的執行,輸出“short circuit error”。
點選檢視程式碼
for(int i=0;i<=ss;i++)
         {
            //System.out.println(series[i].x+" "+series[i].R+series[i].name);
            if(series[i].x==1&&series[i].R==0)
            {
                System.out.println("short circuit error");
                System.exit(0);
            }
         }
  • 並聯電路中包含並聯:我改變了並聯的儲存,增加並聯電路時同時將該電路增加到所有電器元件的連結串列中,這樣並聯電路內查詢其他並聯電路也能找到並將其作為自己的一部分。

  • 增加了一個電器元件-二極體:正向透過,反向截止,這對輸入二極體資訊時就要考慮輸入的管腳順序,而我之前忽略了管腳的順序,所以設計起來有點沒思路了。在補充以下之前我還是設計了一下二極體的類。但是補充後沒思路了就沒繼續設計了。

點選檢視程式碼
class P extends Lead{//二極體
	public P() {}
	public P(int lead1,String name) {
		super(lead1,name);
		k=11;
		R=0;
		I=8; 
        if(lead1==1)
            this.x=1;
        else
            this.x=0;
	} 
	public void print() {
		l();
        if(this.x==1) {
        	if (this.i>this.I) {
        		System.out.println("@"+name+":conduction"+" "+lead1+"-"+lead2+" exceeding current limit error");
			}
        	else
        	 System.out.println("@"+name+":conduction"+" "+lead1+"-"+lead2);}
        else
		 System.out.println("@"+name+":cutoff"+" "+lead1+"-"+lead2);
	}
}

四、總結:

  在這兩次大作業中只完成了一次,也是感覺自己寫的很不好,雖然第三次電路模擬程式拿到了滿分,但是寫的很亂,有很多函式方法都沒有做到單一職責原則,用了很多if-else,雖然也在儘量用一用switch語句了。程式碼中也有很多功能一樣的語句重複重複重複沒有合併,寫的時候老是想到什麼寫什麼,提前設計的總是在真正實踐中改了又改,還是設計的意識不夠強,設計思路不夠清晰。
  在這學期的物件導向設計課程的八次大作業中,感覺到每一次大作業老師都在培養我們提前設計的意識,這幾次大作業老師釋出的時間總是比預計的晚,但是老師會提前把題面發出來,目的應該就是讓我們提前思考,設計一下,這樣開始寫的時候不會毫無頭緒、雜亂無章(雖然我做的不是很好,但是每一次大作業都感覺自己進步了一點點)。
  從第一次設計答題判題程式到最後一次的家居強電電路模擬程式,程式碼的複雜性越來越高,程式碼也越來越長。記得第一次聽老師說大作業的程式碼長度從300行會到700行到1000行甚至更多,我的第一反應是我做的到嗎?寫不出來這麼多吧,而事實時在最後一次拿到滿分的大作業中我的程式碼長度是900行,挺長了。一次次的迭代中類越來越多,類與類之間的關係也越來越複雜。
  在我完成的這八次大作業中,雖然除了最後一次的迭代沒有設計思路,其他都拿到了滿分,但是仍然有很多可以改進的地方:依然沒有很好的實現函式單一職責,但是一次比一次強吧,總算會把功能相同類似的程式碼合併成一個函式了。記得之前的程式碼主類裡只有一個主函式,在一次次的迭代中我學會分類了,將一些功能單拎出來成為一個函式,雖然有些函式的功能比還是很複雜;沒有提前設計的意識,總是想到什麼寫什麼,想用那個資料就直接用了,沒有考慮資料的私有化,就直接呼叫,導致程式碼的安全性、靈活性都不高。不過經過這一學期的大作業磨練後,我明白了提前設計的重要性,提前設計真的能幫助我們在實踐功能時有明確的思路,知道寫這些是為了幹什麼。最後啊,最後一次的大作業真的好難,然後就是可惜看不到老師是怎麼寫這些題目的,感覺每次程式碼的改進都是自己慢慢悟出來的,如果能在作業截至後看到老師是怎麼具體實現我認為很難實現的功能,應該能學到更多。