第四次作业与期中考试总结

一,前言

  第四次作业(四边形),第五次作业(五边形)的实现依托于第三次作业的一些类,例如点类和线类,如果前面的类没有构建好,后面四边形,五边形写起来会非常繁琐代码量会非常的长,代码的结构也会变得杂乱,不容易被人看懂,作业总体难度偏难,但是在构建了图形父类以及知道了一些数学公式之后就显得没有那么难写。期中考试的题目更多的是考察我们对于面向对象,继承,继承所体现的多态,抽象类的知识点的理解,题目设计的算法非常简单,主要考察理解,我就是因为理解的不够深入所以写起来比较慢,最后导致没有写完但是我后来有时间的时候再回过头来看这个题目对以上所说的理解又进一步加深了。

二,设计与分析

作业四题目,点击展开
/*用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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"。*/
作业代码,点击展开
 import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String s=sc.nextLine();
        String regx="[1-5]:";
        if(!s.substring(0,2).matches(regx)){
            System.out.println("Wrong Format");
            System.exit(0);
        }
        String s0=s.substring(2);
        Judge j=new Judge(s0);
        Dot d1=new Dot(s0,1);Dot d2=new Dot(s0,2);Dot d3=new Dot(s0,3);Dot d4=new Dot(s0,4);
        Line l1=new Line(d1,d2);Line l2=new Line(d2,d3);Line l3=new Line(d3,d4);Line l4=new Line(d4,d1);
        if(s.substring(0,2).equals("1:")){
            Judge j1=new Judge(s0,4);
            Judge.judgeCoincide(l1);Judge.judgeCoincide(l2);Judge.judgeCoincide(l3);Judge.judgeCoincide(l4);
            quadrilateral q1=new quadrilateral(l1,l2,l3,l4);
            if(Judge.judgeQuadrilateral(q1)) System.out.print("true ");
            else System.out.print("false ");
            if(q1.b) System.out.println("true");
            else System.out.println("false");
        }
        if(s.substring(0,2).equals("2:")){
            Judge j1=new Judge(s0,4);
            Judge.judgeCoincide(l1);Judge.judgeCoincide(l2);Judge.judgeCoincide(l3);Judge.judgeCoincide(l4);
            quadrilateral q1=new quadrilateral(l1,l2,l3,l4);
            if(!Judge.judgeQuadrilateral(q1)){
                System.out.println("not a quadrilateral");
                System.exit(0);
            }
            if(Judge.judgeDiamond(q1)) System.out.print("true ");
            else System.out.print("false ");
            if(Judge.judgeRectangle(q1)) System.out.print("true ");
            else System.out.print("false ");
            if (Judge.judgeSquare(q1)) System.out.println("true");
            else System.out.println("false");
        }
        if(s.substring(0,2).equals("3:")){
            Judge j1=new Judge(s0,4);
            Judge.judgeCoincide(l1);Judge.judgeCoincide(l2);Judge.judgeCoincide(l3);Judge.judgeCoincide(l4);
            quadrilateral q1=new quadrilateral(l1,l2,l3,l4);
            if(!Judge.judgeQuadrilateral(q1)) {System.out.println("not a quadrilateral");System.exit(0);}
            else if(Judge.concave(l1,l2,l3,l4)) System.out.print("false ");
            else System.out.print("true ");
            myPrint(q1.perimeter);System.out.print(" ");myPrint(q1.s);
        }
        if(s.substring(0,2).equals("4:")){
            Judge j2=new Judge(s0,6);
            Dot d5=new Dot(s0,5);Dot d6=new Dot(s0,6);
            Line l5=new Line(d4,d5);Line l6=new Line(d5,d6);Line l7=new Line(d6,d3);
            Judge.judgeCoincide(l1);
            Judge.correctTriangle(d3,d4,d5,d6);
            if((!Judge.T&&!Judge.Q)||(!Judge.C&&Judge.T)){//不构成三角形和四边形
                System.out.println("not a quadrilateral or triangle");
            }
            else if(Judge.T&&Judge.C){//如果构成三角形并且输入正确
                if(Judge.LineCoincideWithTriangle(l1,Judge.correctTriangle(d3,d4,d5,d6))){
                    System.out.println("The line is coincide with one of the lines");
                }
                else{//输出几点数量和分割面积
                    trianglePointNum(l1,Judge.correctTriangle(d3,d4,d5,d6));
                }
            }
            else{
                quadrilateral q4=new quadrilateral(l3,l5,l6,l7);
                if(Judge.LineCoincideWithQuadrilateral(l1,q4)) System.out.println("The line is coincide with one of the lines");
                else{//输出交点数量和分割面积
                    quadrilateralPointNum(l1,q4);
                }
            }
        }
        if(s.substring(0,2).equals("5:")){
            Judge j3=new Judge(s0,5);
            Dot d5=new Dot(s0,5);Line l5=new Line(d4,d5);Line l8=new Line(d5,d2);
            Judge.correctTriangle(d2,d3,d4,d5);
            if((!Judge.T&&!Judge.Q)||(!Judge.C&&Judge.T)){//不构成三角形和四边形
                System.out.println("not a quadrilateral or triangle");
            }
            else if(Judge.T){//如果构成三角形并且输入正确
                if(triangle.onTheTriangle(d1,Judge.correctTriangle(d2,d3,d4,d5)))
                    System.out.println("on the triangle");
                else if(triangle.inTheTriangle(d1,Judge.correctTriangle(d2,d3,d4,d5)))
                    System.out.println("in the triangle");
                else System.out.println("outof the triangle");
            }
            else{//构成四边形
                quadrilateral q5=new quadrilateral(l2,l3,l5,l8);
                if(quadrilateral.onTheQuadrilateral(d1,q5))//判断点是否在四边形上
                    System.out.println("on the quadrilateral");
                else{
                    if(quadrilateral.inTheQuadrilateral(d1,q5))
                        System.out.println("in the quadrilateral");
                    else System.out.println("outof the quadrilateral");
                }
                //5:1,1 0,10 0,0 30,20 0,80
            }
        }
    }
    public static void myPrint(double data){
        DecimalFormat df = new DecimalFormat("0.0##");
        df.setRoundingMode(RoundingMode.HALF_UP);
        System.out.print(df.format(data));
    }
    public static void trianglePointNum(Line l, triangle t){
        int flag=0,flag2=0,flag1=0;
        Dot[] p=new Dot[3];//记录交点的位置
        Line[] lines=new Line[3];//记录每一条交线
        if(Line.inLine(Line.point(l,t.side[0]),t.side[0])){p[flag++]=Line.point(l,t.side[0]);lines[flag2++]=t.side[0];}
        if(Line.inLine(Line.point(l,t.side[1]),t.side[1])){p[flag++]=Line.point(l,t.side[1]);lines[flag2++]=t.side[1];}
        if(Line.inLine(Line.point(l,t.side[2]),t.side[2])){p[flag++]=Line.point(l,t.side[2]);lines[flag2++]=t.side[2];}
        if(flag==0) System.out.println("0");
        else if(flag==2&&p[0].x==p[1].x&&p[0].y==p[1].y) System.out.println("1");
        else {
            double s1=0,s2=0,temp=0,bottom=0;
            if(flag2==2){
                Line pl=new Line(p[0],p[1]);
                bottom=Dot.distance(p[0],p[1]);
                s1=0.5*bottom*Line.distance(Line.point(lines[0],lines[1]),pl);
                s2=t.s-s1;
            }
            else{
                if(p[0].x==p[1].x&&p[0].y==p[1].y){
                    Line pl=new Line(p[0],p[2]);
                    bottom=Dot.distance(p[0],p[2]);
                    s1=0.5*bottom*Line.distance(lines[2].endPoint1,pl);
                    s2=t.s-s1;
                }
                else if(p[0].x==p[2].x&&p[0].y==p[2].y){
                    Line pl=new Line(p[0],p[1]);
                    bottom=Dot.distance(p[0],p[1]);
                    s1=0.5*bottom*Line.distance(lines[1].endPoint1,pl);
                    s2=t.s-s1;
                }
                else{
                    Line pl=new Line(p[1],p[0]);
                    bottom=Dot.distance(p[1],p[0]);
                    s1=0.5*bottom*Line.distance(lines[0].endPoint1,pl);
                    s2=t.s-s1;
                }
            }
            if(s1>s2){//s1如果大于s2交换,使得s1<s2,便于后续输出
                temp=s1;
                s1=s2;
                s2=temp;
            }
            System.out.print("2 ");myPrint(s1);System.out.print(" ");myPrint(s2);
        }
    }
    public static void quadrilateralPointNum(Line l, quadrilateral q){
        int flag=0,flag2=0,flag1=0,n1=0,n2=0,n3=0,n4=0;
        Dot[] p=new Dot[4];//记录交点的位置
        Line[] lines=new Line[4];//记录每一条交线
        if(Line.inLine(Line.point(l,q.lines[0]),q.lines[0])){n1++;p[flag++]=Line.point(l,q.lines[0]);lines[flag2++]=q.lines[0];}
        if(Line.inLine(Line.point(l,q.lines[1]),q.lines[1])){n2++;p[flag++]=Line.point(l,q.lines[1]);lines[flag2++]=q.lines[1];}
        if(Line.inLine(Line.point(l,q.lines[2]),q.lines[2])){n3++;p[flag++]=Line.point(l,q.lines[2]);lines[flag2++]=q.lines[2];}
        if(Line.inLine(Line.point(l,q.lines[3]),q.lines[3])){n4++;p[flag++]=Line.point(l,q.lines[3]);lines[flag2++]=q.lines[3];}
        if(flag==0) System.out.println("0");
        else if(flag==2&&p[0].x==p[1].x&&p[0].y==p[1].y) System.out.println("1");
        else {
            double s1=0,s2=0,temp=0,bottom=0;
            if(flag==2){//确定交点数为2,还需考虑是否分割成了两个四边形
                if((n1==1&&n2==1)||(n1==1&&n4==1)||(n2==1&&n3==1)||(n3==1&&n4==1)) {//如果交点的两条边相邻,则分割成了一个三角形和不规则图形
                    Line pl = new Line(p[0], p[1]);
                    bottom = Dot.distance(p[0], p[1]);
                    s1 = 0.5 * bottom * Line.distance(Line.point(lines[0], lines[1]), pl);
                    s2 = q.s - s1;
                }
                else{//分割成了两个四边形
                    if(n1==1){
                        Line l2=new Line(p[0],q.lines[1].endPoint1);
                        Line l3=new Line(q.lines[1].endPoint2,p[1]);
                        Line pl=new Line(p[1],p[0]);
                        quadrilateral q1=new quadrilateral(q.lines[1],l3,pl,l2);
                        s1=q1.s;
                        s2=q.s-s1;
                    }
                    if(n2==1){
                        Line l2=new Line(p[1],q.lines[0].endPoint1);
                        Line l3=new Line(q.lines[1].endPoint1,p[0]);
                        Line pl=new Line(p[0],p[1]);
                        quadrilateral q1=new quadrilateral(q.lines[0],l3,pl,l2);
                        s1=q1.s;
                        s2=q.s-s1;
                    }
                }
            }
            else if(flag==3){
                if(p[0].x==p[1].x&&p[0].y==p[1].y){
                    Line pl=new Line(p[0],p[2]);
                    bottom=Dot.distance(p[0],p[2]);
                    s1=0.5*bottom*Line.distance(lines[2].endPoint1,pl);
                    s2=q.s-s1;
                }
                else if(p[0].x==p[2].x&&p[0].y==p[2].y){
                    Line pl=new Line(p[0],p[1]);
                    bottom=Dot.distance(p[0],p[1]);
                    s1=0.5*bottom*Line.distance(lines[1].endPoint1,pl);
                    s2=q.s-s1;
                }
                else{
                    Line pl=new Line(p[1],p[0]);
                    bottom=Dot.distance(p[1],p[0]);
                    s1=0.5*bottom*Line.distance(lines[0].endPoint1,pl);
                    s2=q.s-s1;
                }
            }
            else{
                s2=0.5*q.s;
                s1=s2;
            }
            if(s1>s2){//s1如果大于s2交换,使得s1<s2,便于后续输出
                temp=s1;
                s1=s2;
                s2=temp;
            }
            System.out.print("2 ");myPrint(s1);System.out.print(" ");myPrint(s2);
        }
    }
}
class quadrilateral {
    public boolean b = false;//是否为平行四边形
    public Line[] lines = new Line[4];//存四边形的四条边
    public double s;
    public double perimeter;
    public quadrilateral(Line l1, Line l2, Line l3, Line l4) {//构造四边形
        lines[0] = l1;lines[1] = l2;lines[2] = l3;lines[3] = l4;
        if (l1.slop == l3.slop && l2.slop == l4.slop) b = true;
        perimeter=lines[0].length+lines[1].length+lines[2].length+lines[3].length;
        //凸四边形面积
            Line l6=new Line(lines[1].endPoint1,lines[3].endPoint1);
            triangle t1=new triangle(lines[0],l6,lines[3]);
            l6=new Line(lines[3].endPoint1,lines[1].endPoint1);
            triangle t2=new triangle(lines[1],lines[2],l6);
            s=t1.s+t2.s;
        if(Judge.concave(lines[0], lines[1], lines[2], lines[3])){//如果是凹四边形
            Line l5=new Line(lines[2].endPoint1,lines[0].endPoint1);
            triangle t3=new triangle(lines[0],lines[1],l5);
            l5=new Line(lines[0].endPoint1,lines[2].endPoint1);
            triangle t4=new triangle(lines[2],lines[3],l5);
            double s2=t3.s+t4.s;
            if(s>s2)s=s2;
        }
    }
    public static boolean inTheQuadrilateral(Dot d,quadrilateral q){//判断点是否在四边形内
            Dot d1=new Dot();Dot d2=new Dot();Dot d3=new Dot();Dot d4=new Dot();
            d1.x=q.lines[0].endPoint1.x-q.lines[0].endPoint2.x;d1.y=q.lines[0].endPoint1.y-q.lines[0].endPoint2.y;
            d2.x=q.lines[1].endPoint1.x-q.lines[1].endPoint2.x;d2.y=q.lines[1].endPoint1.y-q.lines[1].endPoint2.y;
            d3.x=q.lines[2].endPoint1.x-q.lines[2].endPoint2.x;d3.y=q.lines[2].endPoint1.y-q.lines[2].endPoint2.y;
            d4.x=q.lines[3].endPoint1.x-q.lines[3].endPoint2.x;d4.y=q.lines[3].endPoint1.y-q.lines[3].endPoint2.y;
            Dot ad=new Dot();Dot bd=new Dot();Dot cd=new Dot();Dot dd=new Dot();
            ad.x=q.lines[0].endPoint1.x-d.x;ad.y=q.lines[0].endPoint1.y-d.y;
            bd.x=q.lines[1].endPoint1.x-d.x;bd.y=q.lines[1].endPoint1.y-d.y;
            cd.x=q.lines[2].endPoint1.x-d.x;cd.y=q.lines[2].endPoint1.y-d.y;
            dd.x=q.lines[3].endPoint1.x-d.x;dd.y=q.lines[3].endPoint1.y-d.y;
            double n1,n2,n3,n4;
            n1=d1.x*ad.y-d1.y*ad.x;n2=d2.x*bd.y-d2.y*bd.x;n3=d3.x*cd.y-d3.y*cd.x;n4=d4.x*dd.y-d4.y*dd.x;
            return ((n1>0&&n2>0&&n3>0&&n4>0)||(n1<0&&n2<0&&n3<0&&n4<0));
    }
    public static boolean onTheQuadrilateral(Dot d, quadrilateral q){
        return Line.inLine(d,q.lines[0])||Line.inLine(d,q.lines[1])||Line.inLine(d,q.lines[2])||(Line.inLine(d,q.lines[3]));
    }
}
class triangle {
    public double s;
    public double perimeter;
    public Line[] side = new Line[3];//三角形最长边
    public triangle(){}
    public triangle(Line l1, Line l2, Line l3) {
        side[0] = l1;side[1] = l2;side[2] = l3;
        s = 0.5 * side[0].length * Line.distance(Line.point(side[1], side[2]), side[0]);
        perimeter = side[0].length + side[1].length + side[2].length;
    }
    public static boolean inTheTriangle(Dot d,triangle t){//判断点是否在三角形内
        if(Line.inLine(d,t.side[0])||Line.inLine(d,t.side[1])||Line.inLine(d,t.side[2])) return false;
        else {
            Dot d1=new Dot();Dot d2=new Dot();Dot d3=new Dot();
            d1.x=t.side[0].endPoint1.x-t.side[0].endPoint2.x;d1.y=t.side[0].endPoint1.y-t.side[0].endPoint2.y;
            d2.x=t.side[1].endPoint1.x-t.side[1].endPoint2.x;d2.y=t.side[1].endPoint1.y-t.side[1].endPoint2.y;
            d3.x=t.side[2].endPoint1.x-t.side[2].endPoint2.x;d3.y=t.side[2].endPoint1.y-t.side[2].endPoint2.y;
            Dot ad=new Dot();Dot bd=new Dot();Dot cd=new Dot();
            ad.x=t.side[0].endPoint1.x-d.x;ad.y=t.side[0].endPoint1.y-d.y;
            bd.x=t.side[1].endPoint1.x-d.x;bd.y=t.side[1].endPoint1.y-d.y;
            cd.x=t.side[2].endPoint1.x-d.x;cd.y=t.side[2].endPoint1.y-d.y;
            double n1,n2,n3;
            n1=d1.x*ad.y-d1.y*ad.x;n2=d2.x*bd.y-d2.y*bd.x;n3=d3.x*cd.y-d3.y*cd.x;
            return ((n1>0&&n2>0&&n3>0)||(n1<0&&n2<0&&n3<0));
        }
    }
   public static boolean onTheTriangle(Dot d,triangle t){//判断点在三角形边线上
        return Line.inLine(d,t.side[0])||Line.inLine(d,t.side[1])||Line.inLine(d,t.side[2]);
    }
}
class Line {
    public double slop;
    public double length;
    public Dot endPoint1 = new Dot();
    public Dot endPoint2 = new Dot();
    public double a;public double b;public double c;
    public Line() {
    }
    public Line(Dot d1, Dot d2) {
        length = Dot.distance(d1, d2);
        endPoint1.x = d1.x;endPoint1.y = d1.y;endPoint2.x = d2.x;endPoint2.y = d2.y;
        a = d2.y - d1.y;b = d1.x - d2.x;c = d1.x * (-a) + d1.y * (-b);
        if (d2.x == d1.x) slop = 99999999;
        else slop = (d2.y - d1.y) / (d2.x - d1.x);
    }
    public static double distance(Dot d, Line l) {//计算点到直线的距离
        double dis = Math.abs(l.a * d.x + l.b * d.y + l.c) / Math.sqrt(l.a * l.a + l.b * l.b);
        return dis;
    }
    public static Dot point(Line l1, Line l2) {//求两条直线的交点
        Dot p = new Dot();
        p.x = (l1.b * l2.c - l2.b * l1.c) / (l2.b * l1.a - l1.b * l2.a);
        p.y = (l1.a * l2.c - l2.a * l1.c) / (l2.a * l1.b - l1.a * l2.b);
        return p;
    }
    public static boolean inLine(Dot p, Line l) {//判断点是否在线内
        return ((Dot.distance(p, l.endPoint1) + Dot.distance(p, l.endPoint2) <= l.length + 0.000001)||
                (p.x==l.endPoint1.x&&p.y==l.endPoint1.y)||(p.x==l.endPoint2.x&&p.y==l.endPoint2.y));
    }
    public static boolean satisfy(Line l1,Line l2){//判断两条线是否重合
        return (l1.slop==l2.slop&&l1.c==l2.c);
    }
    public static boolean vertical(Line l1,Line l2){//判断两条线是否垂直
        if(l1.length== Line.distance(l1.endPoint1,l2))return true;
        else return false;
    }
}
class Judge {
    public static boolean b = false;
    public static boolean T = false;
    public static boolean Q = false;
    public static boolean C = false;//是否正确输入
    public Judge(String s) {
        String regx = "([+|-]?(0|[1-9][0-9]*)(\\.\\d+)?,[+|-]?(0|[1-9][0-9]*)(\\.\\d+)?( [+|-]?(0|[1-9][0-9]*)(\\.\\d+)?,[+|-]?(0|[1-9][0-9]*)(\\.\\d+)?)+)( )?";
        if (s.matches(regx)) b = true;
        else {
            System.out.println("Wrong Format");
            System.exit(0);
        }
    }
    public Judge(String s, int n) {//判断点数量格式是否符合要求
        int flag_dh = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ',') flag_dh++;
        }
        if (flag_dh != n) {
            System.out.println("wrong number of points");
            System.exit(0);
        }
    }
    public static void judgeCoincide(Line l) {//判断构成线的两点是否重合
        if (l.endPoint1.x == l.endPoint2.x && l.endPoint1.y == l.endPoint2.y) {
            System.out.println("points coincide");
            System.exit(0);
        }
    }
    public static boolean judgeQuadrilateral(quadrilateral q){
        if((q.lines[0].slop==q.lines[1].slop||q.lines[1].slop==q.lines[2].slop||q.lines[2].slop==q.lines[3].slop||q.lines[3].slop==q.lines[0].slop)||
                (Line.inLine(Line.point(q.lines[1],q.lines[3]),q.lines[1])&&Line.inLine(Line.point(q.lines[1],q.lines[3]),q.lines[3]))||
                        (Line.inLine(Line.point(q.lines[0],q.lines[2]),q.lines[0])&&Line.inLine(Line.point(q.lines[0],q.lines[2]),q.lines[2])))
                        return false;
                else return true;
    }
    public static boolean judgeDiamond(quadrilateral q){//判断菱形
        if(q.lines[0].length==q.lines[1].length&&q.b)return true;
        else return false;
    }
    public static boolean judgeRectangle(quadrilateral q){//判断矩形
        if(q.b&&Line.vertical(q.lines[0],q.lines[1]))return true;
        else return false;
    }
    public static boolean judgeSquare(quadrilateral q){//判断正方形
        if(Judge.judgeDiamond(q)&&Judge.judgeRectangle(q))return true;//又是菱形又是矩形
        else return false;
    }
    public static boolean concave(Line l1,Line l2,Line l3,Line l4){//判断是否为凸四边形
        Line l5=new Line(l1.endPoint1,l3.endPoint1);
        Line l6=new Line(l4.endPoint1,l2.endPoint1);
        triangle t1=new triangle(l2,l3,l6);
        triangle t2=new triangle(l3,l4,l5);
        l6=new Line(l2.endPoint1,l4.endPoint1);
        l5=new Line(l3.endPoint1,l1.endPoint1);
        triangle t3=new triangle(l1,l6,l4);
        triangle t4=new triangle(l1,l2,l5);
        return (triangle.inTheTriangle(l1.endPoint1,t1)||triangle.inTheTriangle(l2.endPoint1,t2)||triangle.inTheTriangle(l3.endPoint1,t3)||triangle.inTheTriangle(l4.endPoint1,t4));
    }
    public static boolean collinear(Dot d1,Dot d2,Dot d3,Dot d4){//判断四点共线
        Line l1=new Line(d1,d2);Line l2=new Line(d2,d3);Line l3=new Line(d3,d4);
        return (l1.slop==l2.slop&&l1.slop==l3.slop);
    }
    public static triangle correctTriangle(Dot d1,Dot d2,Dot d3,Dot d4){//先判断是否构成三角形四边形,再判断输入
        Line l1=new Line(d1,d2);Line l2=new Line(d2,d3);Line l3=new Line(d3,d4);Line l4=new Line(d4,d1);
        Line l5=new Line(d1,d3);Line l6=new Line(d4,d2);
        triangle t1=new triangle(l2,l3,l6);
        triangle t2=new triangle(l3,l4,l5);
        l6=new Line(d2,d4);
        l5=new Line(d3,d1);
        triangle t3=new triangle(l1,l6,l4);
        triangle t4=new triangle(l1,l2,l5);
        triangle t=new triangle();
        quadrilateral q1=new quadrilateral(l1,l2,l3,l4);
        int flag1=0,flag2=0,flag3=0,flag4=0;
        if(Judge.collinear(d1,d2,d3,d4)){//四点共线,非三角形非四边形
            T=false;Q=false;
        }
        if(triangle.onTheTriangle(d1,t1)) flag1++;
        else if(triangle.onTheTriangle(d2,t2)) flag2++;
        else if(triangle.onTheTriangle(d3,t3)) flag3++;
        else if(triangle.onTheTriangle(d4,t4)) flag4++;
        if(flag1==1||flag2==1||flag3==1||flag4==1){//构成三角形
            T=true;
            if(flag1==1) {
                if(Line.inLine(d1, l6)||(d1.x==l3.endPoint1.x&&d1.y==l3.endPoint1.y)){//判断点是否在相邻点构成的线上
                    C=true;t=t1;
                }
            }
            if(flag2==1) {
                if(Line.inLine(d2, l5)||(d2.x==l4.endPoint1.x&&d2.y==l4.endPoint1.y)){
                    C=true;t=t2;
                }
            }
            if(flag3==1) {
                if(Line.inLine(d3, l6)||(d3.x==l1.endPoint1.x&&d3.y==l1.endPoint1.y)){
                    C=true;t=t3;
                }
            }
            if(flag4==1) {
                if(Line.inLine(d4, l5)||(d4.x==l2.endPoint1.x&&d4.y==l2.endPoint1.y)){
                    C=true;t=t4;
                }
            }
        }else{//构成四边形
            if(Judge.judgeQuadrilateral(q1)) Q=true;
        }
        return t;
    }
    public static boolean LineCoincideWithTriangle(Line l,triangle t){//判断线是否与三角形边重合
        int flag=0;
        if(Line.satisfy(t.side[0],l))flag++;
        if(Line.satisfy(t.side[1],l))flag++;
        if(Line.satisfy(t.side[2],l))flag++;
        return flag==1;
    }
    public static boolean LineCoincideWithQuadrilateral(Line l,quadrilateral q){//判断线是否与四边形边重合
        int flag=0;
        if(Line.satisfy(q.lines[0],l))flag++;
        if(Line.satisfy(q.lines[1],l))flag++;
        if(Line.satisfy(q.lines[2],l))flag++;
        if(Line.satisfy(q.lines[3],l))flag++;
        return flag==1;
    }
}
class Dot {
    public double x;
    public double y;
    public static int dotNum = 0;
    public Dot() {
        dotNum++;
    }
    public Dot(String s, int n) {//获取第n个点的坐标
        dotNum++;
        if(s.charAt(s.length()-1)==' ')
        s += "0,0 0,0 0,0 0,0 0,0 0,0";//防止创建点对象时分割超出temp边界
        else  s += " 0,0 0,0 0,0 0,0 0,0 0,0";
        String[] temp = s.split(" ");
        String[] num = temp[n - 1].split(",");
        x = Double.parseDouble(num[0]);
        y = Double.parseDouble(num[1]);
    }
    public static double distance(Dot d1, Dot d2) {//任意两个点之间的距离
        double dis = Math.sqrt((d1.x - d2.x) * (d1.x - d2.x) + (d1.y - d2.y) * (d1.y - d2.y));
        return dis;
    }
}

