大皮

去见、去学、去写。

南昌航空大学 软件学院 pta java 第一阶段总结

嗨嗨嗨
到了每月一次的总结时间了
主要是总结前三次
具体代码在另外几篇博客里
本博客更多的对一些重要的题目做一个讲解和总结

drawing

目录

代码链接

      第一次作业

      第二次作业

      第三次作业

前言

    三次题目都完(也)(许)写完了,java作业治好了我的精神内耗

drawing

    对于森林小精灵laster、大佬jc等等等等人秒杀三期作业的行为我只能orz.but,他们的强大并不影响我老老实实敲代码,我绝对不当压力小子,坚持稳扎稳打,也希望大家也能耐住性子打代码,不要网上随便找到一串别人的代码就狠狠偷。接下来我会以题量、知识点和难度三个方面对三次作业的总体水平进行一个简单评价。

题量

    题量方面,作业一为7题,作业二三为3题,虽然作业一题量更大但实际上是三的题量更大一些hhhh,在第三次作业的题目里,有很多的case,而那些case要比题目一中的题目要复杂的多,题量最少的是第二次作业。

知识点

    知识点方面,第一二次作业主要是语法的学习,第二次还有于正则表达式的学习,但是用面向过程的方法也能很好解决,第三次作业主要是对面向对象方法的学习,如果方法和类封装的不好会做的很吃力。

难度

    难度方面,最难的肯定是第三次,然后是第一次,最后是第二次。第三次的难度在于早已忘了的的数学知识、复杂的判断,还有精度控制(还有正则表达式hhhh)。第一次的难度更多在于语法的不熟悉,很多人都是第一次用java,而且java的语法扩展上有很多与c不一样的地方,所以难点更多在于对新鲜事物的学习与使用,并且第一次整整有七题,一题一题敲还是要花很长时间的,另外还有一些精度的坑hhhh,真的很浪费时间。

drawing

    第二次和另外两次比起来就好很多,相对来说难度就没那么大,题量或者是题目难度来说,都不是很高,唯一可以体现含金量的正则表达式过程,都被我用if else的分支结构给解决了。

设计与分析

    个人认为,代码的设计构造要比过题思路要重要的多,要是一些方法没封装起来,会让人绕晕,而且代码可读性巨差(有幸看过一些学弟学妹的代码,乍一眼巨晕hhh。他们在一if else中还能把代码思路理清楚真的挺厉害的)。而我也勉勉强强做到了封装。后面我会对几个比较重要的题目进行剖析,按类按方法进行讲解和作用。

7-2 串口字符解析

    很惭愧,这题我用的是面向过程的写法,只有一个类一个方法,圈复杂度有点抽象。
    不急,先看题。
    RS232是串口常用的通信协议,在异步通信模式下,串口可以一次发送5 ~ 8 位数据,收发双方之间没有数据发送时线路维持高电平,相当于接收方持续收到数据“1”(称为空闲位),发送方有数据发送时,会在有效数据(5~8位,具体位数由通信双方提前设置)前加上1位起始位“0”,在有效数据之后加上1位可选的奇偶校验位和1位结束位“1”。请编写程序,模拟串口接收处理程序,注:假定有效数据是8位,奇偶校验位采用奇校验。
    题目的大概意思就是处理一个字符串,并从中读出一段段数据,数据是有包头包尾的,且题目设置一个数据包长度为11个字符串,看懂这些其实就很简单了。即使仅仅使用面对过程的方法也很轻松

    只有一个类,没啥比较,算法简单,圈复杂度也简单。

Main

    很遗憾的,只有一个main类和一个main方法,想来想去还是不想改,大概是记录自己一个学习的过程,让很多年后的我还能看看当年写的屎山hhh。

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String ch;
        int flag=1;
        ch = input.next();
        if(ch.length()<11){
            System.out.printf("null data");
            return;
        }
        A:for(int i=0;i<ch.length();i++){
            if(ch.charAt(i)=='0'&&ch.length()-i>10){
                System.out.printf("%d:",flag++);
                if(ch.charAt(i+10)!='1'){
                    System.out.printf("validate error\n");
                    i+=10;
                    continue ;
                }
                int f=0;
                for(int j=i+1;j<i+9;j++)
                    if(ch.charAt(j)=='1')
                        f++;
                if(((f&1)==0&&ch.charAt(i+9)!='1')||((f&1)==1&&ch.charAt(i+9)!='0')){
                    System.out.printf("parity check error\n");
                    i+=10;
                    continue ;
                }
                for(int j=i+1;j<i+9;j++)
                    System.out.printf("%c",ch.charAt(j));
                i+=10;
                System.out.printf("\n");
            }
        }
        if(flag==1){
            System.out.printf("null data");
            return;
        }
    }

}

