PTA1-3总结

  • 前言

本次博客对pta前三次作业进行多方面总结,对知识点,题量,难度等方面进行分析。第一次作业题量比较多,但大都比较容易,学习了许多基础的方法,除了最后一题因为误差问题卡了一下,其他题目也都顺利完成。还是采用面向过程的思想,第二次作业依旧采用面向过程去写,难度也不是很大,第二题因为自己写了太多自增变量嵌入在for循环当中,导致打印时出错找了很久这个问题,还有就是数组概念也更加清晰。第三次作业难度明显加大了,难度比前两次提升了不少,老师要求采用面向对象去写,前两次都是采用面向过程去写题目,突然要面向对象,一开始真是无从下手,经过自己查阅与询问同学,花费大量时间,再到后来能慢慢去写各个类和方法,创建新对象去调用其他类的方法,花了大量的时间去掌握,虽然还不是特别熟练,但是因此自己的java能力提高了不少。


 

 

  • 设计与分析

    一、

        7-6 学号识别 

           作者 蔡轲

  1. 单位 南昌航空大学

    学校的学号由8位数字组成,前两位是入学年份(省略了20);第3、4位是学院编号,01代表材料学院,02代表机械学院,03代表外语学院,20代表软件学院;第5、6位是学院内部班级编号,最后两位是班级内部学号。如:18011103,入学年份是2018年,材料学院,11班,03号

    输入格式:

    8位数字组成的学号。例如:18011103
    注意:输入学号不是8位或者学院编号不是01、02、03、20其中之一,属于非法输入

    输出格式:

    学号每一项的完整说明。例如:
    入学年份:2018年
    学院:材料学院
    班级:11
    学号:03

    注意:如非法输入,输出“Wrong Format"

    复制代码
    import java.util.Scanner;
    public class Main{
        public static void main(String[] args){
            
           // String x;
            String xn,xy,bj,xh;//分别代表年份,学院编号,学院内部班级编号,班级内部学号
            Scanner sc = new Scanner(System.in);
            String x=sc.next();
            int length=x.length();
            if(x.length()!=8){
                System.out.println("Wrong Format");
                return;
            }
            else{
                xn=x.substring(0,2);
                xy=x.substring(2,4);
                bj=x.substring(4,6);
                xh=x.substring(6,8);
           }
            int value = Integer.parseInt(x.substring(2,4));
             //System.out.println("入学年份:"+"20"+x.substring(0,2)+"年");
            if(value!=01&&value!=02&&value!=03&&value!=20){
                System.out.println("Wrong Format");
                return;
            }
            System.out.println("入学年份:"+"20"+x.substring(0,2)+"年");
            if(value==01){
                 System.out.println("学院:材料学院");
            }else if(value==02){
                 System.out.println("学院:机械学院");
            }else if(value==03){
                 System.out.println("学院:外语学院");
            }else if(value==20){
                 System.out.println("学院:软件学院");
            }else{
                System.out.println("Wrong Format");
            }
            System.out.println("班级:"+x.substring(4,6));
            System.out.print("学号:"+x.substring(6,8));
    
        }
    }
    复制代码

 

 


 

7-7 判断三角形类型

 

输入三角形三条边,判断该三角形为什么类型的三角形。

输入格式:

在一行中输入三角形的三条边的值(实型数),可以用一个或多个空格或回车分隔,其中三条边的取值范围均为[1,200]。

输出格式:

(1)如果输入数据非法,则输出“Wrong Format”;
(2)如果输入数据合法,但三条边不能构成三角形,则输出“Not a triangle”;
(3)如果输入数据合法且能够成等边三角形,则输出“Equilateral triangle”;
(3)如果输入数据合法且能够成等腰直角三角形,则输出“Isosceles right-angled triangle”;
(5)如果输入数据合法且能够成等腰三角形,则输出“Isosceles triangle”;
(6)如果输入数据合法且能够成直角三角形,则输出“Right-angled triangle”;
(7)如果输入数据合法且能够成一般三角形,则输出“General triangle”。