作业四,我创建了一个多边形的父类,然后三角形和四边形都继承这个多边形,多边形里面保存多边形的每一条边,判断不符合要求的输入:z 不与xy都相邻,如z x y s、x z s y、x s z y我的做法是把结果一个一个列出来,但是写题过程中有个测试点一直过不了,之后才发现有种情况没有考虑到就是四边形对d1点和d3点重合构成的三角形也是符和输入条件的。判断四个点是否构成四边形只需要判断相邻边相交,不相邻边不相交即可。判断凹凸四边形可以利用三角形里写的inTheTriangle方法来判断其中一个点是否在另外三个点构成的三角形内如果在的话就是凹四边形,否则是凸四边形

在进行四边形分割我也是列出了所有的情况,大致分为四种,分割成一个三角形一个多边形的(不过四边形顶点),分割成一个三角形一个多边形的(过四边形顶点),分割为两个三角形的,分割为两个四边形的。在每种情况下我都会记录下分割产生的交点和与分割线相交的边,这样方便我之后求面积,如果是分割中有三角形就new一个三角形对象,三角形的三条边分别是两个分割交线和两个分割交点构成的线 ,这样就可以直接得出三角形的面积,分割产生的另一部分的面积就不用再计算直接用四边形面积减少三角形面积即可。分割成两个四边形的情况也是同理,求出其中一个四边形面积另一个四边形面积直接用大的四边形面积减去小四边形面积就行。