7-1 点线形系列1-计算两点之间的距离

    题目简洁明了,就是要给你一串字符,问你其中包含的两个点的距离。
    难点在于正则表达式hhhh,搞了我巨久,好在最后彻底学会了,但是后面的正则表达式还是改了点,光用这个正则表达式后面题目的case过不去。其他没啥难度,算是一个顺承的过程,这个题目写的代码后面还能用。

drawing

    圈复杂度开始抽象起来了hhh。

1.Point

    属于点的类,包含有两点距离计算。

class Point {//点的类
    double x = 0 , y = 0 ;
    double DistanceCalculation(Point b) {
        return Math.sqrt((this.x-b.x)*(this.x-b.x)+(this.y-b.y)*(this.y-b.y));
    }//返回两点距离
}

2.PointTaking

    本来是作为字符输入和坐标剥离的,但是面向过程之魂燃烧,就开始处理起来了,是实际的主函数。

class PointTaking {
    String ch;
    double Solve() {
        Point a = new Point();
        int pos = 0;
        Point b = new Point();
        //  String[]
        String[] c  = this.ch.split(" ");//将字符串以空格分割

        for(String i:c) {//对分割的字符串遍历
            String[] d = i.split(",");
            for(String j:d) {
                //  System.out.printf(j+"\n");
                if(!j.matches("^[+-]?(([0-9][1-9]*\\.\\d+)|(0\\.\\d+)|([0-9][1-9]*))$"))//正则表达式判断是否合法
                    return -1;//返回输入错误
                if(pos==0)//按位读入坐标x1,y1,x2,y2
                    a.x =Double.parseDouble(j);
                else if(pos == 1)
                    a.y = Double.parseDouble(j);
                else if(pos == 2)
                    b.x=Double.parseDouble(j);
                else
                    b.y =Double.parseDouble(j);
                pos++;
            }

        }
        if(c.length!=2)
            return  -2;//返回错误点数量
        return a.DistanceCalculation(b);
    }

}

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"。

    好家伙,一题更比六题强。

drawing

蛋黄猫看完都累趴了

    咱们来梳理一下几个要求:1、判断垂直;2、判断点到直线距离;3、判断三点是否在一条直线;4、判断两直线是否平行;5、计算交叉点。
    梳理完其实就很明了了,我按case给大家讲解一下我的代码。

case1

    首先肯定是判断斜率是否为0,即两点x坐标相等,然后直接输出斜率,斜率这块我是封装在了线的类中的,在后面我会贴上各个类。

drawing

    圈复杂度高起来了。

            if(pointSet[1].x==pointSet[2].x) {
                System.out.printf("Slope does not exist");
                return 4;
            }

            line.a=pointSet[1];
            line.b=pointSet[2];
            System.out.printf(line.slope()+"");

case2

    还是和上题一样,贴上封装好的点到直线距离方法就行,方法会贴在后面。

            line.a = pointSet[2];
            line.b = pointSet[3];
            System.out.printf(line.pointVerticalDistanc(pointSet[1])+"");
            return 4;

case3

    判断是否在一条直线上,直接设置1、2点一条直线,以及1、3点一条直线,判断斜率是否相等,相等就是在一条线上。

            Line line2= new Line();
            line2.a = line.a = pointSet[1];
            line.b=pointSet[2];
            line2.b = pointSet[3];
            if(line2.slope()==line.slope())
                return 1;
            return 2;

case4

    这题不能直接用封装好的斜率了,因为有精度问题,把斜率公式搬过来就a了。

            Line line2= new Line();
            line.a = pointSet[1];
            line.b = pointSet[2];
            line2.a = pointSet[3];
            line2.b = pointSet[4];
            if((line.a.x-line.b.x)*(line2.a.y-line2.b.y)!=(line2.a.x-line2.b.x)*(line.a.y-line.b.y))
                return 2;
            return 1;

case5

    首先求焦点,然后判断是否在两条直线里面就行了,后面我把它封装到了Line类里面了。

            Line line2= new Line();
            line.a = pointSet[1];
            line.b = pointSet[2];
            line2.a = pointSet[3];
            line2.b = pointSet[4];
            if(line2.slope()==line.slope()){
                System.out.print("is parallel lines,have no intersection point");

                return 4;
            }
            Point point= line.intersection(line2);
            System.out.printf(point.x+","+point.y+" ");
            if((point.x<Math.max(line.a.x,line.b.x)&&point.x>Math.min(line.a.x,line.b.x))||(point.x<Math.max(line2.a.x,line2.b.x)&&point.x>Math.min(line2.a.x,line2.b.x)))
                System.out.printf("true");
            else
                System.out.printf("false");
        }
        return 5;

