物件導向程式設計第二單元總結

哦嘞裡個嘞發表於2022-05-01

前言:

  這三週的Java課程主要學習了Collections介面的很多實現。瞭解了一些基本資料型別並可以做一些簡單的運用。在這三週的題目量並不多,但是題目難度有所提升。PTA中的題目集很難像以前那樣拿到滿分。並且每次都會對題目進行迭代,無形中迫使我們需要認真設計類,才能完成後續迭代的需求,加強了對OOP的運用和理解。

 


設計與分析:

 PTA圖形類設計:

   題目描述:

 

 

   類圖:沒有進行類的設計。

   原始碼:

  1 import java.util.Scanner;
  2 
  3 public class Main {
  4     public static void main(String[] args) {
  5         Scanner in = new Scanner(System.in);
  6         String line = in.nextLine();
  7         try {
  8             int coi = Integer.parseInt(line.substring(0, 1));
  9             if (coi < 1 || coi > 5) {
 10                 System.out.print("Wrong Format");
 11                 System.exit(0);
 12             }
 13             switch (coi) {
 14                 case 1:
 15                     System.out.print(calculateSlope(line.substring(2)));
 16                     break;
 17                 case 2:
 18                     System.out.print(calculateDistance(line.substring(2)));
 19                     break;
 20                 case 3:
 21                     System.out.print(isColinear(line.substring(2)));
 22                     break;
 23                 case 4:
 24                     System.out.print(isParallel(line.substring(2)));
 25                     break;
 26                 case 5:
 27                     System.out.print(isIntersectWithinSegment(line.substring(2)));
 28                     break;
 29             }
 30         } catch (Exception e) {
 31             System.out.print("Wrong Format");
 32             System.exit(0);
 33         }
 34     }
 35 
 36     /**
 37      * 計算兩點構成線段的斜率
 38      */
 39     public static double calculateSlope(String data) {
 40         String[] points = data.split(" ");
 41 
 42         String point1 = points[0], point2 = points[1];
 43         double x1 = 0, y1 = 0;
 44         double[] xy = processData(point1);
 45         x1 = xy[0];
 46         y1 = xy[1];
 47 
 48         double x2 = 0, y2 = 0;
 49         xy = processData(point2);
 50         x2 = xy[0];
 51         y2 = xy[1];
 52         if (points.length != 2) {
 53             System.out.print("wrong number of points");
 54             System.exit(0);
 55         }
 56         if (Math.abs(x1 - x2) < 1e-6 && Math.abs(y1 - y2) < 1e-6) {
 57             System.out.print("points coincide");
 58             System.exit(0);
 59         }
 60         if (Math.abs(x1 - x2) < 1e-6) {
 61             System.out.print("Slope does not exist");
 62             System.exit(0);
 63         }
 64 
 65         return (y1 - y2) / (x1 - x2);
 66     }
 67 
 68     /**
 69      * 判斷三點是否在一條直線上
 70      */
 71     public static boolean isColinear(String data) {
 72         String[] points = data.split(" ");
 73 
 74         String point3 = points[2];
 75         String point1 = points[0];
 76         String point2 = points[1];
 77         double x1 = 0, y1 = 0;
 78         double[] xy = processData(point1);
 79         x1 = xy[0];
 80         y1 = xy[1];
 81 
 82         double x2 = 0, y2 = 0;
 83         xy = processData(point2);
 84         x2 = xy[0];
 85         y2 = xy[1];
 86 
 87         double x3 = 0, y3 = 0;
 88         xy = processData(point3);
 89         x3 = xy[0];
 90         y3 = xy[1];
 91 
 92         if (points.length != 3) {
 93             System.out.print("wrong number of points");
 94             System.exit(0);
 95         }
 96 
 97         if (Math.abs(x2 - x3) < 1e-6 && Math.abs(y2 - y3) < 1e-6) {
 98             System.out.print("points coincide");
 99             System.exit(0);
100         } else if (Math.abs(x1 - x3) < 1e-6 && Math.abs(y1 - y3) < 1e-6) {
101             System.out.print("points coincide");
102             System.exit(0);
103         } else if (Math.abs(x1 - x2) < 1e-6 && Math.abs(y1 - y2) < 1e-6) {
104             System.out.print("points coincide");
105             System.exit(0);
106         }
107 
108         if (Math.abs(x1 - x2) > 1e-6) {
109             double k = calculateSlope(points[0] + " " + points[1]);
110             double b = y1 - k * x1;
111             return Math.abs(k * x3 + b - y3) < 1e-6;
112         } else {
113             return Math.abs(x1 - x3) < 1e-6;
114         }
115 
116     }
117 
118     /**
119      * 判斷是否平行
120      */
121     public static boolean isParallel(String data) {
122         String[] points = data.split(" ");
123         String point1 = points[0], point2 = points[1], point3 = points[2], point4 = points[3];
124 
125         double x1 = 0, y1 = 0;
126         double[] xy = processData(point1);
127         x1 = xy[0];
128         y1 = xy[1];
129 
130         double x2 = 0, y2 = 0;
131         xy = processData(point2);
132         x2 = xy[0];
133         y2 = xy[1];
134 
135         double x3 = 0, y3 = 0;
136         xy = processData(point3);
137         x3 = xy[0];
138         y3 = xy[1];
139 
140         double x4 = 0, y4 = 0;
141         xy = processData(point4);
142         x4 = xy[0];
143         y4 = xy[1];
144         if (points.length != 4) {
145             System.out.print("wrong number of points");
146             System.exit(0);
147         }
148         if (Math.abs(x1 - x2) < 1e-6 && Math.abs(y1 - y2) < 1e-6
149                 || Math.abs(x3 - x4) < 1e-6 && Math.abs(y3 - y4) < 1e-6) {
150             System.out.print("points coincide");
151             System.exit(0);
152         }
153 
154         if (Math.abs(x1 - x2) > 1e-6 && Math.abs(x3 - x4) > 1e-6) {
155             double k1 = calculateSlope(point1 + " " + point2);
156             double k2 = calculateSlope(point3 + " " + point4);
157             return Math.abs(k1 - k2) < 1e-6;
158         } else return Math.abs(x1 - x2) < 1e-6 && Math.abs(x3 - x4) < 1e-6;
159     }
160 
161     /**
162      * 判斷交點位置
163      */
164     public static boolean isIntersectWithinSegment(String data) {
165         String[] points = data.split(" ");
166         String point1 = points[0], point2 = points[1], point3 = points[2], point4 = points[3];
167 
168         double x1 = 0, y1 = 0;
169         double[] xy = processData(point1);
170         x1 = xy[0];
171         y1 = xy[1];
172 
173         double x2 = 0, y2 = 0;
174         xy = processData(point2);
175         x2 = xy[0];
176         y2 = xy[1];
177 
178         double x3 = 0, y3 = 0;
179         xy = processData(point3);
180         x3 = xy[0];
181         y3 = xy[1];
182 
183         double x4 = 0, y4 = 0;
184         xy = processData(point4);
185         x4 = xy[0];
186         y4 = xy[1];
187 
188         if (points.length != 4) {
189             System.out.print("wrong number of points");
190             System.exit(0);
191         }
192         if (Math.abs(x1 - x2) < 1e-6 && Math.abs(y1 - y2) < 1e-6
193                 || Math.abs(x3 - x4) < 1e-6 && Math.abs(y3 - y4) < 1e-6) {
194             System.out.print("points coincide");
195             System.exit(0);
196         }
197         if (Math.abs(x1 - x2) < 1e-6 && Math.abs(x3 - x4) < 1e-6) {
198             System.out.print("is parallel lines,have no intersection point");
199             System.exit(0);
200         }
201         if ( Math.abs(x1 - x2) < 1e-6) {
202             double k = calculateSlope(point3 + " " + point4);
203             double b = y4 - k * x4;
204             double y = k * x1 + b;
205             System.out.print(x1 + " " + y + " ");
206             return (y < Math.max(y1, y2) && y > Math.min(y1, y2)) || (x1 < Math.max(x3, x4) && x1 < Math.min(x3, x4));
207         }
208         if ( Math.abs(x3 - x4) < 1e-6) {
209             double k = calculateSlope(point1 + " " + point2);
210             double b = y1 - k * x1;
211             double y = k * x3 + b;
212             System.out.print(x3 + " " + y + " ");
213             return (y < Math.max(y3, y4) && y > Math.min(y3, y4)) || (x3 < Math.max(x1, x2) && x3 > Math.min(x2, x1));
214         }
215         double k1 = calculateSlope(point1 + " " + point2), k2 = calculateSlope(point3 + " " + point4);
216         if ( Math.abs(k1 - k2) < 1e-6) {
217             System.out.print("is parallel lines,have no intersection point");
218             System.exit(0);
219         }
220         double b1 = y1 - k1 * x1;
221         double b2 = y3 - k2 * x3;
222         double x = (-b1 + b2) / (k1 - k2);
223         double y = - (k1 * b2 - k2 * b1) / (k2 - k1);
224         System.out.print(x + " " + y + " ");
225         return (x < Math.max(x1, x2) && x > Math.min(x1, x2)) || (x < Math.max(x3,x4) && x > Math.min(x3, x4));
226     }
227 
228     /**
229      * 計算點到直線的距離
230      */
231     public static double calculateDistance(String data) {
232         String[] points = data.split(" ");
233 
234         String point3 = points[2];
235         String point1 = points[0];
236         String point2 = points[1];
237         double x1 = 0, y1 = 0;
238         double[] xy = processData(point1);
239         x1 = xy[0];
240         y1 = xy[1];
241 
242         double x2 = 0, y2 = 0;
243         xy = processData(point2);
244         x2 = xy[0];
245         y2 = xy[1];
246 
247         double x3 = 0, y3 = 0;
248         xy = processData(point3);
249         x3 = xy[0];
250         y3 = xy[1];
251         if (points.length != 3) {
252             System.out.print("wrong number of points");
253             System.exit(0);
254         }
255         if (Math.abs(x3 - x2) < 1e-6 && Math.abs(y3 - y2) < 1e-6) {
256             System.out.print("points coincide");
257             System.exit(0);
258         }
259 
260         if (Math.abs(x2 - x3) > 1e-6) {
261             double k = calculateSlope(points[1] + " " + points[2]);
262             double b = y1 - k * x1;
263             return Math.abs(k * x1 + b - y1) / Math.sqrt(k * k - 1);
264         } else {
265             return Math.abs(x1 - x2);
266         }
267 
268     }
269 
270     public static void check(String point, int pos) {
271         for (int loop = 0; loop < point.length(); loop++) {
272             if (point.charAt(loop) == '.') {
273                 if (loop == 0 || loop == pos + 1) {
274                     System.out.print("Wrong Format");
275                     System.exit(0);
276                 }
277             }
278             if (point.charAt(loop) == '.') {
279                 if (loop == pos - 1 || loop == point.length() - 1) {
280                     System.out.print("Wrong Format");
281                     System.exit(0);
282                 }
283             }
284         }
285         if (point.charAt(0) == '0' && point.charAt(1) != '.' && point.charAt(1) != ',') {
286             System.out.print("Wrong Format");
287             System.exit(0);
288         } else if (point.length() > pos + 2) {
289             if (point.charAt(pos + 1) == '0' && point.charAt(pos + 2) != '.' && point.charAt(pos + 2) != ',') {
290                 System.out.print("Wrong Format");
291                 System.exit(0);
292             }
293         }
294     }
295 
296     public static double[] processData(String point) {
297         double x = 0, y = 0;
298         int pos = 0;
299         for (int loop = 0; loop < point.length(); loop++) {
300             if (point.charAt(loop) == ',') {
301                 pos = loop;
302             }
303         }
304         check(point, pos);
305         x = Double.parseDouble(point.substring(0, pos));
306         y = Double.parseDouble(point.substring(pos + 1));
307         return new double[]{x, y};
308     }
309 }

 

 