UML类图

这个类图是我进行了一些改进之后的,增加了polygon父类但此时的父类仅仅是能够计算多边形面积和周长,实际上还没起到什么作用,要到作业五我的父类才会起到真正的用处。

  SourceMonitor代码分析

看图就知道代码的圈复杂度很高,我思考了一下是我很多地方把各种要考虑的情况一一列出来了这才导致多加了很多的条件判断,改成循环的话能够减少很多圈复杂度。

 

作业5.1题目,点击此处展开
/*用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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*/
作业5.1代码,点击此处展开
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String s=sc.nextLine();
        String regx="[1-5]:";
        if(!s.substring(0,2).matches(regx)){
            System.out.println("Wrong Format");
            System.exit(0);
        }
        String s0=s.substring(2);
        Judge j=new Judge(s0);
        Dot d1=new Dot(s0,1);Dot d2=new Dot(s0,2);Dot d3=new Dot(s0,3);Dot d4=new Dot(s0,4);Dot d5=new Dot(s0,5);
        Dot d6=new Dot(s0,6);Dot d7=new Dot(s0,7);Line l0=new Line(d1,d2);
        if(s.substring(0,2).equals("1:")){
            Judge j1=new Judge(s0,5);
            pentagon p1=new pentagon(d1,d2,d3,d4,d5);
            if(p1.isPolygon(p1)) System.out.println("true");
            else System.out.println("false");
        }
        else if(s.substring(0,2).equals("2:")){
            Judge j1=new Judge(s0,5);
            Line l1=new Line(d1,d2);Line l2=new Line(d2,d3);Line l3=new Line(d3,d4);Line l4=new Line(d4,d5);Line l5=new Line(d5,d1);
            pentagon p1=new pentagon(d1,d2,d3,d4,d5);
            if(!p1.isPolygon(p1)){
                System.out.println("not a pentagon");
            }else {
                if (p1.isConcave(d1,d2,d3,d4,d5)) System.out.println("false");
                else {
                    System.out.print("true ");myPrint(p1.getPerimeter(p1));System.out.print(" ");myPrint(p1.getArea(p1));
                }
            }
        }
        else{
            Judge j2=new Judge(s0,7);
            Line.epCoincide(new Line(d1,d2));
            triangle.formTriangle(d3,d4,d5,d6,d7);
            quadrilateral.formQuadrilateral(d3,d4,d5,d6,d7);
            if(triangle.T)//如果构成三角形
            {
                triangle t=triangle.formTriangle(d3,d4,d5,d6,d7);
                t.LineCoincideWithPolygon(l0,t);
                t.divisionPolygon(l0,t);
            }
            else if(quadrilateral.Q){//构成四边形
                quadrilateral q=quadrilateral.formQuadrilateral(d3,d4,d5,d6,d7);
                q.LineCoincideWithPolygon(l0,q);
                q.divisionPolygon(l0,q);
            }
            else{
                pentagon p=new pentagon(d3,d4,d5,d6,d7);
                p.LineCoincideWithPolygon(l0,p);
                p.divisionPolygon(l0,p);
            }
        }

    }
    public static void myPrint(double data){
        DecimalFormat df = new DecimalFormat("0.0##");
        df.setRoundingMode(RoundingMode.HALF_UP);
        System.out.print(df.format(data));
    }

}
class Judge {
    public static boolean T = false;
    public static boolean Q = false;
    public static boolean P=false;
    public static boolean C = false;//是否正确输入

