PTA前三次作业总结

一、前言

  1. 前三次作业的难度总的来说是依次递增的,但主要难度还是集中在第三次大作业上,前两次作业只能说是拿来熟悉怎么敲java代码,解决问题的思路还是偏向于面向过程,而到了第三次作业,更要求我们用面向对象的编程思想来解决问题。
  2. 本次总结主要选用第二次作业的第三题以及第三次作业进行总结分析,主要目的是梳理如何设计类及其属性方法的思路,提高自己在之后编程中设计类的能力,也是对之前写题所犯错误的记录,正所谓温故而知新。

二、设计与分析

第二次作业:7-2 串口字符解析

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

  2. 题目分析
    本题难点(关键点)在于判断非法输入,也可以说这一道题就是判断数据是否合法的问题,对于每一个数据,需要输出序号+其有效数据,如果数据出错,则输出的为序号+出错原因,那么很容易想到,只要提取出每一个数据,然后依次判断合法与否并输出结果就行。

  3. 题目设计
    对于输入数据s,若数据不足11位或者输入数据全1没有起始位,则输出"null data"。

     if(s.indexOf('0')==-1||s.length()<11){
         System.out.println("null data");
         return;
     }
    

    对于一个数据d,若其结束符不为1,则输出“validate error”。

     if(d.charAt(10)!='1')
         System.out.println(j+":validate error");
    

    对于一个数据d,其奇偶校验错误,则输出“parity check error”。

     for(int k=0;k<d.length();k++)
         sum+=(int)d.charAt(k)-'0';
     if(sum%2==0)
         System.out.println(j+":parity check error");
    

    若无错误则输出序号+有效数据

  4. 完整代码

     import java.util.Scanner;
     public class Main{
         public static void main(String[] args){
             Scanner input=new Scanner(System.in);
             String s=input.nextLine();
             int i,j=1,sum;
             if(s.indexOf('0')==-1||s.length()<11){
                 System.out.println("null data");
                 return;
             }
             for(i=0;i<s.length();){
                 if(s.charAt(i)=='0'){
                     sum=0;
                     if(i+11>s.length()){
                         return;
                     }
                     else if(s.charAt(i+10)!='1')
                         System.out.println(j+":validate error");
                     else{
                         String s1=s.substring(i+1,i+10);
                         for(int k=0;k<s1.length();k++)
                             sum+=(int)s1.charAt(k)-'0';
                         if(sum%2==0)
                             System.out.println(j+":parity check     error");
                         else
                             System.out.println(j+":"+s1.substring   (0,s1.length()-1));
                     }
                     i+=11;
                     j++;
                 }
                 else i++;
             }
         }
     }
    
  5. SourceMonitor分析
    img
    只能说惨不忍睹,用面向过程写是这样的,由于前两次作业都在PTA上直接写,因此也没有写注释。