分析:為了追求解題速度,沒有進行類的設計,使用了函數語言程式設計,程式碼沒有體現OOP的特性。函式可複用性也很差,基本都是硬編碼出來的垃圾程式碼。給後續的迭代造成了很大的麻煩。

 


 

第一次迭代

 

 題目描述:

 

類圖:同樣沒有進行類的設計。

原始碼(原始碼太長,這裡只給出Main方法):

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String line = in.nextLine();
        try {
            int coi = Integer.parseInt(line.substring(0, 1));
            if (coi < 1 || coi > 5) {
                System.out.print("Wrong Format");
                System.exit(0);
            }
            switch (coi) {
                case 1:
                    judgeTriangle(line.substring(2));
                    break;
                case 2:
                    calculateAttribute(line.substring(2));
                    break;
                case 3:
                    judgeAngle(line.substring(2));
                    break;
                case 4:
                    System.out.println("The point is on the edge of the triangle");
                    break;
                case 5:
                    System.out.println("in the triangle");
                    break;
            }
        } catch (Exception e) {
            System.out.print("Wrong Format");
            System.exit(0);
        }
    }
}

 

分析:由於第一次使用了函式式的程式設計,沒有做類的設計,在時間緊張的情況下我只能對第一次的程式碼進行更改和擴充。這導致編碼過程非常痛苦,每一個函式的內聚性都不高,幾乎需要重寫每一個函式。沒有進行類的設計浪費了我大量的時間。

 


 

