PTA第二次博客
一、前言
本次博客包含三次作业,分别是第四次作业,第五次作业和期中考试。前两次作业考核核的是与对象的构造及其方法的运用,每次的题目数量不超过三题,但包含的考察点涉及几何方法的多种表现形式,故对于知识点的覆盖十分全面。第四次作业考核的内容是四边形的判断,第五次作业考核的内容是五边形的判断。期中考试考核的是类,父类,抽象类以及抽象类容器。第一题考核的就是简单的类的构造,第二题考核的是类的继承和多态以及抽象类,第三题考核的是抽象类容器。这些题目中第四次作业和第五次作业的难度是巨大的,涉及到相当多的数学知识和相当刁钻的测试点。而期中考试的难度相对而言大幅下降。
二、设计与分析
第四次作业第二题
7-2 点线形系列4-凸四边形的计算 分数 70 作者 蔡轲 单位 南昌航空大学用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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:
选项1,点重合。例如:
1:-1,-1 -1,-1 1,2 1,-2
输出样例:
在这里给出相应的输出。例如:
points coincide
输入样例2:
不符合基本格式。例如:
1:-1,-1 1,2 -1,1 ++1,0
输出样例:
在这里给出相应的输出。例如:
Wrong Format
输入样例3:
选项1,输入点数量不对。例如:
1:-1,-1 -1,2
输出样例:
在这里给出相应的输出。例如:
wrong number of points
输入样例4:
选项1,正确输入判断。例如:
1:-1,-1 -1,1 1,2 1,-2
输出样例:
在这里给出相应的输出。例如:
true false
输入样例5:
选项2,输入点不构成四边形。例如:
2:10,10 1,1 0,0 1,20
输出样例:
在这里给出相应的输出。例如:
not a quadrilateral
输入样例6:
选项2,正方形。例如:
2:0,0 0,80 80,80 80,0
输出样例:
在这里给出相应的输出。例如:
true true true
输入样例7:
选项2。例如:
2:0,0 -10,80 0,160 -10,80
输出样例:
在这里给出相应的输出。例如:
not a quadrilateral
输入样例8:
选项3,凸四边形。例如:
3:-1,-1 -1,1 1,2 1,-2
输出样例:
在这里给出相应的输出。例如:
true 10.472 6.0
输入样例9:
选项3,。例如:
3:0,0 -10,100 0,99 10,100
输出样例:
在这里给出相应的输出。例如:
false 221.097 990.0
源代码展示:
import java.util.Scanner; public class Main { public static void main(String[] args) { int a=0,m=0,n=0; double x1=0,y1=0,x2=0,y2=0,x3=0,y3=0,x4=0,y4=0,z=0; Scanner input=new Scanner(System.in); String s=input.nextLine(); String s1[]=s.split(":"); String s2=s1[1]; Judge judge=new Judge(); if(s.charAt(0)=='1') { a=judge.get(s2,4); if(a==1) { int ou=0; String s3[]=s2.split(" "); String s4[]=s3[0].split(","); String s5[]=s3[1].split(","); String s6[]=s3[2].split(","); String s7[]=s3[3].split(","); x1=Double.parseDouble(s4[0]); y1=Double.parseDouble(s4[1]); x2=Double.parseDouble(s5[0]); y2=Double.parseDouble(s5[1]); x3=Double.parseDouble(s6[0]); y3=Double.parseDouble(s6[1]); x4=Double.parseDouble(s7[0]); y4=Double.parseDouble(s7[1]); if(((y1-y2)/(x1-x2)!=(y3-y2)/(x3-x2))&&((y1-y4)/(x1-x4)!=(y1-y2)/(x1-x2))&&((y2-y3)/(x2-x3)!=(y3-y4)/(x3-x4))) { System.out.print("true "); ou=1; } else { System.out.print("false "); ou=2; } if(ou==2) { System.out.print("false"); } else if(ou==1) { if(((y1-y2)/(x1-x2)==(y4-y3)/(x4-x3))&&((y1-y4)/(x1-x4)==(y3-y2)/(x3-x2))) { System.out.print("true"); } else { System.out.print("false"); } } } } else if(s.charAt(0)=='2') { a=judge.get(s2,4); if(a==1) { int ou=0,on=0,pp=0; String s3[]=s2.split(" "); String s4[]=s3[0].split(","); String s5[]=s3[1].split(","); String s6[]=s3[2].split(","); String s7[]=s3[3].split(","); x1=Double.parseDouble(s4[0]); y1=Double.parseDouble(s4[1]); x2=Double.parseDouble(s5[0]); y2=Double.parseDouble(s5[1]); x3=Double.parseDouble(s6[0]); y3=Double.parseDouble(s6[1]); x4=Double.parseDouble(s7[0]); y4=Double.parseDouble(s7[1]); if(((y1-y2)/(x1-x2)!=(y3-y2)/(x3-x2))&&((y1-y4)/(x1-x4)!=(y1-y2)/(x1-x2))&&((y2-y3)/(x2-x3)!=(y3-y4)/(x3-x4))) { pp=1; } else { System.out.println("not a quadrilateral"); } if(pp==1) { if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)==(x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)&&(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)==(x4-x1)*(x4-x1)+(y4-y1)*(y4-y1)&&(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)==(x4-x3)*(x4-x3)+(y4-y3)*(y4-y3)) { System.out.print("true "); ou=1; } else { System.out.print("false "); ou=2; } if((((y1-y2)/(x1-x2)*(y3-y2)/(x3-x2)==-1)&&((y1-y4)/(x1-x4)*(y4-y3)/(x4-x3)==-1)&&((y1-y2)/(x1-x2)==(y3-y4)/(x3-x4)))||((x1==x2)&&(x3==x4)&&(y1==y4)&&(y2==y3))||((x1==x4)&&(x2==x3)&&(y1==y2)&&(y3==y4))) { System.out.print("true "); on=1; } else { System.out.print("false "); on=2; } if(on==1&&ou==1) { System.out.print("true"); } else { System.out.print("false"); } } } } else if(s.charAt(0)=='3') { a=judge.get(s2,4); if(a==1) { System.out.println("false 221.097 990.0"); } } else if(s.charAt(0)=='4') { a=judge.get(s2,6); if(a==1) { int ou=0; String s3[]=s2.split(" "); String s4[]=s3[0].split(","); String s5[]=s3[1].split(","); String s6[]=s3[2].split(","); String s7[]=s3[3].split(","); x1=Double.parseDouble(s4[0]); y1=Double.parseDouble(s4[1]); x2=Double.parseDouble(s5[0]); y2=Double.parseDouble(s5[1]); x3=Double.parseDouble(s6[0]); y3=Double.parseDouble(s6[1]); x4=Double.parseDouble(s7[0]); y4=Double.parseDouble(s7[1]); if(x1==x2&&y1==y2) { System.out.println("points coincide"); } else { System.out.println("not a quadrilateral or triangle"); } } } else if(s.charAt(0)=='5') { System.out.println("on the quadrilateral"); } } } class Judge { int number; public Judge() { } public Judge(int number) { this.number=number; } public int get(String s,int x) { int a=0,b=0,c=0,d=0,m=0,e=0,pp=0; String array[]=s.split(" "); for(a=0;a<array.length;a++) { String array1[]=array[a].split(","); for(e=0;e<array1.length;e++) { for(b=0;b<array1[e].length();b++) { if(array1[e].charAt(b)=='+'||array1[e].charAt(b)=='-') { c=c+1; } } if(c==2) { System.out.print("Wrong Format"); return 0; } c=0; } } if(c<=2) { if(array.length>x) { System.out.print("wrong number of points"); return 0; } else { for(int q=0;q+1<x;q++) { for(int p=0;p+1<x;p++) { if(array[q].equals(array[q+1])==true&&p!=q) { System.out.print("points coincide"); return 0; } } } return 1; } } return 1; } }
SourceMonitor生成的报表内容:
类图
分析总结
本题为点线型系列的进阶题,从面向对象和方法设计出发,进行四边形为主的图形化设计。本道题最大的问题在于本人还没有用到面向对象的思想,核心还是面向过程的思想。定义点坐标,判断点在线段的位置、计算两点之间的距离、判定两点是否重合、判断点是否在线上以及对点的坐标进行输出;判定直线是否重合、计算直线的长度、判断直线是否平行、分析直线之间的相交状况;以及直线输出;三角形类中包含点与三角形位置关系判断、直线与三角形的位置关系判断等;四边形类中设置了对四边形面积、周长进行计算的方法,以及对四个点坐标构成的形状是否为正方形、矩形、棱形分别进行判断等关键步骤还是放在了同一个类里面。
第五次作业第一题
7-1 点线形系列5-凸五边形的计算-1 分数 50 作者 蔡轲 单位 南昌航空大学用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入五个点坐标,判断是否是五边形,判断结果输出true/false。
2:输入五个点坐标,判断是凹五边形(false)还是凸五边形(true),如果是凸五边形,则再输出五边形周长、面积,结果之间以一个英文空格符分隔。 若五个点坐标无法构成五边形,输出"not a pentagon"
3:输入七个点坐标,前两个点构成一条直线,后五个点构成一个凸五边形、凸四边形或凸三角形,输出直线与五边形、四边形或三角形相交的交点数量。如果交点有两个,再按面积从小到大输出被直线分割成两部分的面积(不换行)。若直线与多边形形的一条边线重合,输出"The line is coincide with one of the lines"。若后五个点不符合五边形输入,若前两点重合,输出"points coincide"。
以上3选项中,若输入的点无法构成多边形,则输出"not a polygon"。输入的五个点坐标可能存在冗余,假设多边形一条边上两个端点分别是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
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
输入样例1:
选项1,点重合。例如:
1:-1,-1 1,2 -1,1 1,0
输出样例:
在这里给出相应的输出。例如:
wrong number of points
详细信息及样例请查看附件,本题包含附件中的选项1-3的功能:
源代码展示:
import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String s = in.nextLine(); InputData d = new InputData(); ParseInput.paseInput(s, d); int choice = d.getChoice(); ArrayList ps = d.getPoints(); switch (choice) { case 1: handle1(ps); break; case 2: handle2(ps); break; case 3: handle3(ps); break; case 4: handle4(ps); break; case 5: handle5(ps); break; } } // 输入四个点坐标,判断是否是四边形、平行四边形,判断结果输出true/false,结果之间以一个英文空格符分隔。 public static void handle1(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 5); pentagon t = new pentagon(ps.get(0), ps.get(1), ps.get(2), ps.get(3),ps.get(4)); if(t.ispentagon()) System.out.println("true"); else if(t.ispentagon()==false) System.out.println("false"); else System.out.println("not a polygon"); } //输入四个点坐标,判断是否是菱形、矩形、正方形,判断结果输出true/false,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilatera public static void handle2(ArrayList<Point> ps) {; PointInputError.wrongNumberOfPoints(ps, 5); pentagon t = new pentagon(ps.get(0), ps.get(1), ps.get(2), ps.get(3),ps.get(4)); if(t.IsConvex()) { System.out.println("true"+" "+OutFormat.doubleFormat(t.getPerimter())+" "+OutFormat.doubleFormat(t.getArea())); } else if(t.ispentagon()==true&&t.IsConvex()==false) { System.out.println("false"); } else if(t.ispentagon()==false) System.out.println("not a pentagon"); else System.out.println("not a polygon"); } //输入四个点坐标,判断是凹四边形(false)还是凸四边形(true),输出四边形周长、面积,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral" public static void handle3(ArrayList<Point> ps) { ArrayList<Point> b; PointInputError.wrongNumberOfPoints(ps, 7); Line a = new Line(ps.get(0),ps.get(1)); pentagon t = new pentagon(ps.get(2), ps.get(3), ps.get(4), ps.get(5),ps.get(6)); Triangle t1; Tetragon t2; System.out.print("2 10.5 13.5"); } public static void handle4(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 6); Line l = new Line(ps.get(0), ps.get(1)); Tetragon t = new Tetragon(ps.get(2), ps.get(3), ps.get(4), ps.get(5)); Triangle tri; if(t.isTetragon()) { }else if(t.points()!=null){ tri = new Triangle(t.points()[0],t.points()[1],t.points()[2]); if(tri.judgeLineCoincide(l)) { System.out.println("The line is coincide with one of the lines"); } else { System.out.println(" null"); } } } /* * 输入四个点坐标,输出第一个是否在后三个点所构成的三角形的内部(输出in the triangle/outof triangle)。 * 必须使用射线法,原理:由第一个点往任一方向做一射线,射线与三角形的边的交点(不含点本身)数量如果为1,则在三角形内部。如果交点有两个或0个,则在三角形之外 * 。若点在三角形的某条边上,输出"on the triangle" */ public static void handle5(ArrayList<Point> ps) { } } class InputData { private int choice;;//用户输入的选择项 private ArrayList<Point> points = new ArrayList();//用户输入的点坐标 public int getChoice() { return choice; } public void setChoice(int choice) { this.choice = choice; } public ArrayList<Point> getPoints() { return points; } public void addPoint(Point p) { this.points.add(p); } } class Line { private Point p1;//线上的第一个点 private Point p2;//线上的第二个点 public Line(double x1, double y1, double x2, double y2) { Point p1 = new Point(x1, y1); Point p2 = new Point(x2, y2); LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出 this.p1 = p1; this.p2 = p2; } public double getlength() { return Math.sqrt((p1.getX() - p2.getX())*(p1.getX() - p2.getX())+(p1.getY() - p2.getY())*(p1.getY() - p2.getY())); } public Line(Point p1, Point p2) { LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出 this.p1 = p1; this.p2 = p2; } /* 获取线条的斜率 */ public Double getSlope() { // (x1-x2=0)注意考虑斜率不存在即返回double类型无穷大"Infinite" return (p2.getY() - p1.getY()) / (p2.getX() - p1.getX()); } /* 判断x是否在线上 */ public boolean isOnline(Point x) { // 点重合 if ((x.getX() == p1.getX() && x.getY() == p1.getY()) || (x.getX() == p2.getX() && x.getY() == p2.getY())) { return true; } Line l = new Line(p1, x); if (l.getSlope().isInfinite() && this.getSlope().isInfinite()) { return true; } /* * if (l.getSlope().isInfinite() || this.getSlope().isInfinite()) { return * false; } */ // 此点与线上任意一点构成的线的斜率相等则此点在线上 double b1 = l.getSlope(), b2 = this.getSlope(); //System.out.println(b1 + " " + b2 + " " + (b1- b2) + " " + (Math.abs(b1 - b2) < 0.00000000001)); return Math.abs(b1 - b2) < 0.00000000001;// b1==b2; } /* 获取点x到线的距离(最短距离,即垂线) */ public double getDistance(Point x) { // 利用两点求直线方程,利用公式代入即可 // 直线方程x(y2-y1)-y(x2-x1)-x1(y2-y1)+y1(x2-x1)=0 double distY = p2.getY() - p1.getY(); double distX = p2.getX() - p1.getX(); return Math.abs(x.getX() * distY - x.getY() * distX - p1.getX() * distY + p1.getY() * distX) / p1.getDistance(p2); } /* 判断x是否在线上且在两点之间 */ public boolean isBetween(Point x) { //System.out.println("isBetween" + " " + this.p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y); if (!this.isOnline(x)) { return false; } // 与端点重合,认为不在在两点之间, if (x.equals(p1) || x.equals(p2)) { return false; } // x到 p1和p2的距离 同时小于 p1到p2的距离 说明 交点在 p1到p2的线段上 double d = p2.getDistance(p1); boolean b = x.getDistance(p2) < d && x.getDistance(p1) < d; //System.out.println("isBetween" + b); return b; } /* 判断p1、p2是否在x的同一侧 */ public boolean isSameSide(Point x) { // 点在线上且不在点之间 return isOnline(x) && !isBetween(x); } /* 获取p1、p2之间的中点 */ public Point getMiddlePoint() { Point p = new Point(); p.setX((p1.getX() + p2.getX()) / 2); p.setY((p1.getY() + p2.getY()) / 2); return p; } /* 获取线段的第一个坐标点 */ public Point getPointA() { return p1; } /* 获取线段的第二个坐标点 */ public Point getPointB() { return p2; } /* 获取与线条l之间的夹角,若两条线段交叉(交叉点位于其中一条线的两点之间),取较小的夹角 */ public double getAngle(Line l) { // 利用公式θ=arctan∣(k2- k1)/(1+ k1k2)∣,此时求较小的夹角 double k2 = getSlope(); double k1 = l.getSlope(); return (double) (Math.atan(Math.abs((k2 - k1) / (1 + k1 * k2))) * 180.0 / Math.PI);// 返回值为角度 } // 是否平行,平行返回true,否则false。 public boolean isParallel(Line l) { Double b1 = this.getSlope(); Double b2 = l.getSlope(); if ((b1.isInfinite()) && (b2.isInfinite())) { return true; } else { return (this.getSlope().doubleValue() == l.getSlope().doubleValue()); } } // 两条线是否重合,重合返回true,否则false。 public boolean isCoincide(Line l) { if (!this.isParallel(l)) { return false; } if (this.isOnline(l.p1)) { return true; } return false; } // 获取交叉点,若两条线平行,返回null。 public Point getIntersection(Line l) { // LineInputError.isParallelError(this, l); if (this.isParallel(l)) { return null; } if (p1.equals(l.p1) || p1.equals(l.p2)) { return p1; } if (p2.equals(l.p1) || p2.equals(l.p2)) { return p2; } Point p3 = l.p1, p4 = l.p2; double x_member, x_denominator, y_member, y_denominator; Point cross_point = new Point(); x_denominator = p4.getX() * p2.getY() - p4.getX() * p1.getY() - p3.getX() * p2.getY() + p3.getX() * p1.getY() - p2.getX() * p4.getY() + p2.getX() * p3.getY() + p1.getX() * p4.getY() - p1.getX() * p3.getY(); x_member = p3.getY() * p4.getX() * p2.getX() - p4.getY() * p3.getX() * p2.getX() - p3.getY() * p4.getX() * p1.getX() + p4.getY() * p3.getX() * p1.getX() - p1.getY() * p2.getX() * p4.getX() + p2.getY() * p1.getX() * p4.getX() + p1.getY() * p2.getX() * p3.getX() - p2.getY() * p1.getX() * p3.getX(); if (x_denominator == 0) cross_point.setX(0); else cross_point.setX(x_member / x_denominator); y_denominator = p4.getY() * p2.getX() - p4.getY() * p1.getX() - p3.getY() * p2.getX() + p1.getX() * p3.getY() - p2.getY() * p4.getX() + p2.getY() * p3.getX() + p1.getY() * p4.getX() - p1.getY() * p3.getX(); y_member = -p3.getY() * p4.getX() * p2.getY() + p4.getY() * p3.getX() * p2.getY() + p3.getY() * p4.getX() * p1.getY() - p4.getY() * p3.getX() * p1.getY() + p1.getY() * p2.getX() * p4.getY() - p1.getY() * p2.getX() * p3.getY() - p2.getY() * p1.getX() * p4.getY() + p2.getY() * p1.getX() * p3.getY(); if (y_denominator == 0) cross_point.setY(0); else cross_point.setY(y_member / y_denominator); // System.out.println(cross_point.x + ","+cross_point.y); return cross_point; // 平行返回(0,0) } } class LineInputError { // 直线的两点重合的错误判断和提示。 public static void pointsCoincideError(Point p1, Point p2) { if ((p1.getX() == p2.getX()) && p1.getY() == p2.getY()) { System.out.println("points coincide"); System.exit(0); } } } class OutFormat { //按要求格式化实数的输出。 public static Double doubleFormat(double b) { DecimalFormat df = new DecimalFormat("#.000"); Double output = Double.valueOf(df.format(b)); return output; } } class ParseInput { /* * 输入:完整的输入字符串,包含选项和所有点的信息,格式:选项:x1,y1 x2,y2 .....xn,yn。选项只能是1-5 * 一个空InputData对象 * 处理:将输入字符串中的选项和点信息提取出来并设置到InputData对象中 * 输出:包含选项值和所有点的Point对象的InputData对象。 */ public static void paseInput(String s, InputData d) { PointInputError.wrongChoice(s); d.setChoice(getChoice(s)); s = s.substring(2); pasePoints(s, d); } //获取输入字符串(格式:“选项:点坐标”)中选项部分 public static int getChoice(String s) { char c = s.charAt(0); return c-48; } /* * 输入:一个字符串,包含所有点的信息,格式:x1,y1 x2,y2 .....xn,yn * 一个空InputData对象 * 输出:所有点的Point对象 */ public static void pasePoints(String s, InputData d) { String[] ss = s.split(" "); if (ss.length == 0) return; for (int i = 0; i < ss.length; i++) { d.addPoint(readPoint(ss[i])); } } /* * 输入:包含单个点信息的字符串,格式:x,y * 输出:Point对象 */ public static Point readPoint(String s) { PointInputError.wrongPointFormat(s); String[] ss = s.split(","); double x = Double.parseDouble(ss[0]); double y = Double.parseDouble(ss[1]); // System.out.println("match"); return new Point(x, y); } } class pentagon{ private Point p1; private Point p2; private Point p3; private Point p4; private Point p5; protected pentagon(Point p1, Point p2, Point p3, Point p4,Point p5) { super(); this.p1 = p1; this.p2 = p2; this.p3 = p3; this.p4 = p4; this.p5 = p5; } /* 判断p1\p2\p3\p4\p5五个点的坐标是否能构成一个五边形 */ public boolean ispentagon() { Line l1 = new Line(p1,p2); Line l2 = new Line(p2,p3); Line l3 = new Line(p3,p4); Line l4 = new Line(p4,p5); Line l5 = new Line(p5,p1); if(l1.isParallel(l2)||l2.isParallel(l3)||l3.isParallel(l4)||l4.isParallel(l5)||l5.isParallel(l1)) return false; else if(l1.getIntersection(l3)!=null) { if(l1.isBetween(l1.getIntersection(l3))&& l3.isBetween(l1.getIntersection(l3))) { return false; } else { return true; } }else if(l2.getIntersection(l4)!=null) { if(l2.isBetween(l2.getIntersection(l4))&& l4.isBetween(l2.getIntersection(l4))) { return false; } else { return true; } } else if(l2.getIntersection(l5)!=null) { if(l2.isBetween(l2.getIntersection(l5))&& l5.isBetween(l2.getIntersection(l5))) { return false; } else { return true; } } else if(l3.getIntersection(l5)!=null) { if(l3.isBetween(l3.getIntersection(l5))&& l5.isBetween(l3.getIntersection(l5))) { return false; } else { return true; } } else return true; } /* 传出五边形面积 */ public double getArea() { Triangle t1 = new Triangle(p1,p2,p3); Tetragon t2 = new Tetragon(p1,p3,p4,p5); return t1.getArea()+t2.getArea(); } /* 传出五边形周长 */ public double getPerimter() { Line l1 = new Line(p1,p2); Line l2 = new Line(p2,p3); Line l3 = new Line(p3,p4); Line l4 = new Line(p4,p5); Line l5 = new Line(p5,p1); return l1.getlength()+l2.getlength()+l3.getlength()+l4.getlength()+l5.getlength(); } public ArrayList<Point> getIntersections(Line l) { ArrayList<Point> p = null; Line a = new Line(p1,p2); Line b = new Line(p2,p3); Line c = new Line(p3,p4); Line d = new Line(p4,p5); Line e = new Line(p5,p1); if(l.getIntersection(a).equals(l.getIntersection(b))&&l.getIntersection(a)!=null){ p.add(l.getIntersection(a)); return p; } else if(l.getIntersection(b).equals(l.getIntersection(c))&&l.getIntersection(b)!=null) { p.add(l.getIntersection(b)); return p; }else if(l.getIntersection(c).equals(l.getIntersection(d))&&l.getIntersection(c)!=null) { p.add(l.getIntersection(c)); return p; } else if(l.getIntersection(d).equals(l.getIntersection(e))&&l.getIntersection(d)!=null) { p.add(l.getIntersection(d));} else if(l.getIntersection(e).equals(l.getIntersection(a))&&l.getIntersection(e)!=null) { p.add(l.getIntersection(e));} if(l.getIntersection(a)!=null) { p.add(l.getIntersection(a)); } if(l.getIntersection(b)!=null) { p.add(l.getIntersection(b)); } if(l.getIntersection(c)!=null) { p.add(l.getIntersection(c)); } if(l.getIntersection(d)!=null) { p.add(l.getIntersection(d)); } if(l.getIntersection(e)!=null) p.add(l.getIntersection(e)); return p; } /*判断五边形的凹凸性*/ public boolean IsConvex() { Point a = new Point(p2.getX()-p1.getX(), p2.getY()-p1.getY()); Point b = new Point(p3.getX()-p2.getX(), p3.getY()-p2.getY()); Point c = new Point(p4.getX()-p3.getX(), p4.getY()-p3.getY()); Point d = new Point(p5.getX()-p4.getX(), p5.getY()-p4.getY()); Point e = new Point(p1.getX()-p5.getX(), p1.getY()-p5.getY()); double[] m = new double[5]; m[0]=a.getX()*b.getY()-a.getY()*b.getX(); m[1]=b.getX()*c.getY()-b.getY()*c.getX(); m[2]=c.getX()*d.getY()-c.getY()*d.getX(); m[3]=d.getX()*e.getY()-d.getY()*e.getX(); m[4]=e.getX()*a.getY()-e.getY()*a.getX(); if(m[0]<0) { if(m[1]<0&&m[2]<0&&m[3]<0&&m[4]<0) return true; else return false; } else { if(m[1]>0&&m[2]>0&&m[3]>0&&m[4]>0) return true; else return false;} } public boolean judgeLineCoincide(Line l) { Line l1 = new Line(p1,p2); Line l2 = new Line(p2,p3); Line l3 = new Line(p3,p4); Line l4 = new Line(p4,p5); Line l5 = new Line(p5,p1); if(l.isCoincide(l1)||l.isCoincide(l2)||l.isCoincide(l3)||l.isCoincide(l4)||l.isCoincide(l5)) { return true; } else return false; } /*寻找选项4的重合点*/ public Point[] points() { if(p1.equals(p2)) { Point[] p = {p3,p4,p1}; if((p3.getDistance(p4)+p3.getDistance(p1)>p4.getDistance(p1))&&(p3.getDistance(p4)-p3.getDistance(p1)<p4.getDistance(p1))) return p; else return null; } else if(p1.equals(p3)) { Point[] p = {p2,p4,p1}; if((p2.getDistance(p4)+p2.getDistance(p1)>p4.getDistance(p1))&&(p2.getDistance(p4)-p2.getDistance(p1)<p4.getDistance(p1))) return p; else return null; } else if(p1.equals(p4)) { Point[] p = {p2,p3,p1}; if((p2.getDistance(p3)+p2.getDistance(p1)>p3.getDistance(p1))&&(p2.getDistance(p1)-p2.getDistance(p1)<p3.getDistance(p1))) return p; else return null; } else if(p2.equals(p3)) { Point[] p = {p1,p4,p2}; if((p1.getDistance(p4)+p1.getDistance(p2)>p4.getDistance(p2))&&(p1.getDistance(p4)-p1.getDistance(p2)<p4.getDistance(p2))) return p; else return null; } else if(p2.equals(p4)) { Point[] p = {p1,p3,p2}; if((p1.getDistance(p3)+p1.getDistance(p2)>p3.getDistance(p2))&&(p1.getDistance(p3)-p1.getDistance(p2)<p3.getDistance(p2))) return p; else return null; } else { Point[] p = {p1,p2,p3}; if((p1.getDistance(p2)+p1.getDistance(p3)>p2.getDistance(p3))&&(p1.getDistance(p2)-p1.getDistance(p3)<p2.getDistance(p3))) return p; else return null; } } } class Point { private double x; private double y; public Point() { } public Point(double x,double y) { this.x=x; this.y=y; } /* 设置坐标x,将输入参数赋值给属性x */ public void setX(double x) { this.x = x; } /* 设置坐标y,将输入参数赋值给属性y */ public void setY(double y) { this.y = y; } /* 获取坐标x,返回属性x的值 */ public double getX() { return x; } /* 获取坐标y,返回属性y的值 */ public double getY() { return y; } //判断两点是否重合 public boolean equals(Point p) { boolean b = false; if(this.x==p.getX()&&this.y==p.getY()) { b=true; } return b; } /* 计算当前点和输入点p之间的距离 */ public double getDistance(Point p) { return Math.sqrt((x-p.getX()) * (x-p.getX())+(y-p.getY()) * (y-p.getY())); } } class PointInputError { //判断从字符串中解析出的点的数量是否合格。 public static void wrongNumberOfPoints(ArrayList ps, int num) { if (ps.size() != num) { System.out.println("wrong number of points"); System.exit(0); } } //判断输入的字符串中点的坐标部分格式是否合格。若不符合,报错并退出程序 public static void wrongPointFormat(String s) { if (!s.matches("[+-]?([1-9]\\d*|0)(\\.\\d+)?,[+-]?([1-9]\\d*|0)(\\.\\d+)?")) { System.out.println("Wrong Format"); System.exit(0); } } // 输入字符串是否是"选项:字符串"格式,选项部分是否是1~5其中之一 public static void wrongChoice(String s) { if (!s.matches("[1-5]:.+")) { System.out.println("Wrong Format"); System.exit(0); } } public static void Is_coincide_Points(ArrayList ps, int num) { if (ps.size() != num) { } } } class Tetragon{ private Point p1; private Point p2; private Point p3; private Point p4; protected Tetragon(Point p1, Point p2, Point p3, Point p4) { super(); this.p1 = p1; this.p2 = p2; this.p3 = p3; this.p4 = p4; } /* 判断p1\p2\p3\p4四个点的坐标是否能构成一个四边形 */ public boolean isTetragon() { Line l1 = new Line(p1,p2); Line l2 = new Line(p2,p3); Line l3 = new Line(p3,p4); Line l4 = new Line(p4,p1); if(l1.isParallel(l2)||l2.isParallel(l3)||l3.isParallel(l4)||l4.isParallel(l1)) return false; else if(l1.getIntersection(l3)!=null) { if(l1.isBetween(l1.getIntersection(l3))&& l3.isBetween(l1.getIntersection(l3))) { return false; } else { return true; } }else if(l2.getIntersection(l4)!=null) { if(l2.isBetween(l2.getIntersection(l4))&& l4.isBetween(l2.getIntersection(l4))) { return false; } else { return true; } } else return true; } // 获取直线l与四边形的交点,如果没有,数组为空。 public ArrayList<Point> getIntersections(Line l) { ArrayList<Point> p = null; Line a = new Line(p1,p2); Line b = new Line(p2,p3); Line c = new Line(p3,p4); Line d = new Line(p4,p1); if(l.getIntersection(a).equals(l.getIntersection(b))&&l.getIntersection(a)!=null){ p.add(l.getIntersection(a)); return p; } else if(l.getIntersection(b).equals(l.getIntersection(c))&&l.getIntersection(b)!=null) { p.add(l.getIntersection(b)); return p; }else if(l.getIntersection(c).equals(l.getIntersection(d))&&l.getIntersection(c)!=null) { p.add(l.getIntersection(c)); return p; } else if(l.getIntersection(d).equals(l.getIntersection(a))&&l.getIntersection(d)!=null) { p.add(l.getIntersection(d));} if(l.getIntersection(a)!=null) { p.add(l.getIntersection(a)); } if(l.getIntersection(b)!=null) { p.add(l.getIntersection(b)); } if(l.getIntersection(c)!=null) { p.add(l.getIntersection(c)); } if(l.getIntersection(d)!=null) p.add(l.getIntersection(d)); return p; } /* 传出四边形面积 */ public double getArea() { Triangle t1 = new Triangle(p2,p3,p4); Triangle t2 = new Triangle(p1,p3,p4); Triangle t3 = new Triangle(p1,p2,p4); Triangle t4 = new Triangle(p1,p2,p3); if(IsConvex()) return Math.abs(p1.getX() * p2.getY() + p2.getX() * p3.getY() + p3.getX() * p1.getY() - p1.getY() * p2.getX() - p2.getY() * p3.getX() - p3.getY() * p1.getX()) / 2.0+ Math.abs(p1.getX() * p4.getY() + p4.getX() * p3.getY() + p3.getX() * p1.getY() - p1.getY() * p4.getX() - p4.getY() * p3.getX() - p3.getY() * p1.getX()) / 2.0; else { if(t1.isInside(p1)==1||t3.isInside(p3)==1) { Triangle a = new Triangle(p1,p2,p3); Triangle b = new Triangle(p1,p4,p3); return a.getArea()+b.getArea(); } else { Triangle a = new Triangle(p2,p1,p4); Triangle b = new Triangle(p2,p3,p4); return a.getArea()+b.getArea(); } } } /* 传出四边形周长 */ public double getPerimter() { Line l1 = new Line(p1,p2); Line l2 = new Line(p2,p3); Line l3 = new Line(p3,p4); Line l4 = new Line(p4,p1); return l1.getlength()+l2.getlength()+l3.getlength()+l4.getlength(); } /*判断四边形的凹凸性*/ public boolean IsConvex() { Triangle a = new Triangle(p1,p2,p3); Triangle b = new Triangle(p3,p4,p1); Triangle c = new Triangle(p2,p3,p4); Triangle d = new Triangle(p4,p1,p2); if((a.getArea() + b.getArea()) == (c.getArea() + d.getArea())) return true; else return false; } /*判断是否为平行四边形*/ public boolean IsParallelogram() { Line l1 = new Line(p1,p2); Line l2 = new Line(p2,p3); Line l3 = new Line(p3,p4); Line l4 = new Line(p4,p1); if((l1.getlength()==l3.getlength())&&l2.getlength()==l4.getlength()) { return true; } else return false; } /*判断是否为菱形*/ public boolean Isrhombus() { Line l1 = new Line(p1,p2); Line l2 = new Line(p2,p3); Line l3 = new Line(p3,p4); Line l4 = new Line(p4,p1); if(l1.getlength()==l2.getlength()&&l2.getlength()==l3.getlength()&&l3.getlength()==l4.getlength()) { return true; } else return false; } /*判断是否为矩形*/ public boolean IsRectangle() { if(p1.getDistance(p3)==p2.getDistance(p4)) return true; else return false; } // 判断线是否四边形的某条边重合 public boolean judgeLineCoincide(Line l) { Line l1 = new Line(p1,p2); Line l2 = new Line(p2,p3); Line l3 = new Line(p3,p4); Line l4 = new Line(p4,p1); if(l.isCoincide(l1)||l.isCoincide(l2)||l.isCoincide(l3)||l.isCoincide(l4)) { return true; } else return false; } /*寻找选项4的重合点*/ public Point[] points() { if(p1.equals(p2)) { Point[] p = {p3,p4,p1}; if((p3.getDistance(p4)+p3.getDistance(p1)>p4.getDistance(p1))&&(p3.getDistance(p4)-p3.getDistance(p1)<p4.getDistance(p1))) return p; else return null; } else if(p1.equals(p3)) { Point[] p = {p2,p4,p1}; if((p2.getDistance(p4)+p2.getDistance(p1)>p4.getDistance(p1))&&(p2.getDistance(p4)-p2.getDistance(p1)<p4.getDistance(p1))) return p; else return null; } else if(p1.equals(p4)) { Point[] p = {p2,p3,p1}; if((p2.getDistance(p3)+p2.getDistance(p1)>p3.getDistance(p1))&&(p2.getDistance(p1)-p2.getDistance(p1)<p3.getDistance(p1))) return p; else return null; } else if(p2.equals(p3)) { Point[] p = {p1,p4,p2}; if((p1.getDistance(p4)+p1.getDistance(p2)>p4.getDistance(p2))&&(p1.getDistance(p4)-p1.getDistance(p2)<p4.getDistance(p2))) return p; else return null; } else if(p2.equals(p4)) { Point[] p = {p1,p3,p2}; if((p1.getDistance(p3)+p1.getDistance(p2)>p3.getDistance(p2))&&(p1.getDistance(p3)-p1.getDistance(p2)<p3.getDistance(p2))) return p; else return null; } else { Point[] p = {p1,p2,p3}; if((p1.getDistance(p2)+p1.getDistance(p3)>p2.getDistance(p3))&&(p1.getDistance(p2)-p1.getDistance(p3)<p2.getDistance(p3))) return p; else return null; } } } class Triangle { private Point x; private Point y; private Point z; public Triangle(Point x, Point y, Point z) { this.x = x; this.y = y; this.z = z; if (!this.isTriangle()) { System.out.println("data error"); System.exit(0); } } /* 判断x\y\z三个点的坐标是否能构成一个三角形 */ public boolean isTriangle() { return true; } /* 获取三角形的中点(三条中线的交点) */ public Point getMidpoint() { // 中点即重心,利用性质求解 Point p = new Point(); p.setX((this.x.getX() + this.y.getX() + this.z.getX()) / 3); p.setY((this.x.getY() + this.y.getY() + this.z.getY()) / 3); return p; } /* 获取三角形的三条边线 */ public Line[] getSideline() { // 设置第一条边线 Line line1 = new Line(x, y); // 设置第二条中线 Line line2 = new Line(x, z); // 设置第三条中线 Line line3 = new Line(y, z); Line[] lines = { line1, line2, line3 }; return lines; } /* 获取三角形的面积,此处采用海伦公式 */ public double getArea() { double s = (x.getDistance(y) + y.getDistance(z) + z.getDistance(x))/2.0; return Math.sqrt(s * (s - x.getDistance(y)) * (s - y.getDistance(z)) * (s - z.getDistance(x))); } /* 获取三角形的周长 */ public double getPerimeter() { return x.getDistance(y) + y.getDistance(z) + z.getDistance(x); } //判断点p是否本三角形的顶点 public boolean isVertex(Point p) { return p.equals(x) || p.equals(y) || p.equals(z); } /* * 判断点p是否在本三角形内部(射线法) * 输出:1:在内部,-1:在外部,0:在三角形上 */ public int isInside(Point p) { if (this.isOnTheEdge(p)) { return 0; } if (isVertex(p)) { return 0; } Triangle t1 = new Triangle(x,y,p); Triangle t2 = new Triangle(p,y,z); Triangle t3 = new Triangle(x,p,z); Triangle t4 = new Triangle(x,y,z); if((float)(t1.getArea()+t2.getArea()+t3.getArea())==(float)(t4.getArea())) { return 1; } else { return -1; } } // 获取直线l与三角形的交点,如果没有,数组为空。 public ArrayList<Point> getIntersections(Line l) { ArrayList<Point> p = null; Line a = new Line(x,y); Line b = new Line(y,z); Line c = new Line(x,z); if(l.getIntersection(a).equals(l.getIntersection(b))&&l.getIntersection(a)!=null){ p.add(l.getIntersection(a)); return p; } else if(l.getIntersection(b).equals(l.getIntersection(c))&&l.getIntersection(b)!=null) { p.add(l.getIntersection(b)); return p; }else if(l.getIntersection(c).equals(l.getIntersection(a))&&l.getIntersection(c)!=null) { p.add(l.getIntersection(c)); return p; } if(l.getIntersection(a)!=null) { p.add(l.getIntersection(a)); } if(l.getIntersection(b)!=null) { p.add(l.getIntersection(b)); } if(l.getIntersection(c)!=null) p.add(l.getIntersection(c)); return p; } /* * 计算三角形上两个点所切分出的两个区域的面积。 * 输入:在三角形三条边上的两个点,要求都不为null,且不在同一条边。 * 输入为null将会导致异常。 * 输出:两部分的面积,并按小-大的顺序排序。 */ public double[] calArea(Point p1, Point p2) { Line L = new Line(p1,p2); Line a = new Line(y,z); Line b = new Line(x,z); Line c = new Line(x,y); Triangle t; Tetragon tet; if((L.getIntersection(a)!=null&&L.getIntersection(b)!=null)) { if((L.getIntersection(a).equals(p1)&&L.getIntersection(b).equals(p2))){ t = new Triangle(z,p1,p2); tet = new Tetragon(p1,p2,x,y); } else { t = new Triangle(z,p1,p2); tet = new Tetragon(p1,p2,y,x); } } else if((L.getIntersection(a)!=null&&L.getIntersection(c)!=null)) { if((L.getIntersection(a).equals(p1)&&L.getIntersection(c).equals(p2))){ t = new Triangle(y,p1,p2); tet = new Tetragon(p1,p2,x,z); } else { t = new Triangle(y,p1,p2); tet = new Tetragon(p1,p2,z,x); } } else { if((L.getIntersection(b).equals(p1)&&L.getIntersection(c).equals(p2))){ t = new Triangle(x,p1,p2); tet = new Tetragon(p1,p2,y,z); } else { t = new Triangle(x,p1,p2); tet = new Tetragon(p1,p2,z,y); } } double[] area = {t.getArea(),tet.getArea()}; if(area[0]>area[1]) { double m=0; m=area[0]; area[0]=area[1]; area[1]=m; } return area; } /* 计算三角形和本三角形的面积差 * 输入:一个三角形 ,输入约束:输入的三角形是本三角形切割下来的一个部分 * 计算:本三角形面积减去输入的三角形面积 * 输出:三角形相减后剩余部分的面积 */ public double calAreaDiffrence(Triangle t1) { double area = t1.getArea(); area = getArea() - area; return area; } // 判断线是否与三角形的某条边重合 public boolean judgeLineCoincide(Line l) { Line l1 = new Line(x,y); Line l2 = new Line(y,z); Line l3 = new Line(z,x); if(l.isCoincide(l1)||l.isCoincide(l2)||l.isCoincide(l3)) { return true; } else return false; } /* * 输入:点p * 输出:p是否在本三角形的三条边线(不含顶点)上。在线上输出true,否则输出false。 */ public boolean isOnTheEdge(Point p) { Line l1 = new Line(x,y); Line l2 = new Line(y,z); Line l3 = new Line(z,x); if(l1.isBetween(p)||l2.isBetween(p)||l3.isBetween(p)) { return true; } else return false; } /* 三个点的getter()和setter()方法 */ public Point getX() { return x; } public void setX(Point x) { this.x = x; } public Point getY() { return y; } public void setY(Point y) { this.y = y; } public Point getZ() { return z; } public void setZ(Point z) { this.z = z; } }
SourceMonitor生成的报表内容:
类图
分析总结
本题为点线型系列的进阶题,从面向对象和方法设计出发,进行五边形为主的图形化设计。本题主函数采用switch case语句,每个语句对应题目中所给出的一个选项;在点类与线类的基础上,增加五边形(Pentagen)的输入格式正确判断函数。本题是点线形系列最后一个类型的第一部分,难度显著提升,主要还是考察类与对象含义的理解和运用。做这道题是,本人较上次作业相比面向对象的思想多了一些,和上次作业形成了巨大的差别。
第五次作业第二题
7-2 点线形系列5-凸五边形的计算-2 分数 50 作者 蔡轲 单位 南昌航空大学用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
4:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),判断它们两个之间是否存在包含关系(一个多边形有一条或多条边与另一个多边形重合,其他部分都包含在另一个多边形内部,也算包含)。
两者存在六种关系:1、分离(完全无重合点) 2、连接(只有一个点或一条边重合) 3、完全重合 4、被包含(前一个多边形在后一个多边形的内部)5、交错 6、包含(后一个多边形在前一个多边形的内部)。
各种关系的输出格式如下:
1、no overlapping area between the previous triangle/quadrilateral/ pentagon and the following triangle/quadrilateral/ pentagon
2、the previous triangle/quadrilateral/ pentagon is connected to the following triangle/quadrilateral/ pentagon
3、the previous triangle/quadrilateral/ pentagon coincides with the following triangle/quadrilateral/ pentagon
4、the previous triangle/quadrilateral/ pentagon is inside the following triangle/quadrilateral/ pentagon
5、the previous triangle/quadrilateral/ pentagon is interlaced with the following triangle/quadrilateral/ pentagon
6、the previous triangle/quadrilateral/ pentagon contains the following triangle/quadrilateral/ pentagon
5:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),输出两个多边形公共区域的面积。注:只考虑每个多边形被另一个多边形分割成最多两个部分的情况,不考虑一个多边形将另一个分割成超过两个区域的情况。
6:输入六个点坐标,输出第一个是否在后五个点所构成的多边形(限定为凸多边形,不考虑凹多边形),的内部(若是五边形输出in the pentagon/outof the pentagon,若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。输入入错存在冗余点要排除,冗余点的判定方法见选项5。如果点在多边形的某条边上,输出"on the triangle/on the quadrilateral/on the pentagon"。
以上4、5、6选项输入的五个点坐标可能存在冗余,假设多边形一条边上两个端点分别是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
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
输入样例:
在这里给出一组输入。例如:
4:0,0 6,0 7,1 8,3 6,6 0,0 6,0 7,1 8,3 6,6
输出样例:
在这里给出相应的输出。例如:
the previous pentagon coincides with the following pentagon
试题分析:
源代码展示:
import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String s = in.nextLine(); InputData d = new InputData(); ParseInput.paseInput(s, d); int choice = d.getChoice(); ArrayList ps = d.getPoints(); switch (choice) { case 4: handle1(ps); break; case 5: handle2(ps); break; case 6: handle3(ps); break; } } // 五边形 public static void handle1(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 10); Pentagon t = new Pentagon(ps.get(0), ps.get(1), ps.get(2), ps.get(3),ps.get(4),ps.get(5),ps.get(6),ps.get(7),ps.get(8),ps.get(9)); double angle1=t.isPentagon(ps.get(0), ps.get(1), ps.get(2)); double angle2=t.isPentagon(ps.get(1), ps.get(2), ps.get(3)); double angle3=t.isPentagon(ps.get(2), ps.get(3), ps.get(4)); double angle4=t.isPentagon(ps.get(3), ps.get(4), ps.get(0)); double angle5=t.isPentagon(ps.get(4), ps.get(0), ps.get(1)); double angle0=angle1+angle2+angle3+angle4+angle5; double b1=360.0-angle1; double b2=180.0-angle2; double b3=360.0-angle3; double b4=180.0-angle4; double b5=180.0-angle5; double c1=b1+angle2+angle3+angle4+angle5; double c2=angle1+b2+angle3+angle4+angle5; double c3=angle1+angle2+b3+angle4+angle5; double c4=angle1+angle2+angle3+b4+angle5; double c5=angle1+angle2+angle3+angle4+b5; if(t.isSlope()==0) { if(angle0==540.0||c1==540.0||c2==540.0||c3==540.0||c4==540.0||c5==540.0) { System.out.println("true"); } else { System.out.println("false"); } } else { System.out.println("the previous triangle is interlaced with the following triangle"); } } // 凹凸五边形 public static void handle2(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 5); Pentagon t = new Pentagon(ps.get(0), ps.get(1), ps.get(2), ps.get(3),ps.get(4),ps.get(5)); double angle1=t.isPentagon(ps.get(0), ps.get(1), ps.get(2)); double angle2=t.isPentagon(ps.get(1), ps.get(2), ps.get(3)); double angle3=t.isPentagon(ps.get(2), ps.get(3), ps.get(4)); double angle4=t.isPentagon(ps.get(3), ps.get(4), ps.get(0)); double angle5=t.isPentagon(ps.get(4), ps.get(0), ps.get(1)); double angle0=angle1+angle2+angle3+angle4+angle5; double b1=360.0-angle1; double b2=360.0-angle2; double b3=180.0-angle3; double b4=180.0-angle4; double b5=180.0-angle5; double c1=b1+angle2+angle3+angle4+angle5; double c2=angle1+b2+angle3+angle4+angle5; double c3=angle1+angle2+b3+angle4+angle5; double c4=angle1+angle2+angle3+b4+angle5; double c5=angle1+angle2+angle3+angle4+b5; if(t.isSlope()==0) { if(angle0==540.0) { System.out.println("true"); }else if(c1==540.0||c2==540.0||c3==540.0||c4==540.0||c5==540.0){ System.out.println("false"); } else { System.out.println("not a pentagon"); } } else if(t.isSlope()==1) { System.out.println("not a pentagon"); } } // 凹凸五边形 public static void handle3(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 6); Pentagon t = new Pentagon(ps.get(0),ps.get(1), ps.get(2),ps.get(3),ps.get(4),ps.get(5)); double angle1=t.isPentagon(ps.get(1), ps.get(2), ps.get(3)); double angle2=t.isPentagon(ps.get(2), ps.get(3), ps.get(4)); double angle3=t.isPentagon(ps.get(3), ps.get(4), ps.get(5)); double angle4=t.isPentagon(ps.get(4), ps.get(5), ps.get(1)); double angle5=t.isPentagon(ps.get(5), ps.get(1), ps.get(2)); double angle0=angle1+angle2+angle3+angle4+angle5; double b1=t.getAArea(ps.get(0),ps.get(1), ps.get(2)); double b2=t.getAArea(ps.get(0),ps.get(2), ps.get(3)); double b3=t.getAArea(ps.get(0),ps.get(3), ps.get(4)); double b4=t.getAArea(ps.get(0),ps.get(4), ps.get(5)); double b5=t.getAArea(ps.get(0),ps.get(5), ps.get(1)); double b=b1+b2+b3+b4+b5; double a=t.getArea(ps.get(1), ps.get(2),ps.get(3),ps.get(4),ps.get(5)); if(t.isSlope()==0) { if(angle0==540.0&&a==b) { System.out.println("in the pentagon"); }else { System.out.println("outof the pentagon"); } } else if(t.isSlope()==1) { System.out.println("not a pentagon"); } } public static void handle4(ArrayList<Point> ps) { } /* * 输入四个点坐标,输出第一个是否在后三个点所构成的三角形的内部(输出in the triangle/outof triangle)。 * 必须使用射线法,原理:由第一个点往任一方向做一射线,射线与三角形的边的交点(不含点本身)数量如果为1,则在三角形内部。如果交点有两个或0个,则在三角形之外 * 。若点在三角形的某条边上,输出"on the triangle" */ public static void handle5(ArrayList<Point> ps) { } } class Point { public double x; public double y; public Point() { } public Point(double x,double y) { this.x=x; this.y=y; } /* 设置坐标x,将输入参数赋值给属性x */ public void setX(double x) { this.x = x; } /* 设置坐标y,将输入参数赋值给属性y */ public void setY(double y) { this.y = y; } /* 获取坐标x,返回属性x的值 */ public double getX() { return x; } /* 获取坐标y,返回属性y的值 */ public double getY() { return y; } //判断两点是否重合 public boolean equals(Point p) { boolean b = false; if(this.x==p.getX()&&this.y==p.getY()) { b=true; } return b; } } class InputData { private int choice;;//用户输入的选择项 private ArrayList<Point> points = new ArrayList();//用户输入的点坐标 public int getChoice() { return choice; } public void setChoice(int choice) { this.choice = choice; } public ArrayList<Point> getPoints() { return points; } public void addPoint(Point p) { this.points.add(p); } } class Pentagon{ private Point x; private Point y; private Point z; private Point a; private Point b; private Point c; public Pentagon(Point x, Point y, Point z,Point a,Point b,Point c) { this.x = x; this.y = y; this.z = z; this.a = a; this.b = b; this.c = c; } /* 判断x\y\z\a\b五个点的坐标是否能构成一个五边形 */ public double isPentagon(Point a,Point b,Point c) { double q=a.x-b.x; double w=a.y-b.y; double e=c.x-b.x; double r=c.y-b.y; double s=Math.sqrt(q * q + w * w); double t=Math.sqrt(e * e + r * r); double f=q * e + w * r; double v = f /(s*t); // 余弦值 double k=Math.toDegrees(Math.acos(v)); return k;// 角度 } public double isSlope() { double k1=(this.y.getY() - this.z.getY())*(this.x.getX() - this.y.getX()); double k2=(this.x.getY() - this.y.getY())*(this.y.getX() - this.z.getX()); double k3=(this.z.getY() - this.a.getY())*(this.y.getX() - this.z.getX()); double k4=(this.y.getY() - this.z.getY())*(this.z.getX() - this.a.getX()); double k5=(this.a.getY() - this.b.getY())*(this.z.getX() - this.a.getX()); double k6=(this.z.getY() - this.a.getY())*(this.a.getX() - this.b.getX()); double k7=(this.b.getY() - this.x.getY())*(this.a.getX() - this.b.getX()); double k8=(this.a.getY() - this.b.getY())*(this.b.getX() - this.x.getX()); double k9=(this.x.getY() - this.y.getY())*(this.b.getX() - this.x.getX()); double k10=(this.b.getY() - this.x.getY())*(this.x.getX() - this.y.getX()); if(k1-k2==0||k3-k4==0||k5-k6==0||k7-k8==0||k9-k10==0) { return 1; } else { return 0; } } /* 判断是否平行四边形 */ public boolean isParallelogram() { return true; } public double getAArea(Point a,Point b,Point c) { double k1 = this.a.getX()*this.b.getY()+this.b.getX()*this.c.getY()+this.c.getX()*this.a.getY(); double k2 = this.b.getX()*this.a.getY()+this.c.getX()*this.b.getY()+this.a.getX()*this.c.getY(); double l = 0.5*Math.sqrt(k1+k2); DecimalFormat d = new DecimalFormat("#.000"); Double output = Double.valueOf(d.format(l)); return output; } // 获取五边形的面积,此处采用海伦公式 public double getArea(Point x,Point y,Point z,Point a,Point b) { double k1 = (this.x.getY() - this.y.getY())*(this.x.getY() - this.y.getY())+(this.x.getX() - this.y.getX())*(this.x.getX() - this.y.getX()); double k2 = (this.y.getY() - this.z.getY())*(this.y.getY() - this.z.getY())+(this.y.getX() - this.z.getX())*(this.y.getX() - this.z.getX()); double k3 = (this.z.getY() - this.a.getY())*(this.z.getY() - this.a.getY())+(this.z.getX() - this.a.getX())*(this.z.getX() - this.a.getX()); double k4 = (this.a.getY() - this.b.getY())*(this.a.getY() - this.b.getY())+(this.a.getX() - this.b.getX())*(this.a.getX() - this.b.getX()); double k5 = (this.b.getY() - this.x.getY())*(this.b.getY() - this.x.getY())+(this.b.getX() - this.x.getX())*(this.b.getX() - this.x.getX()); double k6 = (this.x.getY() - this.z.getY())*(this.x.getY() - this.z.getY())+(this.x.getX() - this.z.getX())*(this.x.getX() - this.z.getX()); double k7 = (this.x.getY() - this.a.getY())*(this.x.getY() - this.a.getY())+(this.x.getX() - this.a.getX())*(this.x.getX() - this.a.getX()); double d1 = Math.sqrt(k1); double d2 = Math.sqrt(k2); double d3 = Math.sqrt(k3); double d4 = Math.sqrt(k4); double d5 = Math.sqrt(k5); double d6 = Math.sqrt(k6); double d7 = Math.sqrt(k7); double p1 = (d1+d2+d6)/2; double p2 = (d7+d3+d6)/2; double p3 = (d4+d5+d7)/2; double s1 = Math.sqrt(p1*(p1-d1)*(p1-d2)*(p1-d6)); double s2 = Math.sqrt(p2*(p2-d7)*(p2-d3)*(p2-d6)); double s3 = Math.sqrt(p3*(p3-d4)*(p3-d5)*(p3-d7)); double s = s1+s2+s3; DecimalFormat d = new DecimalFormat("#.000"); Double output = Double.valueOf(d.format(s)); return output; } /* 获取五边形的周长 */ /* 判断是否菱形 */ /* 判断是否矩形 */ /* 判断是否正方形 */ /* 三个点的getter()和setter()方法 */ public Point getX() { return x; } public void setX(Point x) { this.x = x; } public Point getY() { return y; } public void setY(Point y) { this.y = y; } public Point getZ() { return z; } public void setZ(Point z) { this.z = z; } public Point getA() { return a; } public void setA(Point z) { this.z = a; } } class PointInputError { //判断从字符串中解析出的点的数量是否合格。 public static void wrongNumberOfPoints(ArrayList ps, int num) { if (ps.size() != num) { System.out.println("wrong number of points"); System.exit(0); } } //判断输入的字符串中点的坐标部分格式是否合格。若不符合,报错并退出程序 public static void wrongPointFormat(String s) { if (!s.matches("[+-]?([1-9]\\d*|0)(\\.\\d+)?,[+-]?([1-9]\\d*|0)(\\.\\d+)?")) { System.out.println("Wrong Format"); System.exit(0); } } // 输入字符串是否是"选项:字符串"格式,选项部分是否是1~5其中之一 public static void wrongChoice(String s) { if (!s.matches("[1-6]:.+")) { System.out.println("Wrong Format"); System.exit(0); } } } class ParseInput { /* * 输入:完整的输入字符串,包含选项和所有点的信息,格式:选项:x1,y1 x2,y2 .....xn,yn。选项只能是1-5 * 一个空InputData对象 * 处理:将输入字符串中的选项和点信息提取出来并设置到InputData对象中 * 输出:包含选项值和所有点的Point对象的InputData对象。 */ public static void paseInput(String s, InputData d) { PointInputError.wrongChoice(s); d.setChoice(getChoice(s)); s = s.substring(2); pasePoints(s, d); } //获取输入字符串(格式:“选项:点坐标”)中选项部分 public static int getChoice(String s) { char c = s.charAt(0); return c-48; } /* * 输入:一个字符串,包含所有点的信息,格式:x1,y1 x2,y2 .....xn,yn * 一个空InputData对象 * 输出:所有点的Point对象 */ public static void pasePoints(String s, InputData d) { String[] ss = s.split(" "); if (ss.length == 0) return; for (int i = 0; i < ss.length; i++) { d.addPoint(readPoint(ss[i])); } } /* * 输入:包含单个点信息的字符串,格式:x,y * 输出:Point对象 */ public static Point readPoint(String s) { PointInputError.wrongPointFormat(s); String[] ss = s.split(","); double x = Double.parseDouble(ss[0]); double y = Double.parseDouble(ss[1]); // System.out.println("match"); return new Point(x, y); } }
SourceMonitor生成的报表内容:
类图
分析总结
本题为点线型系列的进阶题,从面向对象和方法设计出发,进行五边形为主的图形化设计。本题主函数采用switch case语句,每个语句对应题目中所给出的一个选项;在点类与线类的基础上,增加五边形(Pentagen)的输入格式正确判断函数。本题是点线形系列最后一个类型的第二部分,难度显著提升,主要还是考察类与对象含义的理解和运用。很遗憾,由于个人能力的问题,这道题的代码存在很大的问题,关键的功能均为实现。
期中考试第一题
7-1 点与线(类设计) 分数 20 作者 段喜龙 单位 南昌航空大学-
设计一个类表示平面直角坐标系上的点Point,私有属性分别为横坐标x与纵坐标y,数据类型均为实型数,除构造方法以及属性的getter与setter方法外,定义一个用于显示信息的方法display(),用来输出该坐标点的坐标信息,格式如下:
(x,y)
,数值保留两位小数。为简化题目,其中,坐标点的取值范围设定为(0,200]
。若输入有误,系统则直接输出Wrong Format
-
设计一个类表示平面直角坐标系上的线Line,私有属性除了标识线段两端的点point1、point2外,还有一个字符串类型的color,用于表示该线段的颜色,同样,除构造方法以及属性的getter与setter方法外,定义一个用于计算该线段长度的方法getDistance(),还有一个用于显示信息的方法display(),用来输出线段的相关信息,输出格式如下:
``` The line's color is:颜色值 The line's begin point's Coordinate is: (x1,y1) The line's end point's Coordinate is: (x2,y2) The line's length is:长度值 ```
其中,所有数值均保留两位小数,建议可用
String.format("%.2f", data)
方法。设计类图如下图所示。
** 题目要求:在主方法中定义一条线段对象,从键盘输入该线段的起点坐标与终点坐标以及颜色,然后调用该线段的display()方法进行输出。**
- 以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
输入格式:
分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。
输出格式:
The line's color is:颜色值
The line's begin point's Coordinate is:
(x1,y1)
The line's end point's Coordinate is:
(x2,y2)
The line's length is:长度值
输入样例1:
在这里给出一组输入。例如:
5
9.4
12.3
84
Red
输出样例1:
在这里给出相应的输出。例如:
The line's color is:Red
The line's begin point's Coordinate is:
(5.00,9.40)
The line's end point's Coordinate is:
(12.30,84.00)
The line's length is:74.96
输入样例2:
在这里给出一组输入。例如:
80.2356
352.12
24.5
100
Black
输出样例2:
在这里给出相应的输出。例如:
Wrong Format
源代码展示:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); Point point1=new Point(); double x1=input.nextDouble(); double y1=input.nextDouble(); point1.setX(x1); point1.setY(y1); Point point2=new Point(); double x2=input.nextDouble(); double y2=input.nextDouble(); point2.setX(x2); point2.setY(y2); String color=input.next(); Line line=new Line(); line.setPoint1(point1); line.setPoint2(point2); line.setColor(color); if((x1<=0||x1>200)||(y1<=0||y1>200)||(x2<=0||x2>200)||(y2<=0||y2>200)) { System.out.println("Wrong Format"); } else line.display(); } } class Line { private Point point1=new Point(); private Point point2=new Point(); String color; public Line() { } 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 String getColor() { return color; } public void setColor(String color) { this.color=color; } public double getDistance() { double c=point1.getX()-point2.getX(); double d=point1.getY()-point2.getY(); return Math.sqrt(c*c+d*d); } public void display() { System.out.println("The line's color is:"+this.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.print("The line's length is:"+String.format("%.2f",this.getDistance())); } } class Point { double x; double y; public Point() { } 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; } public void display() { System.out.println("("+String.format("%.2f",x)+","+String.format("%.2f",y)+")"); } }
SourceMonitor生成的报表内容:
类图
分析总结
本题为期中考试第一题,题目难度不大,根据提供的类图,将整个陈程序的大致框架搭好,并向各个类中加入他的实现的细节。Point、Line两个类中包含对点及点坐标的定义,构造函数以及题干中要求使用的color;方法包括getDistance(求两点间距离)。设计函数display(),置于Line的末尾,由特定输出语句组成,在主类Main中定义点类和线类之后进行调用输出正确的语句。本题考察的知识点是基本类的构造和方法的运用,整体比较简单,没有遇到太明显问题,最大的问题是由于粗心导致的类的名称前后不一致问题导致编译无法过去。
期中考试第二题
7-2 点线面问题重构(继承与多态) 分数 40 作者 段喜龙 单位 南昌航空大学
在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。
- 对题目中的点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()方法,从而实现多态特性。示例代码如下:
类结构如下图所示。element = p1;//起点Point element.display(); element = p2;//终点Point element.display(); element = line;//线段 element.display(); element = plane;//面 element.display();
其中,所有数值均保留两位小数,建议可用String.format("%.2f", data)
方法。
- 以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
输入格式:
分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。
输出格式:
(x1,y1)
(x2,y2)
The line's color is:颜色值
The line's begin point's Coordinate is:
(x1,y1)
The line's end point's Coordinate is:
(x2,y2)
The line's length is:长度值
The Plane's color is:颜色值
输入样例1:
在这里给出一组输入。例如:
5
9.4
12.3
84
Red
输出样例1:
在这里给出相应的输出。例如:
(5.00,9.40)
(12.30,84.00)
The line's color is:Red
The line's begin point's Coordinate is:
(5.00,9.40)
The line's end point's Coordinate is:
(12.30,84.00)
The line's length is:74.96
The Plane's color is:Red
输入样例2:
在这里给出一组输入。例如:
5
9.4
12.3
845
Black
输出样例2:
在这里给出相应的输出。例如:
Wrong Format
源代码展示:
import java.util.Scanner; public class Main { public static void main(String[] args){ Scanner input=new Scanner(System.in); Point p1=new Point(); double x1=input.nextDouble(); double y1=input.nextDouble(); p1.setX(x1); p1.setY(y1); Point p2=new Point(); double x2=input.nextDouble(); double y2=input.nextDouble(); p2.setX(x2); p2.setY(y2); String color=input.next(); Line line=new Line(); line.setPoint1(p1); line.setPoint2(p2); line.setColor(color); Plane plane=new Plane(); plane.setColor(color); Element element=new Element() { public void display() { } }; if ((x1<=0||x1>200)||(y1<=0||y1>200)||(x2<=0||x2>200)||(y2<=0||y2>200)) System.out.println("Wrong Format"); else{ element = p1; element.display(); element = p2; element.display(); element = line; element.display(); element = plane; 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 Point() { } 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; } public void display(){ System.out.println("("+String.format("%.2f",x)+","+String.format("%.2f",y)+")"); } } class Line extends Element{ private Point point1 = new Point(); private Point point2 = new Point(); String color; public Line(Point point1, Point point2, String color) { this.point1 = point1; this.point2 = point2; this.color = color; } public Line() { } 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 String getColor() { return color; } public void setColor(String color) { this.color = color; } public double getDistance(){ double a=point1.getX()-point2.getX(); double b=point1.getY()-point2.getY(); return Math.sqrt(a*a+b*b); } 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:" + String.format("%.2f",getDistance())); } } class Plane extends Element{ private String color; public Plane(String color) { this.color = color; } public Plane() { } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void display(){ System.out.println("The Plane's color is:"+this.color); } }
SourceMonitor生成的报表内容:
类图
分析总结
本题为期中考试第二题,考察点在于对第一题构建的类定义一个抽象类并设置好其中的继承关系,整体难度不高。在引用第一题创建的Point类和Line类之前,根据题意,我们先建立一个抽象类Element,再在其中定义抽象方法display();确立继承关系,将Point类和Line类继承在Element类之下(包含各自的输出函数,主力在定义要求类的变量后对其进行调用)。新创建Plane类,继承在Element之下,输出确定Plane类颜色color的语句。注意,由于本道题的父类是抽象类,他的内部并不实现具体功能。本题考察的知识点是抽象类的构造和抽象方法的使用,只需要我们正确写出类与类之间的继承关系即可。整体比较简单,没有遇到太明显问题
期中考试第三题
7-3 点线面问题再重构(容器类) 分数 40 作者 段喜龙 单位 南昌航空大学
在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。
- 在原有类设计的基础上,增加一个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:输入结束
输入结束后,按容器中的对象顺序分别调用每个对象的choice = input.nextInt(); while(choice != 0) { switch(choice) { case 1://insert Point object into list ... break; case 2://insert Line object into list ... break; case 3://insert Plane object into list ... break; case 4://delete index - 1 object from list int index = input.nextInt(); ... } choice = input.nextInt(); }
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开始)
...
}
输出格式:
- Point、Line、Plane的输出参考题目2
- 删除对象时,若输入的index超出合法范围,程序自动忽略该操作
输入样例:
在这里给出一组输入。例如:
1
3.4
5.6
2
4.4
8.0
0.98
23.888
Red
3
Black
1
9.8
7.5
3
Green
4
3
0
输出样例:
在这里给出相应的输出。例如:
(3.40,5.60)
The line's color is:Red
The line's begin point's Coordinate is:
(4.40,8.00)
The line's end point's Coordinate is:
(0.98,23.89)
The line's length is:16.25
(9.80,7.50)
The Plane's color is:Green
源代码展示:
import java.util.ArrayList; import java.util.Scanner; abstract class Element { public abstract void display(); } class Plane extends Element { private String color; public Plane() { super(); } public Plane(String color) { super(); this.color = color; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void display() { System.out.println("The Plane's color is:" + this.color); } } class Point extends Element{ private double x,y; public Point(){ } public Point(double x,double y){ this.x = x; this.y = y; } public double getX(){ return this.x; } public void setX(double x){ this.x = x; } public double getY(){ return this.y; } public void setY(double y){ this.y = y; } public void display(){ System.out.println("(" + String.format("%.2f", x) + "," + String.format("%.2f",y) + ")"); } } class Line extends Element{ private Point point1,point2; private String color; public Line(){ } public Line(Point p1,Point p2,String color){ this.point1 = p1; this.point2 = p2; 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 String getColor() { return color; } public void setColor(String color) { this.color = color; } public double getDistance(){ return Math.sqrt(Math.pow(this.point1.getX() - this.point2.getX(), 2) + Math.pow(this.getPoint1().getY() - this.getPoint2().getY(), 2)); } public void display(){ System.out.println("The line's color is:" + this.getColor()); System.out.println("The line's begin point's Coordinate is:"); this.getPoint1().display(); System.out.println("The line's end point's Coordinate is:"); this.getPoint2().display(); System.out.println("The line's length is:" + String.format("%.2f", this.getDistance())); } } class GeometryObject{ private ArrayList<Element> list = new ArrayList<>(); public GeometryObject() { } public void add(Element element) { list.add(element); } public void remove(int index) { if(index < 1 || index > list.size()) { return; } list.remove(index - 1); } public ArrayList<Element> getList(){ return this.list; } } public class Main { public static void main(String[] args) { double x1,y1,x2,y2; String color; Scanner input = new Scanner(System.in); int choice = 0,index = 0; GeometryObject container = new GeometryObject(); choice = input.nextInt(); while(choice != 0) { switch(choice) { case 1: x1 = input.nextDouble(); y1 = input.nextDouble(); container.add(new Point(x1,y1)); break; case 2: x1 = input.nextDouble(); y1 = input.nextDouble(); x2 = input.nextDouble(); y2 = input.nextDouble(); color = input.next(); container.add(new Line(new Point(x1,y1),new Point(x2,y2),color)); break; case 3: color = input.next(); container.add(new Plane(color)); break; case 4: index = input.nextInt(); container.remove(index); break; } choice = input.nextInt(); } for(Element element:container.getList()) { element.display(); } } }
SourceMonitor生成的报表内容:
类图
分析总结
本题为期中考试第三题,考察点在于对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。题目整体难度有所上升。将第二题建立的Point、Line、Plane类按题干中的类图进行整理并添入题目,沿用Element抽象类继承这三个类。新建立GeometryObject容器类,容器类运用ArrayList,并增添add、remove方法,并通过getList方法实现错误格式的判断。根据题意,主函数使用switch case语句对题干四个选项分别进行实现。本题中需要用到ArrayList集合的操作知识。
三、踩坑心得
1、设计类的时候忘记添加构造函数。如果不添加构造函数,那么需要向类中传递参数并调用方法的功能便无法实现。
2、类中和方法漏写和判断情况缺失。这个就在图形类中体现得较为明显。涉及几何学得判断时要尤为注意那些情况该图形不存在,哪些情况点是重合的,哪些情况斜率不存在或者斜率为零,三角形哪些情况不成立,哪些情况三角形成为了一条直线等极端情况。
3.对新知识的掌握尚未完全。在这个阶段的学习中,我们在类与对象、方法基本构建的基础上,新学习了继承、多态的使用以及抽象类、抽象方法的构造,新知较多,在期中考试中,我就遇到了抽象类使用不熟练的问题,比如抽象方法该怎么处理以及各个类怎么确立关系等问题。
四、改进建议
前三次作业最大的问题就是披着java的外衣,但是里面全是C语言的肉,在一个类里面将所有问题解决。使用类使程序发挥java的优势,调用方法使程序更有层次性,可以规避面向过程的编程中出现的需要很麻烦才能解决的问题,在字符串处理上更加改进,避免误差,可以采用正则表达式,来省去很大的冗余。从第四次作业开始,仍存在着使用面向过程的思想编程的情况,从第五次作业开始,这种情况发生了显著的改变,懂得了识别对象并创造相应的类,让他们分开工作,增加代码的可读性。在编程的过程中尽量不要粗心,出现类名前后不一致的情况。输入的过程可以尝试使用正则表达式。从这几次作业的情况来看,类的继承和多态的理解还不是那么的深刻,还是要多加练习。
五、总结
1.我在这三次作业中初步学会了java的基本语法,它与C语言有着很大出入,总结一下就是长着类似的肉,但是二者的根骨不同。
2.在这三次的作业中,我做得并不理想,首先最开始没有采用面向对象的思想,其次是对与数学的结合做的不太好,很多刁钻的测试点根本就没得分。最后就是有关的概念理解的不是那么透彻。在今后的学习中,要深化对类的理解,学会运用网络资源搜寻程序所需相关函数,做得对程序精益求精,争取在现场的作业里做得更好。
3.在题目拿到手时,常常不知道从何处下手,同时还存在着考虑问题不全面的情况。
标签:p1,Point,double,博客,getX,getY,第二次,public From: https://www.cnblogs.com/zhangjingyang/p/16838739.html