首页 > 其他分享 >题目集4~6的总结

题目集4~6的总结

时间:2022-10-29 22:00:34浏览次数:41  
标签:总结 输出 题目 Point double 坐标 new 三角形

  • 前言:

前两次大作业题目主要是对java基本语法的考察,例如:基础类型的使用以及String类方法的使用。第三次大作业则开始进入到面向对象程序设计的范畴,考察了类的设计。总体来说题目量适中,难度循序渐进,较为适合在这之前从未接触过面向对象程序设计的新手。
  • 设计与分析:

    • 第二次作业7-2  

 

RS232是串口常用的通信协议,在异步通信模式下,串口可以一次发送5~8位数据,收发双方之间没有数据发送时线路维持高电平,相当于接收方持续收到数据“1”(称为空闲位),发送方有数据发送时,会在有效数据(5~8位,具体位数由通信双方提前设置)前加上1位起始位“0”,在有效数据之后加上1位可选的奇偶校验位和1位结束位“1”。请编写程序,模拟串口接收处理程序,注:假定有效数据是8位,奇偶校验位采用奇校验。

输入格式:

由0、1组成的二进制数据流。例如:11110111010111111001001101111111011111111101111

输出格式:

过滤掉空闲、起始、结束以及奇偶校验位之后的数据,数据之前加上序号和英文冒号。
如有多个数据,每个数据单独一行显示。
若数据不足11位或者输入数据全1没有起始位,则输出"null data",
若某个数据的结束符不为1,则输出“validate error”。
若某个数据奇偶校验错误,则输出“parity check error”。
若数据结束符和奇偶校验均不合格,输出“validate error”。
如:11011或11111111111111111。
例如:
1:11101011
2:01001101
3:validate error

这一次作业完全按照面向过程方法实现,主要是对正则表达式的应用和String类方法的应用,仅有一个主类和一个主方法,因为整体难度较为简单,所以没有采用面向对象思想进行编程。但是从ScoureMonitor生成结果来看应该对代码进行一定程度的拆分以减少复杂度。

 

 首先检查数据长度和是否存在有效数据:

if(s.length() < 11 || s.matches("1+"))
            System.out.println("null data");

 

如果长度符合预期并且存在有效数据则进行如下处理:

通过变量count记录有效数据个数,通过end和parityCheck变量判断数据是否合法,count1统计数据中”1“的个数判断是否符合奇偶校验,通过循环来搜索有效数据