第二次迭代:

題目描述:

 

類圖:

 

 

分析:

  設計了點,線和四邊形類,對它們進行了封裝。設計ParseInput類對輸入進行處理,得到整潔的資料,方便之後的運算。在四邊形類中,將四個點作為其的私有屬性,設定check方法檢測自身能否成為四邊形,以及判斷是否為特殊四邊形的方法。在Line類中,將兩個Point物件作為其私有屬性,設定getSlope方法,與hasSlope方法共同獲取斜率。新增isOnline(Point point), isBetween(Point point)和isSameSide(Point point)方法來判斷點與直線的關係。isParallel(Line line)方法判斷兩條直線的關係。 

 

 

心得:

  通過兩次迭代,我切實體會到了先設計再編碼的重要性了。不通過嚴謹設計寫出來的程式碼,不用談什麼物件導向程式設計原則,也不存在什麼可擴充套件性。一時追求解題速度可能後面要花上幾倍,幾十倍的時間來重構程式碼。不如在編寫之前就做好設計,也許剛開始進度會比別人慢,但是越迭代到後期,每一次的工作量就會比硬編碼少得多。

 

 


連結串列練習

  原始碼:

class LinkedList<E> implements LinearLIstInterface<E> {
    private Node<E> last;
    private Node<E> first;
    private int length;