    public Judge(String s) {
        String regx = "[+|-]?(0|[1-9][0-9]*)(\\.\\d+)?,[+|-]?(0|[1-9][0-9]*)(\\.\\d+)?( [+|-]?(0|[1-9][0-9]*)(\\.\\d+)?,[+|-]?(0|[1-9][0-9]*)(\\.\\d+)?)+";
        if (!s.matches(regx))
        {
            System.out.println("Wrong Format");
            System.exit(0);
        }
    }
    public Judge(String s, int n) {//判断点数量格式是否符合要求
        int flag_dh = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ',') flag_dh++;
        }
        if (flag_dh != n) {
            System.out.println("wrong number of points");
            System.exit(0);
        }
    }
    
}
class Dot {
        public double x;
        public double y;
        public static int dotNum = 0;
        public Dot() {
            dotNum++;
        }
        public Dot(String s, int n) {//获取第n个点的坐标
            dotNum++;
            if(s.charAt(s.length()-1)==' ')
                s += "0,0 0,0 0,0 0,0 0,0 0,0";//防止创建点对象时分割超出temp边界
            else  s += " 0,0 0,0 0,0 0,0 0,0 0,0";
            String[] temp = s.split(" ");
            String[] num = temp[n - 1].split(",");
            x = Double.parseDouble(num[0]);
            y = Double.parseDouble(num[1]);
        }
        public static double distance(Dot d1,Dot d2) {//任意两个点之间的距离
            return Math.sqrt((d1.x - d2.x) * (d1.x - d2.x) + (d1.y - d2.y) * (d1.y - d2.y));
        }
        public static boolean coincidence(Dot d1, Dot d2){//判断两点是否重合
            return (d1.x == d2.x && d1.y == d2.y);
        }
    }
class Line {
    public double slop;
    public double length;
    public Dot endPoint1 = new Dot();
    public Dot endPoint2 = new Dot();
    public double a;public double b;public double c;
    public Line() {
    }
    public Line(Dot d1, Dot d2) {
        length = Dot.distance(d1, d2);
        endPoint1.x = d1.x;endPoint1.y = d1.y;endPoint2.x = d2.x;endPoint2.y = d2.y;
        a = d2.y - d1.y;b = d1.x - d2.x;c = d1.x * (-a) + d1.y * (-b);
        if (d2.x == d1.x) slop = 99999999;
        else slop = (d2.y - d1.y) / (d2.x - d1.x);
    }
    public static double distance(Dot d, Line l) {//计算点到直线的距离
        return Math.abs(l.a * d.x + l.b * d.y + l.c) / Math.sqrt(l.a * l.a + l.b * l.b);
    }
    public static Dot point(Line l1, Line l2) {//求两条直线的交点
        Dot p = new Dot();
        p.x = (l1.b * l2.c - l2.b * l1.c) / (l2.b * l1.a - l1.b * l2.a);
        p.y = (l1.a * l2.c - l2.a * l1.c) / (l2.a * l1.b - l1.a * l2.b);
        return p;
    }
    public static boolean inLine(Dot p, Line l) {//判断点是否在线内
        return (Dot.distance(p, l.endPoint1) + Dot.distance(p, l.endPoint2) <= l.length + 0.000001||
                (p.x==l.endPoint1.x&&p.y==l.endPoint1.y)||(p.x==l.endPoint2.x&&p.y==l.endPoint2.y));
    }
    public static boolean satisfy(Line l1, Line l2){//判断两条线是否重合
        return (l1.slop==l2.slop&&distance(l1.endPoint1,l2)==0);
    }
    public static boolean vertical(Line l1, Line l2){//判断两条线是否垂直
        return l1.length == Line.distance(l1.endPoint1, l2);
    }
    public static boolean lineIntersect(Line l1, Line l2) {//判断两条线没有延长也相交,
        return (Line.inLine(Line.point(l1, l2), l1) && Line.inLine(Line.point(l1, l2), l2));
    }
    public static void epCoincide(Line l) {//判断构成线的两点是否重合
        if (l.endPoint1.x == l.endPoint2.x && l.endPoint1.y == l.endPoint2.y) {
            System.out.println("points coincide");
            System.exit(0);
        }
    }
}
class triangle extends polygon{
    public static boolean T=false;
    public triangle(Dot d1,Dot d2,Dot d3){
        super(d1,d2,d3);
    }
    public static triangle formTriangle(Dot...dots){//5个点构成三角形
        for(int i=0;i<dots.length;i++){//5个点
            triangle t=new triangle(dots[(i+2)%dots.length],dots[(i+3)%dots.length],dots[(i+4)%dots.length]);
            if(t.isPolygon(t)) {
                 if (t.onThePolygon(dots[i], t) && t.onThePolygon(dots[(i + 1)% dots.length], t)) {T = true;return t;}
            }
        }
        return null;
    }
}
class quadrilateral extends polygon{
    public static boolean Q=false;
    public quadrilateral(Dot d1,Dot d2,Dot d3,Dot d4){
        super(d1,d2,d3,d4);
    }
    public quadrilateral(){}
        public static quadrilateral formQuadrilateral(Dot...dots){//5个点构成四边形,并判断输入
            for(int i=0;i<dots.length;i++){
                quadrilateral q=new quadrilateral(dots[(i+1)% dots.length],dots[(i+2)% dots.length],dots[(i+3)% dots.length],dots[(i+4)% dots.length]);
                if(q.isPolygon(q)){
                    if((q.onThePolygon(dots[i],q)&&Line.inLine(dots[i],q.side[q.arrLength-1]))||Dot.coincidence(dots[i],dots[(i+2)% dots.length])||Dot.coincidence(dots[i],dots[(i+3)% dots.length])){Q=true;return q;}
                }
            }
            return null;
        }
    }
