nchu第二次面向对象编程博客作业

前言:

  本次博客包含的内容有pta题目集4(四边形)、5(五边形)以及期中考试三次题目集。其中第四次和第五次题目集难度较大,比较复杂,涉及的知识点也比较多。而期中考试由于是在课堂上完成,难度较小,代码长度也比较少。

  这次的作业由于有了一定的基础,写起题目来也更加规范,也在老师的讲解后学会了继承与多态以及对象数组、动态链表的使用方法。

设计与分析:

  题目4-7-2:点线形系列4-凸四边形的计算

用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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"。

输入样例9:

选项3,。例如:

3:0,0 -10,100 0,99 10,100

输出样例:

在这里给出相应的输出。例如:

false 221.097 990.0

题目分析:

  这个题目需要我们设计一个四边形的类,我的思路是要用到四个point点类以及六个line边类来存储四边形的四个点和四条边和两条对角线,此外我们还用了两个大小为四的对象数组来存四个点和四条边

    point a;
    point b;
    point c;
    point d;
    line ab;
    line bc;
    line cd;
    line ad;
    line ac;
    line bd;
    point[] dian=new point[4];
    line[] bian =new line[4];

  判断是否是四边形我的思路是判断对角线交点是否在任一对角线内,这样就可以排除所有的不是四边形的情况。而平行四边形则是在四边形的基础上判断是否有一组对边平行且相等。

/*判断是否四边形
    是则true否则false
     */
    boolean isQuadrangle() {
        if (isPointEql()) {
            return false;
        } else if (ab.shifoupingxin(bc) || ab.shifoupingxin(ad) || bc.shifoupingxin(cd) || cd.shifoupingxin(ad)) {
            return false;
        }
        point m = new point();
        m = ac.qiujiaodain(bd);
        return (ac.xianduannei(m) || bd.xianduannei(m));
    }

 /*判断平行四边形
    是则true否则false
     */
    boolean isRhomboid() {
        if (isQuadrangle()) {
            return ab.shifoupingxin(cd) && bc.shifoupingxin(ad);
        } else
            return false;
    }

 判断菱形的方法是平行四边形的情况下判断对角线是否垂直;矩形的方法是平行四边形的情况下判断是否有一个角为直角;正方形的方法是判断是否同时为菱形和矩形。

    /*判断菱形
    是则true否则false
     */
    boolean isRhombus() {
        if (isRhomboid()) {
            return ac.shifoucuizhi(bd);
        }
        return false;
    }

    /*判断矩形
    是则true否则false
     */
    boolean isRectangle() {
        if (isRhomboid()) {
            return ab.shifoucuizhi(bc);
        }
        return false;
    }

    /*判断正方形
   是则true否则false
    */
    boolean isSquare() {
        if (isRhomboid()) {
            return isRhombus() && isRectangle();
        }
        return false;
    }

判断凹凸四边形是判断对角线是否相交,相交则为凸四边形,否则为凹四边形。面积用的是求对角线分割的两个三角形的面积之和,凹四边形则求两个对角线分别分隔的两三角形面积之和中更小的一个。周长则是四条边的长度之和

     /*判断凹凸四边形
    凹四边形false,凸四边形true
     */
    boolean isTuQuadrangle() {
        point o = new point();
        o = ac.qiujiaodain(bd);
        return ac.xianduannei(o) && bd.xianduannei(o);
    }
    /*求周长
    返回周长的double值
     */
    double perimeter() {
        return ab.length + bc.length + cd.length + ad.length;
    }

    /*求面积
    返回四边形面积
     */
    double area() {
        triangle t1 = new triangle();
        triangle t2 = new triangle();
        triangle t3 = new triangle();
        triangle t4 = new triangle();
        t1.createTriangle(a, b, c);
        t2.createTriangle(a, c, d);
        t3.createTriangle(a, b, d);
        t4.createTriangle(b, c, d);
        if (isTuQuadrangle()) {

            return t1.mianji() + t2.mianji();
        } else {
            return Math.min(t1.mianji() + t2.mianji(), t4.mianji() + t3.mianji());
        }
    }