slope()

    简单的(y1-y2)/(x1-x2),判断一下斜率是否为0就行。

double slope(){//斜率
        if(this.a.x==this.b.x)
            return 0;
        return (this.a.y-this.b.y)/(this.a.x-this.b.x);
    }

intercept()

    也是一个公式的解决方法,用来为求两条直线是否是同一条直线做铺垫的。

    double intercept() {//截距
            return this.a.x-(this.slope())*this.a.y;
    }

pointVerticalDistanc()

    高中点到直线距离公式,死去的高中数学突然攻击我hhhh。

double pointVerticalDistanc(Point c){//点到线距离
        if(this.a.x==this.b.x)
            return Math.abs(c.x-this.a.x);
        if(this.a.y==this.b.y)
            return Math.abs(c.y-this.a.y);
        return Math.abs((this.a.y-this.b.y)*c.x+(this.b.x-this.a.x)*c.y+this.a.x*this.b.y-this.a.y*this.b.x)/
                Math.sqrt((this.a.y-this.b.y)*(this.a.y-this.b.y)+(this.a.x-this.b.x)*(this.a.x-this.b.x));
    }

7-3 点线形系列3-三角形的计算

    本次博客的最难题来了。简单分析一下这题的五个case,除了第四个很难之外,其他case其实都还好,各种格式错误、输入错误来来回回折磨我几个小时,我的强迫症一发作就必须把前面的case过掉才会安心做其他的case,然后就是疯狂提交:

drawing

    这也是一个调试小技巧,看懂掌声。
    按照规矩,咱们继续来看看题:

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"

    简单解读一下:1、判断三角形两条或者三条边是不是相等;2、输出周长面积重心;3、判断三角形内是否有钝角和直角;4、判断三角形和直线焦点,如果被分割输出被分割后面积;5、判断点是否在三角形内。浅谈一下,难度最高的肯定是case4,折磨了我巨久hhhh。

drawing

    摆烂下次一定。

    然后我们按类来讲讲我的代码。

case1

    点线距离公式直接用,就前面7-1封装的方法。

            int num = 0;
            double[] distance = new double [5];
            distance[1]=pointSet[1].DistanceCalculation(pointSet[2]);
            distance[2]=pointSet[1].DistanceCalculation(pointSet[3]);
            distance[3]=pointSet[2].DistanceCalculation(pointSet[3]);
            Arrays.sort(distance,0,4);
            //  System.out.printf(distance[1]+" "+distance[2]+" "+distance[3]+"\n");
            if(distance[1]+distance[2]<=distance[3])
                return -3;
            if(distance[1]==distance[2]||distance[2]==distance[3]||distance[3]==distance[1])
                System.out.printf("true ");
            else
                System.out.printf("false ");
            if(distance[1]==distance[2]&&distance[1]==distance[3]&&distance[3]==distance[2])
                System.out.printf("true");
            else
                System.out.printf("false");