    public LinkedList() {
        this.length = 0;
        last = new Node<>();
        first = new Node<>();
    }

    @Override
    public boolean isEmpty() {
        return length == 0;
    }

    @Override
    public int size() {
        return length;
    }

    public void addFirst(E o) {
        if(this.isEmpty()) {
            this.first = new Node<>(o);
            this.last = this.first;
        } else {
            Node<E> temp = new Node<>(o);
            temp.setNext(first);
            this.first = temp;
        }
        length++;
    }

    public void addLast(E o) {
        if (this.isEmpty()) {
            addFirst(o);
        } else {
            Node<E> temp = new Node<>(o);
            last.setNext(temp);
            last = temp;
            length++;
        }

    }

    @Override
    public void add(E o) {
        if (this.isEmpty()) {
            addFirst(o);
        } else {
            addLast(o);
        }
    }

    @Override
    public void printList() {
        Node<E> loop = first;
        System.out.print("[ ");
        while (loop != null) {
            System.out.print(loop.getO().toString() + " ");
            loop = loop.getNext();
        }
        System.out.println("]");
    }

    @Override
    public void add(int index, E o) {
        if ( index < 0 || index > length - 1) {
            System.out.println("Wrong Index");
            System.exit(0);
        }
        if (index == 0) {
            addFirst(o);
        } else if (index == length - 1) {
            addLast(o);
        } else {
            int pos = 0;

            Node<E> loop = first;
            while (loop != null) {
                if ( pos + 1 == index) {
                    Node<E> temp = new Node<>(o);
                    temp.setNext(loop.getNext());
                    loop.setNext(temp);
                    break;
                }
                pos++;
                loop = loop.getNext();
            }
        }
        length++;
    }

    @Override
    public void remove(int index) {
        if ( index < 0 || index > length - 1) {
            System.out.println("Wrong Index");
            System.exit(0);
        }
        int pos = 0;
        Node<E> loop = first;
        while (loop != null) {
            if (pos + 1 == index) {
                loop.setNext(loop.getNext().getNext());
                break;
            } else {
                pos++;
            }
            loop = loop.getNext();
        }
        length--;
    }

    @Override
    public E get(int index) {
        if (index < 0 || index > length - 1) {
            System.out.println("Wrong Index");
            System.exit(0);
        }
        int pos = 0;
        for (Node<E> loop = first; loop.getNext() == null; loop = loop.getNext()) {
            if (pos == index) {
                return loop.getO();
            }
            pos++;
        }
        return null;
    }

}


 

期中考試題目總結

第一題:

題目描述:

 

 

 

類圖:

 

 

 

分析:由於給出了類圖,當時寫題得時候非常快,照著類圖寫就是了,沒什麼大問題。


 

第二題