判断四个点是否为三角形,以及去除冗余点的方法如下

   /*判断是否是一个三角形
    是则true否则false
     */
    boolean isTriangle() {
        if (a.iseql(b) || a.iseql(c) || a.iseql(d) || b.iseql(c) || b.iseql(d) || c.iseql(d)) {
            return true;
        } else
            return ac.xianduannei(b) || ac.xianduannei(d) || bd.xianduannei(a) || bd.xianduannei(c);
    }

    /*如果是个三角形,去除冗余点
    返回三角形
     */
    triangle threePoint() {
        triangle t = new triangle();
        if (a.iseql(b) || a.iseql(c) || a.iseql(d)) {
            t.createTriangle(b, c, d);
        } else if (b.iseql(c) || b.iseql(d)) {
            t.createTriangle(a, c, d);
        } else if (c.iseql(d)) {
            t.createTriangle(a, b, c);
        } else if (ac.xianduannei(b)) {
            t.createTriangle(a, c, d);
        } else if (ac.xianduannei(d)) {
            t.createTriangle(a, b, c);
        } else if (bd.xianduannei(a)) {
            t.createTriangle(b, c, d);
        } else if (bd.xianduannei(c)) {
            t.createTriangle(a, b, d);
        }
        return t;
    }

求直线与四边形交点的个数方法,以及求被分割的较大部分面积的方法如下。


    /*求交点个数
    输入一条直线
    输出直线与四边形的交点
     */
    int numOfPoint(line l) {
        int sum = 0;
        triangle t1 = new triangle();//分成两个三角形求线段l与两三角形的交点个数
        t1.createTriangle(a, b, c);
        triangle t2 = new triangle();
        t2.createTriangle(a, d, c);
        if (l.shifoupingxin(ac) && l.iszhixianshang(a) && l.iszhixianshang(c)) {//线段ac与l重合
            if (l.onTheLine(a))
                sum++;
            if (l.onTheLine(c))
                sum++;
            return sum;
        } else if (l.shifoupingxin(ac) && !l.iszhixianshang(a)) {//l和ac平行
            sum = t1.jiaodiangeshu(l) + t2.jiaodiangeshu(l);
            return sum;
        } else if (l.onTheLine(a) || l.onTheLine(c)) {//顶点a或c在直线l上
            sum = t1.jiaodiangeshu(l) + t2.jiaodiangeshu(l) - 1;
            return sum;
        } else if (ac.onTheLine(l.qiujiaodain(ac)) && l.onTheLine(l.qiujiaodain(ac))) {//l与ac交点在线段ac内
            sum = t2.jiaodiangeshu(l) + t1.jiaodiangeshu(l) - 2;
            return sum;
        } else//l与ac交点不在线段ac内
            sum = t1.jiaodiangeshu(l) + t2.jiaodiangeshu(l);
        return sum;
    }

    /*求四边形被直线l分割的两部分面积较大的那部分面积
    输入线段l
    输出较大部分面积
     */
    double biggerArea(line l) {
        point[] P = new point[4];
        line[] L = new line[4];
        P[0] = a;
        P[1] = b;
        P[2] = c;
        P[3] = d;
        L[0] = ab;
        L[1] = bc;
        L[2] = cd;
        L[3] = ad;
        if (isTuQuadrangle()) {//凸四边形的情况
            for (int i = 0; i < 2; i++) {//l过对角线,分隔为两个三角形
                if (l.iszhixianshang(P[i]) && l.iszhixianshang(P[i + 2])) {
                    triangle t1 = new triangle();
                    t1.createTriangle(P[i], P[i + 1], P[i + 2]);
                    return Math.max(t1.mianji(), area() - t1.mianji());
                }
            }
            for (int i = 0; i < 4; i++) {//l过一个顶点,分割为一个三角形和一个四边形
                if (l.iszhixianshang(P[i]) && L[(i + 1) % 4].xianduannei(l.qiujiaodain(L[(i + 1) % 4]))) {
                    triangle t1 = new triangle();
                    t1.createTriangle(P[i], P[(i + 1) % 4], l.qiujiaodain(L[(i + 1) % 4]));
                    return Math.max(t1.mianji(), area() - t1.mianji());
                }
                if (l.iszhixianshang(P[i]) && L[(i + 2) % 4].xianduannei(l.qiujiaodain(L[(i + 2) % 4]))) {
                    triangle t1 = new triangle();
                    t1.createTriangle(P[i], P[(i + 3) % 4], l.qiujiaodain(L[(i + 2) % 4]));
                    return Math.max(t1.mianji(), area() - t1.mianji());
                }
            }
            for (int i = 0; i < 2; i++) {//l分隔为两个四边形mncb和mndc
                if (L[i].xianduannei(l.qiujiaodain(L[i])) && L[i + 2].xianduannei(l.qiujiaodain(L[i + 2]))) {
                    quadrangle q1 = new quadrangle();
                    point m = l.qiujiaodain(L[i]);
                    point n = l.qiujiaodain(L[i + 2]);
                    q1.setQuadrangle(m, n, P[i + 2], P[i + 1]);
                    return Math.max(q1.area(), area() - q1.area());
                }
            }
            for (int i = 0; i < 4; i++) {//l分隔为一个三角形和一个五边形
                if (L[i].xianduannei(l.qiujiaodain(L[i])) && L[(i + 1) % 4].xianduannei(l.qiujiaodain(L[(i + 1) % 4]))) {
                    triangle t1 = new triangle();
                    point m = l.qiujiaodain(L[i]);
                    point n = l.qiujiaodain(L[(i + 1) % 4]);
                    t1.createTriangle(P[(i + 1) % 4], m, n);
                    return Math.max(t1.mianji(), area() - t1.mianji());
                }
            }


        } else {
            for (int i = 0; i < 4; i++) {//l分隔为一个三角形和一个五边形
                if (L[i].xianduannei(l.qiujiaodain(L[i])) && L[(i + 1) % 4].xianduannei(l.qiujiaodain(L[(i + 1) % 4]))) {
                    triangle t1 = new triangle();
                    point m = l.qiujiaodain(L[i]);
                    point n = l.qiujiaodain(L[(i + 1) % 4]);
                    t1.createTriangle(P[(i + 1) % 4], m, n);
                    return Math.max(t1.mianji(), area() - t1.mianji());
                }
            }

        }

        return 0;
    }