复制代码
import java.util.*;
public class Main{
    public static void main(String[] args){

    Scanner input = new Scanner(System.in);
        double x=input.nextDouble();
        double y=input.nextDouble();
        double z=input.nextDouble();
        if(x<1||x>200||y<1||y>200||z<1||z>200){
            System.out.println("Wrong Format");
           return;
        }else if((x+y<=z)||(x+z<=y)||(y+z<=x))
                 {
            System.out.println("Not a triangle");
            return;
        }
            else if(x==y&&y==z&&x==z){
            System.out.println("Equilateral triangle");
            return;
        }else if(Math.abs(x*x+y*y-z*z)<0.000001){
            if(x==y){
            System.out.println("Isosceles right-angled triangle");
            }
                else {
                    System.out.println("Right-angled triangle");
                }
        }else if(Math.abs(y*y+z*z-x*x)<0.000001){
            if(y==z){
            System.out.println("Isosceles right-angled triangle");
            }
                else {
                    System.out.println("Right-angled triangle");
                }
            return;
        }else if(Math.abs(x*x+z*z-y*y)<0.000001){
            if(x==z){
            System.out.println("Isosceles right-angled triangle");}
                else {
                    System.out.println("Right-angled triangle");
                }
            return;}
        else if(x==y||y==z||x==z){
            System.out.println("Isosceles triangle");
            return;
        }
        else {
            System.out.println("General triangle");
            }
        }
        }
复制代码

 

踩坑心得:第一次作业题目偏简单,但是学习了一些比较基础的方法,例如Integer.psrseInt()整型数据类型Integer转换为基本数据类型int和substring()字符串截取方法,主要在 7-6 体现。还有就是注意精度(double和float的使用),以及证明直角三角形存在误差。可以设置一个很小的误差比如0.000001.


 

pta二、

7-3 String的格式判断与内容提取
 
作者 蔡轲
单位 南昌航空大学

学校学生学号格式定义如下:
2位年级号+2位学院号+2位班级号+2位序号,如19041103,
编写程序处理用全院学生学号连接起来的长字符串,学院编号为20,包括17、18、19、20四个年级,请从字符串中提取特定两个班级202017班、202061班同学的学号后四位输出,输出编号之间用空格分隔,不换行。
注意:需要排除非法输入。

输入格式:

全院学生学号组成的长字符串(学号之间无分隔)
学号格式定义如下:
2位年级号+2位学院号+2位班级号+2位序号,如19041103,

输出格式:

特定两个班级202017班、202061班同学的学号后四位
如:1701 6103 1704

复制代码
import java.util.*;
public class Main{
    public static void main(String[] args){
        String nj,xy,bj,xh;
        Scanner sc = new Scanner(System.in);
        String s=sc.nextLine();
  for(int i=0;i<s.length();i++){
            char ch=s.charAt(i);
            if(ch<'0'||ch>'9'){
                System.out.print("Wrong Format");
                return;
            }
  }
        if(s.length()%8!=0){
            System.out.print("Wrong Format");
            return;
        }
        int count=0;
        for(int i=0;i<s.length();i+=8){
            int value=Integer.parseInt(s.substring(i,i+6));
            int last=Integer.parseInt(s.substring(i+4,i+8));
            if(value==202017||value==202061){
                if(count==1){
                System.out.print(" ");}
                System.out.print(last);
                count=1;
            }
        }
    }
}
复制代码

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

复制代码
import java.util.*;
 
public class Main {
 
    public static void main(String[] args) {
        
        Scanner sc = new Scanner(System.in);
    
        String a = sc.nextLine();
        char[] b=new char[500];
       int x=0;
        int y=1;
       int count=0;
       for(int i=0;i<a.length();i++){
           b[i]=a.charAt(i);  //字符串转化为整型数字
           if(b[i]=='1'){
              
               count++;//数据‘1’空闲位自增
           }
       }if(count==a.length()||a.length()<11){
           System.out.print("null data");//数据全为1或者不足11位
       }
        else {
            for(int i=0;i<a.length();i++){
                if(b[i]=='0'&&i+10<a.length()){
                    String str=a.substring(i+1,i+9);//字符串截取
                      for(int j=i+1;j<i+9;j++)
                      {
                          if(b[j]=='1'){
                             // int x=0;
                              x++;//记录1的个数进行奇偶校验
                          }
                      }
                   // int y=1;
                  if(b[i+10]!='1'){
                       System.out.println(y+":"+"validate error");
                        y++;
                  }
                 else if(x%2!=1&&b[i+9]=='0'){
                        System.out.println(y+":"+"parity check error");
                     y++;
                    }
                    else if (x%2==1&&b[i+9]=='1')
                    {
                         System.out.println(y+":"+"parity check error");
                        y++;
                    }
                    else if(x%2==1&&b[i+9]=='0'&&b[i+10]=='1'){
                        System.out.println(y+":"+str);
                        y++;
                    }else if(x%2==0&&b[i+9]=='1'&&b[i+10]=='1'){
                        System.out.println(y+":"+str);
                        y++;
                    } 
                    i=i+10;//11一个循环
                    x=0;
                }
            }
        }
        }
}
复制代码