class pentagon extends polygon {
    public pentagon(Dot d1, Dot d2, Dot d3, Dot d4, Dot d5){
        super(d1,d2,d3,d4,d5);
    }
    public  boolean isConcave(Dot...dots){//判断是否为凹五边形
        for(int i=0;i<5;i++){
            quadrilateral q=new quadrilateral(dots[(i+1)% dots.length],dots[(i+2)% dots.length],dots[(i+3)% dots.length],dots[(i+4)% dots.length]);
            if(q.inThePolygon(dots[i],q))return true;
        }
        return false;
    }
}
class polygon {
    private double s;
    private double perimeter;
    public int arrLength;
    public  Dot[] dots=new Dot[5];//构成多边形的点
    public Line[] side=new Line[5];//多边形的边
    public polygon(){}
    public polygon(Dot...dots){//多边形由线构成
        double temp=0;
        arrLength= dots.length;
        for(int i=0;i<dots.length;i++){
            side[i]=new Line(dots[i],dots[(i+1)%dots.length]);
            this.dots[i]=dots[i];
            perimeter+=new Line(dots[i],dots[(i+1)%dots.length]).length;
            temp+=(dots[i].x*dots[(i+1)%dots.length].y-dots[i].y*dots[(i+1)% dots.length].x);
        }
        s=0.5*Math.abs(temp);
    }
    public  double getArea(polygon p){
        return p.s;
    }
    public  double getPerimeter(polygon p){
        return p.perimeter;
    }
    public  boolean isPolygon(polygon p){//判断n个点能构成n边形
        for (int i = 0; i < p.arrLength; i++) {
            for (int j = i; j < p.arrLength-1; j++) {
                if (Line.satisfy(p.side[i], p.side[j + 1]))//两条线重合
                    return false;
            }
        }
        if(p.arrLength>3) {
            for (int i = 0; i < p.arrLength-2; i++) {
                if(p.arrLength==4){
                if (Line.lineIntersect(p.side[i], p.side[(i + 2) % p.arrLength]))
                    return false;
                }
                else if(p.arrLength==5){
                    if(Line.lineIntersect(p.side[i], p.side[(i + 3) % p.arrLength])||Line.lineIntersect(p.side[i], p.side[(i + 2) % p.arrLength]))
                        return false;
                }
            }
        }
        return true;
    }
    public  boolean onThePolygon(Dot d,polygon p){//判断点是否在多边形边上
        for(int i=0;i<p.arrLength;i++){
            if(Line.inLine(d,p.side[i])) return true;
        }
        return false;
    }
    public boolean inThePolygon(Dot d,polygon p){//判断点在多边形内
        double[] temp = new double[p.arrLength];
        Dot n1=new Dot();
        Dot n2=new Dot();
        int flag1=0,flag2=0;
        for(int i=0;i<p.arrLength;i++){
            n1.x=p.dots[i].x-p.dots[(i+1)%p.arrLength].x;
            n1.y=p.dots[i].y-p.dots[(i+1)%p.arrLength].y;
            n2.x=p.dots[i].x-d.x;
            n2.y=p.dots[i].y-d.y;
            if(n1.x*n2.y-n1.y*n2.x>0)flag1++;
            else if(n1.x*n2.y-n1.y*n2.x<0)flag2++;
        }
        return flag1 == p.arrLength || flag2 == p.arrLength;
    }
    public void LineCoincideWithPolygon(Line l,polygon p){//直线与多边形重合
        for(int i=0;i<p.arrLength;i++){
            if(Line.satisfy(l,p.side[i])){
                System.out.println("The line is coincide with one of the lines");
                System.exit(0);
            }
        }
    }
    public void divisionPolygon(Line l,polygon p){
        Dot[] temp=new Dot[10];
        Dot[] d=new Dot[4];//记录交点
        int num=0,flag=0;
        for(int i=0;i<p.arrLength;i++){
            if(p.dots[i].x*l.a+p.dots[i].y*l.b+l.c>0)
                temp[num++]=p.dots[i];
            if(Line.inLine(Line.point(l,new Line(p.dots[i],p.dots[(i+1)%p.arrLength])),new Line(p.dots[i],p.dots[(i+1)%p.arrLength]))){
                if(flag==0||!Dot.coincidence(Line.point(l,p.side[i]),d[flag-1])) {
                    d[flag++]=Line.point(l,new Line(p.dots[i],p.dots[(i+1)%p.arrLength]));
                    temp[num++]=Line.point(l,new Line(p.dots[i],p.dots[(i+1)%p.arrLength]));
                }
            }
        }
        if(flag==0) System.out.println("0");
        else if(flag==1) System.out.println("1");
        else{
            Dot[] Temp=new Dot[num];
            System.arraycopy(temp, 0, Temp, 0, num);
            polygon p0=new polygon(Temp);
            double s1=p0.s;double s2=p.s-s1;
             if(s1>s2){
                double n=s1;
                s1=s2;
                s2=n;
            }
            System.out.print("2 ");Main.myPrint(s1);System.out.print(" ");Main.myPrint(s2);
        }
    }
}

 

相对于作业四我增加的polygon起到了实质的作用,我通过分析找到了一些多边形通用的方法通过查阅资料找到了一个多边形求面积的通解方法例如三角形面S三角形=0.5∗((x1∗y2+x2∗y3+x3∗y1)−(y1∗x2+y2∗x3+y3∗x1))公式如下:

  求多边形面积以此类推,这个公式为我后来在父类中进行面积分割也起到了关键作用,在构建polygon父类的构造方法时我并不知道构造的是几边形,所以不知道多边形的dots数组和lines数组应该初始化存多少个点多少个边,这种情况下可以采用可变参数的做法来接收不确定参数个数的参数这里我是通过点来构造的所以父类构造多边形方法的形参写的是polygon(Dot...dots)这样可以通过子类构造方法传递的参数来接收对应的参数个数,例如三角形构造方法public triangle(Dot d1,Dot d2,Dot d3){super(d1,d2,d3);},传递了三个点,调用父类构造方法接收了三个参数,四边形的构造方法public quadrilateral(Dot d1,Dot d2,Dot d3,Dot d4){ super(d1,d2,d3,d4);},传递了四个点,调用父类构造方法接收了四个参数,五边形以此类推,这里可以看出可变数组的厉害了,可以接收多个参数。

  这仅仅是我的构造方法,父类的作用不止于此,我在父类中添加了一些具有多边形共性的方法,在构造方法中使用的鞋带定理已经把多边形面积求出,而鞋带定理的使用是要知道多边形每个点的坐标就能求出对应的面积,因此在分割多边形求面积的时候我把之前的分割四边形,和现在的分割五边形转化为求分割交点的共性问题,只要我知道了分割的交点和分割线其中一侧的点,这几个点就能构成一个多边形,求得这个多边形面积另外一个多边形的面积也就出来了,这样我也不用在分割四边形和分割五边形中各写一个方法来分割了,直接在父类使用以上做法进行分割,这种做法非常符合继承的特点,因为除了题目要求的分割四边形,分割五边形外,我还可以分割六边形,七边形,八边形等等,真正的做到了分割多边形。

  父类polygon中我还添加了判断n个点构成n边形的方法之前的代码也是分别在judge类里面判断的这次直接拿到父类判断,在父类中只需要一个判断方法就可以判断三角形,四边形,五边形,n边形了。还增加了判断点是否在多边形上,判断点是否在多边形内,判断直线与多边形重合等等含有多边形共性的方法。

UML类图

从类图可以看出我的父类中有很多子类共性的方法,子类的方法个数和作业4.2的相比少了很多结构也更加清晰了,这个时候的父类真正的发挥了他的作用

SourceMonitor代码分析

额...圈复杂度还是很高我又分析了一下,因为我看了一下我的子类的SourceMonitor分析图圈复杂度都很低,所以导致圈复杂度这么高的原因是我的Main方法中使用了太多的if else嵌套了。

 

作业5.2,点击此处展开
 /*用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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*/