判断点是否在四边形内的方法如下。


    /*判断点是否在图形内
    输入一个点
    若点在四边形内返回0在四边形上返回1四边形外返回2
     */
    int isInQar(point m) {
        point n = new point();
        n.setpoint(999, -99);
        line l = new line();
        l.setl(m, n);
        if (ab.xianduannei(m) || bc.xianduannei(m) || cd.xianduannei(m) || ad.xianduannei(m) || a.iseql(m) || b.iseql(m) || c.iseql(m) || d.iseql(m))
            return 1;
        else if (numOfPoint(l) == 1)
            return 0;
        else if (numOfPoint(l) != 1) {
            return 2;
        }
        return 2;

    }

这是各类之间的联系图

这是SourceMonitor生成的报表内容

踩坑心得:

  刚开始写这道题的时候没有用对象数组存四个点和四条边,导致后面计算直线与四边形交点个数和求分隔的面积时有太多重复的相似代码,完全可以使用对象数组存储四个点和边,这样只要考虑一种情况就能应用到四条边上。一开始也没注意是求直线与四边形交点个数,写的时候是按照线段与四边形交点各数求的,属实是没仔细看题犯糊涂了。

题目5-7:点线形系列5-凸五边形的计算

用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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

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坐标之间以英文","分隔,点与点之间以一个英文空格分隔。

输出格式:

基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"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

输入样例:

在这里给出一组输入。例如:

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 

题目分析:

 本题我们需要设计一个五边形的类,我的设计思路是用五个point点类存放五边形的五个点,十个line线类来存放五条边和五条对角线,还用到对象数组来存放这些点和边。

    point a=new point();
    point b=new point();
    point c=new point();
    point d=new point();
    point e=new point();
    line ab,bc,cd,de,ea;
    line ac,ce,eb,bd,da;
    point[] dian=new point[5];
    line[] bian =new line[5];
    line[] djx =new line[5];

 判断是否为五边形和凸五边形的方法如下:


    /*判断是否为五边形
    是则返回true否则false
     */
    boolean isFiveAngle(){
        for (int i = 0; i < 5; i++) {
            if (bian[i].shifoupingxin(bian[(i+1)%5])){
                return false;
            } else if (bian[i].xiangjiao(bian[(i+2)%5])||bian[i].xiangjiao(bian[(i+3)%5])) {
                return false;
            }
        }
        return true;
    }
    /*判断是否为凸五边形
    是则返回true否则false
     */
    boolean isTuFiveAngle (){
        if(isFiveAngle()){
            for (int i = 0; i < 5; i++) {
                if (!djx[i].xiangjiao(djx[(i+2)%5])||!djx[i].xiangjiao(djx[(i+3)%5]))
                    return false;
            }
            return true;
        }return false;
    }