int count = 1;
            for(int i = s.indexOf('0');s.substring(i).matches(".*0+.*") && i + 10 < s.length();i = s.indexOf('0',i) + 11) {
                boolean end = (s.charAt(s.indexOf('0',i) + 10) == '1');
                int count1 = 0;
                boolean parityCheck = true;
                for(int j = s.indexOf('0',i) + 1;j <= s.indexOf('0',i) + 9;j++) {
                    if(s.charAt(j) == '1')
                        count1++;
                    parityCheck = (count1 % 2 == 1);
                }
                System.out.print(count++ + ":");
                if(end && parityCheck)
                    System.out.println(s.substring(s.indexOf('0',i) + 1,s.indexOf('0',i) + 9));
                else if(!end && !parityCheck)
                    System.out.println("validate error");
                else if(!end && parityCheck)
                    System.out.println("validate error");
                else if(end && !parityCheck)
                    System.out.println("parity check error");

 

 

 

 

    • 第三次作业7-1

 

输入连个点的坐标,计算两点之间的距离

 

输入格式:

 

4个double类型的实数,两个点的x,y坐标,依次是x1、y1、x2、y2,两个点的坐标之间以空格分隔,每个点的x,y坐标以英文“,”分隔。例如:0,0 1,1或0.1,-0.3 +3.5,15.6。
若输入格式非法,输出"Wrong Format"。
若输入格式合法但坐标点的数量超过两个,输出“wrong number of points”。

 

输出格式:

 

计算所得的两点之间的距离。例如:1.4142135623730951

 

 

 

 正式进入面向对象程序设计的第一道题,这题本身并不复杂,主要是运用正则表达式对输入进行处理;实现的功能也只有求两点间的距离。

 

 下面是用于格式处理的Processing类

class Processing {
    String s;
    Processing() {
        Scanner input = new Scanner(System.in);
        s = input.nextLine();
    }
    boolean isLegal() {
        final String S = "[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)";
        //return (this.s.matches(S + "," + S + "(\\sS,S)+"));
        //return (this.s.matches("S,S\\sS,S"));
        return (this.s.matches(S + "," + S + "(\\s" + S +","+ S + ")+"));
    }
    void getCoordinates(Point a,Point b) {
        String[] tokens = this.s.split("\\s");
        String[] tokensA = tokens[0].split(",");
        String[] tokensB = tokens[1].split(",");
        a.setX(Double.parseDouble(tokensA[0]));
        a.setY(Double.parseDouble(tokensA[1]));
        b.setX(Double.parseDouble(tokensB[0]));
        b.setY(Double.parseDouble(tokensB[1]));
    }
    int numberOfPoints() {
        String[] tokens = this.s.split("\\s");
        return tokens.length;
    }
}

 

 这段代码复用性很高,略微改进后在后面两题则无需再次更改。而且在输入是否符合格式方面的函数非常简洁。曾使用过非常多方案但是没有得到想要的效果。最后在想通matches方法的输入是个字符串之后终于完成了对格式判断的书写,先用一个字符串S表示浮点数或整数,后再通过字符串拼接‘+’完成正则表达式的书写,非常简洁直观。

主要改变为读取坐标后采用Point数组返回,改进后代码如下:

class Processing {
    String s;
    Processing() {
        Scanner input = new Scanner(System.in);
        s = input.nextLine();
    }
    boolean isLegal() {
        final String S = "[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)";
        final String REGEX = "[1-5]:" + S + "," + S + "(\\s" + S +","+ S + ")+";
        return (this.s.matches(REGEX));
    }
    int whichCase() {
        char situation = this.s.charAt(0);
        return situation - '0';
    }
    Point[] getCoordinates(int n) {
        Point[] a = new Point[n];
        String[] tokens = this.s.split(":");
        String[] coordinate = tokens[1].split("\\s");
        for(int i = 0;i < n;i++) {
            String[] number = coordinate[i].split(",");
            a[i] = new Point(Double.parseDouble(number[0]),Double.parseDouble(number[1]));
        }
        return a;
    }
    int numberOfPoints() {
        String[] tokens = this.s.split("\\s");
        return tokens.length;
    }
    static double format(double x) {
        return (int)(x * 1e6 + 0.5) / 1e6 / 1.0;
    }
}

 

 由于这是后面题目的铺垫,所以创建一个Point类来完成题目的编写,下面是Point类的属性和构造方法

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

 

后续实现求解距离的方法如下

double distance(Point a) {
        double distance = Math.sqrt(Math.pow(this.x - a.x,2) + Math.pow(this.y - a.y,2));
        return distance;

 

简单地套用距离公式 

    • 第三次作业7-2

 

用户输入一组选项和数据,进行与直线有关的计算。选项包括:
1:输入两点坐标,计算斜率,若线条垂直于X轴,输出"Slope does not exist"。
2:输入三个点坐标,输出第一个点与另外两点连线的垂直距离。
3:输入三个点坐标,判断三个点是否在一条线上,输出true或者false。
4:输入四个点坐标,判断前两个点所构成的直线与后两点构成的直线是否平行,输出true或者false.
5:输入四个点坐标,计算输出前两个点所构成的直线与后两点构成的直线的交点坐标,x、y坐标之间以英文分隔",",并输出交叉点是否在两条线段之内(不含四个端点)的判断结果(true/false),判断结果与坐标之间以一个英文空格分隔。若两条线平行,没有交叉点,则输出"is parallel lines,have no intersection point"。

 

输入格式:

 

基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。
例如:1:0,0 1,1
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
不论哪个选项,如果格式、点数量都符合要求,但构成任一条线的两个点坐标重合,输出"points coincide",

 

输出格式:

 

见题目描述。

 

 下面是Line类的属性和构造方法

    Point a,b;
    double A,B,C;
    Line(Point newA,Point newB) {
        a = new Point();
        a = newA;
        b = new Point();
        b = newB;
        A = b.y - a.y;
        B = a.x - b.x;
        C = b.x * a.y - a.x * b.y ;
    }
   

 

在Line类中,使用了直线的一般方程的三个参数作为类的属性之一,在后面的方法中可以非常方便地套用数学公式得出结果。

而参数的求解放在了类的构造函数中,也符合直线的特征,有了直线自然也就有了一般方程的三个参数。而直线类的创捷需要两个点类作为参数,也符合两点确定一条直线的基本数学思维。

但是由于求直线交点的方法没有判断直线是否平行,而给后一题埋下了大坑。 也是简单的套用公式,求解交点方法如下:

Point intersectionOfTwoLines(Line a) {
        double denominator = this.A * a.B - a.A * this.B;
        double x = -(a.B * this.C - this.B * a.C) / denominator;
        double y = -(this.A * a.C - a.A * this.C) / denominator;
        Point intersection = new Point(x,y);
        return intersection;
    }

 

修改后有检查的方法如下:

Point intersectionOfTwoLines(Line a) {
        Point intersection;
        double denominator = this.A * a.B - a.A * this.B;
        if(Math.abs(denominator) < 1e-6)
            intersection = null;
        else {
            double x = -(a.B * this.C - this.B * a.C) / denominator;
            double y = -(this.A * a.C - a.A * this.C) / denominator;
            intersection = new Point(x,y);
        }
        return intersection;
    }

 

若两直线平行则交点为空。

判断三点是否在同一直线上只需判断第三个点是否位于前两个点所构成的直线上即可。判断方法如下:

static boolean isInALine(Point a,Point b,Point c) {
        if(a.isCoincide(b) || a.isCoincide(c) || b.isCoincide(c))
            return true;
        else {
            Line la = new Line(a,b);
            if(la.isPointOnLine(c))
                return true;
            else
                return false;
        }

 

 

 

    • 第三次作业7-3

 

用户输入一组选项和数据,进行与三角形有关的计算。选项包括:
1:输入三个点坐标,判断是否是等腰三角形、等边三角形,判断结果输出true/false,两个结果之间以一个英文空格符分隔。
2:输入三个点坐标,输出周长、面积、重心坐标,三个参数之间以一个英文空格分隔,坐标之间以英文","分隔。
3:输入三个点坐标,输出是钝角、直角还是锐角三角形,依次输出三个判断结果(true/false),以一个英文空格分隔,
4:输入五个点坐标,输出前两个点所在的直线与三个点所构成的三角形相交的交点数量,如果交点有两个,则按面积大小依次输出三角形被直线分割成两部分的面积。若直线与三角形一条线重合,输出"The point is on the edge of the triangle"
5:输入四个点坐标,输出第一个是否在后三个点所构成的三角形的内部(输出in the triangle/outof triangle)。
必须使用射线法,原理:由第一个点往任一方向做一射线,射线与三角形的边的交点(不含点本身)数量如果为1,则在三角形内部。如果交点有两个或0个,则在三角形之外。若点在三角形的某条边上,输出"on the triangle"

 

输入格式:

 

基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。

 

输出格式:

 

基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
如果输入的三个点无法构成三角形,输出"data error"。
注意:输出的数据若小数点后超过6位,只保留小数点后6位,多余部分采用四舍五入规则进到最低位。小数点后若不足6位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333333,1.0按格式输出为1.0

 

选项4中所输入线的两个点坐标重合,输出"points coincide",

 

 

 

 

 下面是Triangle类的属性和构造方法

    Point a,b,c;
    double x,y,z;
    Triangle(Point a,Point b,Point c) {
        this.a = new Point(a.x,a.y);
        this.b = new Point(b.x,b.y);
        this.c = new Point(c.x,c.y);
        double[] sideLength = {a.distance(b),a.distance(c),b.distance(c)};
        Arrays.sort(sideLength);
        x = sideLength[0];
        y = sideLength[1];
        z = sideLength[2];
    }
    

 

 为这一题新创建的三角形类。将顶点坐标和三角形边长作为类的属性,以方便后续功能的实现。由于后续踩坑,所以应该在构造方法里判断三点是否能构成三角形。

个人认为首先要提到的一点就是在坐标系下判断三点是否构成三角形不需要判断边长,而只需要判断三点是否在同一直线上即可,所以判断三点能否构成三角形只需要调用Line类中的方法。

 

四选项,一共有多种情况需要考虑。

首先要判断两点构成的直线是否于三角形的边重合,判断代码如下:

int mark = 0;
                                for(int i = 0;i < 3;i++)
                                    if(l1.isPointOnLine(abc.getVertex()[i]))
                                        mark++;
                                if(mark == 2)
                                    System.out.println("The point is on the edge of the triangle");

其次就被交点的个数不确定从而不能使用数组所困扰,索幸在采用了ArrayList后问题得到了解决。求出直线和三角形三条边所在直线所有交点;再排除不在线段上的交点,剩下的点即为直线与三角形的交点。方法如下:

Point[] intersectionOfLineAndTriangle(Line l) {
        Point[] intersection = null;
        Line[] side = this.getSide();
        ArrayList<Point> potential = new ArrayList<>();
        for(int i = 0;i < 3;i++) {
            Point a = l.intersectionOfTwoLines(side[i]);
            if(a != null && side[i].isOnSegment(a))
                potential.add(l.intersectionOfTwoLines(side[i]));
        }
        for(int i = 0;i < potential.size();i++) {
            for(int j = i + 1;j < potential.size();j++) {
                if(potential.get(i).isCoincide(potential.get(j))) {
                    potential.remove(j);
                }
            }
        }
        intersection = new Point[potential.size()];
        potential.toArray(intersection);
        return intersection;
    }

 

这时候根据交点数的不同又分为多种情况。若交点为0和1则可以直接输出交点个数。

而交点数为2的则需进一步求出分割后两部分面积 。

求面积的思路为:先求出分割后三角形的面积S1;再用原三角形面积减去S1得到另一部分分割后面积。这种思路则需要知道直线与三角形交点与哪个原三角形顶点构成了三角形。通过判断三角形顶点在直线两侧的个数来判断与哪个点构成三角形。以下是求解面积部分对交点的处理


if(intersection.length == 2) {
  ArrayList<Point> p = new ArrayList<>();
   ArrayList<Point> q = new ArrayList<>();
   Point[] vertex = abc.getVertex();
   for(int i = 0;i < 3;i++) {
     if(l1.whichSideOfLine(vertex[i]) == 1)
         p.add(vertex[i]);
      else if(l1.whichSideOfLine(vertex[i]) == 2)
          q.add(vertex[i]);
   }
    double s1,s2;
    Point m = null;
     if(q.size() == 1 && p.size() == 1)
       m = q.get(0);
     else if(q.size() == 1 && p.size() != 1)
        m = q.get(0);
    else if(q.size() != 1 && p.size() == 1)
       m = p.get(0);
   Triangle t1 = new Triangle(intersection[0],intersection[1],m);
   s1 = t1.area();
   s2 = abc.area() - s1;
   s1 = Processing.format(s1);
   s2 = Processing.format(s2);
   System.out.println(" " + Math.min(s1,s2) + " " + Math.max(s1,s2));


 

这段对选项四的处理过于冗长需要从主函数中加以拆分。 

  • 踩坑心得:

      1.首先是语法问题,String不能通过‘==’来比较两个字符串是否相等,而应该通过equals()方法;

    2.第三次大作业的平均圈复杂度尚在可以接受的范围内,但是最大圈复杂度超标,因为主函数情况太多导致需要的分支语句较多所以最大圈复杂度的函数出现在主函数里;

 

 

 

    3.charAt()方法返回的是char而不是String;

    4.一定要养成书写注释的习惯,否则也会给自己的代码书写带来困扰。

    5.构造函数要检查输入是否合法!

  • 改进建议:

   1.积极书写注释,并在下一次大作业中对自己书写的所有方法写上相应注释;

    2.对主函数进行拆分,对每个不同的选项单独书写函数以降低圈复杂度;

    3.类的数据域尚未进行封装,之后对每个类的数据域进行封装,并加上相应的访问器和修改器。

  • 总结:

  通过这三次大作业,特别是最后一次大作业:初步窥探了面向对象程序设计的思想和方法;初步掌握了java编程的语法规则;初步编写了对显示的抽象——类;但是还没有养成书写注释的习惯,给自己的编程带来了一定的阻碍,更不利于别人阅读自己书写的代码。对个人而言感触最深的一节课是”多项式“的那节课,老师提出问题后的想法是创建”加法类“和”乘法类“,个人认为这其实还是一种面向过程的思维,分为这两个类实际上只是为了在实现功能上能够复用代码,而不是对现实世界的抽象,这两个”类“被叫做函数更加贴切。而当老师说出分为”单项式类“和”多项式类“的时候,犹如醍醐灌顶,这才是对现实世界的抽象,这才是面向对象,这一刻我真正敲开了面向对象的大门。

 

 

  • 前言:

前两次大作业题目主要是对java基本语法的考察,例如:基础类型的使用以及String类方法的使用。第三次大作业则开始进入到面向对象程序设计的范畴,考察了类的设计。总体来说题目量适中,难度循序渐进,较为适合在这之前从未接触过面向对象程序设计的新手。
  • 设计与分析:

    • 第二次作业7-2  

 

RS232是串口常用的通信协议,在异步通信模式下,串口可以一次发送5~8位数据,收发双方之间没有数据发送时线路维持高电平,相当于接收方持续收到数据“1”(称为空闲位),发送方有数据发送时,会在有效数据(5~8位,具体位数由通信双方提前设置)前加上1位起始位“0”,在有效数据之后加上1位可选的奇偶校验位和1位结束位“1”。请编写程序,模拟串口接收处理程序,注:假定有效数据是8位,奇偶校验位采用奇校验。

输入格式:

由0、1组成的二进制数据流。例如:11110111010111111001001101111111011111111101111

输出格式:

过滤掉空闲、起始、结束以及奇偶校验位之后的数据,数据之前加上序号和英文冒号。
如有多个数据,每个数据单独一行显示。
若数据不足11位或者输入数据全1没有起始位,则输出"null data",
若某个数据的结束符不为1,则输出“validate error”。
若某个数据奇偶校验错误,则输出“parity check error”。
若数据结束符和奇偶校验均不合格,输出“validate error”。
如:11011或11111111111111111。
例如:
1:11101011
2:01001101
3:validate error

这一次作业完全按照面向过程方法实现,主要是对正则表达式的应用和String类方法的应用,仅有一个主类和一个主方法,因为整体难度较为简单,所以没有采用面向对象思想进行编程。但是从ScoureMonitor生成结果来看应该对代码进行一定程度的拆分以减少复杂度。

 

 首先检查数据长度和是否存在有效数据:

if(s.length() < 11 || s.matches("1+"))
            System.out.println("null data");

 

如果长度符合预期并且存在有效数据则进行如下处理:

通过变量count记录有效数据个数,通过end和parityCheck变量判断数据是否合法,count1统计数据中”1“的个数判断是否符合奇偶校验,通过循环来搜索有效数据

int count = 1;
            for(int i = s.indexOf('0');s.substring(i).matches(".*0+.*") && i + 10 < s.length();i = s.indexOf('0',i) + 11) {
                boolean end = (s.charAt(s.indexOf('0',i) + 10) == '1');
                int count1 = 0;
                boolean parityCheck = true;
                for(int j = s.indexOf('0',i) + 1;j <= s.indexOf('0',i) + 9;j++) {
                    if(s.charAt(j) == '1')
                        count1++;
                    parityCheck = (count1 % 2 == 1);
                }
                System.out.print(count++ + ":");
                if(end && parityCheck)
                    System.out.println(s.substring(s.indexOf('0',i) + 1,s.indexOf('0',i) + 9));
                else if(!end && !parityCheck)
                    System.out.println("validate error");
                else if(!end && parityCheck)
                    System.out.println("validate error");
                else if(end && !parityCheck)
                    System.out.println("parity check error");

 

 

 

 

    • 第三次作业7-1

 

输入连个点的坐标,计算两点之间的距离

 

输入格式:

 

4个double类型的实数,两个点的x,y坐标,依次是x1、y1、x2、y2,两个点的坐标之间以空格分隔,每个点的x,y坐标以英文“,”分隔。例如:0,0 1,1或0.1,-0.3 +3.5,15.6。
若输入格式非法,输出"Wrong Format"。
若输入格式合法但坐标点的数量超过两个,输出“wrong number of points”。

 

输出格式:

 

计算所得的两点之间的距离。例如:1.4142135623730951

 

 

 

 正式进入面向对象程序设计的第一道题,这题本身并不复杂,主要是运用正则表达式对输入进行处理;实现的功能也只有求两点间的距离。

 

 下面是用于格式处理的Processing类

class Processing {
    String s;
    Processing() {
        Scanner input = new Scanner(System.in);
        s = input.nextLine();
    }
    boolean isLegal() {
        final String S = "[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)";
        //return (this.s.matches(S + "," + S + "(\\sS,S)+"));
        //return (this.s.matches("S,S\\sS,S"));
        return (this.s.matches(S + "," + S + "(\\s" + S +","+ S + ")+"));
    }
    void getCoordinates(Point a,Point b) {
        String[] tokens = this.s.split("\\s");
        String[] tokensA = tokens[0].split(",");
        String[] tokensB = tokens[1].split(",");
        a.setX(Double.parseDouble(tokensA[0]));
        a.setY(Double.parseDouble(tokensA[1]));
        b.setX(Double.parseDouble(tokensB[0]));
        b.setY(Double.parseDouble(tokensB[1]));
    }
    int numberOfPoints() {
        String[] tokens = this.s.split("\\s");
        return tokens.length;
    }
}

 

 这段代码复用性很高,略微改进后在后面两题则无需再次更改。而且在输入是否符合格式方面的函数非常简洁。曾使用过非常多方案但是没有得到想要的效果。最后在想通matches方法的输入是个字符串之后终于完成了对格式判断的书写,先用一个字符串S表示浮点数或整数,后再通过字符串拼接‘+’完成正则表达式的书写,非常简洁直观。

主要改变为读取坐标后采用Point数组返回,改进后代码如下:

class Processing {
    String s;
    Processing() {
        Scanner input = new Scanner(System.in);
        s = input.nextLine();
    }
    boolean isLegal() {
        final String S = "[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)";
        final String REGEX = "[1-5]:" + S + "," + S + "(\\s" + S +","+ S + ")+";
        return (this.s.matches(REGEX));
    }
    int whichCase() {
        char situation = this.s.charAt(0);
        return situation - '0';
    }
    Point[] getCoordinates(int n) {
        Point[] a = new Point[n];
        String[] tokens = this.s.split(":");
        String[] coordinate = tokens[1].split("\\s");
        for(int i = 0;i < n;i++) {
            String[] number = coordinate[i].split(",");
            a[i] = new Point(Double.parseDouble(number[0]),Double.parseDouble(number[1]));
        }
        return a;
    }
    int numberOfPoints() {
        String[] tokens = this.s.split("\\s");
        return tokens.length;
    }
    static double format(double x) {
        return (int)(x * 1e6 + 0.5) / 1e6 / 1.0;
    }
}

 

 由于这是后面题目的铺垫,所以创建一个Point类来完成题目的编写,下面是Point类的属性和构造方法

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

 

后续实现求解距离的方法如下

double distance(Point a) {
        double distance = Math.sqrt(Math.pow(this.x - a.x,2) + Math.pow(this.y - a.y,2));
        return distance;

 

简单地套用距离公式 

    • 第三次作业7-2

 

用户输入一组选项和数据,进行与直线有关的计算。选项包括:
1:输入两点坐标,计算斜率,若线条垂直于X轴,输出"Slope does not exist"。
2:输入三个点坐标,输出第一个点与另外两点连线的垂直距离。
3:输入三个点坐标,判断三个点是否在一条线上,输出true或者false。
4:输入四个点坐标,判断前两个点所构成的直线与后两点构成的直线是否平行,输出true或者false.
5:输入四个点坐标,计算输出前两个点所构成的直线与后两点构成的直线的交点坐标,x、y坐标之间以英文分隔",",并输出交叉点是否在两条线段之内(不含四个端点)的判断结果(true/false),判断结果与坐标之间以一个英文空格分隔。若两条线平行,没有交叉点,则输出"is parallel lines,have no intersection point"。

 

输入格式:

 

基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。
例如:1:0,0 1,1
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
不论哪个选项,如果格式、点数量都符合要求,但构成任一条线的两个点坐标重合,输出"points coincide",

 

输出格式:

 

见题目描述。

 

 下面是Line类的属性和构造方法

    Point a,b;
    double A,B,C;
    Line(Point newA,Point newB) {
        a = new Point();
        a = newA;
        b = new Point();
        b = newB;
        A = b.y - a.y;
        B = a.x - b.x;
        C = b.x * a.y - a.x * b.y ;
    }
   

 

在Line类中,使用了直线的一般方程的三个参数作为类的属性之一,在后面的方法中可以非常方便地套用数学公式得出结果。

而参数的求解放在了类的构造函数中,也符合直线的特征,有了直线自然也就有了一般方程的三个参数。而直线类的创捷需要两个点类作为参数,也符合两点确定一条直线的基本数学思维。

但是由于求直线交点的方法没有判断直线是否平行,而给后一题埋下了大坑。 也是简单的套用公式,求解交点方法如下:

Point intersectionOfTwoLines(Line a) {
        double denominator = this.A * a.B - a.A * this.B;
        double x = -(a.B * this.C - this.B * a.C) / denominator;
        double y = -(this.A * a.C - a.A * this.C) / denominator;
        Point intersection = new Point(x,y);
        return intersection;
    }

 

修改后有检查的方法如下:

Point intersectionOfTwoLines(Line a) {
        Point intersection;
        double denominator = this.A * a.B - a.A * this.B;
        if(Math.abs(denominator) < 1e-6)
            intersection = null;
        else {
            double x = -(a.B * this.C - this.B * a.C) / denominator;
            double y = -(this.A * a.C - a.A * this.C) / denominator;
            intersection = new Point(x,y);
        }
        return intersection;
    }

 

若两直线平行则交点为空。

判断三点是否在同一直线上只需判断第三个点是否位于前两个点所构成的直线上即可。判断方法如下:

static boolean isInALine(Point a,Point b,Point c) {
        if(a.isCoincide(b) || a.isCoincide(c) || b.isCoincide(c))
            return true;
        else {
            Line la = new Line(a,b);
            if(la.isPointOnLine(c))
                return true;
            else
                return false;
        }

 

 

 

    • 第三次作业7-3

 

用户输入一组选项和数据,进行与三角形有关的计算。选项包括:
1:输入三个点坐标,判断是否是等腰三角形、等边三角形,判断结果输出true/false,两个结果之间以一个英文空格符分隔。
2:输入三个点坐标,输出周长、面积、重心坐标,三个参数之间以一个英文空格分隔,坐标之间以英文","分隔。
3:输入三个点坐标,输出是钝角、直角还是锐角三角形,依次输出三个判断结果(true/false),以一个英文空格分隔,
4:输入五个点坐标,输出前两个点所在的直线与三个点所构成的三角形相交的交点数量,如果交点有两个,则按面积大小依次输出三角形被直线分割成两部分的面积。若直线与三角形一条线重合,输出"The point is on the edge of the triangle"
5:输入四个点坐标,输出第一个是否在后三个点所构成的三角形的内部(输出in the triangle/outof triangle)。
必须使用射线法,原理:由第一个点往任一方向做一射线,射线与三角形的边的交点(不含点本身)数量如果为1,则在三角形内部。如果交点有两个或0个,则在三角形之外。若点在三角形的某条边上,输出"on the triangle"

 

输入格式:

 

基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。

 

输出格式:

 

基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
如果输入的三个点无法构成三角形,输出"data error"。
注意:输出的数据若小数点后超过6位,只保留小数点后6位,多余部分采用四舍五入规则进到最低位。小数点后若不足6位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333333,1.0按格式输出为1.0

 

选项4中所输入线的两个点坐标重合,输出"points coincide",

 

 

 

 

 下面是Triangle类的属性和构造方法

    Point a,b,c;
    double x,y,z;
    Triangle(Point a,Point b,Point c) {
        this.a = new Point(a.x,a.y);
        this.b = new Point(b.x,b.y);
        this.c = new Point(c.x,c.y);
        double[] sideLength = {a.distance(b),a.distance(c),b.distance(c)};
        Arrays.sort(sideLength);
        x = sideLength[0];
        y = sideLength[1];
        z = sideLength[2];
    }
    

 

 为这一题新创建的三角形类。将顶点坐标和三角形边长作为类的属性,以方便后续功能的实现。由于后续踩坑,所以应该在构造方法里判断三点是否能构成三角形。

个人认为首先要提到的一点就是在坐标系下判断三点是否构成三角形不需要判断边长,而只需要判断三点是否在同一直线上即可,所以判断三点能否构成三角形只需要调用Line类中的方法。

 

四选项,一共有多种情况需要考虑。

首先要判断两点构成的直线是否于三角形的边重合,判断代码如下:

int mark = 0;
                                for(int i = 0;i < 3;i++)
                                    if(l1.isPointOnLine(abc.getVertex()[i]))
                                        mark++;
                                if(mark == 2)
                                    System.out.println("The point is on the edge of the triangle");

其次就被交点的个数不确定从而不能使用数组所困扰,索幸在采用了ArrayList后问题得到了解决。求出直线和三角形三条边所在直线所有交点;再排除不在线段上的交点,剩下的点即为直线与三角形的交点。方法如下:

Point[] intersectionOfLineAndTriangle(Line l) {
        Point[] intersection = null;
        Line[] side = this.getSide();
        ArrayList<Point> potential = new ArrayList<>();
        for(int i = 0;i < 3;i++) {
            Point a = l.intersectionOfTwoLines(side[i]);
            if(a != null && side[i].isOnSegment(a))
                potential.add(l.intersectionOfTwoLines(side[i]));
        }
        for(int i = 0;i < potential.size();i++) {
            for(int j = i + 1;j < potential.size();j++) {
                if(potential.get(i).isCoincide(potential.get(j))) {
                    potential.remove(j);
                }
            }
        }
        intersection = new Point[potential.size()];
        potential.toArray(intersection);
        return intersection;
    }

 

这时候根据交点数的不同又分为多种情况。若交点为0和1则可以直接输出交点个数。

而交点数为2的则需进一步求出分割后两部分面积 。

求面积的思路为:先求出分割后三角形的面积S1;再用原三角形面积减去S1得到另一部分分割后面积。这种思路则需要知道直线与三角形交点与哪个原三角形顶点构成了三角形。通过判断三角形顶点在直线两侧的个数来判断与哪个点构成三角形。以下是求解面积部分对交点的处理


if(intersection.length == 2) {
  ArrayList<Point> p = new ArrayList<>();
   ArrayList<Point> q = new ArrayList<>();
   Point[] vertex = abc.getVertex();
   for(int i = 0;i < 3;i++) {
     if(l1.whichSideOfLine(vertex[i]) == 1)
         p.add(vertex[i]);
      else if(l1.whichSideOfLine(vertex[i]) == 2)
          q.add(vertex[i]);
   }
    double s1,s2;
    Point m = null;
     if(q.size() == 1 && p.size() == 1)
       m = q.get(0);
     else if(q.size() == 1 && p.size() != 1)
        m = q.get(0);
    else if(q.size() != 1 && p.size() == 1)
       m = p.get(0);
   Triangle t1 = new Triangle(intersection[0],intersection[1],m);
   s1 = t1.area();
   s2 = abc.area() - s1;
   s1 = Processing.format(s1);
   s2 = Processing.format(s2);
   System.out.println(" " + Math.min(s1,s2) + " " + Math.max(s1,s2));


 

这段对选项四的处理过于冗长需要从主函数中加以拆分。 

  • 踩坑心得:

      1.首先是语法问题,String不能通过‘==’来比较两个字符串是否相等,而应该通过equals()方法;

    2.第三次大作业的平均圈复杂度尚在可以接受的范围内,但是最大圈复杂度超标,因为主函数情况太多导致需要的分支语句较多所以最大圈复杂度的函数出现在主函数里;

 

 

 

    3.charAt()方法返回的是char而不是String;

    4.一定要养成书写注释的习惯,否则也会给自己的代码书写带来困扰。

    5.构造函数要检查输入是否合法!

  • 改进建议:

   1.积极书写注释,并在下一次大作业中对自己书写的所有方法写上相应注释;

    2.对主函数进行拆分,对每个不同的选项单独书写函数以降低圈复杂度;

    3.类的数据域尚未进行封装,之后对每个类的数据域进行封装,并加上相应的访问器和修改器。

  • 总结:

  通过这三次大作业,特别是最后一次大作业:初步窥探了面向对象程序设计的思想和方法;初步掌握了java编程的语法规则;初步编写了对显示的抽象——类;但是还没有养成书写注释的习惯,给自己的编程带来了一定的阻碍,更不利于别人阅读自己书写的代码。对个人而言感触最深的一节课是”多项式“的那节课,老师提出问题后的想法是创建”加法类“和”乘法类“,个人认为这其实还是一种面向过程的思维,分为这两个类实际上只是为了在实现功能上能够复用代码,而不是对现实世界的抽象,这两个”类“被叫做函数更加贴切。而当老师说出分为”单项式类“和”多项式类“的时候,犹如醍醐灌顶,这才是对现实世界的抽象,这才是面向对象,这一刻我真正敲开了面向对象的大门。

 

 

标签:总结,输出,题目,Point,double,坐标,new,三角形
From: https://www.cnblogs.com/Zexu3366/p/16839990.html

相关文章