作业5.2代码,点击此处展开
 import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String s=sc.nextLine();
        String regx="[1-6]:";
        if(!s.substring(0,2).matches(regx)){
            System.out.println("Wrong Format");
            System.exit(0);
        }
        String s0=s.substring(2);
        Judge j=new Judge(s0);
        Dot d1=new Dot(s0,1);Dot d2=new Dot(s0,2);Dot d3=new Dot(s0,3);Dot d4=new Dot(s0,4);Dot d5=new Dot(s0,5);
        Dot d6=new Dot(s0,6);Dot d7=new Dot(s0,7);Dot d8=new Dot(s0,8);Dot d9=new Dot(s0,9);Dot d10=new Dot(s0,10);
        Line l0=new Line(d1,d2);
        if(s.substring(0,2).equals("4:")){
            Judge j1=new Judge(s0,10);
            polygon p1=new polygon();
            polygon p2=new polygon();
            triangle.formTriangle(d1,d2,d3,d4,d5);
            quadrilateral.formQuadrilateral(d1,d2,d3,d4,d5);
            if(triangle.T){
                p1=triangle.formTriangle(d1,d2,d3,d4,d5);
                triangle.T=false;
            }
            else if(quadrilateral.Q) {
                p1=quadrilateral.formQuadrilateral(d1,d2,d3,d4,d5);
                quadrilateral.Q=false;
            }
            else p1=new polygon(d1,d2,d3,d4,d5);
            triangle.formTriangle(d6,d7,d8,d9,d10);
            quadrilateral.formQuadrilateral(d6,d7,d8,d9,d10);
            if(triangle.T){
                p2=triangle.formTriangle(d6,d7,d8,d9,d10);
            }
            else if (quadrilateral.Q){
                p2=quadrilateral.formQuadrilateral(d6,d7,d8,d9,d10);
            }
            else p2=new polygon(d6,d7,d8,d9,d10);
            p1.relationship(p1,p2);
        }
        else if(s.substring(0,2).equals("5:")) {
            Judge j1=new Judge(s0,10);
//            if(s.matches(""))
            polygon p1=new polygon();
            polygon p2=new polygon();
            triangle.formTriangle(d1,d2,d3,d4,d5);
            quadrilateral.formQuadrilateral(d1,d2,d3,d4,d5);
            if(triangle.T){
                p1=triangle.formTriangle(d1,d2,d3,d4,d5);
                triangle.T=false;
            }
            else if(quadrilateral.Q) {
                p1=quadrilateral.formQuadrilateral(d1,d2,d3,d4,d5);
                quadrilateral.Q=false;
            }
            else p1=new polygon(d1,d2,d3,d4,d5);
            triangle.formTriangle(d6,d7,d8,d9,d10);
            quadrilateral.formQuadrilateral(d6,d7,d8,d9,d10);
            if(triangle.T){
                p2=triangle.formTriangle(d6,d7,d8,d9,d10);
            }
            else if (quadrilateral.Q){
                p2=quadrilateral.formQuadrilateral(d6,d7,d8,d9,d10);
            }
            else p2=new polygon(d6,d7,d8,d9,d10);
            myPrint(p1.crossArea(p1,p2));
        }
        else{
            Judge j2=new Judge(s0,6);
            triangle t=triangle.formTriangle(d2,d3,d4,d5,d6);
            quadrilateral q=quadrilateral.formQuadrilateral(d2,d3,d4,d5,d6);
            if(triangle.T){
                if(t.onThePolygon(d1,t)) System.out.println("on the triangle");
                else if(t.inThePolygon(d1,t))
                    System.out.println("in the triangle");
                else System.out.println("outof the triangle");
            } else if (quadrilateral.Q) {
                if(q.onThePolygon(d1,q)) System.out.println("on the quadrilateral");
                else if(q.inThePolygon(d1,q))
                    System.out.println("in the quadrilateral");
                else System.out.println("outof the quadrilateral");
            }
            else{
                pentagon p=new pentagon(d2,d3,d4,d5,d6);
                if(p.onThePolygon(d1,p)) System.out.println("on the pentagon");
                else if(p.inThePolygon(d1,p)) System.out.println("in the pentagon");
                else System.out.println("outof the pentagon");
            }
        }
    }
    public static void myPrint(double data){
        DecimalFormat df = new DecimalFormat("0.0##");
        df.setRoundingMode(RoundingMode.HALF_UP);
        System.out.print(df.format(data));
    }
}
class Judge {
    public static int index;
    public Judge(){}
    public Judge(String s) {
        String regx = "[+|-]?(0|[1-9][0-9]*)(\\.\\d+)?,[+|-]?(0|[1-9][0-9]*)(\\.\\d+)?( [+|-]?(0|[1-9][0-9]*)(\\.\\d+)?,[+|-]?(0|[1-9][0-9]*)(\\.\\d+)?)+";
        if (!s.matches(regx))
        {
            System.out.println("Wrong Format");
            System.exit(0);
        }
    }
    public Judge(String s, int n) {//判断点数量格式是否符合要求
        int flag_dh = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ',') flag_dh++;
        }
        if (flag_dh != n) {
            System.out.println("wrong number of points");
            System.exit(0);
        }
    }
    public boolean polygonCoincidence(polygon p1,polygon p2){//判断多边形完全重合
        if(p1.arrLength==p2.arrLength) {
            int flag=0;
            for (int i = 0; i < p1.arrLength; i++) {
                for (int j = 0; j < p2.arrLength; j++) {
                    if(Line.lineSegmentCoincidence(p1.side[i],p2.side[j]))flag++;//记录重合的边的数量
                }
            }
            return flag == p1.arrLength;
        }
        return false;
    }
    public boolean polyContain(polygon p1,polygon p2) {//判断多边形包含被包含关系
        int flag = 0;
        for (int i = 0; i < p1.arrLength; i++) {
            if (p1.inThePolygon(p1.dots[i], p2) || p1.onThePolygon(p1.dots[i], p2)) flag++;
        }
        return (flag == p1.arrLength&&!polygonCoincidence(p1,p2));
    }
    public boolean polygonSeparate(polygon p1,polygon p2){//判断多边形分离
        int flag1=0,flag2=0;
        for(int i=0;i<p1.arrLength;i++){
            if(p1.inThePolygon(p1.dots[i],p2)||p1.onThePolygon(p1.dots[i],p2))flag1++;
        }
        for(int i=0;i<p2.arrLength;i++){
            if(p2.inThePolygon(p2.dots[i],p1)||p2.onThePolygon(p2.dots[i],p1))flag2++;
        }
        return flag1==0&&flag2==0;
    }
    public boolean polygonConnect(polygon p1,polygon p2){//判断多边形连接
        int flag1=0,flag2=0,flag3=0,index1=0,index2=0;
        for(int i=0;i<p1.arrLength;i++){
            if(p1.onThePolygon(p1.dots[i],p2)){flag1++;index1=i;}
            if(p1.LineCoincideWithPolygon2(p1.side[i],p2)){flag2++;index2=i;}
            if(p1.inThePolygon(p1.dots[i],p2))flag3++;
        }
        for(int i=0;i<p2.arrLength;i++){
            if(p2.inThePolygon(p2.dots[i],p1 ))flag3++;
        }
        if(flag1==1&&flag2==2&&flag3==0){
            if(Line.inLine(p1.dots[index1],p2.side[Judge.index]))return true;
        }
        return (((flag1==1&&flag2==0)||flag1==0&&flag2==1)&&flag3==0);
    }
    public boolean isConnected(polygon p,polygon p2) {
        for (int i = 0; i < p.arrLength; i++) {
            for (double j = 0; j < 1; j += 0.20) {
                Dot point = new Dot();
                point.x=p.dots[i].x - (p.dots[i].x - p.dots[(i + 1) % p.arrLength].x) * j;
                point.y=p.dots[i].y - (p.dots[i].y - p.dots[(i + 1) % p.arrLength].y) * j;
                if (p.inThePolygon(point,p2)) return false;
            }
        }
        return true;
    }
}
class Dot {
        public double x;
        public double y;
        public static int dotNum = 0;
        public Dot() {
            dotNum++;
        }
        public Dot(String s, int n) {//获取第n个点的坐标
            dotNum++;
            if(s.charAt(s.length()-1)==' ')
                s += "0,0 0,0 0,0 0,0 0,0 0,0";//防止创建点对象时分割超出temp边界
            else  s += " 0,0 0,0 0,0 0,0 0,0 0,0";
            String[] temp = s.split(" ");
            String[] num = temp[n - 1].split(",");
            x = Double.parseDouble(num[0]);
            y = Double.parseDouble(num[1]);
        }
        public static double distance(Dot d1,Dot d2) {//任意两个点之间的距离
            return Math.sqrt((d1.x - d2.x) * (d1.x - d2.x) + (d1.y - d2.y) * (d1.y - d2.y));
        }
        public static boolean coincidence(Dot d1, Dot d2){//判断两点是否重合
            return (d1.x == d2.x && d1.y == d2.y);
        }
    }
class Line {
    public double slop;
    public double length;
    public Dot endPoint1 = new Dot();
    public Dot endPoint2 = new Dot();
    public double a;public double b;public double c;
    public Line() {
    }
    public Line(Dot d1, Dot d2) {
        length = Dot.distance(d1, d2);
        endPoint1.x = d1.x;endPoint1.y = d1.y;endPoint2.x = d2.x;endPoint2.y = d2.y;
        a = d2.y - d1.y;b = d1.x - d2.x;c = d1.x * (-a) + d1.y * (-b);
        if (d2.x == d1.x) slop = 99999999;
        else slop = (d2.y - d1.y) / (d2.x - d1.x);
    }
    public static double distance(Dot d, Line l) {//计算点到直线的距离
        return Math.abs(l.a * d.x + l.b * d.y + l.c) / Math.sqrt(l.a * l.a + l.b * l.b);
    }
    public static Dot point(Line l1, Line l2) {//求两条直线的交点
        Dot p = new Dot();
        p.x = (l1.b * l2.c - l2.b * l1.c) / (l2.b * l1.a - l1.b * l2.a);
        p.y = (l1.a * l2.c - l2.a * l1.c) / (l2.a * l1.b - l1.a * l2.b);
        return p;
    }
    public static boolean inLine(Dot p, Line l) {//判断点是否在线内
        return (Dot.distance(p, l.endPoint1) + Dot.distance(p, l.endPoint2) <= l.length + 0.000001||
                (p.x==l.endPoint1.x&&p.y==l.endPoint1.y)||(p.x==l.endPoint2.x&&p.y==l.endPoint2.y));
    }
    public static boolean satisfy(Line l1, Line l2){//判断两条线是否重合
        return (l1.slop==l2.slop&&distance(l1.endPoint1,l2)==0);
    }
    public static boolean lineSegmentCoincidence(Line l1,Line l2) {//判断线段重合
        return ((Dot.coincidence(l1.endPoint1, l2.endPoint1) && Dot.coincidence(l1.endPoint2, l2.endPoint2)) || (Dot.coincidence(l1.endPoint2, l2.endPoint1) && Dot.coincidence(l1.endPoint1, l2.endPoint2)));
    }
    public static boolean vertical(Line l1, Line l2){//判断两条线是否垂直
        return l1.length == Line.distance(l1.endPoint1, l2);
    }
    public static boolean lineIntersect(Line l1, Line l2) {//判断两条线没有延长也相交,
        return (Line.inLine(Line.point(l1, l2), l1) && Line.inLine(Line.point(l1, l2), l2));
    }
    public static void epCoincide(Line l) {//判断构成线的两点是否重合
        if (l.endPoint1.x == l.endPoint2.x && l.endPoint1.y == l.endPoint2.y) {
            System.out.println("points coincide");
            System.exit(0);
        }
    }
}
class triangle extends polygon{
    public static boolean T=false;
    public triangle(Dot d1,Dot d2,Dot d3){
        super(d1,d2,d3);
    }
    public static triangle formTriangle(Dot...dots){//5个点构成三角形
        for(int i=0;i<dots.length;i++){//5个点
            triangle t1=new triangle(dots[(i+2)%dots.length],dots[(i+3)%dots.length],dots[(i+4)%dots.length]);
            if(t1.isPolygon(t1)) {
                 if (t1.onThePolygon(dots[i], t1) && t1.onThePolygon(dots[(i + 1)% dots.length], t1)) {T = true;return t1;}
            }
            triangle t2=new triangle(dots[(i+1)%dots.length],dots[(i+3)%dots.length],dots[(i+4)%dots.length]);
            if(t2.isPolygon(t2)){
                if(t2.onThePolygon(dots[i],t2)&&t2.onThePolygon(dots[(i+2)%dots.length],t2)){T = true;return t2;}
            }
        }
        return null;
    }
}
class quadrilateral extends polygon{
    public static boolean Q=false;
    public quadrilateral(Dot d1,Dot d2,Dot d3,Dot d4){
        super(d1,d2,d3,d4);
    }
    public quadrilateral(){}