求五边形周长,面积的方法如下:

    /*求五边形周长
    返回五边形的周长
     */
    double perimeter(){
        double sum=0;
        for (int i = 0; i < 5; i++) {
            sum+=bian[i].length;
        }
        return sum;
    }
    /*求五边形面积
    返回五边形的面积
     */
    double area(){

        if (isTuFiveAngle()){
            triangle t=new triangle(a,b,c);
            quadrangle q=new quadrangle(a,c,d,e);
            return t.mianji()+q.area();
        }
        else {
            return 0;
        }
    }

判断是否为四边形并去除冗余点的方法如下:

/*判断是否是四边形
是返回true否则false
 */
boolean isQuadrangle(){
    for (int i = 0; i < 5; i++) {
        for (int j = i; j < 4; j++) {
            if (dian[i].iseql(dian[(j+1)%5])){
                return true;
            }
        }

        line l=new line(dian[(i+1)%5],dian[(i+4)%5]);
        if (l.onTheLine(dian[i])){
            return true;
        }
    }
    return false;
}
/*若是四边形返回四边形,去除冗余点
返回四边形
 */
quadrangle fourPoint(){
    quadrangle q=new quadrangle();
    for (int i = 0; i < 5; i++) {
        for (int j = i; j < 4; j++) {
            if (dian[i].iseql(dian[(j+1)%5])){
                q.setQuadrangle(dian[(i+1)%5],dian[(i+2)%5],dian[(i+3)%5],dian[(i+4)%5]);
            }
        }

        line l=new line(dian[(i+1)%5],dian[(i+4)%5]);
        if (l.onTheLine(dian[i])){
            q.setQuadrangle(dian[(i+1)%5],dian[(i+2)%5],dian[(i+3)%5],dian[(i+4)%5]);
        }
    }return q;
}

求直线与五边形交点个数的方法如下:

/*求线和五边形交点个数
输入一条线段
输出交点个数
 */
int numOfPoint(line l){
    int sum=0;
    triangle t=new triangle(a,b,c);
    quadrangle q=new quadrangle(a,c,d,e);
    if (ac.chonghe(l)){
        if (l.onTheLine(a))
            sum++;
        if (l.onTheLine(c))
            sum++;
    }
    else if (l.shifoupingxin(ac)&&!l.onTheLine(a))
    {
        sum=t.jiaodiangeshu(l)+q.numOfPoint(l);

    } else if (l.onTheLine(a)||l.onTheLine(c)) {
        sum=t.jiaodiangeshu(l)+q.numOfPoint(l)-1;
    } else if (l.xiangjiao(ac)) {
        sum=t.jiaodiangeshu(l)+q.numOfPoint(l)-2;
    } else if (!l.xiangjiao(ac)) {
        sum=t.jiaodiangeshu(l)+q.numOfPoint(l);
    }
    return sum;
}

求被直线分隔的较大部分面积如下:

/*若交点个数为2,求被分割的两部分面积中较大的那部分
输入一条线段
返回较大部分的面积
 */