第三次作业:7-1 点线形系列1-计算两点之间的距离

  1. 题目内容
    输入两个点的坐标,计算两点之间的距离
  2. 题目分析
    本题还是非常简单的,用面向过程的方法几行就能搞定,但是,为了之后几题的代码复用,采用面向对象的方式编写。
  3. 题目设计
    很容易想到可以设计一个Point类,由于点有x,y坐标,因此在Point类里要有这两个属性,计算两点之间的距离也可以放在Point类中
     class Point{
         double x,y;
         public double getDis(Point a){
             //具体实现
         }
     }
    
    可以构建Input类和Format类这两个工具类来分别处理用户的输入以及数据的格式,方便之后复用。
     class Input{
         //对用户输入的各种提取方法,具体由题目规则而编写
     }
     class Format{
         //对格式的不同判断方法,具体由题目规则而编写
     }
    
  4. 完整源码(其中多余的部分是在之后的题目中添加的,本题中用不到)
     import java.util.ArrayList;
     import java.util.Scanner;
    
     public class question_1 {
     	public static void main(String[] args) {
     		Scanner input=new Scanner(System.in);
     		String[] s=Input.get_xy(input.nextLine());//利用get_xy方法获取  坐标数组
     
     		if(!Format.True_Format(s))
     			System.out.println("Wrong Format");
     		else if(s.length!=2)
     			System.out.println("wrong number of points");
     		else {
     			Point p1=new Point(s[0]);
     			Point p2=new Point(s[1]);
     			System.out.println(p1.get_dis(p2));
     		}
     
     	}
     }
    
     class Input{
     
     	/* 从用户的输入中获取坐标
     	 * 输入:s为一个只含坐标的字符串
     	 * 输出:String类型的坐标数组(按空格划分,所以坐标可能正确,判断格式    正确与否放在Format类里)
     	 * */
     	public static String[] get_xy(String s) { //s为坐标
     		return s.split(" ");
     	}
     
     	/* 从用户的输入中分离坐标和选项
     	 * 输入:s为一个选项+坐标的输入
     	 * 输出:分离选项,坐标字符串
     	 * */
     	public static String[] split_input(String s) {//
     		if(s.indexOf(':')==-1) {
     			System.out.print("Wrong Format");
     			System.exit(0);
     		}
     		return s.split(":");
     	}
     }
    
     class Format{
    
     	/* 判断坐标数组s中每个值是否合法
     	 * 输入:坐标数组s
     	 * 输出:每个值都合法输出true,有一个不合法则输出false
     	 * */
     	public static boolean True_Format(String[] s) {
     		for(int i=0;i<s.length;i++) {
     			if(!True_Format(s[i]))
     				return false;
     		}
     		return true;
     	}
     
     	//判断坐标s是否合法
     	public static boolean True_Format(String s) {
     		if(s.split(",").length!=2)
     			return false;
     		else if(s.matches("^([+-])?([1-9][0-9]*|[0])(.0*[1-9]+)?,{1}    ([+-])?([1-9][0-9]*|[0])(.0*[1-9]+)?$"))//判断是否为合法坐标的  一个正则表达式(0.0能通过这个判断,如果需要不通过需要改动)
     			return true;
     		return false;
     	}
     
     	// 格式化字符串
     	public static double Format_Str(double s,int num) {
     		String s1=String.format("%.6f",s);//保留6位
             s=Double.parseDouble(s1);
     		return s;
     	}
     }
    
     class Point{
         double x,y;
    
         public Point(String a) {//传入参数为"x,y"这类的字符串
         	String[] s=a.split(",");
         	this.Set_x(Double.parseDouble(s[0]));
         	this.Set_y(Double.parseDouble(s[1]));
         }
    
         public Point(double x,double y) {
         	this.Set_x(x);
         	this.Set_y(y);
         }
    
         //求两点之间距离
         public double get_dis(Point a){
             return Math.sqrt(Math.pow((this.x-a.x),2)+Math.pow((this.y-a.   y),2));
         }
    
         /* 判断本身与其他的点是否相等
     	 * 输入:点列表a
     	 * 输出:如果点列表a中有与本身坐标相同的点则返回true,否则false
     	 * */
         public boolean Equel(ArrayList<Point> a) {
         	for(int i=0;i<a.size();i++) {
         		if(this.Equel(a.get(i)))
         			return true;
         	}
         	return false;
         }
    
         //判断两点坐标是否相等
         public boolean Equel(Point a) {
         	if(Math.abs(this.x-a.x)<0.000001&&Math.abs(this.y-a.y)<0.   000001)
         		return true;
         	return false;
         }
    
         //设置自身的x坐标
         public void Set_x(double x) {
         	this.x=x;
         }
    
         //设置自身的y坐标
         public void Set_y(double y) {
         	this.y=y;
         }
     }
    
  5. SourceMonitor分析
    img
    在绿色部分中的是符合期望的,这里挑没有在绿色部分中的项说,Comments是注释占比,超了还行......本来是想多写点注释方便以后回顾的,问题不大。Methods/Class是类和方法的数量,由于本题简单,因此不需要很多的类与方法,因此偏少情有可原,另外Avg Stmts也是一样的原因,总体来看还不错。再看柱状图,深度集中在2上下,因此还算比较良好的。

