作业总结
前言:
随着学习的不断深入,作业的难度也逐渐提升,自己对于平面直角坐标系的相关计算的熟练程度还是不高,对于期中考试的Arraylist类也不是很熟,仍要努力。
设计与分析:
pta上图形设计类题目一直都挺难的,题目要求也很多,这道题和上次的题目有点相似,但是复杂程度又上了一个台阶。题目要求如下:
- 用户输入一组选项和数据,进行与四边形有关的计算。
- 以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
- 选项包括:
- 1:输入四个点坐标,判断是否是四边形、平行四边形,判断结果输出true/false,结果之间以一个英文空格符分隔。
- 2:输入四个点坐标,判断是否是菱形、矩形、正方形,判断结果输出true/false,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
- 3:输入四个点坐标,判断是凹四边形(false)还是凸四边形(true),输出四边形周长、面积,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
- 4:输入六个点坐标,前两个点构成一条直线,后四个点构成一个四边形或三角形,输出直线与四边形(也可能是三角形)相交的交点数量。如果交点有两个,再按面积从小到大输出四边形(或三角形)被直线分割成两部分的面积(不换行)。若直线与四边形或三角形的一条边线重合,输出"The line is coincide with one of the lines"。若后四个点不符合四边形或三角形的输入,输出"not a quadrilateral or triangle"。
- 后四个点构成三角形的情况:假设三角形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
- 1)符合要求的输入:顶点重复或者z与xy都相邻,如x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
- 2) 不符合要求的输入:z 不与xy都相邻,如z x y s、x z s y、x s z y
- 5:输入五个点坐标,输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形(判定方法见选项4)的内部(若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。如果点在多边形的某条边上,输出"on the triangle或者on the quadrilateral"。若后四个点不符合四边形或三角形,输出"not a quadrilateral or triangle"。
-
输入格式:
- 基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
-
输出格式:
- 基本输出格式见每种选项的描述。
- 异常情况输出:
- 如果不符合基本格式,输出"Wrong Format"。
- 如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
- 注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
- 选项1、2、3中,若四边形四个点中有重合点,输出"points coincide"。
- 选项4中,若前两个输入线的点重合,输出"points coincide"。
这次我从第一个要求开始就感觉无从下手了,百度了一下以后才稍微有了一点思路,判定四边形只要看是否有三个点连成直线即可,如果给出的四个点中有三个点在同一条直线上那就不是四边形了,代码如下:
1 class SBX 2 { 3 public int Px1, Px2, Px3, Px4, Py1, Py2, Py3, Py4; //顶点坐标 4 public boolean IsSBX() //判断是否是四边形 5 { 6 if ((Py4 - Py3) * (Px4 - Px2) == (Py4 - Py2) * (Px4 - Px3)) 7 return false; 8 else if ((Py4 - Py3) * (Px4 - Px1) == (Py4 - Py1) * (Px4 - Px3)) 9 return false; 10 else if ((Py4 - Py2) * (Px4 - Px1) == (Py4 - Py1) * (Px4 - Px2)) 11 return false; 12 else if ((Py3 - Py2) * (Px3 - Px1) == (Py3 - Py1) * (Px3 - Px2)) 13 return false; //任意三个顶点成直线,非四边形 14 else 15 return true; 16 }
然后判断是否为平行四边形只需要在是四边形的前提下判断两组对边是否分别平行(即边的斜率相等)即可,通过代码实现如下:
1 class PXSBX extends SBX //平行四边形类,继承四边形类 2 { 3 public boolean IsPXSBX() //判断是否为平行四边形 4 { 5 if (((Py2 - Py1) * (Px4 - Px3) == (Py4 - Py3) * (Px2 - Px1)) && ((Py4 - Py1) * (Px2 - Px3) == (Py2 - Py3) * (Px4 - Px1))) 6 return true; 7 else if (((Py3 - Py1) * (Px4 - Px2) == (Py4 - Py2) * (Px3 - Px1)) && ((Py4 - Py1) * (Px2 - Px3) == (Py2 - Py3) * (Px4 - Px1))) 8 return true; 9 else if (((Py2 - Py1) * (Px4 - Px3) == (Py4 - Py3) * (Px2 - Px1)) && ((Py3 - Py1) * (Px2 - Px4) == (Py2 - Py4) * (Px3 - Px1))) 10 return true; //两组对边分别平行(即边的斜率相等)的四边形则为平行四边形 11 else 12 return false; 13 } 14 }
对于第二个要求,只要先判断四边形是否是平行四边形,如果不是,那肯定不是矩形、菱形或者正方形其中之一,如果是接下来再判断是否是矩形,若为四边相等的平行四边形则为菱形,若为四边相等的矩形则为正方形,通过代码实现如下:
1 class JX extends PXSBX 2 { 3 public boolean IsJX() //判断是否为矩形 4 { 5 double I1, I2, I3; //某个顶点分别到其他三个顶点的距离的平方 6 I1= Math.Abs((Px1 - Px2) * (Px1 - Px2) + (Py1 - Py2) * (Py1 - Py2)); 7 I2= Math.Abs((Px1 - Px3) * (Px1 - Px3) + (Py1 - Py3) * (Py1 - Py3)); 8 I3= Math.Abs((Px1 - Px4) * (Px1 - Px4) + (Py1 - Py4) * (Py1 - Py4)); 9 if (I1 > I2 && I1 > I3 && (I2 + I3 == I1)) 10 return true; 11 else if (I2 > I1 && I2 > I3 && (I1 + I3 == I2)) 12 return true; 13 else if (I3 > I1 && I3 > I2 && (I1 + I2 == I3)) 14 return true; //勾股定理,及有一个直角的平行四边形为矩形 15 else 16 return false; 17 } 18 }
第三个要求坦白说我对于判断四边形的凹凸性毫无经验, 只能再次百度,其中的数学原理是:按照输入顺序依次将点连接起来,对于连续的三个点p0,p1,p2,另向量a=p1-p0,b=p2-p1,若是凸多边形,那么b相对于a一定是向逆时针方向旋转的,判断两向量的旋转方向,可以使用向量的叉积 a×b = x1×y2 - x2×y1,分为三种情况:
a×b > 0 b在a的逆时针方向
a×b = 0 b平行于a(共线)
a×b < 0 b在a的顺时针方向
代码如下:
1 t1 = (p4.x-p1.x)(p2.y-p1.y)-(p4.y-p1.y)(p2.x-p1.x); 2 t2 = (p1.x-p2.x)(p3.y-p2.y)-(p1.y-p2.y)(p3.x-p2.x); 3 t3 = (p2.x-p3.x)(p4.y-p3.y)-(p2.y-p3.y)(p4.x-p3.x); 4 t4 = (p3.x-p4.x)(p1.y-p4.y)-(p3.y-p4.y)(p1.x-p4.x); 5 if (t1*t2*t3*t4 < 0) 6 return Concavequadrilateral;//(凹四边形) 7 if (t1*t2*t3*t4 < 0) 8 return Convexquadrilateral;//(凸四边形)
对于第四和第五个要求则难度加倍了,对于第四个要求判断形状和第一题类似,但是求分割的面积则要依据后四个点构成图形的形状有所不同,如果是三角形就容易一点,因为如果直线将三角形分为两个图形的话其中必有一个是三角形,我们只要求出这个小三角形的面积,然后用大三角形的面积减去小三角形的面积即可;但是如果后四个点构成的是四边形的话要麻烦的多,因为直线与四边形相交有可能将四边形分割为一个四边形一个三角形或者两个三角形或者两个四边形,判断的难度很大。第五个要求判断的方法要用到第三个要求中的矢量叉乘法,
计算矢量叉积是与直线和线段相关算法的核心部分。设矢量P = ( x1, y1 ),Q = ( x2, y2 ),则矢量叉积定义为由(0,0)、p1、p2和p1+p2所组成的平行四边形的带符号的面积,即:P × Q = x1*y2 - x2*y1,其结果是一个标量。显然有性质 P × Q = - ( Q × P ) 和 P × ( - Q ) = - ( P × Q )。一般在不加说明的情况下,本文下述算法中所有的点都看作矢量,两点的加减法就是矢量相加减,而点的乘法则看作矢量叉积。叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:
若 P × Q > 0 , 则P在Q的顺时针方向。
若 P × Q < 0 , 则P在Q的逆时针方向。
若 P × Q = 0 , 则P与Q共线,但可能同向也可能反向。
所以,假设该凸四边形为ABCD,且ABCD顺时针,待判断的点为M,则需要满足:
AB × AM>0
BC × BM>0
CD × CM>0
DA × DM>0
即可证明点M在凸四边形内部。
接下来的期中考试题目难度也是逐级递增的,后面的题只要改一改前面的代码就可以用了,而且这次期中考试也考察了我们对于类图的熟悉程度和将类图转化为代码的能力,题目要求如下:
-
设计一个类表示平面直角坐标系上的点Point,私有属性分别为横坐标x与纵坐标y,数据类型均为实型数,除构造方法以及属性的getter与setter方法外,定义一个用于显示信息的方法display(),用来输出该坐标点的坐标信息,格式如下:
(x,y),数值保留两位小数。为简化题目,其中,坐标点的取值范围设定为(0,200]。若输入有误,系统则直接输出Wrong Format -
设计一个类表示平面直角坐标系上的线Line,私有属性除了标识线段两端的点point1、point2外,还有一个字符串类型的color,用于表示该线段的颜色,同样,除构造方法以及属性的getter与setter方法外,定义一个用于计算该线段长度的方法getDistance(),还有一个用于显示信息的方法display(),用来输出线段的相关信息

我的代码如下:
1 import java.util.Scanner; 2 public class Main { 3 public static void main(String[] args){ 4 Scanner sc = new Scanner(System.in); 5 Line l = new Line(); 6 double a[] = new double[4]; 7 for(int i = 0;i < a.length;i ++) { 8 a[i] = sc.nextDouble(); 9 if(a[i] > 200 || a[i] <= 0) { 10 System.out.println("Wrong Format"); 11 return; 12 } 13 } 14 Point p1 = new Point(); 15 p1.setX(a[0]); 16 p1.setY(a[1]); 17 Point p2 = new Point(); 18 p2.setX(a[2]); 19 p2.setY(a[3]); 20 l.setColor(sc.next()); 21 l.setPoint1(p1); 22 l.setPoint2(p2); 23 l.display(); 24 } 25 } 26 class Point{ 27 private double x; 28 private double y; 29 public Point(){ 30 31 } 32 public Point(double x,double y){ 33 x = getX(); 34 y = getY(); 35 } 36 public void display() { 37 System.out.printf("(%.2f,%.2f)",x,y); 38 } 39 public double getY() { 40 return y; 41 } 42 public void setY(double y) { 43 this.y = y; 44 } 45 public double getX() { 46 return x; 47 } 48 public void setX(double x) { 49 this.x = x; 50 } 51 52 } 53 class Line{ 54 private Point point1,point2; 55 private String color; 56 public Line() { 57 58 } 59 public Line(Point p1,Point p2,String color) { 60 point1 = p1; 61 point2 = p2; 62 this.color = color; 63 } 64 public Point getPoint1() { 65 return point1; 66 } 67 public void setPoint1(Point point1) { 68 this.point1 = point1; 69 } 70 public Point getPoint2() { 71 return point2; 72 } 73 public void setPoint2(Point point2) { 74 this.point2 = point2; 75 } 76 public String getColor() { 77 return color; 78 } 79 public void setColor(String color) { 80 this.color = color; 81 } 82 public double getDistance() { 83 return Math.sqrt(Math.pow(point1.getX()-point2.getX(), 2) + Math.pow(point1.getY()-point2.getY(),2)); 84 } 85 public void display() { 86 System.out.println("The line's color is:" + getColor()); 87 System.out.println("The line's begin point's Coordinate is:"); 88 System.out.printf("(%.2f,%.2f)\n",point1.getX(),point1.getY()); 89 System.out.println("The line's end point's Coordinate is:"); 90 System.out.printf("(%.2f,%.2f)\n",point2.getX(),point2.getY()); 91 System.out.printf("The line's length is:%.2f" ,getDistance()); 92 } 93 }
看起来挺容易的题目,只要照着类图将所有的方法写出来,然后在适当的地方调用即可。
第二题要求如下:
在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。
- 对题目中的点Point类和线Line类进行进一步抽象,定义一个两个类的共同父类Element(抽象类),将display()方法在该方法中进行声明(抽象方法),将Point类和Line类作为该类的子类。
- 再定义一个Element类的子类面Plane,该类只有一个私有属性颜色color,除了构造方法和属性的getter、setter方法外,display()方法用于输出面的颜色,输出格式如下:
The Plane's color is:颜色 - 在主方法内,定义两个Point(线段的起点和终点)对象、一个Line对象和一个Plane对象,依次从键盘输入两个Point对象的起点、终点坐标和颜色值(Line对象和Plane对象颜色相同),然后定义一个Element类的引用,分别使用该引用调用以上四个对象的display()方法,从而实现多态特性。

这道题考察了我们对继承和多态的熟悉程度,还有一个接口,也挺容易的。
1 import java.util.Scanner; 2 public class Main { 3 public static void main(String[] args){ 4 Scanner sc = new Scanner(System.in); 5 Line l = new Line(); 6 Plane pl = new Plane(); 7 double a[] = new double[4]; 8 for(int i = 0;i < a.length;i ++) { 9 a[i] = sc.nextDouble(); 10 if(a[i] > 200 || a[i] <= 0) { 11 System.out.println("Wrong Format"); 12 return; 13 } 14 } 15 Point p1 = new Point(); 16 p1.setX(a[0]); 17 p1.setY(a[1]); 18 Point p2 = new Point(); 19 p2.setX(a[2]); 20 p2.setY(a[3]); 21 l.setColor(sc.next()); 22 pl.setColor(l.getColor()); 23 l.setPoint1(p1); 24 l.setPoint2(p2); 25 l.display(); 26 } 27 } 28 abstract class Element{ 29 public abstract void display(); 30 } 31 class Plane extends Element{ 32 private String color; 33 Plane(){ 34 35 } 36 Plane(String color){ 37 38 } 39 public String getColor() { 40 return color; 41 } 42 43 public void setColor(String color) { 44 this.color = color; 45 } 46 47 public void display() { 48 System.out.println("The Plane's color is:" + getColor()); 49 } 50 51 } 52 class Point extends Element{ 53 private double x; 54 private double y; 55 public Point(){ 56 57 } 58 public Point(double x,double y){ 59 x = getX(); 60 y = getY(); 61 } 62 public void display() { 63 System.out.printf("(%.2f,%.2f)",x,y); 64 } 65 public double getY() { 66 return y; 67 } 68 public void setY(double y) { 69 this.y = y; 70 } 71 public double getX() { 72 return x; 73 } 74 public void setX(double x) { 75 this.x = x; 76 } 77 78 } 79 class Line extends Element{ 80 private Point point1,point2; 81 private String color; 82 public Line() { 83 84 } 85 public Line(Point p1,Point p2,String color) { 86 point1 = p1; 87 point2 = p2; 88 this.color = color; 89 } 90 public Point getPoint1() { 91 return point1; 92 } 93 public void setPoint1(Point point1) { 94 this.point1 = point1; 95 } 96 public Point getPoint2() { 97 return point2; 98 } 99 public void setPoint2(Point point2) { 100 this.point2 = point2; 101 } 102 public String getColor() { 103 return color; 104 } 105 public void setColor(String color) { 106 this.color = color; 107 } 108 public double getDistance() { 109 return Math.sqrt(Math.pow(point1.getX()-point2.getX(), 2) + Math.pow(point1.getY()-point2.getY(),2)); 110 } 111 public void display() { 112 System.out.printf("(%.2f,%.2f)\n",point1.getX(),point1.getY()); 113 System.out.printf("(%.2f,%.2f)\n",point2.getX(),point2.getY()); 114 System.out.println("The line's color is:" + getColor()); 115 System.out.println("The line's begin point's Coordinate is:"); 116 System.out.printf("(%.2f,%.2f)\n",point1.getX(),point1.getY()); 117 System.out.println("The line's end point's Coordinate is:"); 118 System.out.printf("(%.2f,%.2f)\n",point2.getX(),point2.getY()); 119 System.out.printf("The line's length is:%.2f\n" ,getDistance()); 120 System.out.println("The Plane's color is:" + getColor()); 121 } 122 }
第三题则增加了一个容器类,考察我们对ArrayList类的熟悉程度已及能否熟练运用,ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。ArrayList 继承了 AbstractList ,并实现了 List 接口。在这题中我们需要运用ArrayList类自带的一些方法来帮助我们解题,比如add()和remove()方法在这题就有出场,题目要求如下:
在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。
- 在原有类设计的基础上,增加一个GeometryObject容器类,其属性为
ArrayList<Element>类型的对象(若不了解泛型,可以不使用<Element>) - 增加该类的
add()方法及remove(int index)方法,其功能分别为向容器中增加对象及删除第index - 1(ArrayList中index>=0)个对象 - 在主方法中,用户循环输入要进行的操作(choice∈[0,4]),其含义如下:
- 1:向容器中增加Point对象
- 2:向容器中增加Line对象
- 3:向容器中增加Plane对象
- 4:删除容器中第index - 1个数据,若index数据非法,则无视此操作
- 0:输入结束

可以看出来类图也更加复杂了,说实话我对ArrayList类并不熟悉所以这题没有拿到满分。
1 import java.util.Scanner; 2 import java.util.ArrayList; 3 4 public class Main { 5 public static void main(String[] args) { 6 Scanner sc = new Scanner(System.in); 7 GeometryObject g= new GeometryObject(); 8 int choice = sc.nextInt(); 9 double a[] = new double[4]; 10 while (choice != 0) { 11 switch (choice) { 12 case 1:// insert Point object into list 13 14 for (int i = 0; i < 2; i++) { 15 a[i] = sc.nextDouble(); 16 if (a[i] > 200 || a[i] <= 0) { 17 System.out.println("Wrong Format"); 18 return; 19 } 20 } 21 Point p1 = new Point(); 22 g.add(p1); 23 break; 24 case 2:// insert Line object into list 25 Line l = new Line(); 26 for (int i = 0; i < 4; i++) { 27 a[i] = sc.nextDouble(); 28 if (a[i] > 200 || a[i] <= 0) { 29 System.out.println("Wrong Format"); 30 return; 31 } 32 } 33 Point p11 = new Point(); 34 p11.setX(a[0]); 35 p11.setY(a[1]); 36 Point p21 = new Point(); 37 p21.setX(a[2]); 38 p21.setY(a[3]); 39 l.setColor(sc.next()); 40 // l.setPoint1(p11); 41 // l.setPoint2(p21); 42 // l.display(); 43 g.add(l); 44 break; 45 case 3:// insert Plane object into list 46 Plane pl = new Plane(); 47 pl.setColor(sc.next()); 48 g.add(pl); 49 break; 50 case 4:// delete index - 1 object from list 51 int index = sc.nextInt(); 52 g.remove(index); 53 case 0: 54 break; 55 } 56 choice = sc.nextInt(); 57 } 58 } 59 } 60 61 abstract class Element { 62 public abstract void display(); 63 } 64 65 class Plane extends Element { 66 private String color; 67 68 Plane() { 69 70 } 71 72 Plane(String color) { 73 74 } 75 76 public String getColor() { 77 return color; 78 } 79 80 public void setColor(String color) { 81 this.color = color; 82 } 83 84 public void display() { 85 System.out.println("The Plane's color is:" + getColor()); 86 } 87 88 } 89 90 class Point extends Element { 91 private double x; 92 private double y; 93 94 public Point() { 95 96 } 97 98 public Point(double x, double y) { 99 x = getX(); 100 y = getY(); 101 } 102 103 public void display() { 104 System.out.printf("(%.2f,%.2f)", x, y); 105 } 106 107 public double getY() { 108 return y; 109 } 110 111 public void setY(double y) { 112 this.y = y; 113 } 114 115 public double getX() { 116 return x; 117 } 118 119 public void setX(double x) { 120 this.x = x; 121 } 122 123 } 124 125 class Line extends Element { 126 private Point point1, point2; 127 private String color; 128 129 public Line() { 130 131 } 132 133 public Line(Point p1, Point p2, String color) { 134 point1 = p1; 135 point2 = p2; 136 this.color = color; 137 } 138 139 public Point getPoint1() { 140 return point1; 141 } 142 143 public void setPoint1(Point point1) { 144 this.point1 = point1; 145 } 146 147 public Point getPoint2() { 148 return point2; 149 } 150 151 public void setPoint2(Point point2) { 152 this.point2 = point2; 153 } 154 155 public String getColor() { 156 return color; 157 } 158 159 public void setColor(String color) { 160 this.color = color; 161 } 162 163 public double getDistance() { 164 return Math.sqrt(Math.pow(point1.getX() - point2.getX(), 2) + Math.pow(point1.getY() - point2.getY(), 2)); 165 } 166 167 public void display() { 168 System.out.printf("(%.2f,%.2f)\n", point1.getX(), point1.getY()); 169 System.out.printf("(%.2f,%.2f)\n", point2.getX(), point2.getY()); 170 System.out.println("The line's color is:" + getColor()); 171 System.out.println("The line's begin point's Coordinate is:"); 172 System.out.printf("(%.2f,%.2f)\n", point1.getX(), point1.getY()); 173 System.out.println("The line's end point's Coordinate is:"); 174 System.out.printf("(%.2f,%.2f)\n", point2.getX(), point2.getY()); 175 System.out.printf("The line's length is:%.2f\n", getDistance()); 176 System.out.println("The Plane's color is:" + getColor()); 177 } 178 } 179 180 class GeometryObject { 181 private ArrayList<Element> list = new ArrayList<>(); 182 183 public GeometryObject() { 184 // TODO Auto-generated constructor stub 185 } 186 187 public void add(Element element) { 188 list.add(element); 189 } 190 191 public void remove(int index) { 192 if(index < 0) { 193 194 }else { 195 list.remove(index - 1); 196 } 197 } 198 199 public ArrayList<Element> getList() { 200 for(int i=0;i<list.size();i++) { 201 list.get(i).display(); 202 } 203 return list; 204 } 205 }
心得体会:
通过这几次作业,我自认为收获了很多,在写题之前要弄清楚题目要求,在心中有个大致的框架,比如要写哪些函数,我要怎么做才能满足这个要求,这么做会不会太麻烦了,有没有什么更好的解决方法等等,万万不可想到哪写到哪,我在写题过程中查阅了许多资料,我也将在接下来的学习过程中不断充实自己的知识体系,虽然现在仍然不擅长写平面直角坐标系下的计算题,但我不会退缩,下次也会争取写出来。我还会不断学习,争取掌握ArrayList类的使用方法!
改进建议:
对于老师布置的作业,我觉得在pta的作业截止以后最好能给我们一份正确的代码,让我们学习一下解题思路和解题技巧,也能让我们发现自己的不足,对于我自身,我也会在课余时间多花些时间在复习和预习上面,老师讲过了ArrayList类,但是因为我并没有好好复习导致没有取得满意的分数,这点让我很自责,我将花更多时间用在练习上,不断提高自己的能力。

浙公网安备 33010602011771号