double biggerArea(line l){
    double s=0;
    for (int i = 0; i < 5; i++) {
        if (l.onTheLine(dian[i])){//点在线上
            if (l.onTheLine(dian[(i+2)%5])){//两点在线上
                triangle t=new triangle(dian[i],dian[(i+1)%5],dian[(i+2)%5]);
                s=Math.max(t.mianji(),area()-t.mianji());
                return s;
            }
            if (l.onTheLine(dian[(i+3)%5])){
                triangle t=new triangle(dian[i],dian[(i+3)%5],dian[(i+4)%5]);
                s=Math.max(t.mianji(),area()-t.mianji());
                return s;
            }
            if (l.xiangjiao(bian[(i+1)%5])){//一个为三角形,一个为六边形
                triangle t=new triangle(dian[i],dian[(i+1)%5],l.qiujiaodain(bian[(i+1)%5]));
                s=Math.max(area()-t.mianji(),t.mianji());
            }
            if (l.xiangjiao(bian[(i+2)%5])){//一个为四边形,一个为五边形
                quadrangle q=new quadrangle(dian[i],dian[(i+1)%5],dian[(i+2)%5],l.qiujiaodain(bian[(i+2)%5]));
                s=Math.max(area()-q.area(),q.area());
            }
            if (l.xiangjiao(bian[(i+3)%5])){//一个为三角形,一个为六边形
                triangle t=new triangle(dian[i],dian[(i+4)%5],l.qiujiaodain(bian[(i+3)%5]));
                s=Math.max(area()-t.mianji(),t.mianji());
            }
        }
        if (l.xiangjiao(bian[i])&&l.xiangjiao(bian[(i+1)%5])){//若与两条邻边相交,一个三角形一个六边形
            triangle t=new triangle(dian[(i+1)%5],l.qiujiaodain(bian[i]),l.qiujiaodain(bian[(i+1)%5]));
            s= Math.max(area()-t.mianji(),t.mianji());
            break;
            }
        if (l.xiangjiao(bian[i])&&l.xiangjiao(bian[(i+2)%5])){//若不与邻边相交,一个四边形,一个五边形
            quadrangle q=new quadrangle(dian[(i+1)%5],dian[(i+2)%5],l.qiujiaodain(bian[i]),l.qiujiaodain(bian[(i+2)%5]));
            s= Math.max(area()-q.area(),q.area());
            break;
        }

    }
    return s;
}

判断点是否在五边形内部的方法如下:


/*判断点是否在五边形内部
输入一个点
若在五边形内部输出true 否则false
 */
boolean isPointIn(point m){
    point x=new point(99,-999);
    line l=new line(x,m);
    return numOfPoint(l)==1;
}
/*判断点是否在五边形的边上
输入一个点
若在边上输出true 否则输出false
 */
boolean isPointOn(point m){
    for (int i = 0; i < 5; i++) {
        if (bian[i].onTheLine(m))
            return true;
    }
    return false;
}

这是本题各类之间的联系图

这是SourceMonitor生成的报表内容

踩坑心得:

  本次题目的难度比较大,我有好多点没有做出来,所以这次的代码量比较少,实现了基本的内容。其他的内容没有来的及去完成。本题也用了对象数组来帮助我们完成计算交点个数等方法,这里的一些方法的主要思想基本和前两次的内容差不多,所以我就没有进行过多的赘述,大家也应该能够看得懂。

改进建议:

  本次题目剩余的功能可以用求五条边的交点个数和点是否在图形内的方法结合起来进行计算求解,若五个点都在另一个五边形的外面就是分离,若五个点都在五边形内部就是包含或被包含,若两各五边形有交点就是交错,若只有一个交点或一条边重合就是连接,五个点完全相同就是重合。大致思路就是这样的,具体的实现我没有来的及去完成。

期中考试:

  期中考试一共有三题,都是关于点线面的重构,由于是在课堂上完成的,题目难度并不大,主要是考查多态与继承和动态数组的掌握程度,大家在完成了前面几次题目集后想必这种难度的题目应当是都不会有什么太大的问题。

  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)方法。

      设计类图如下图所示。
     

1641304523(1).jpg

** 题目要求:在主方法中定义一条线段对象,从键盘输入该线段的起点坐标与终点坐标以及颜色,然后调用该线段的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
 
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();
     
     
    类结构如下图所示。

1641340607(1).jpg

其中,所有数值均保留两位小数,建议可用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:颜色值
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()方法进行输出。
    类图如下所示:

classdiagram.jpg

  • 以下情况为无效作业
    • 无法运行
    • 设计不符合所给类图要求
    • 未通过任何测试点测试
    • 判定为抄袭

输入格式:

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

题目分析:

  由于这三题的关联性较强,我就一起进行分析了:分析题目后我们得知,父类只需要有一个display的方法就可以了,而电线面类都继承父类element,这里的父类主要是一种身份识别的功能,点线面类都是element这种类型的类,我们在第三题写动态数组时就要用到这种特性。具体的实现没有什么难点,大家直接按照题目给的类图完成基本没有什么问题,我就直接放代码了。

这里是用到的点线面类和他们的父类以及最后的容器类:


abstract class Element{
    abstract void display();
}
class Point extends Element{
    private double x,y;
    public Point(){}
    public Point(double x,double y){
        this.x=x;
        this.y=y;
    }
    boolean isIn0to200(){
        return (x>0&&x<=200&&y>0&&y<=200);
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

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

    public void setY(double y) {
        this.y = y;
    }
    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();
    private String color;
    public Line(){}
    public Line(Point x,Point y,String color){
        this.point1=x;
        this.point2=y;
        this.color=color;
    }

    public Point getPoint1() {
        return point1;
    }

    public Point getPoint2() {
        return point2;
    }

    public String getColor() {
        return color;
    }

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

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

    public void setPoint1(Point point1) {
        this.point1 = point1;
    }
    double getDistance(){
        double d=0;
        d= Math.pow((point1.getX()- point2.getX()),2)+Math.pow((point1.getY()- point2.getY()),2);
        return Math.sqrt(d);
    }
    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.println("The line's length is:"+String.format("%.2f",getDistance()));

    }
}

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

    public String getColor() {
        return color;
    }

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

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

class GeometryObject{
    ArrayList<Element> elements=new ArrayList<>();
    void add(Element element){
        elements.add(element);
    }
    void remove(int index){
        elements.remove(index-1);
    }
    int size(){
        return elements.size();
    }

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

这是第一题的主函数:

public class Main1 {
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        Point p1=new Point(in.nextDouble(),in.nextDouble());
        Point p2=new Point(in.nextDouble(),in.nextDouble());
        if (p1.isIn0to200()&&p2.isIn0to200()){
            Line line=new Line(p1,p2,in.next());
            line.display();
        }
        else System.out.println("Wrong Format");

    }
}

这是第二题的主函数:


public class Main2 {
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        Point p1=new Point(in.nextDouble(), in.nextDouble());
        Point p2=new Point(in.nextDouble(),in.nextDouble());
        String color=in.next();
        if (p1.isIn0to200()&&p2.isIn0to200()){
            Line line=new Line(p1,p2,color);
            Plane plane=new Plane(color);
            Element element;
            element = p1;//起点Point
            element.display();

            element = p2;//终点Point
            element.display();

            element = line;//线段
            element.display();

            element = plane;//面
            element.display();
        }else System.out.println("Wrong Format");

    }
}

这是第三题的主函数:

public class Main3 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int choice = in.nextInt();
        GeometryObject geometryObject = new GeometryObject();
        while (choice != 0) {
            switch (choice) {
                case 1:
                    Point point = new Point(in.nextDouble(), in.nextDouble());
                    if (point.isIn0to200()) {
                        geometryObject.add(point);
                    }
                    break;

                case 2:
                    Point p1 = new Point(in.nextDouble(), in.nextDouble());
                    Point p2 = new Point(in.nextDouble(), in.nextDouble());
                    if (p1.isIn0to200() && p2.isIn0to200()) {
                        Line line = new Line(p1, p2, in.next());
                        geometryObject.add(line);

                        break;
                    }
                case 3:
                    String color = in.next();
                    Plane plane = new Plane(color);
                    geometryObject.add(plane);
                    break;

                case 4:
                    int index = in.nextInt();
                    if (index>0&&index<=geometryObject.size()){
                        geometryObject.remove(index);
                    }

                    break;
                default:break;

            }
            choice = in.nextInt();
        }

        for (int i = 0; i < geometryObject.size(); i++) {
            geometryObject.elements.get(i).display();
        }
    }
}

这里是各类之间的联系图:

这是SourceMonitor生成的报表内容:

踩坑心得:

  这里要注意判断给的范围是否合适,以及输出的格式是保留两位小数,可以用老师题目给的方法完成。还有while循环内要记得更新choice,第三题判断如果不合法直接略过这个点就可以了,不需要额外的输出。注意删除的是第i-1位的数组,不在数组范围内的不用删除。

总结:

  本次的三个题目中除了期中考试的题目由于课上完成难度较为简单,其他两个难度总体上来说是比较难的,涉及的知识点也多,不太容易能够融汇贯通的串联起来,还要求以前写的方法考虑的足够全面,有些时候少考虑的情况在后面也许就会用的到。这几次的作业帮助我们学习了解了继承与多态的方法,虽然我这次四边形五边形没有用到这个,但是用继承和多态会使后面的复杂度降低不少。经过这几次的作业以后,确实使我对java有了更深的理解,也让我能够更加熟练的使用java来编写程序了。感谢您的阅读!

 

posted @ 2022-10-29 22:20  浪里老黑龙  阅读(43)  评论(0编辑  收藏  举报