case2

    周长就是三点距离和,面积是点到直线距离乘上直线长度,重心是三点横纵坐标之和的三分之一。

        else if (x == 2) {
            double[] distance = new double [5];
            distance[1]=pointSet[1].DistanceCalculation(pointSet[2]);
            distance[2]=pointSet[1].DistanceCalculation(pointSet[3]);
            distance[3]=pointSet[2].DistanceCalculation(pointSet[3]);
            Arrays.sort(distance,0,4);
            if(distance[1]+distance[2]<=distance[3])

                return -3;
            System.out.printf(printDouble(distance[1]+distance[2]+distance[3])+" "+printDouble(Math.sqrt((distance[1]+distance[2]+distance[3])*(distance[1]+distance[2]-distance[3])*(distance[1]+distance[3]-distance[2])*(distance[2]+distance[3]-distance[1]))/4)+" "+printDouble((pointSet[1].x+pointSet[2].x+pointSet[3].x)/3)+","+printDouble((pointSet[1].y+pointSet[2].y+pointSet[3].y)/3));

case3

    向量法完美解决。

            double[] distance = new double [5];
            distance[1] = pointSet[1].DistanceCalculation(pointSet[2]);
            distance[2] = pointSet[1].DistanceCalculation(pointSet[3]);
            distance[3] = pointSet[2].DistanceCalculation(pointSet[3]);
            Arrays.sort(distance,0,4);
            if(distance[1]+distance[2]<=distance[3])
                return -3;


            if((int)(distance[1]*distance[1])+(int)(distance[2]*distance[2])==(int)(distance[3]*distance[3]))
                System.out.printf("false true false");
            else if(distance[1]*distance[1]+distance[2]*distance[2]>distance[3]*distance[3])
                System.out.printf("false false true");
            else
                System.out.printf("true false false");

case4

    判断几个连接点直接用上个题目case5的代码就行,面积计算如下图:

drawing
            if(pointSet[1].x==pointSet[2].x&&pointSet[1].y==pointSet[2].y) {
                System.out.printf("points coincide");
                return 5;
            }
            double[] distance = new double [5];
            if((pointSet[5].x==pointSet[3].x&&pointSet[3].x==pointSet[4].x)||(pointSet[5].y==pointSet[3].y&&pointSet[3].y==pointSet[4].y))
                return -3;
            line.a=pointSet[1];line.b = pointSet[2];
            Triangle tri = new Triangle();
            tri.a = new Line();
            tri.b = new Line();
            tri.c = new Line();
            tri.a.a = pointSet[3];tri.a.b = pointSet[4];
            tri.b.a = pointSet[3];tri.b.b = pointSet[5];
            tri.c.a = pointSet[4];tri.c.b = pointSet[5];
            int num = 0;
            if(line.judgeIntersection(tri.a)==1)
                num++;
            if(line.judgeIntersection(tri.b)==1)
                num++;
            if(line.judgeIntersection(tri.c)==1)
                num++;
            if(num==0) {
                System.out.printf("0");
                return  5;
            }
            if(num==1||(num==2&&(line.sameIntersection(tri.c, tri.a)||line.sameIntersection(tri.b, tri.a)||line.sameIntersection(tri.c, tri.b)))){
                System.out.printf("1");
                return 5;
            }
            System.out.printf("2 ");
            double s = tri.area(),s2=0;
            if(line.judgeIntersection(tri.c)==-1|| line.sameIntersection(tri.c, tri.a)|| line.sameIntersection(tri.b, tri.c)){
                s2 = areaCalculation(pointSet[3],pointSet[4],pointSet[5],line,s);
            }
                
            else if(line.judgeIntersection(tri.b)==-1||line.sameIntersection(tri.a, tri.b)){
                s2=  areaCalculation(pointSet[4],pointSet[3],pointSet[5],line,s);
            }
                
            else
                s2 = areaCalculation(pointSet[5],pointSet[4],pointSet[3],line,s);
            System.out.printf(printDouble(Math.min(s2,s-s2))+" "+printDouble(Math.max(s2,s-s2)));

case5

    case5用点射法固定好了,代码如下。

            double[] distance = new double [5];
            if((pointSet[2].x==pointSet[3].x&&pointSet[3].x==pointSet[4].x)||(pointSet[2].y==pointSet[3].y&&pointSet[3].y==pointSet[4].y))
                return -3;
            Triangle a= new Triangle(),b= new Triangle(),c= new Triangle(),d= new Triangle();
            a.b= new Line();a.a= new Line();a.c = new Line();
            b.b= new Line();b.a= new Line();b.c = new Line();
            c.b= new Line();c.a= new Line();c.c = new Line();
            d.b= new Line();d.a= new Line();d.c = new Line();
            a.a.a=pointSet[2];a.a.b = pointSet[3];
            a.b.a=pointSet[2];a.b.b = pointSet[4];
            a.c.a=pointSet[4];a.c.b = pointSet[3];
            b.a.a=pointSet[1];b.a.b = pointSet[3];
            b.b.a=pointSet[1];b.b.b = pointSet[4];
            b.c.a=pointSet[4];b.c.b = pointSet[3];
            c.a.a=pointSet[2];c.a.b = pointSet[1];
            c.b.a=pointSet[2];c.b.b = pointSet[4];
            c.c.a=pointSet[4];c.c.b = pointSet[1];
            d.a.a=pointSet[2];d.a.b = pointSet[3];
            d.b.a=pointSet[2];d.b.b = pointSet[1];
            d.c.a=pointSet[1];d.c.b = pointSet[3];
            if(d.area()==0||b.area()==0||c.area()==0)
                System.out.println("on the triangle");
            else if(Math.abs(a.area()-b.area()-c.area()-d.area())<0.0005)
                System.out.printf("in the triangle");
            else
                System.out.println("outof the triangle");

sameIntersection()

    

boolean sameIntersection(Line line1,Line line2){//判断相交点是否相同
        Point point1=this.intersection(line1),point2=this.intersection(line2);
        if(point2.x==point1.x&&point1.y==point2.y)
            return true;
        return false;
    }

vectorComputation()

    判断点是否在线内好方法

 public static double vectorComputation(Point a,Point b,Point c){//计算点线是否相交
        double x1 = a.x-c.x, y1=a.y-c.y,x2=b.x-c.x,y2=b.y-c.y;
        return  x1*y2-x2*y1;
    }

Triangle

    除了之前用的一些类外,针对第三题我重新设置了一个类Triangle,主要功能是计算三角形的面积。

public class Triangle {
    Line a;
    Line b;
    Line c;

    public Triangle() {
    }

    double area() {
        double p = (Math.sqrt((this.a.a.x - this.a.b.x) * (this.a.a.x - this.a.b.x) + (this.a.a.y - this.a.b.y) * (this.a.a.y - this.a.b.y)) + Math.sqrt((this.b.a.x - this.b.b.x) * (this.b.a.x - this.b.b.x) + (this.b.a.y - this.b.b.y) * (this.b.a.y - this.b.b.y)) + Math.sqrt((this.c.a.x - this.c.b.x) * (this.c.a.x - this.c.b.x) + (this.c.a.y - this.c.b.y) * (this.c.a.y - this.c.b.y))) / 2.0;
        return Math.sqrt(p * (p - Math.sqrt((this.a.a.x - this.a.b.x) * (this.a.a.x - this.a.b.x) + (this.a.a.y - this.a.b.y) * (this.a.a.y - this.a.b.y))) * (p - Math.sqrt((this.b.a.x - this.b.b.x) * (this.b.a.x - this.b.b.x) + (this.b.a.y - this.b.b.y) * (this.b.a.y - this.b.b.y))) * (p - Math.sqrt((this.c.a.x - this.c.b.x) * (this.c.a.x - this.c.b.x) + (this.c.a.y - this.c.b.y) * (this.c.a.y - this.c.b.y))));
    }
}

踩坑心得

    这三次作业有很多巨让人难受的坑,有时候写着写着就摆烂了,一个点过不去就像蚂蚁在身上爬。第一个碰到的坑当然是第一次作业的第二题,要转换成float类型,要不然精度一直错hhhh,在不断的试错后,才成功。然后就是7-9,他有个转义符点的判断,这个也是蒙了一下。第二次作业最麻烦的就是最后一题,一直有三个case过不去,主要原因就是没有用正则表达式,所以正则表达式还是很重要的,要不然就得多用巨多if和else。
    回头看过去,没想到第三次作业的第二题wa的次数要比第三题多,其实也就是距离的精度问题以及正则表达式错误hhhh,第三题是我wa麻了的一题,题干中第四个case的格式判断我放在了外面,然后就会有各种莫名其妙的答案错误,而后改到case4里面后,仍然wa,而后发现是判断的问题。第四个case是我最头疼的,一开始我借用了别人的数学方法,结果一直错,直到我拿出纸笔计算才发现,那个公式根本就是错误的

drawing

    这起码浪费了我三个小时的时间,期间我一直在根据那个公式推理hhhh。后面我还少了一个零焦点的判断,以至于我一直以为是精度的问题,最主要的是直线过端点的情况没有考虑完全,导致后来的公式也是一直错误hhhhh,精度方面倒没啥问题。

改进建议

    不应该偷懒不学正则表达式,其实在第二次作业的时候我就以及看过正则表达式了,我还把别人使用正则表达式的代码贴了出来,有兴趣的可以点那几个发绿的字去看看。另外就是圈复杂度太高,下次写的时候一定要加强封装,让圈复杂度降低到10。

总结

    此三次练习,让我学会了基本的数据输入输出,简单的数据处理,还有字符串的各项操作,题目集难度由浅入深,我逐步学习了正则表达式、基本语法、封装等专业知识,由此我也看到了自己学习的东西尚浅,对于许多知识点掌握得仍旧不熟练,我应当在后期的学习中巩固基础,同时拓宽知识面,如自学正则表达式等有助于让代码更加简洁的方法。也让我学会了很多关于Java的字符串处理的语法和方法,同时我对于类的使用还不是很熟练,要加强面向对象理念。

drawing

posted on 2022-09-27 17:57  大皮QAQ  阅读(122)  评论(0编辑  收藏  举报

导航

回到顶部叭QAQ