題目描述:

 

 

 類圖:

 

 

 分析:這一題的關鍵就是把Element類抽象出來,再通過子類複寫父類方法實現多型。

 


 

 第三題:

題目描述:

 

原始碼:

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        double x1;
        double y1;
        double x2;
        double y2;
        String color;
        GeometryObject geometryObject = new GeometryObject();
        int choice = in.nextInt();
        while(choice != 0){
            switch(choice) {
                case 1: x1 = in.nextDouble();
                y1 = in.nextDouble();
                    if (x1 < 0 || x1 > 200 || y1 < 0 || y1 > 200) {
                        System.out.println("Wrong Format");
                        System.exit(0);
                    } else
                        geometryObject.add(new Point(x1, y1));
                //insert Point object into list
                    break;
                case 2:x1 = in.nextDouble();
                    y1 = in.nextDouble();
                    x2 = in.nextDouble();
                    y2 = in.nextDouble();
                    color = in.next();
                    if (x1 < 0 || x1 > 200 || y1 < 0 || y1 > 200 || x2 < 0 || x2 > 200 || y2 < 0 || y2 > 200) {
                        System.out.println("Wrong Format");
                        System.exit(0);
                    } else
                        geometryObject.add(new Line(new Point(x1, y1), new Point(x2, y2), color));//insert Line object into list
                    break;
                case 3:color = in.next();
                geometryObject.add(new Plane(color));//insert Plane object into list
                    break;
                case 4:int index = in.nextInt();
                if (index > geometryObject.getList().size() || index < 1){
                    choice = in.nextInt();
                    continue;
                }
                geometryObject.remove(index - 1);//delete index - 1 object from list
                    break;
            }
            choice = in.nextInt();

        }
        for(Element element:geometryObject.getList()){
            element.display();
        }
    }
}

abstract class Element {
    public abstract void display();
}

class Point extends Element {
    private double x;
    private double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return x;
    }

    public void setX(double x) {
        this.x = x;
    }

    public double getY() {
        return y;
    }

    public void setY(double y) {
        this.y = y;
    }

    @Override
    public void display() {
        System.out.printf("(%.2f,%.2f)%n", x, y);
    }
}

class Line extends Element {
    private Point point1;
    private Point point2;
    private String color;

    public Line(Point point1, Point point2, String color) {
        this.point1 = point1;
        this.point2 = point2;
        this.color = color;
    }

    public Point getPoint1() {
        return point1;
    }

    public void setPoint1(Point point1) {
        this.point1 = point1;
    }

    public Point getPoint2() {
        return point2;
    }

    public void setPoint2(Point point2) {
        this.point2 = point2;
    }

    public double getDistance() {
        return Math.sqrt((getPoint1().getX() - getPoint2().getX()) * (getPoint1().getX() - getPoint2().getX())
                + (getPoint1().getY() - getPoint2().getY()) * (getPoint1().getY() - getPoint2().getY()));
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public void display() {
        System.out.println("The line's color is:" + color);
        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.printf("The line's length is:%.2f%n", getDistance());
    }
}

class Plane extends Element {
    private String color;

    public Plane(String color) {
        this.color = color;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public void display() {
        System.out.println("The Plane's color is:" + color);
    }
}

class GeometryObject{
    private ArrayList<Element> list = new ArrayList<>();

    public GeometryObject() {
    }

    public GeometryObject(ArrayList<Element> list) {
        this.list = list;
    }

    public ArrayList<Element> getList() {
        return list;
    }

    public void setList(ArrayList<Element> list) {
        this.list = list;
    }

    public void add(Element element){
        list.add(element);
    }

    public void remove(int index){
        list.remove(index);
    }
}

 

 類圖:

 

 分析:GeometryObject類中有用到泛型和ArrayList資料型別,在Main方法中使用了foreach迴圈。


 

踩坑心得:

  先動筆再動手!先動筆再動手!先動筆再動手!後期改程式碼真的是折磨,如果前期做好類的設計,只要需求大體不變,迭代起來非常輕鬆。


 

總結:

  掌握一些基本的資料結構用法,淺學了一下Java FX,還有幾種設計模式,以及lambda表示式和Stream 的簡單使用。覺得自己還是需要加強類設計的能力,有時長時間設計不出來類圖,非常難受,有時類的設計又太過複雜,很難實現。在設計類和害怕設計的太過複雜之中患得患失。所以有必要加強一下設計能力。

 

 

相關文章