可以看到这次代码最大深度以及平均深度超出了良好范围,一个函数当中包含很多函数语句。

错误为自增变量设置导致在for循环当中没有变回初值,后面在第二层循环外给变量重新赋值最后测试点通过

 

踩坑心得:第二次作业难度提升了一点点,在第二次作业中用ASCII码表用的较为频繁,用了charAt()方法(字符的索引),主要是判断格式输入是否正确,a-z,A-Z以及1-9。还有就是next()以及nextLine()两个之间的区别。next()一定要读取到有效字符后才可以结束输入,对输入有效字符之前遇到的空格键、Tab键或Enter键等结束符,next()方法会自动将其去掉,只有在输入有效字符之后,next()方法才将其后输入的空格键、Tab键或Enter键等视为分隔符或结束符。比如,在控制台输入“ gjm gjm ”时,一次next()读入进来的仅仅是"gjm"。它不能得到带空格的字符串的。nextLine()方法的结束符只是Enter键,即nextLine()方法返回的是Enter键之前的所有字符。比如,在控制台输入“ gjm gjm ”时,一次nextLine()读入进来的结果是" gjm gjm "。它是可以得到带空格的字符串的。在第三题当中因为空格这一区别,先是用的next(),导致一个测试点一直没过,最后问了室友才知道要用nextLine()。

改进建议: 对自增变量多一个心眼或者写好注释,就不会在调试的时候一直发现不了错误,特别是嵌套在for循环语句当中的变量。


 

pta三、

7-1 点线形系列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

 

  • 设计与分析

设计点和输入两个类,创造两个点对象,计算距离

复制代码
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        double s=0;
      //  String l=input.nextLine();
        Input x=new Input();
        x.l=input.nextLine();
        Dian p=new Dian();
        Dian p1=new Dian();//创造一个使用distance方法的对象,子类的无参数构造方法
        Dian p2=new Dian();
        if(x.shuru()==0){
            System.out.print("Wrong Format");
        }else if(x.shuru()==1){
            System.out.print("wrong number of points");
        }else{
            p1.setX(x.getX(0));
            p1.setY(x.getY(0));
            p2.setX(x.getX(1));
            p2.setY(x.getY(1));
            s=p.distance(p1,p2);
            System.out.print(s);
        }
    }
}
class Dian{
    private double x,y;//私有化,需要设定的方法 对象才能拥有相应属性
     public double distance(Dian p1,Dian p2){
        double s;
        s=Math.sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
        return s;
    }

    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;
    }
    public Dian(){
         super();//子类无参数构造器
    }
}
class Input{
    String l;
    int shuru(){
        String dian[]=l.split(" ");
        String x[]=null;
        for(String i:dian){
            x=i.split(",");
            for(String j:x){
                if (!j.matches("^[+-]?(0|(0\\.\\d+)?|[1-9]*(\\.\\d+)?)$")) {
                   // System.out.print("Wrong Format");
                    return 0;
                }
            }
        }
        if(dian.length!=2){
           // System.out.print("wrong number of points");
            return 1;
        }
        return 2;
    }
    double getX(int a){
        String[] dian =l.split(" ");
        String[] num=dian[a].split(",");
        return Double.parseDouble(num[0]);
    }
    double getY(int a){
        String[] dian =l.split(" ");
        String[] num=dian[a].split(",");
        return Double.parseDouble(num[1]);
    }
}
复制代码

踩坑心得:第一题代码长度不长,所用的类和方法也比较简单,合法输入以及获取点,刚开始写再回过头来发现其实一个类就够了,第一题只是预热,所以可以从上图看到代码各方面都比较良好,复杂度不高。

改进建议:非法输入可以用正则表达式,简单精炼,出错率较低。


7-2 点线形系列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",

  • 设计与分析

设计点和线两个类,判断非法输入用正则表达式编写,if else 语句判断题目五种情况,首先判断输入点的个数是否正确,再执行下一步,调用各种方法实现题目。

