BLOG-2 對7-10周的學習總結
面向物件程式設計---七到十週綜合性學習
引言:過去幾周的Java的學習經歷了PTA大作業四,期中考試,還有兩次實驗。對遇見的題目和知識點進行整理和分析。
PTA大作業四
前言:這次的大作業共三道題。第一題是對正則表示式的考察,第二題考察四邊形相關知識,第三題設計一個銀行服務類。
對於正則表示式的學習會優化程式碼的結構,減少選擇和迴圈對格式的判斷。只需要規定正確的表達就可以規範化格式問題。
第二題則是本次作業的難點,要求用計算機語言來實現幾何圖形的判斷,不僅是對程式設計能力的考察,更要求較高的數學能力和空間想象能力。寫這道題可以充分體現出程式設計的特色,需要與數學縝密的結合。用計算機語言來嚴謹的轉化數學語言,這可以有效的鍛鍊我們面對複雜需求下的程式設計實現。這道題對於初學者算是一道難題,不僅要求對常用的數學方法的程式碼表示,如向量叉乘,射線法,兩直線相交求交點,判斷凹凸多邊形.......
第三道題則是根據類圖設計出一個類,要求實現相關的功能,需要把握類與類之間的關係和其中的具體細節。
題目集得分:96 題目集用時:十小時以上。 題目難度:難(是我寫過最難的題目了,以後還會更難)
各題目 設計與分析 踩坑心得 改進意見 核心程式碼分析:
(1)7-2 點線形系列4-凸四邊形的計算
設計與分析:
這道題的程式碼量達到了五百行。這個題目有五分分支,每個分支難度遞增又彼此不同。分支和程式碼量的增加直接導致程式碼的質量下降。
這是由於在做題目時只考慮如何實現程式碼的功能,為了寫程式碼而去寫程式碼,而沒有考慮到程式碼的質量。這道題的難處之一在於輸入檢測。
我推翻了前幾次的格式判斷函式,用正則表示式的思想,不去管有多少種錯誤,而只需要通過一定的分支判斷出正確的格式,遮蔽掉錯誤的格式
這次的格式控制不僅程式碼量大大下降,而且格式的控制更加的簡便,而且這樣的程式碼讀起來會更加的容易理解。
踩坑心得:
這個題出題人為了避免四個點構成四個點的情況過多,規定輸入的四個點兩兩相鄰,避免了構成四邊形情況過多,但是產生了新的問題。
比如判斷是否構成四邊形。
按照正常來說,是需要輸入的點不是三點(四點)共線,就一定能構成四邊形。
然而如果按照題目的輸入要求,就不能判斷所有的三點共線情況 。而是按照輸入要求只能選擇其中的一個問題,才可達到題目的要求。
而我一開始設計了所有的情況,反而是畫蛇添足了。
這題所有的坑都來自非法輸入(以下是我對於輸入非法的一些樣例)
1:+-2,001 3,1
2: 02.,3 1,2,3
3: 1+2,-0 1,2 (末尾有空格)
4:1, 1,,2
這題我被反覆折磨,其實就是做重複的事情,由於沒有提示測試樣例的點,那我只能一步一步地去嘗試。
在經過大量輸入之後,我總結了以上的輸入非法並對程式碼進行改進,直到通過所有的測試點。其中的難受真的時不想體驗第二遍。
改進建議:
1、由圖可知,該題的圈複雜度為73。這裡有點可惜,如果小於10程式碼質量就會很好。改進可以減少迴圈的使用。
2、這題可以將獲取字串變成一個字元陣列。此題可以將split方法改進,提高程式的執行效率
核心程式碼分析:
① 格式控制程式碼
static int is_format(int m,String str) { str = str.trim(); String []s =str.split("[ ,]"); int count=0 ,count1=1,sum=0; loop:for(int i=0;i<s.length;i++) { if(s[i].length()==0){ return 0; } for(int j=0;j<s[i].length();j++) { sum=0; char ch = s[i].charAt(j); if(j+1==s[i].length()) { if(ch=='+'||ch=='-'||ch=='.') return 0; if(ch>='0'&&ch<='9'&&i+1==s.length) break loop; else if(i+1!=s.length) continue; else return 0; } char ch1 = s[i].charAt(j+1); if(ch=='0'&&j==0){ if(ch1>='0'&&ch<='9') return 0; } if(ch=='+'||ch=='-') { if(j==0&&(ch1>='0'&&ch1<='9')) continue; else return 0; } else if(ch=='.'||ch1=='.') { sum++; if(((ch1<'0'||ch1>'9')&&ch=='.')||sum>2||((ch<'0'||ch>'9')&&ch1=='.')) return 0; else continue; } else if(ch>='0'&&ch<='9') continue; return 0; } } if(s.length==0){ return 0; } if(s.length!=m) { return -1; } if(s.length==m){ return 1; } return 0; }
②判斷四個點是否構成三角形
static boolean IsSJX(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4) { double a = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); double b = Math.sqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3)); double c = Math.sqrt((x3-x4)*(x3-x4)+(y3-y4)*(y3-y4)); double d = Math.sqrt((x4-x1)*(x4-x1)+(y4-y1)*(y4-y1)); if(k(x1,y1,x2,y2)!=-100&&k(x2,y2,x3,y3)!=-100&&k(x3,y3,x4,y4)!=-100&&k(x4,y4,x1,y1)!=-100) {//四個點構成三角形 if((y2-y1)*(x3-x2)==(y3-y2)*(x2-x1)){ //點1,2,3共線 if(on(x2,y2,x1,y1,x3,y3)) //3 2 1 為什麼是||而不是&&? // if(a+b+c>d&&c+d>a+b&&a+b+d>c) return true; } if((y3-y2)*(x4-x3)==(y4-y3)*(x3-x2)) { //2,3,4共線 if(on(x3,y3,x2,y2,x4,y4)) if(b+c+a>d&&b+c+d>a&&a+d>b+c) return true; } if((y4-y1)*(x1-x2)==(y1-y2)*(x4-x1)) //4 1 2 if(on(x1,y1,x4,y4,x2,y2)) return true; if((y4-y1)*(x1-x3)==(y1-y3)*(x4-x1)) //1 4 3 if(on(x4,y4,x1,y1,x3,y3)) return true; // return true; } if(k(x1,y1,x2,y2)==-100||k(x2,y2,x3,y3)==-100||k(x3,y3,x4,y4)==-100||k(x4,y4,x1,y1)==-100) { if((k(x1,y1,x2,y2)==-100&&k(x2,y2,x3,y3)==-100)||(k(x2,y2,x3,y3)==-100&&k(x3,y3,x4,y4)==-100)||(k(x3,y3,x4,y4)==-100&&k(x4,y4,x1,y1)==-100)||(k(x4,y4,x1,y1)==-100&&k(x1,y1,x2,y2)==-100)) return false; else if(a+b+c>d&&a+b+d>c&&a+c+d>b&&b+c+d>a) return true; } return false; }
期中考試
前言:期中考試時間比較緊張,只有兩個小時,題目也是三個題目。但是這三個題目作為考試設計的非常的巧妙,題目承上啟下,寫起來重複的內容越來越少,而考察了最近學習的內容。
主要考察了繼承,多型,介面,容器類,ArrayList ,set和get方法,泛類。
各題目 設計與分析 踩坑心得 改進意見 核心程式碼分析:
題目:7-1 點與線(類設計)
設計與分析:
踩坑心得:
這道題倒不是很難,不過需要理解類圖中類之間的關係,才可以很好的解決這樣的問題
程式碼的有些語句判斷過長,可以將其拆分,增強觀感
改進意見:
暫無。
核心程式碼分析:
這題是對點與線的型別設計。很好的闡述了類之間的設計
import java.util.Scanner; public class Main { } class Point{ private double x; private double y; public Point() { } public Point(double x,double y) { this.x = x; this.y =y; } public double getX() { return x; } public double getY(){ return y; } public void setX(double x) { this.x = x; } public void setY(double y) { this.y = y; } public void display() { System.out.println("("+String.format("%.2f", getX())+","+String.format("%.2f", getY())+")"); } } class Line { private String color; private Point Point1,Point2 = new Point(); Line(){ } Line(Point Point1,Point Point2,String color){ this.Point1 = Point1; this.Point2 = Point2; this.color = color; } Point getPoint1() { return Point1; } Point getPoint2() { return Point2; } void setPoint1(Point Point1) { this.Point1 = Point1; } void setPoint2(Point Point2) { this.Point2 = Point2; } String getcolor(){ return color; } void setcolor(String color) { this.color = color; } String getDistance() { Double data = Math.sqrt((Point1.getX()-Point2.getX())*(Point1.getX()-Point2.getX())+(Point1.getY()-Point2.getY())*(Point1.getY()-Point2.getY())); return String.format("%.2f", data); } public void display() { System.out.println("The line's color is:"+getcolor()); System.out.println("The line's begin point's Coordinate is:"); Point1.display(); System.out.println("The line's end point's Coordinate is:"); Point2.display(); System.out.println("The line's length is:"+getDistance()); } }
這是第二題的類圖
核心程式碼分析:
這道題附上運用多型的系列程式碼進行說明
public static void main(String []arge) { Scanner input = new Scanner(System.in); Double x1,y1,x2,y2; String color; x1 = input.nextDouble(); y1 = input.nextDouble(); x2 = input.nextDouble(); y2 = input.nextDouble(); color = input.next(); Point p1 = new Point(x1,y1); Point p2 = new Point(x2,y2); Line line = new Line (p1,p2,color); Plane plane = new Plane(color); Element element ; if((x1<=0||x1>200)||(x2<=0||x2>200)||(y1<=0||y1>200)||(y2<=0||y2>200)) System.out.println("Wrong Format"); else { element = p1;//起點Point element.display(); element = p2;//終點Point element.display(); element = line;//線段 element.display(); element = plane;//面 element.display(); } }
7-3 點線面問題再重構(容器類)
類圖如下
這道題主要是書寫一個容器類,用到ArrayList的add和delete方法做到增加和減少。
這個需要熟練的運用ArrayLIst的方法,對於Java課程的學習上課聽講有很好的檢驗效果。
而這道題的容器類只要理解好這個類圖的類與類之間的關係,就很容易做出來了。
踩坑心得:
這就是我對ArrayList不熟悉導致的 我在刪除的時候書寫的程式碼時list.remove(index);
對比上圖 我忘記了應該刪除的是index-1而不是index導致這道題目的錯誤
這就很好的說明了我對Java的ArrayList不夠熟悉,對於下標引用的不夠熟悉,這說明我們在學習的過程中需要注意細節,差之毫釐,謬以千里。
在這裡也給我自己一個警示,上課需要非常的專心。
改進意見:
1、如複雜度分析圖所示,本題的圈複雜度為33,超過了程式碼的一般範圍,這就意味這該程式碼的可讀性非常的差,而對與前文提到的方法都可有效減少圈複雜度。
2、本題的程式碼有兩百多行,程式碼的簡化就顯得尤為重要,應該適當的合適程式碼的邏輯,讓程式碼模組化。
3、如果能夠將程式碼的邏輯顛倒一下,程式將更加的合理。
核心程式碼如下:
class Plane extends Element{ private String color; public void display(){ System.out.println("The Plane's color is:"+getColor()); } Plane(){ } Plane(String color){ this.color = color ; } String getColor() { return color; } void setColor(String color) { this.color = color; } } class GeometryObject { ArrayList<Element> list =new ArrayList<Element>(); GeometryObject(){ } public void add(Element element) { list.add(element); } public void remove(int index) { if(index<list.size()) list.remove(index-1); } public void getlist() { for( Element element : list) element.display(); } }
這一排的程式碼很好的說明了如何書寫容器類。
對於這接下來的程式碼書寫有很好的借鑑作用。
switch(choice) {
case 1://insert Point object into list
輸入“點”物件的x,y值
break;
case 2://insert Line object into list
輸入“線”物件兩個端點的x,y值
break;
case 3://insert Plane object into list
輸入“面”物件的顏色值
break;
case 4://delete index - 1 object from list
輸入要刪除的物件位置(從1開始)
...
}
學習心得:
1、讓我對自己的水平有了一定的認知,提醒我今後的學習還有很多改進的地方,領悟自上而下逐步細化的程式設計思想更加的透徹
2、深刻了解了關於Java程式結構和程式碼書寫的規範,以及要遵守的程式碼書寫規範,拔高了我對程式設計的眼界和深度,學習了很多程式設計時使用的技巧和方法
3、積累了一些debug的經驗,深刻認識到了除錯的重要性,學會了除錯的基本技巧,如何設定斷點,單步進入,跟蹤引數,以及更改程式碼的邏輯順序,排除邏輯錯誤,對提高程式碼的質量大有改善。
4、學會了對於一些類的使用,瞭解瞭如何使用例項方法,抽象方法,和包括ArrayList的使用方法,這對於今後的學習有很大的提示空間。
特別鳴謝出題目的老師和幫助我修改程式碼的同學們,讓我有了提高自己的機會