第三次作业:7-2 点线形系列2-线的计算

  1. 题目内容
    用户输入一组选项和数据,进行与直线有关的计算。选项包括:
    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"。
  2. 题目分析
    本题开始变得复杂,显然在Main函数里需要使用switch语句根据输入的选项进行相应的操作,不仅要对每个操作进行实现,还需要对不同的格式进行判断。同样采用面向对象的方式,并且可以利用7-1的代码。
  3. 题目设计
    本题中提到了线的概念,而过两点确定一条直线,因此可以构建Line类,其中包含过的两个点p1,p2。ABC为直线一般方程的参数。
     class Line{
         Point p1,p2;
         Double A,B,C;
     }
    
    再设计直线中可能用到的方法,想不出来后可以看看题目,分析需要用到直线方法并且再添加到设计中去。
     class Line{
     	Point p1,p2;
     	Double A,B,C;
     	public double Get_Slope() {
     		//计算斜率
     	}
    
     	public double P_to_L_dis(Point a) {
     		//求点a到自身的距离
     	}
     
     	public boolean Slope_Exist() {
     		//判断斜率是否存在
     	}
     
     	public boolean Line_Parallel(Line l2) {
     		//两直线是否平行
     	}
     
     	public boolean Line_Cioncide(Line l2) {
     		//两直线是否重合
     	}
     
     	public boolean Point_Cioncide() {
     		//线本身的两点是否是一个点
     	}
     
     	public Point Cross_Point(Line l2) {
     		//求两线交点
     	}
     
     	public boolean Cross_In_Line(Point a) {
     		//点是否在线段s上
     	}
     }
    
  4. 完整源码(新增的,可以复用7-1中的Point类、Input类和Format类)
     import java.util.Scanner;
     public class question_2 {
     	public static void main(String[] args) {
     		Scanner input=new Scanner(System.in);
     		String input_str=input.nextLine();
     		String[] s=Input.split_input(input_str);
     		String op_str=s[0],xy_str=s[1];
     		String[] x_y=Input.get_xy(xy_str);
     		if(!Format.True_Format(x_y)) {
     			System.out.print("Wrong Format");
     			return;
     		}
     		switch (op_str) {
     			case "1":
     				if(x_y.length!=2)
     					System.out.print("wrong number of points");
     				else {
     					Point p1=new Point(x_y[0]);
     					Point p2=new Point(x_y[1]);
     					Line l1=new Line(p1,p2);
     					if(l1.Point_Cioncide())
     						System.out.print("points coincide");
     					else if(!l1.Slope_Exist())
     						System.out.print("Slope does not exist");
     					else
     						System.out.print(l1.Get_Slope());
     				}
     				break;
     			case "2":
     				if(x_y.length!=3)
     					System.out.print("wrong number of points");
     				else {
     					Point p1=new Point(x_y[0]);
     					Point p2=new Point(x_y[1]);
     					Point p3=new Point(x_y[2]);
     					Line l1=new Line(p2,p3);
     					if(l1.Point_Cioncide())
     						System.out.print("points coincide");
     					else
     						System.out.print(l1.P_to_L_dis(p1));
     				}
     				break;
     			case "3":
     				if(x_y.length!=3)
     					System.out.print("wrong number of points");
     				else {
     					Point p1=new Point(x_y[0]);
     					Point p2=new Point(x_y[1]);
     					Point p3=new Point(x_y[2]);
     					Line l1=new Line(p1,p2);
     					Line l2=new Line(p2,p3);
     					Line l3=new Line(p1,p3);
     					if(l1.Point_Cioncide()||l2.Point_Cioncide()||l3.    Point_Cioncide())
     						System.out.print("points coincide");
     					else if(l1.Line_Cioncide(l2))
     						System.out.print("true");
     					else
     						System.out.print("false");
     				}
     				break;
     			case "4":
     				if(x_y.length!=4)
     					System.out.print("wrong number of points");
     				else {
     					Point p1=new Point(x_y[0]);
     					Point p2=new Point(x_y[1]);
     					Point p3=new Point(x_y[2]);
     					Point p4=new Point(x_y[3]);
     					Line l1=new Line(p1,p2);
     					Line l2=new Line(p3,p4);
     					if(l1.Point_Cioncide()||l2.Point_Cioncide())
     						System.out.print("points coincide");
     					else{
     						if(l1.Line_Parallel(l2))
     							System.out.print("true");
     						else
     							System.out.print("false");
     					}
     				}
     				break;
     			case "5":
     				if(x_y.length!=4)
     					System.out.print("wrong number of points");
     				else {
     					Point p1=new Point(x_y[0]);
     					Point p2=new Point(x_y[1]);
     					Point p3=new Point(x_y[2]);
     					Point p4=new Point(x_y[3]);
     					Line l1=new Line(p1,p2);
     					Line l2=new Line(p3,p4);
     					if(l1.Point_Cioncide()||l2.Point_Cioncide())
     						System.out.print("points coincide");
     					else{
     						if(l1.Line_Parallel(l2))
     							System.out.print("is parallel lines,have    no intersection point");
     						else {
     							Point cross=l1.Cross_Point(l2);
     							System.out.print(cross.x+","+cross.y+" ");
     							if(l1.Point_In_Line(cross)||l2. Point_In_Line(cross))
     								System.out.print("true");
     							else
     								System.out.print("false");
     						}
     
     					}
     				}
     				break;
     			default:System.out.print("Wrong Format");
     		}
     	}
     }
    
     class Line{
     	Point p1,p2;
     	Double A,B,C;
     
     	/* 构造函数
     	 * 输入:线的两个点a,b
     	 * 输出:
     	 * */
     	public Line(Point a,Point b) {
     		this.Set_p1(a);
     		this.Set_p2(b);
     		this.getABC();
     	}
     
     	/* 构造函数
     	 * 输入:两个点的坐标
     	 * 输出:
     	 * */
     	public Line(double x1,double y1,double x2,double y2) {
     		Point p1=new Point(x1,y1);
     		Point p2=new Point(x2,y2);
     		this.Set_p1(p1);
     		this.Set_p2(p2);
     		this.getABC();
     	}
     
     	//设置线的构造点
     	public void Set_p1(Point a){
     		this.p1=a;
     	}
     
     	public void Set_p2(Point a) {
     		this.p2=a;
     	}
     	//计算直线一般式方程的ABC
     	public void getABC() {
     		this.A=p2.y-p1.y;
     		this.B=p1.x-p2.x;
     		this.C=p2.x*p1.y-p1.x*p2.y;
     	}
     
     	/* 获取自身斜率
     	 * 输入:
     	 * 输出:自身斜率
     	 * */
     	public double Get_Slope() {
     		return -this.A/this.B;
     	}
     
     	/* 计算点到线的距离
     	 * 输入:点a
     	 * 输出:点a到自身的距离
     	 * */
     	public double P_to_L_dis(Point a) {
     		double dis=Math.abs(this.A*a.x+this.B*a.y+this.C)/Math.sqrt (Math.pow(this.A,2)+Math.pow(this.B,2));
     		return dis;
     	}
     
     	/* 计算线的长度
     	 * 输入:
     	 * 输出:自身的长度
     	 * */
     	public double Get_Length() {
     		return this.p1.get_dis(this.p2);
     	}
     
     	/* 计算线的长度是否相等
     	 * 输入:线l
     	 * 输出:两线是否相等
     	 * */
     	public boolean Length_Equel(Line l) {
     		if(Math.abs(this.Get_Length()-l.Get_Length())<0.000001)
     			return true;
     		return false;
     	}
     
     	/* 计算线斜率是否存在
     	 * 输入:
     	 * 输出:斜率存在则返回true,否则返回false
     	 * */
     	public boolean Slope_Exist() {
     		if(this.B==0)
     			return false;
     		return true;
     	}
     
     	/* 判断两线是否平行
     	 * 输入:线l2
     	 * 输出:两线平行则输出true,否则输出false
     	 * */
     	public boolean Line_Parallel(Line l2) {
     		if(Math.abs(this.A*l2.B-this.B*l2.A)<0.000001&&Math.abs(this.   A*l2.C-this.C*l2.A)>0.000001)
     			return true;
     		return false;
     	}
     
     	/* 判断两线是否重合
     	 * 输入:线l2
     	 * 输出:两线重合则输出true,否则输出false
     	 * */
     	public boolean Line_Cioncide(Line l2) {
     		if(Math.abs(this.A*l2.B-this.B*l2.A)<0.000001&&Math.abs(this.   A*l2.C-this.C*l2.A)<0.000001)
     			return true;
     		return false;
     	}
     
     	/* 判断线的两点是否重合
     	 * 输入:
     	 * 输出:两点重合则输出true,否则输出false
     	 * */
     	public boolean Point_Cioncide() {
     		if(this.p1.Equel(this.p2))
     			return true;
     		return false;
     	}
     
     	/* 求两线交点
     	 * 输入:线l2
     	 * 输出:交点
     	 * */
     	public Point Cross_Point(Line l2) {
     		double Y=(this.C*l2.A-l2.C*this.A)/(this.A*l2.B-l2.A*this.B);
     		double X=(l2.C*this.B-this.C*l2.B)/(this.A*l2.B-l2.A*this.B);
     		Point p=new Point(X,Y);
     		return p;
     	}
     
     	/* 求点是否在线内(即在线段内)
     	 * 输入:点a
     	 * 输出:点在线段内则输出true,否则输出false
     	 * */
     	public boolean Point_In_Line(Point a) {
     		if(a.get_dis(this.p1)+a.get_dis(this.p2)-this.Get_Length()<0.   00000001)
     			return true;
     		return false;
     	}
     }
    
  5. SourceMonitor分析
    img
    对于题目二,主要是最大复杂度太高了,Avg Depth也很高,查看代码发现,主要是主函数的锅,在主函数里镶嵌了太多的switch和if else语句,因此拉高了整个程序的复杂度,其他到还好,通过柱图可以发现,深度在2,5这里较多,普遍较高,还需要改进。