        public static quadrilateral formQuadrilateral(Dot...dots){//5个点构成四边形,并判断输入
            for(int i=0;i<dots.length;i++){
                quadrilateral q=new quadrilateral(dots[(i+1)% dots.length],dots[(i+2)% dots.length],dots[(i+3)% dots.length],dots[(i+4)% dots.length]);
                if(q.isPolygon(q)){
                    if((q.onThePolygon(dots[i],q)&&Line.inLine(dots[i],q.side[q.arrLength-1]))||Dot.coincidence(dots[i],dots[(i+2)% dots.length])||Dot.coincidence(dots[i],dots[(i+3)% dots.length])){Q=true;return q;}
                }
            }
            return null;
        }
    }
class pentagon extends polygon {
    public pentagon(Dot d1, Dot d2, Dot d3, Dot d4, Dot d5){
        super(d1,d2,d3,d4,d5);
    }
    public  boolean isConcave(Dot...dots){//判断是否为凹五边形
        for(int i=0;i<5;i++){
            quadrilateral q=new quadrilateral(dots[(i+1)% dots.length],dots[(i+2)% dots.length],dots[(i+3)% dots.length],dots[(i+4)% dots.length]);
            if(q.inThePolygon(dots[i],q))return true;
        }
        return false;
    }
}
class polygon {
    private double s;
    private double perimeter;
    public int arrLength;
    public  Dot[] dots=new Dot[5];//构成多边形的点
    public Line[] side=new Line[5];//多边形的边
    public polygon(){}
    public polygon(Dot...dots){//多边形由线构成
        double temp=0;
        arrLength= dots.length;
        for(int i=0;i<dots.length;i++){
            side[i]=new Line(dots[i],dots[(i+1)%dots.length]);
            this.dots[i]=dots[i];
            perimeter+=new Line(dots[i],dots[(i+1)%dots.length]).length;
            temp+=(dots[i].x*dots[(i+1)%dots.length].y-dots[i].y*dots[(i+1)% dots.length].x);
        }
        s=0.5*Math.abs(temp);
    }
    public  double getArea(polygon p){
        return p.s;
    }
    public  double getPerimeter(polygon p){
        return p.perimeter;
    }
    public  boolean isPolygon(polygon p){//判断n个点能构成n边形
        for (int i = 0; i < p.arrLength; i++) {
            for (int j = i; j < p.arrLength-1; j++) {
                if (Line.satisfy(p.side[i], p.side[j + 1]))//两条线重合
                    return false;
            }
        }
        if(p.arrLength>3) {
            for (int i = 0; i < p.arrLength-2; i++) {
                if(p.arrLength==4){
                if (Line.lineIntersect(p.side[i], p.side[(i + 2) % p.arrLength]))
                    return false;
                }
                else if(p.arrLength==5){
                    if(Line.lineIntersect(p.side[i], p.side[(i + 3) % p.arrLength])||Line.lineIntersect(p.side[i], p.side[(i + 2) % p.arrLength]))
                        return false;
                }
            }
        }
        return true;
    }
    public  boolean onThePolygon(Dot d,polygon p){//判断点是否在多边形边上
        for(int i=0;i<p.arrLength;i++){
            if(Line.inLine(d,p.side[i])) return true;
        }
        return false;
    }
    public void LineCoincideWithPolygon(Line l,polygon p){//直线与多边形重合,延长线也算
        for(int i=0;i<p.arrLength;i++){
            if(Line.satisfy(l,p.side[i])){
                System.out.println("The line is coincide with one of the lines");
                System.exit(0);
            }
        }
    }
    public boolean LineCoincideWithPolygon2(Line l,polygon p){//直线与多边形重合,延长线也算
        for(int i=0;i<p.arrLength;i++){
            if(Line.lineIntersect(l,p.side[i])){
                Judge.index=i;//记录相交的边
                return true;
            }
        }
        return false;
    }
    public void divisionPolygon(Line l,polygon p){//直线分割多边形面积
        Dot[] temp=new Dot[10];
        Dot[] d=new Dot[4];//记录交点
        int num=0,flag=0;
        for(int i=0;i<p.arrLength;i++){
            if(p.dots[i].x*l.a+p.dots[i].y*l.b+l.c>0)
                temp[num++]=p.dots[i];
            if(Line.inLine(Line.point(l,new Line(p.dots[i],p.dots[(i+1)%p.arrLength])),new Line(p.dots[i],p.dots[(i+1)%p.arrLength]))){
                if(flag==0||!Dot.coincidence(Line.point(l,p.side[i]),d[flag-1])) {
                    d[flag++]=Line.point(l,new Line(p.dots[i],p.dots[(i+1)%p.arrLength]));
                    temp[num++]=Line.point(l,new Line(p.dots[i],p.dots[(i+1)%p.arrLength]));
                }
            }
        }
        if(flag==0) System.out.println("0");
        else if(flag==1) System.out.println("1");
        else{
            Dot[] Temp=new Dot[num];
            System.arraycopy(temp, 0, Temp, 0, num);
            polygon p0=new polygon(Temp);
            double s1=p0.s;double s2=p.s-s1;
             if(s1>s2){
                double n=s1;
                s1=s2;
                s2=n;
            }
            System.out.print("2 ");Main.myPrint(s1);System.out.print(" ");Main.myPrint(s2);
        }
    }
    public boolean inThePolygon(Dot d,polygon p){//判断点在多边形内
        Dot n1=new Dot();
        Dot n2=new Dot();
        int flag1=0,flag2=0;
        for(int i=0;i<p.arrLength;i++){
            n1.x=p.dots[i].x-p.dots[(i+1)%p.arrLength].x;
            n1.y=p.dots[i].y-p.dots[(i+1)%p.arrLength].y;
            n2.x=p.dots[i].x-d.x;
            n2.y=p.dots[i].y-d.y;
            if(n1.x*n2.y-n1.y*n2.x>0)flag1++;
            else if(n1.x*n2.y-n1.y*n2.x<0)flag2++;
        }
        return (flag1 == p.arrLength || flag2 == p.arrLength);
    }
    public String polygonName(polygon p){
        String s;
        if(p.arrLength==3)s="triangle";
        else if(p.arrLength==4) s="quadrilateral";
        else s="pentagon";
        return s;
    }
    public void relationship(polygon p1,polygon p2){//判断两个多边形的关系
        Judge j=new Judge();
        if(j.polygonSeparate(p1,p2)) System.out.println("no overlapping area between the previous "+polygonName(p1)+" and the following "+polygonName(p2));//分离
        else if(j.polyContain(p1,p2)) System.out.println("the previous "+polygonName(p1)+" is inside the following "+polygonName(p2));//被包含
        else if(j.polyContain(p2,p1)) System.out.println("the previous "+polygonName(p1)+" contains the following "+polygonName(p2));//包含
        else if(j.polygonCoincidence(p1,p2)) System.out.println("the previous "+polygonName(p1)+" coincides with the following "+polygonName(p2));//重合
        else if(j.isConnected(p1,p2)) System.out.println("the previous "+polygonName(p1)+" is connected to the following "+polygonName(p2));
        else System.out.println("the previous "+polygonName(p1)+" is interlaced with the following "+polygonName(p2));
    }
    public double crossArea(polygon p1,polygon p2){
        Judge j=new Judge();
        if(j.polygonCoincidence(p1,p2)) return p1.s;
        else if(j.polyContain(p1,p2)) return p1.s;
        else if(j.polyContain(p2,p1)) return p2.s;
        return 4;
    }
}

  作业5.2同样延续作业5.1的设计方式,5.2需要判断多边形的位置关系,而判断位置关系的一些工具函数我全部放在了父类polygon中,多边形的位置关系有分离,连接,完全重合 ,被包含,交错和包含经过初步分析会发现交错的情况比较多也是当中最复杂的,所以我在这里取了个巧,就是先判断其它的五中情况然后剩下的情况就是多边形交错的情况了,这样一来避免了直接和判断交错打交道,省了很多麻烦。计算多边形分割面积的时候也可以先把简单的情况先判断计算出来,包含,被包含和重合的面积是最好计算的,剩下的就是计算多边形相交的情况。但是由于pta提交时间有限,所以我计算多边形相交的分割面积没有完全写完,最终得了96分。

UML类图

SourceMonitor代码分析

代码的圈复杂度和作业4.25.1的复杂度类似,还是之前分析的原因,Main方法中if else嵌套太多。

 

期中考试7.1题目,点击此处展开
 /*设计一个类表示平面直角坐标系上的点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)方法。*/
7.1代码,点击此处展开
 import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String color=new String();
        Point point1=new Point(sc.nextDouble(),sc.nextDouble());
        Point point2=new Point(sc.nextDouble(),sc.nextDouble());
        color=sc.next();
        if(judge(point1)||judge(point2)){
            System.out.println("Wrong Format");
        }
        else{
            Line l=new Line(point1,point2,color);
            l.display();
        }
    }
    public static boolean judge(Point point1){
        return ((point1.getX()<=0||point1.getX()>200)||(point1.getY()<=0||point1.getY()>200));
    }
}
class Point {
    private double x;
    private double y;

    Point(){

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

    public void setX(double x) {
        this.x = x;
    }
    public void setY(double y) {
        this.y = y;
    }
    void display(){
        System.out.print("(");print.myPrint(x);System.out.print(",");print.myPrint(y);System.out.println(")");
    }
}
class Line {
    private Point point1;
    private Point point2;
    private String color;
    Line(){

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

    public Point getPoint1() {
        return point1;
    }

    public Point getPoint2() {
        return point2;
    }

    public String getColor() {
        return color;
    }

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

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

    public void setColor(String color) {
        this.color = color;
    }
    public double getDistance(Point point1,Point point2){
        return Math.sqrt(Math.pow(point1.getX()-point2.getX(),2)+Math.pow(point1.getY()-point2.getY(),2));
    }
    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.print("The line's length is:");print.myPrint(getDistance(point1,point2));
        System.out.println();
    }
}
class print {
    public static void myPrint(double data){
        DecimalFormat df = new DecimalFormat("0.00");
        df.setRoundingMode(RoundingMode.HALF_UP);
        System.out.print(df.format(data));
    }
}

 