复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        String[] a = str.split(":");
        if(a[0].isEmpty()||a[0].equals("")){
            System.out.println("Wrong Format");
            return;
        }
        int option = Integer.parseInt(a[0]);
        String[] points = a[1].split(" ");
//        System.out.println(points[0]);
//        System.out.println(points[1]);
        if(!str.matches("^[1-5]:(([+-]?(0(\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)),([+-]?(0(\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)) )*(([+-]?(0(\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)),([+-]?(0(\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?))) *"))
        {
            System.out.println("Wrong Format");
            return;
        } if(option == 1){
            if (points.length != 2) {
                System.out.print("wrong number of points");
               return;
            }
            Point point1 = new Point();
            Point point2 = new Point();
            for (int i = 0;i < 2; i++) {
                String[] p = points[i].split(",");
                String x1 = p[0];
                String y1 = p[1];
                if(i == 0){
                    point1.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
                if(i == 1){
                    point2.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
            }
            Line line = new Line();
            line.p1 = point1;
            line.p2 = point2;
            if(point1.check_point(point2)){
                System.out.println("points coincide");
                return;
            }
            if(!line.check_slope()){
                System.out.println("Slope does not exist");
                return;
            }
            System.out.println(line.xielv());
        }
        if(option == 2){
            if (points.length != 3) {
                System.out.print("wrong number of points");
               return;
            }
            Point point1 = new Point();
            Point point2 = new Point();
            Point point3 = new Point();

            for (int i = 0;i < 3; i++) {
                String[] p = points[i].split(",");
                String x1 = p[0];
                String y1 = p[1];
                if(i == 0){
                    point1.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
                if(i == 1){
                    point2.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
                if(i == 2){
                    point3.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
            }
            Line line = new Line();
            line.p1 = point2;
            line.p2 = point3;
            if(point2.check_point(point3)){
                System.out.println("points coincide");
                return;
            }
            if(!line.check_slope()){
                System.out.println(Math.abs(point1.getX()-point2.getX()));
                return;
            }
           System.out.println(line.linedistance(point1));
        }
        if(option == 3){
            if (points.length != 3) {
                System.out.print("wrong number of points");
                return;
            }
            Point point1 = new Point();
            Point point2 = new Point();
            Point point3 = new Point();
            for (int i = 0;i < 3; i++) {
                String[] p = points[i].split(",");
                String x1 = p[0];
                String y1 = p[1];
                if(i == 0){
                    point1.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
                if(i == 1){
                    point2.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
                if(i == 2){
                    point3.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
            }
            Line line = new Line();
            line.p1 = point2;
            line.p2 = point3;
            //if(point2.check_point(point3)||point1.check_point(point2)||point1.check_point(point3)){
              //  System.out.println("points coincide");
               // return;
          //  }
            if(!line.check_slope()){
                System.out.println(point1.getX()==point2.getX());
                return;
            }else 
                
            System.out.println(line.if_on_line(point1));
        }
        if(option == 4 || option == 5){
    
            if (points.length != 4) {
                System.out.print("wrong number of points");
                return;
            }
            Point point1 = new Point();
            Point point2 = new Point();
            Point point3 = new Point();
            Point point4 = new Point();
            for (int i = 0;i < 4; i++) {
                String[] p = points[i].split(",");
                String x1 = p[0];
                String y1 = p[1];
                if(i == 0){
                    point1.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
                if(i == 1){
                    point2.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
                if(i == 2){
                    point3.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
                if(i == 3){
                    point4.input(Double.parseDouble(x1),Double.parseDouble(y1));
                }
            }
            Line line1 = new Line();
            Line line2 = new Line();
            line1.p1 = point1;
            line1.p2 = point2;
            line2.p1 = point3;
            line2.p2 = point4;
            if (line1.p1.check_point(line1.p2)||line2.p1.check_point(line2.p2)){
                System.out.println("points coincide");
            return;
            }
            if(option == 4){
                if(!line1.check_slope()&&!line2.check_slope())
                {
                    System.out.println("true");
                    return;
                }else if (!line1.check_slope()&&line2.check_slope())
                {
                    System.out.println("false");
                    return;
                }else if (line1.check_slope()&&!line2.check_slope())
                {
                    System.out.println("false");
                    return;
                }else
                System.out.println(line1.parallel(line2) != -1 );
            }
            if(option == 5){

                if(line1.parallel(line2) != -1){
                    System.out.println("is parallel lines,have no intersection point");
                   return;
                }

                Point point = line1.jiaodian(line2);
if(point.x==point1.x&&point.y==point1.y){
    System.out.print(point.getX() + "," + point.getY() + " " +"false"); 
  
}else if(point.x==point2.x&&point.y==point2.y){
    System.out.print(point.getX() + "," + point.getY() + " " +"false"); 
   
}else if(point.x==point3.x&&point.y==point3.y){
    System.out.print(point.getX() + "," + point.getY() + " " +"false"); 
    
}else if(point.x==point4.x&&point.y==point4.y){
    System.out.print(point.getX() + "," + point.getY() + " " +"false"); 、
}else              
    System.out.println(point.getX() + "," + point.getY() + " " +(line1.if_in_line(point) || line2.if_in_line(point)));     
            }
        }
    }
}
class Point {
    String l;
    public double x, y;
    //读入x y 的值//
    public void input(double x, double y) {
        this.x = x;
        this.y = y;
    }
    //读取x的值//
    public double getX() {
        return x;
    }
    //读取y的值//
    public double getY() {
        return y;
    }
    //计算两点的距离//
    public double calculate_distance(Point p) {
        return Math.sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
    }
    //检查线的两点是否重合//
    public boolean check_point(Point p) {
        boolean flag = false;
        if (Math.abs(x - p.getX()) < 1e-16 && Math.abs(y - p.getY()) < 1e-16)
            flag = true;
        return flag;
    }
}
class Line {
    Point p1 = new Point();
    Point p2 = new Point();
double a,b,c;
    //检查线段的斜率是否存在//
    public boolean check_slope() {
        boolean flag = true;
        if (Math.abs(p1.getX() - p2.getX()) < 1e-15) {
            flag = false;
        }
        return flag;
    }
    //计算线段的斜率//
    public double xielv() {
        return (p1.getY() - p2.getY()) / (p1.getX() - p2.getX());
    }
    //计算点到直线的距离//
     public double linedistance(Point l) {
        zcline(this);
        double distance;
       // if (if_on_line(l)) {
         //   distance = 0;//在直线上
        //} else {
            distance=Math.abs(a*l.getX()+b*l.getY()+c)/Math.sqrt(a*a+b*b);
          //  distance = Math.abs(a.getX() * p1.getY() + p1.getX() * p2.getY() + p2.getX() * a.getY() - a.getX() * p2.getY() - p1.getX() * a.getY() - p2.getX() * p1.getY()) / p1.calculate_distance(p2);
        //}
        return distance;
    }
    //判断点是否再直线上//
    public boolean if_on_line(Point p) {
        boolean flag = false;
        Line l2 = new Line();
        l2.p1 = p1;
        l2.p2 = p;
        if (this.xielv() == l2.xielv()) {
            flag = true;
        }
        return flag;
    }
    //判断点是否在线段内//
//在线段内返回true,在线段外返回false//
    public boolean if_in_line(Point p) {
        boolean flag = false;
        if (if_on_line(p)) {
            if (p.calculate_distance(p1) > p1.calculate_distance(p2) || p.calculate_distance(p2) > p1.calculate_distance(p2))
                return flag;
            else {
                flag = true;
            }
            return flag;
        }
        return flag;
    }
    //判断两直线是否平行//
//若两直线平行返回1,若两直线重合返回0,若两直线相交返回-1
    public int parallel(Line l) {//判断是否平行
        int count;
        if (this.xielv() != l.xielv()) {
            count = -1;
        } else {
            if (l.linedistance(p1) == 0) {
                count = 0;
            } else {
                count = 1;
            }
        }
        return count;
    }
public void zcline(Line l){
        l.a= l.p1.getY()- l.p2.getY();
        l.b= l.p2.getX()-l.p1.getX();
        l.c= l.p2.getY()*l.p1.getX()-l.p2.getX()*l.p1.getY();
    }
    //计算两直线交点,返回Point//
    public Point jiaodian(Line l) {
        zcline(l);
        zcline(this);
        Point p = new Point();
        double x,y;
        x=(b*l.c-l.b*c)/(a*l.b-l.a*b);
        y=(a*l.c-l.a*c)/(l.a*b-a*l.b);
        p.input(x,y);
        return p;
    }
}
复制代码

踩坑心得:第二题相比第一题难度提升很大,用边和点两个类,以及要熟悉正则表达式的编写,边和点两个类中含有较多种方法,可以从上图可知,代码的圈复杂度明显增大,平均深度也较大,代码水平质量不是很高,第一次用面向对象的方法写还是比较吃力,用了较多的if else语句。题目并没有过全部测试点,输入所有测试案列依旧有测试点过不去,对类的方法属性掌握不够熟练。

改进建议:减少if else 语句的运用,擅长于用少而精炼的方法来排出非法输入以及特殊情况,以及对类中方法的作用性更加明了。

 


 

7-3 点线形系列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",

  • 设计与分析

创造点、线、三角形三个类。点构成边,边构成三角形,再根据三角形的性质,判断能否构成三角形,直线与三角形的三条边有没有交点,有几个交点,再根据面积公式算出面积。用左边轴辅助解题会更好。

下面为三个类的设计,主类与前一题大差不差

复制代码
class Point {
    String l;
    public double x;
    public double y;
    //读入x y 的值//
    public void input(double x, double y) {
        this.x = x;
        this.y = y;
    }
    //读取x的值//
    public double getX() {
        return x;
    }

    //读取y的值//
    public double getY() {
        return y;
    }

    public boolean check_point(Point p) {
        boolean flag = false;
        if (Math.abs(x - p.getX()) < 1e-16 && Math.abs(y - p.getY()) < 1e-16)
            flag = true;

        return flag;
    }

    public double calculate_distance(Point p) //点的距离
    {

        return Math.sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
    }
}
class Line {
    Point p3 = new Point();
    double a, b, c;
    Point p1 = new Point();
    Point p2 = new Point();

    //检查线段的斜率是否存在//
    public boolean check_slope() {
        boolean flag = true;
        if (Math.abs(p1.getX() - p2.getX()) < 1e-15) {
            flag = false;
        }
        return flag;
    }
    //点到直线距离
    public double linedistance(Point l) {
        zcline(this);
        double distance;
        distance = Math.abs(a * l.getX() + b * l.getY() + c) / Math.sqrt(a * a + b * b);
        return distance;
    }
    //计算线段的斜率//
    public double xielv() {
        return (p1.getY() - p2.getY()) / (p1.getX() - p2.getX());
    }

    public boolean if_on_line(Point p) {
        boolean flag = false;
        Line l2 = new Line();
        l2.p1 = p1;
        l2.p2 = p;
        if (Math.abs(this.a * p.x + this.b * p.y + this.c) < 1e-15) {
            flag = true;
        }
        return flag;
    }
    //判断点是否在线段内//
//在线段内返回true,在线段外返回false
    public boolean if_in_line(Point p) {
        boolean flag = false;
        if (if_on_line(p)) {
            if (p.calculate_distance(p1) > p1.calculate_distance(p2) || p.calculate_distance(p2) > p1.calculate_distance(p2))
                return flag;
            else {
                flag = true;
            }
            return flag;
        }

        return flag;
    }
    //判断两直线是否平行//
//若两直线平行返回1,若两直线重合返回0,若两直线相交返回-1
    public int parallel(Line l) {//判断是否平行
        int count;
        if (this.xielv() != l.xielv()) {
            count = -1;
        } else {
            if (l.linedistance(p1) == 0) {
                count = 0;
            } else {
                count = 1;
            }
        }
        return count;
    }
    //直线一般表达式
    public void zcline(Line l) {
        l.a = l.p1.getY() - l.p2.getY();
        l.b = l.p2.getX() - l.p1.getX();
        l.c = l.p2.getY() * l.p1.getX() - l.p2.getX() * l.p1.getY();
    }
    //计算两直线交点,返回Point
    public Point jiaodian(Line l) {
        zcline(l);
        zcline(this);
        Point p = new Point();
        double x, y;
        x = (b * l.c - l.b * c) / (a * l.b - l.a * b);
        y = (a * l.c - l.a * c) / (l.a * b - a * l.b);
        p.input(x, y);
        return p;
    }
}
class Triangle {
    Point p1 = new Point();
    Point p2 = new Point();
    Point p3 = new Point();

    //j检查能否构成三角形
    public boolean checktriangle() {
        boolean flag = true;
        if (Math.abs(p1.calculate_distance(p2) - p1.calculate_distance(p3)) < p2.calculate_distance(p3)
                && Math.abs(p1.calculate_distance(p3) + p1.calculate_distance(p2)) > p2.calculate_distance(p3)) {
            flag = false;
        }
        return flag;
    }

    //判断为等腰三角形==0还是等边三角形==1
    public int shape_what_triangle() {
        int shape = 0;
        if (Math.abs(p1.calculate_distance(p2) - p1.calculate_distance(p3)) < 1e-15 && Math.abs(p2.calculate_distance(p1) - p2.calculate_distance(p3)) < 1e-15) {
            shape = 1;
        }
        return shape;

    }

    //计算周长
    public double calculateC() {
        return p1.calculate_distance(p2) + p1.calculate_distance(p3) + p2.calculate_distance(p3);
    }

    //计算面积
    public double calculateS() {
        return Math.abs(p1.getX() * p2.getY() + p2.getX() * p3.getY() + p3.getX() * p1.getY()
                - p1.getX() * p3.getY() - p2.getX() * p1.getY() - p3.getX() * p2.getY()) / 2;
    }

    //计算三角形重心
    public Point zhongxin() {
        Point p = new Point();
        double dx = (p1.getX() + p2.getX() + p3.getX()) / 3;
        double dy = (p1.getY() + p2.getY() + p3.getY()) / 3;
        p.input(dx, dy);
        return p;
    }

    //若是锐角三角形返回1,若是直角三角形返回0,若是钝角三角形则返回-1
    public int shape_jiao_triangle() {
        int shape;
        double s1 = (p2.getX() - p1.getX()) * (p3.getX() - p1.getX())
                + (p2.getY() - p1.getY()) * (p3.getY() - p1.getY());
        double s2 = (p3.getX() - p2.getX()) * (p1.getX() - p2.getX())
                + (p3.getY() - p2.getY()) * (p1.getY() - p2.getY());
        double s3 = (p1.getX() - p3.getX()) * (p2.getX() - p3.getY())
                + (p1.getY() - p3.getY()) * (p2.getY() - p3.getY());
        if (s1 < 0 || s2 < 0 || s3 < 0) {
            shape = 1;
        } else if (s1 == 0 || s2 == 0 || s3 == 0) {
            shape = 0;
        } else {
            shape = -1;
        }
        return shape;
    }
    //计算直线与三角形的交点 返回交点个数

    public int calculate_sum_jiaodian(Line a) {
        int sum = 0;
        Line l1 = new Line();
        l1.p1 = p1;
        l1.p2 = p2;
        l1.zcline(l1);
        Line l2 = new Line();
        l2.p1 = p1;
        l2.p2 = p3;
        l2.zcline(l2);
        Line l3 = new Line();
        l3.p1 = p2;
        l3.p2 = p3;
        l3.zcline(l3);
        if (l1.parallel(a) == 1) {
            Point point1 = a.jiaodian(l2);
            if (l2.if_in_line(point1)) {
                sum++;
            }
            Point point2 = a.jiaodian(l3);
            if (l3.if_in_line(point2)) {
                sum++;
            }
        } else if (l2.parallel(a) == 1) {
            Point point1 = a.jiaodian(l1);
            if (l1.if_in_line(point1)) {
                sum++;
            }
            Point point2 = a.jiaodian(l3);
            if (l3.if_in_line(point2)) {
                sum++;
            }
        } else if (l3.parallel(a) == 1) {
            Point point1 = a.jiaodian(l1);
            if (l1.if_in_line(point1)) {
                sum++;
            }
            Point point2 = a.jiaodian(l2);
            if (l2.if_in_line(point2) && !point1.check_point(point2)) {
                sum++;
            }
        } else {
            Point point1 = a.jiaodian(l1);
            if (l1.if_in_line(point1)) {
                sum++;
            }
            Point point2 = a.jiaodian(l2);
            if (l2.if_in_line(point2) && !point1.check_point(point2)) {
                sum++;
            }
            Point point3 = a.jiaodian(l3);
            if (l3.if_in_line(point3) && !point1.check_point(point3) && !point2.check_point(point3)) {
                sum++;
            }
        }
        return sum;
    }

    //分割后三角形面积
    public double fenge_triangleS(Line l) {

        Line l1 = new Line();
        Line l2 = new Line();
        Line l3 = new Line();

        Point p1 = new Point();
        Point p2 = new Point();
        Point p3 = new Point();
        p1 = l.p1;
        p2 = l.p2;
        p3 = l.p3;
        l1.p1 = p1;
        l1.p2 = p2;
        l2.p2 = p2;
        l2.p3 = p3;
        l3.p1 = p1;
        l3.p3 = p3;
        l1.zcline(l1);
        l1.zcline(l2);
        l1.zcline(l3);

        double s = 0;

        if (l.parallel(l1) != -1) {

            p1 = l.jiaodian(l3);

            p2 = l.jiaodian(l2);

            l.p1 = p1;
            l.p2 = p2;
            s = l1.linedistance(this.p3) * p1.calculate_distance(p2) / 2;
            if (s <= calculateS() / 2)
                return s;
            else
                return calculateS() - s;

        }
        if (l.parallel(l3) != -1) {

            p1 = l.jiaodian(l1);
            p2 = l.jiaodian(l2);
            l.p1 = p1;
            l.p2 = p2;
            s = l.linedistance(this.p1) * p1.calculate_distance(p2) / 2;
            if (s <= calculateS() / 2)
                return s;
            else
                return calculateS() - s;
        }
        if (l.parallel(l2) != -1) {

            p1 = l.jiaodian(l3);
            p2 = l.jiaodian(l1);

            l.p1 = p1;
            l.p2 = p2;

            s = l.linedistance(this.p2) * p1.calculate_distance(p2) / 2;
            if (s <= calculateS() / 2)
                return s;
            else
                return calculateS() - s;
        }
        p1 = l.jiaodian(l1);
        p2 = l.jiaodian(l3);
        p3 = l.jiaodian(l2);
        if (!l1.if_in_line(p1)) {

            l.p2 = p2;
            l.p3 = p3;

            s = l.linedistance(this.p1) * p2.calculate_distance(p3) / 2;
        }
        if (!l3.if_in_line(p2)) {
            l.p1 = p1;
            l.p3 = p3;
            s = l.linedistance(this.p2) * p1.calculate_distance(p3) / 2;
        }
        if (!l2.if_in_line(p3)) {
            l.p1 = p1;
            l.p2 = p2;
            s = l.linedistance(this.p3) * p1.calculate_distance(p2) / 2;
        }
        if (s <= calculateS() / 2)
            return s;
        else
            return calculateS() - s;
    }

    //判断是否在三角形内部

    public boolean if_inside(Point p) {
        Line a = new Line();
        Line b = new Line();
        Line c = new Line();
        a.p1 = p1;
        a.p2 = p2;
        b.p1 = p2;
        b.p2 = p3;
        c.p1 = p3;
        c.p2 = p1;
        a.zcline(a);
        b.zcline(b);
        c.zcline(c);
        double s1 = a.linedistance(p) * (a.p1).calculate_distance(a.p2) * 1 / 2;
        double s2 = b.linedistance(p) * (b.p1).calculate_distance(b.p2) * 1 / 2;
        double s3 = c.linedistance(p) * (c.p1).calculate_distance(c.p2) * 1 / 2;

        if (Math.abs(s1 + s2 + s3 - calculateS()) < 1e-15)
            return true;
        else
            return false;
    }
}

可以看到这题代码圈复杂度较高,以及最大复杂度,平均复杂度为3.95,也算良好。
复制代码

 

踩坑心得:本次代码也没有满分,还没有足够的能力去过每一个测试点,就算测试样例都过也依旧有测试点错误,写类的时候还需要注意是私有变量还是公有变量,对类的对象定义时变量名也要注意,还有创造线对象时,不要忽略计算这个线具体的表达式,题目要求射线法,但是实在逻辑思维容易混乱,最终还是用了面积法。

改进建议:对if else语句的运用也要减少,提升自己的逻辑思维,多写注释,多动手操作,考虑多种情况,还要加强对类中属性和方法的定义使用,静态方法和动态方法的使用。


 

  • 总结

这三次作业不仅是找回之前的语言知识,也是对java类的属性和方法的了解和初步掌握,在自己完成题目训练的过程中,不单单只考虑通过题目的测试,另一方面要去思考如何提高代码的可读性和简洁性,更好的展现知识成果。对老师上课讲的内容要及时实践温习,这样只有在做题时更加游刃有余。

 

 

 

 

 
 
posted @ 2022-10-02 18:09  Dtyyyy  阅读(283)  评论(0)    收藏  举报