第三次作业:7-2 点线形系列2-线的计算

  1. 题目内容
    用户输入一组选项和数据,进行与三角形有关的计算。选项包括:
    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"
  2. 题目分析
    本题内容很多,且需要结合点,线,三角形综合应用,肯定是需要用面向对象的方式,否则代码量可能好几千。
  3. 题目设计
    本题中出现了三角形,因此可以构建一个三角形类,三角形有三条边,因此属性可以设计为
     class Triangle{
         Line l1,l2,l3;
     }
    
    同理,可以思考三角形本身应该具有什么样的方法,三角形与点间有怎么样的方法,三角形与线间有什么样的方法,两个三角形之间有什么样的方法等等,具体方法设计因篇幅原因不再展示,直接展示写完具体实现之后的类。
  4. 完整源码(新增的,可以复用7-1,7-2中的类)
     import java.util.ArrayList;
     import java.util.Scanner;
    
     public class question_3 {
     	public static void main(String[] args) {
     		Scanner input=new Scanner(System.in);
     		String input_str=input.nextLine();
     		String[] s=Input.split_input(input_str);
     		String op_str=s[0],xy_str=s[1];
     		String[] x_y=Input.get_xy(xy_str);
     		if(!Format.True_Format(x_y)) {
     			System.out.print("Wrong Format");
     			return;
     		}
     		switch (op_str) {
     			case "1":
     				if(x_y.length!=3)
     					System.out.print("wrong number of points");
     				else {
     					Point p1=new Point(x_y[0]);
     					Point p2=new Point(x_y[1]);
     					Point p3=new Point(x_y[2]);
     					Line l1=new Line(p1,p2);
     					Line l2=new Line(p1,p3);
     					Line l3=new Line(p2,p3);
     					Triangle t1=new Triangle(l1,l2,l3);
     					if(!t1.Is_Triangle())
     						System.out.print("data error");
     					else {
     						if(t1.Is_DengBian())
     							System.out.print("true true");
     						else {
     							if(t1.Is_DengYao())
     								System.out.print("true false");
     							else
     								System.out.print("false false");
     						}
     					}
     				}
     				break;
     			case "2":
     				if(x_y.length!=3)
     					System.out.print("wrong number of points");
     				else {
     					Point p1=new Point(x_y[0]);
     					Point p2=new Point(x_y[1]);
     					Point p3=new Point(x_y[2]);
     					Line l1=new Line(p1,p2);
     					Line l2=new Line(p1,p3);
     					Line l3=new Line(p2,p3);
     					Triangle t1=new Triangle(l1,l2,l3);
     					if(!t1.Is_Triangle())
     						System.out.print("data error");
     					else {
     						double cir=t1.Get_Cir();
     					    double are=t1.Get_Area();
     						Point core=t1.Get_Core();
     						System.out.print(Format.Format_Str(cir,6)+"     ");
     						System.out.print(Format.Format_Str(are,6)+"     ");
     						System.out.print(Format.Format_Str(core.x,6)    +","+Format.Format_Str(core.y,6));
     					}
     				}
     				break;
     			case "3":
     				if(x_y.length!=3)
     					System.out.print("wrong number of points");
     				else {
     					Point p1=new Point(x_y[0]);
     					Point p2=new Point(x_y[1]);
     					Point p3=new Point(x_y[2]);
     					Line l1=new Line(p1,p2);
     					Line l2=new Line(p1,p3);
     					Line l3=new Line(p2,p3);
     					Triangle t1=new Triangle(l1,l2,l3);
     					if(!t1.Is_Triangle())
     						System.out.print("data error");
     					else {
     						double max_angle=t1.Get_MaxAngle();
     						if(90-max_angle<-0.000001)
     							System.out.print("true false false");
     						else if(Math.abs(90-max_angle)<=0.000001)
     							System.out.print("false true false");
     						else
     							System.out.print("false false true");
     					}
     				}
     				break;
     			case "4":
     				if(x_y.length!=5)
     					System.out.print("wrong number of points");
     				else {
     					Point p1=new Point(x_y[0]);
     					Point p2=new Point(x_y[1]);
     					Point p3=new Point(x_y[2]);
     					Point p4=new Point(x_y[3]);
     					Point p5=new Point(x_y[4]);
     					Line l1=new Line(p1,p2);
     					Line l2=new Line(p3,p4);
     					Line l3=new Line(p3,p5);
     					Line l4=new Line(p4,p5);
     					Triangle t1=new Triangle(l2,l3,l4);
     					if(l1.Point_Cioncide())
     						System.out.print("points coincide");
     					else if(!t1.Is_Triangle())
     						System.out.print("data error");
     					else if(l1.Line_Cioncide(t1.l1)||l1.Line_Cioncide   (t1.l2)||l1.Line_Cioncide(t1.l3))
     						System.out.print("The point is on the edge of   the triangle");
     					else{
     						ArrayList<Point> crosspoint=t1.Line_CrossPoint  (l1);
     						System.out.print(crosspoint.size());
     						if(crosspoint.size()==2) {
     							double area1=t1.LineCross_Area(crosspoint.  get(0),crosspoint.get(1));
     							double area2=t1.Get_Area()-area1;
     							area1=Format.Format_Str(area1,6);
     							area2=Format.Format_Str(area2,6);
     							if(area1<area2)
     								System.out.print(" "+area1+" "+area2);
     							else
     								System.out.print(" "+area2+" "+area1);
     						}
     					}
     				}
     				break;
     			case "5":
     				if(x_y.length!=4)
     					System.out.print("wrong number of points");
     				else {
     					Point p1=new Point(x_y[0]);
     					Point p2=new Point(x_y[1]);
     					Point p3=new Point(x_y[2]);
     					Point p4=new Point(x_y[3]);
     					Line l1=new Line(p2,p3);
     					Line l2=new Line(p2,p4);
     					Line l3=new Line(p3,p4);
     					Triangle t1=new Triangle(l1,l2,l3);
     					if(!t1.Is_Triangle())
     						System.out.print("data error");
     					else if(t1.Point_On_Triangle(p1))
     						System.out.print("The point is on the edge of   the triangle");
     					else{
     						if(t1.Point_in_Triangle(p1))
     							System.out.print("in the triangle");
     						else
     							System.out.print("outof the triangle");
     					}
     				}
     				break;
     			default:System.out.print("Wrong Format");
     		}
     	}
     }
    
     class Triangle{
     	Line l1,l2,l3;
     	/* 构造方法
     	 * 输入:线l1,l2,l3
     	 * 输出:
     	 * */
     	public Triangle(Line l1,Line l2,Line l3) {
     		this.l1=l1;
     		this.l2=l2;
     		this.l3=l3;
     	}
     
     	/* 构造方法
     	 * 输入:点p1,p2,p3
     	 * 输出:
     	 * */
     	public Triangle(Point p1,Point p2,Point p3) {
     		this.l1=new Line(p1,p2);
     		this.l2=new Line(p1,p3);
     		this.l3=new Line(p2,p3);
     	}
     
     	/* 构造方法
     	 * 输入:三个点的坐标
     	 * 输出:
     	 * */
     	public Triangle(double x1,double y1,double x2,double y2,double x3,  double y3) {
     		this.l1=new Line(new Point(x1,y1),new Point(x2,y2));
     		this.l2=new Line(new Point(x1,y1),new Point(x3,y3));
     		this.l3=new Line(new Point(x2,y2),new Point(x3,y3));
     	}
     
     	/* 判断点是否在三角形内
     	 * 输入:点p1
     	 * 输出:点在三角形内则输出true,否则输出false
     	 * */
     	public boolean Point_in_Triangle(Point p1) {
     		Point p2=new Point(p1.x+1,p1.y);
     		ArrayList<Point> p=this.RayLine_CrossPoint(p1,p2);
     		if(p.size()!=1)
     			return false;
     		return true;
     	}
     
     	/* 判断点是否在三角形上
     	 * 输入:点p1
     	 * 输出:点在三角形上则输出true,否则输出false
     	 * */
     	public boolean Point_On_Triangle(Point p1) {
     		if(this.l1.Point_In_Line(p1)||this.l2.Point_In_Line(p1)||this.  l3.Point_In_Line(p1))
     			return true;
     		return false;
     	}
     
     	/* 求两交点连线将三角形分割后,其中一个三角形的面积(其余部分面积为总面  积减该面积)
     	 * 输入:点p1,p2
     	 * 输出:切割的一个三角形的面积
     	 * */
     	public double LineCross_Area(Point p1, Point p2) {
     		Point p3=null;
     		if(this.l1.Point_In_Line(p1)&&this.l2.Point_In_Line(p2))
     			p3=this.l1.p1;
     		else if(this.l1.Point_In_Line(p1)&&this.l3.Point_In_Line(p2))
     			p3=this.l1.p2;
     		else if(this.l2.Point_In_Line(p1)&&this.l3.Point_In_Line(p2))
     			p3=this.l2.p2;
     		Triangle t=new Triangle(p3,p1,p2);
     		return t.Get_Area();
     	}
     
     	/* 求线l与三角形交点数量
     	 * 输入:线l
     	 * 输出:线与三角形的交点列表(重复点已去除)
     	 * */
     	public ArrayList<Point> Line_CrossPoint(Line l) {
     		ArrayList<Point> p = new ArrayList<Point>();
     		Point crossp1=this.l1.Cross_Point(l);
     		Point crossp2=this.l2.Cross_Point(l);
     		Point crossp3=this.l3.Cross_Point(l);
     		if(this.l1.Point_In_Line(crossp1)&&!crossp1.Equel(p))
     			p.add(crossp1);
     		if(this.l2.Point_In_Line(crossp2)&&!crossp2.Equel(p))
     			p.add(crossp2);
     		if(this.l3.Point_In_Line(crossp3)&&!crossp3.Equel(p))
     			p.add(crossp3);
     		return p;
     	}
     
     	/* 求p1向p2引出的射线与三角形交点数量
     	 * 输入:点p1,p2
     	 * 输出:该射线与三角形的交点列表
     	 * */
     	public ArrayList<Point> RayLine_CrossPoint(Point p1,Point p2) {
     		Line l1=new Line(p1,p2);
     		ArrayList<Point> p = this.Line_CrossPoint(l1); //求l1直线与三   角形的交点
     		double side1,side2;//side用于判断交点在不在射线上
     		for(int i=0;i<p.size();) {
     			Point p3=p.get(i);
     			side1=p1.x-p3.x;
     			side2=p1.x-p2.x;
     			if(side1*side2<0)
     				p.remove(i);
     			else i++;
     		}
     		return p;
     	}
     
     	/* 求三角形最大的角的角度
     	 * 输入:
     	 * 输出:三角形最大的角的角度
     	 * */
     	public double Get_MaxAngle() {
     		double a1=this.Get_Angle(this.l1, this.l2, this.l3);
     		double a2=this.Get_Angle(this.l2, this.l1, this.l3);
     		double a3=this.Get_Angle(this.l3, this.l1, this.l2);
     		return Math.max(Math.max(a1,a2),Math.max(a1,a3));
     	}
     
     	/* 求三角形的角度
     	 * 输入:线l1,l2,l3
     	 * 输出:线l1的对角的角度
     	 * */
     	public double Get_Angle(Line l1,Line l2,Line l3) {
     		double a=l1.Get_Length(),b=l2.Get_Length(),c=l3.Get_Length();
     		double ans=(Math.pow(b,2)+Math.pow(c,2)-Math.pow(a, 2))/    (2*b*c);
     		return Math.acos(ans)*180/Math.PI;
     	}
     
     	/* 求三角形的重心
     	 * 输入:
     	 * 输出:三角形重心对象
     	 * */
     	public Point Get_Core() {
     		double x=(this.l1.p1.x+this.l1.p2.x+this.l2.p2.x)/3;
     		double y=(this.l1.p1.y+this.l1.p2.y+this.l2.p2.y)/3;
     		return new Point(x,y);
     	}
     
     	/* 求三角形的面积
     	 * 输入:
     	 * 输出:三角形的面积
     	 * */
     	public double Get_Area() {
     		return this.l3.P_to_L_dis(this.l1.p1)*this.l3.Get_Length()/2;
     	}
     
     	/* 求三角形的周长
     	 * 输入:
     	 * 输出:三角形周长
     	 * */
     	public double Get_Cir() {
     		return this.l1.Get_Length()+this.l2.Get_Length()+this.l3.   Get_Length();
     	}
     
     	/* 判断三角形是否为等边三角形
     	 * 输入:
     	 * 输出:是等边三角形则输出true,否则输出false;
     	 * */
     	public boolean Is_DengBian() {
     		if(this.l1.Length_Equel(this.l2)&&this.l1.Length_Equel(this.    l3))
     			return true;
     		return false;
     	}
     
     	/* 判断三角形是否为等腰三角形
     	 * 输入:
     	 * 输出:是等腰三角形则输出true,否则输出false;
     	 * */
     	public boolean Is_DengYao() {
     		if(this.l1.Length_Equel(this.l2)||this.l1.Length_Equel(this.    l3)||this.l2.Length_Equel(this.l3))
     			return true;
     		return false;
     	}
     
     	/* 判断三角形的三点是否为正确的三角形
     	 * 输入:
     	 * 输出:能构成三角形则输出true,否则输出false;
     	 * */
     	public boolean Is_Triangle() {
     		if(this.l1.Get_Length()+this.l2.Get_Length()-this.l3.   Get_Length()>0.000001)
     			return true;
     		return false;
     	}
     }
    
  5. SourceMonitor分析
    img
    这里Avg Depth和Max Complexity超标的原因还是主函数(主函数有点冗余),其他的方面其实还不错,由于题目加了很多的格式判断,因此把判断部分全放在了主函数里,造成了大量ifelse等等。其他部分的对象方法调用设计都还比较符合期望。柱状图中,大部分深度也集中在2,还算比较好的。