  期中考试的题目考察的是我们对于类图,继承,多态,抽象类的理解,题目给予我们类图按照规范的方法去构造类和方法,根据7.1的类图提示我们需要创建一个点的类,和线的类而点和线的类在作业中已经写了,只不过我写的不规范,没有使用getset方法,其实改起来和快只需要把成员变量改private关键词修饰的然后再添加对应的gettersetter,这是出于数据的安全性考虑的,这样子类不能直接访问父类成员变量只能够通过访问父类给的接口方法来访问成员变量或者修改变量。

 

期中考试7.2题目,点击此处展开
 /*在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。

对题目中的点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();*/
7.2代码,点击此处展开
 import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String color=new String();
        Point point1=new Point(sc.nextDouble(),sc.nextDouble());
        Point point2=new Point(sc.nextDouble(),sc.nextDouble());
        color=sc.next();
        if(judge(point1)||judge(point2)){
            System.out.println("Wrong Format");
        }
        else{
            Line l=new Line(point1,point2,color);
            Plane p=new Plane(color);
            Element element=point1;
            element.display();
            element =point2;
            element.display();
            element=l;
            element.display();
            element=p;
            element.display();
        }
    }
    public static void myPrint(double data){
        DecimalFormat df = new DecimalFormat("0.00");
        df.setRoundingMode(RoundingMode.HALF_UP);
        System.out.print(df.format(data));
    }
    public static boolean judge(Point point1){
        return ((point1.getX()<=0||point1.getX()>200)||(point1.getY()<=0||point1.getY()>200));
    }
}
class Point extends Element{
    private double x;
    private double y;

    Point(){

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

    public void setX(double x) {
        this.x = x;
    }
    public void setY(double y) {
        this.y = y;
    }
    @Override
    void display(){
        System.out.print("(");
        Main.myPrint(x);System.out.print(",");Main.myPrint(y);System.out.println(")");
    }
}
class Line extends Element{
    private Point point1;
    private Point point2;
    private String color;
    Line(){

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

    public Point getPoint1() {
        return point1;
    }

    public Point getPoint2() {
        return point2;
    }

    public String getColor() {
        return color;
    }

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

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

    public void setColor(String color) {
        this.color = color;
    }
    public double getDistance(Point point1, Point point2){
        return Math.sqrt(Math.pow(point1.getX()-point2.getX(),2)+Math.pow(point1.getY()-point2.getY(),2));
    }
    @Override
    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.print("The line's length is:");
        Main.myPrint(getDistance(point1,point2));
        System.out.println();
    }
}
class Plane extends Element{
    private String color;
    Plane(){}
    Plane(String color){
        this.color=color;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
    @Override
    void display(){
        System.out.println("The Plane's color is:"+color);
    }
}
abstract class Element {
    abstract void display();
}

 

  题目7.2相比于7.1又有完善,添加了抽象类Element,Dot,Line,Plane类继承了抽象类,抽象类里面有一个display抽象方法,需要子类重写该方法display自己需要展示的数据。抽象类的理念是对某个操作下一个定义,但交给子类去实现,强迫子类一定要实现这个方法,所以如果子类忘了去实现的话,软件出错的几率会很高。使用抽象抽象类可以在实际开发复杂的项目中减少出错的几率。

 

期中考试7.3题目,点击此处展开
 /*在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。

在原有类设计的基础上,增加一个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()方法进行输出。*/
7.3代码,点击此处展开
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Scanner;
import java.util.ArrayList;
public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        GeometryObject g = new GeometryObject();
        String color = new String();
        int choice;
        choice = sc.nextInt();
        while (choice != 0) {
            switch (choice) {
                case 1://insert Point object into list
                    Point p1 = new Point(sc.nextDouble(), sc.nextDouble());
                    g.add(p1);
                    break;
                case 2://insert Line object into list
                    Point d1 = new Point(sc.nextDouble(), sc.nextDouble());
                    Point d2 = new Point(sc.nextDouble(), sc.nextDouble());
                    color=sc.next();
                    Line l = new Line(d1,d2,color);
                    g.add(l);
                    break;
                case 3://insert Plane object into list
                    Plane p2 = new Plane(sc.next());
                    g.add(p2);
                    break;
                case 4://delete index - 1 object from list
                    int index = sc.nextInt();
                    g.remove(index);
            }
            choice = sc.nextInt();
        }
        for(int i=0;i<g.elements.size();i++){
            g.elements.get(i).display();
        }
    }

    public static void myPrint(double data){
        DecimalFormat df = new DecimalFormat("0.00");
        df.setRoundingMode(RoundingMode.HALF_UP);
        System.out.print(df.format(data));
    }
    public static boolean judge(Point point1){
        return ((point1.getX()<=0||point1.getX()>200)||(point1.getY()<=0||point1.getY()>200));
    }
}
class GeometryObject {
    ArrayList<Element> elements=new ArrayList<Element>();

    GeometryObject(){}
    void add(Element element){
        elements.add(element);
    }
    void remove(int index){
        if(index>=0&&index<elements.size())
        elements.remove(index-1);
    }
    public ArrayList<Element> getList() {
        return elements;
    }
}
class Point extends Element{
    private double x;
    private double y;

    Point(){

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

    public void setX(double x) {
        this.x = x;
    }
    public void setY(double y) {
        this.y = y;
    }
    @Override
    void display(){
        System.out.print("(");
        Main.myPrint(x);System.out.print(",");Main.myPrint(y);System.out.println(")");
    }
}
class Line extends Element{
    private Point point1;
    private Point point2;
    private String color;
    Line(){

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

    public Point getPoint1() {
        return point1;
    }

    public Point getPoint2() {
        return point2;
    }

    public String getColor() {
        return color;
    }

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

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

    public void setColor(String color) {
        this.color = color;
    }
    public double getDistance(Point point1, Point point2){
        return Math.sqrt(Math.pow(point1.getX()-point2.getX(),2)+Math.pow(point1.getY()-point2.getY(),2));
    }
    @Override
    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.print("The line's length is:");
        Main.myPrint(getDistance(point1,point2));
        System.out.println();
    }
}
class Plane extends Element{
    private String color;
    Plane(){}
    Plane(String color){
        this.color=color;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
    @Override
    void display(){
        System.out.println("The Plane's color is:"+color);
    }
}
abstract class Element {
    abstract void display();
}

 

相比于7.17.2的题目7.3又有了优化,那就是多了一ArrayList<Element>类型的容器,去储存所有创建的对象。可以通过add()方法往对象集合中放对象,使用removeint index)方法删除集合中下标为index-1的对象。Size()方法则是返回集合中元素的个数,类似于数值中的length()方法。

由于题目已经给了类图而且帮我们规定好了方法所以这里我就不放类图和代码圈复杂度分析了。

 

三,踩坑心得

  作业四我没使用到父类,一开始也没有要构建父类的想法,直到后面写到五边形我发现不构建个父类的话代码量会非常的大而且结构紊乱。还有就是我四个点构成四边形和三角形是把符合输入情况一一列出然后构建相应的三角形或四边形虽然在这个题目这样做不是很复杂但是当做到五边形的时候我才发现什么叫做绝望,所以在判断符合条件输入的时候最好是要使用循环去遍历每一个点和每一条边这样考虑了特殊情况就不会遗漏掉一种情况而且代码也缩减了不少。所以在一开始就要用继承多态的思维去考虑这类题目,也不会导致我多次重构代码了,这里也算是个大坑吧,让我花费了大量时间重构代码。

  期中考试7.3这道题不难,但是考试的时候我没拿满分,因为我没看清楚题目,题目中提到分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。这个真的把我坑惨了,我最后写完了一直在不到问题所在直到考试时间结束也没找到。这里我解释一下next()和nextLine()的区别,nextLine是整行读取,读取到空格时并不会停止读取,只有当读取到回车的时候才会停止读取该行,而next()不一样的是当读取到空格也会停止读取,然后题目上说,可以用一个或多个空格所以才出现了InputMismatchException输入不匹配的报错。唉,痛失满分啊!。

改正前:  改正后:

 

四,改进建议

  作业5.1中我觉得可以不用子类,因为这个题目中所要我们实现的东西在我构建的父类中的共性方法中都有体现,我完全可以不用去创建三角形,四边形,五边形的对象,因为我不需要知道它是几边形就能实现题目要求。而且代码量能够进一步缩短。

  我的作业四和作业五都没有使用private对父类的成员变量进行保护,规范的代码还是要靠getset方法对私有变量的值进行访问和修改,虽然只是做题目,但是我们还是需要带着工程化的思想去写这个题目把所有问题考虑全面。通过其中考试中给的规范的结构,我才意识到规范的代码是多么的重要。

五,总结

  这段时间的作业难度较大,每一次作业都像是在打一个终极大BOSS,在找到BOSS的路上有许多数不尽的困难需要我去解决,当打完一个BOSS后才发现后面的BOSS更难打需要我不断的更新装备重构我的代码才能去与大BOSS抗衡。不过有一说一经过这么多次作业的折磨后,我对面向对象的思维理解更加深入,对于继承,继承体现出来的多态,以及抽象类,抽象方法的理解也更加深入,使用起来也更加得心应手了。还有对于数据的保护也有了一定的理解,一些类的私有属性要用private关键词修饰,而且其他类不能直接拿到该类的成员变量,只有通过调用该类里预留的getset方法去实现数据的访问或修改,这也是出于项目开发安全性去考虑的,也让代码更加规范。所以以后写程序都应该按照这个结构去写,才能让自己显得更加专业。这段时间我收获了很多java的知识,但是更重要的是我花了很多的时间去克服这些问题,这让我获得了很大的提升,对自己的编程能力也愈发自信。

 


__EOF__

本文作者wwk-blogs
本文链接https://www.cnblogs.com/wwk-blogs/p/16836285.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   wwk的hello_world  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示