三、踩坑心得

  1. 第三次作业7-1
    这题坑很难受,对于0,0这一个数据需要判断成错误输入,当时改了很久才发现。
  2. 第三次作业7-2
    这题又双叒叕来搞事情,在7-1里不能通过的0,0在这一题有可以通过了,真的是很离谱,只能说测试点很搞心态了。输入的判断最好要用正则表达式,不然光判断就得写上100行。
  3. 第三次作业7-3
    这题要注意的是格式化输出,单纯的String.Format()会保留多余的0,要消去。还要注意有三维坐标点,四维坐标点等等,要注意删除(case 8好像是这个情况),当时以为自己的正则能把这个点筛掉,然后在48分卡了好久....不知道是这个错了

四、改进意见

  1. 首先一定要把主函数给改掉,由于之前设定了Format类来判断格数正确与否,可以将所有的格式判断都放到里面(虽然当初设计的时候就是这样想的,但是后来敲着敲着就没想到放在Format里),尽量将主函数简化,可以避免圈复杂度过高的问题
  2. 代码中没有对类的属性进行私有化(private),觉得很麻烦,但其实实际上是需要的,写题的时候偷懒就没写。。

五、总结

这三次作业可以说是从面向过程到面向对象的一个过渡吧,虽然在第三次作业中大部分采用了面向对象的设计思想,但是实际上实现的时候难免会在某些地方写成了面向过程(包括main函数和某些方法内部其实还可以再拆分)。总得来说还是不太熟练,但是对于类的设计还是增加了一点点的经验,并且对字符串处理,修饰符等知识点的掌握程度也有了较大的提升(顺便还复习了一波数学:一般式啥的早忘了...我都无语了)。在之后也会想改进一下现在的代码,方便后面的题目复用。

posted @ 2022-10-02 20:57  昌航小迷弟二号  阅读(71)  评论(2)    收藏  举报