BLOG-1
前言
难度
- 前两次都分别可以在一个晚上写完,第三次足足花费了我一周。
- 前两次的测试点清晰简单,第三次的测试点多而不易于发现。
- 第三次对输入格式的判断也是错综复杂。
题量
- 第一次的题目虽然有9道,但是每题的代码行数很少,第二次题目的量少且行数少,第三次看似只有三题,但是代码量远超前两次。
知识点
- 1-7-3首次使用split函数
public String[] split(String regex)以regex分割,将字符串分割为字符串数组
- 1-7-6使用到equals函数
public boolean equals(Object o)
返回一个boolean类型,第一次了解到Java中字符串的比较不能直接使用‘==’。
- 1-7-8使用到ToCharArray函数和contains函数
public char[] toCharArray() public boolean contains(CharSequence chars)
第一个函数字符串转化为字符数组,第二个函数判断字符串中是否包含某一个字符
- 2-7-2使用到index of函数和charAT函数
int indexOf(String str, int fromIndex) char charAt(int index)
第一个函数 从fromIndex位置开始向后遍历,返回第一次找到 str 字符串的位置 第二个函数返回在index位置上的字符
- 3-7-1计算两点的距离
∣AB∣=√[(x1-x2)²+(y1-y2)²]
- 3-7-2直线的基本公式
Ax+By+C=0
这里不采用 y=kx+b,避免后面判断直线平行等问题斜率不存在难以讨论。
- 3-7-3三角形面积的计算
采用S=|(x1y2-x1y3+x2y3-x2y1+x3y1-x2y2)| 而不用S=√p (p-a) (p-b) (p-c)第二个海伦公式边长的时候已经开过根号,再次开根号会有误差过大的原因,所有我这边采用的是点求三角形面积
设计与分析
2-7-2串口字符解析
RS232是串口常用的通信协议,在异步通信模式下,串口可以一次发送5~8位数据,收发双方之间没有数据发送时线路维持高电平,相当于接收方持续收到数据“1”(称为空闲位),
发送方有数据发送时,会在有效数据(5~8位,具体位数由通信双方提前设置)前加上1位起始位“0”,在有效数据之后加上1位可选的奇偶校验位和1位结束位“1”。请编写程序,
模拟串口接收处理程序,注:假定有效数据是8位,奇偶校验位采用奇校验。
- 源码
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner( System.in ); String str = sc.nextLine(); if( str.length() < 11 || !str.contains("0")) { System.out.println("null data"); return ; }else { int num = 0 ; int count = 1; while( str.length()-num >= 11) { num = str.indexOf("0",num); System.out.print(count+":"); count++; if( str.charAt(num+10) != '1') { System.out.print("validate error"); }else { int sum = 0; for( int i=num ; i<num+10; i++) { if( str.charAt(i) == '1') { sum++; } } if( sum % 2 != 1) { System.out.print("parity check error"); }else { System.out.print(str.substring(num+1, num+9)); } } System.out.println(); num += 11 ; } } } }
- 源码分析
奇校验判断代码 for( int i=num ; i<num+10; i++) { if( str.charAt(i) == '1') { sum++; } } if( sum % 2 != 1) { System.out.print("parity check error"); }else { System.out.print(str.substring(num+1, num+9)); }
偶校验:连同校验位使得所有位上的1相加为偶数
3-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”。
- 源码
import java.util.Scanner; public class Main { /*用于判断输入是否合法 * 合法就返回一个数组 * 不合法就返回空 */ static String[] isLegal( String string) { String[] str = string.split(",| "); for( int i = 0 ; i < str.length; i++) { if(!str[i].matches("[+-]?[1-9]\\d*(\\.\\d+)?|[+-]?[0](\\.\\d+)?")) { System.out.println("Wrong Format"); return null; } } if(str.length > 4) { System.out.println("wrong number of points"); return null; } return str; } public static void main(String[] args) { Point p1 = new Point(); Point p2 = new Point(); Scanner sc = new Scanner(System.in); String s = sc.nextLine(); if( isLegal(s) != null) { String[] str = isLegal(s); p1.setPoint(str[0], str[1]); p2.setPoint(str[2], str[3]); System.out.println(p1.calculateDistance(p2)); } } } class Point { private double x; private double y; /*public Point(double x, double y) { //构造函数 super(); this.x = x; this.y = y; } double getx() { return this.x; } double gety() { return this.y; }*/ /*用于判断输入是否合法 * 合法就返回一个数组 * 不合法就返回空 */ void setPoint( String stringx, String stringy) { //建立点的 x y 坐标 this.x = Double.parseDouble(stringx) ; this.y = Double.parseDouble(stringy) ; } double calculateDistance( Point point) { //计算两点的距离 double num = (this.x - point.x)*(this.x - point.x) + (this.y - point.y)*(this.y - point.y); return Math.sqrt(num); } boolean isCoincide( Point point) { //判断两点是否重合 return this.x==point.x&&this.y==point.y; } }
- 源码分析


本题比较简单,平均圈复杂只有3,该题也仅仅用到一个类。
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"。
源码
import java.util.Scanner;
public class Main {
/*用于判断输入是否合法
* 合法就返回一个数组
* 不合法就返回空
*/
static String[] isLegal( String string) {
String[] str = string.split(",| |:");
if( !string.contains(":") || !string.contains(",") || !string.contains(" ")) {
System.out.println("Wrong Format");
return null;
}
if(string.charAt(string.length()-1) ==' ' || string.charAt(string.length()-1) ==':' || string.charAt(string.length()-1) ==','|| !str[0].matches("[12345]") ) {
System.out.println("Wrong Format");
return null;
}
for( int i = 1 ; i < str.length; i++) {
if(!str[i].matches("[+-]?[1-9]\\d*(\\.\\d+)?|[+-]?[0](\\.\\d+)?")) {
System.out.println("Wrong Format");
return null;
}
}
int len = Integer.parseInt(str[0]) ;
if(len == 1) {
if(string.split(" ").length + string.split(":").length - string.split(",").length == 1 ) {
if( str.length != 5) {
System.out.println("wrong number of points");
return null;
}
}else {
System.out.println("Wrong Format");
return null;
}
}else if( len == 2 || len == 3) {
if(string.split(" ").length + string.split(":").length - string.split(",").length == 1) {
if( str.length != 7) {
System.out.println("wrong number of points");
return null;
}
}else {
System.out.println("Wrong Format");
return null;
}
}else if( len == 4 || len == 5) {
if(string.split(" ").length + string.split(":").length - string.split(",").length == 1) {
if( str.length != 9) {
System.out.println("wrong number of points");
return null;
}
}else {
System.out.println("Wrong Format");
return null;
}
}
return str;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
if( isLegal(s) != null) {
String[] str = isLegal(s) ;
int len = Integer.parseInt(str[0]) ;
if(len == 1) {
Point p1 = new Point(str[1], str[2]);
Point p2 = new Point(str[3], str[4]);
if(p1.isCoincide(p2)) {
System.out.println("points coincide");
}else if(p1.getx() == p2.getx()) {
System.out.println("Slope does not exist");
}else {
Line l1 = new Line(p1,p2);
System.out.println(l1.getK());
}
}else if(len == 2) {
Point p1 = new Point(str[1], str[2]);
Point p2 = new Point(str[3], str[4]);
Point p3 = new Point(str[5], str[6]);
if(p2.isCoincide(p3)) {
System.out.println("points coincide");
}else {
Line l1 = new Line(p2,p3);
System.out.println(l1.calculateDistance(p1));
}
}else if(len == 3) {
Point p1 = new Point(str[1], str[2]);
Point p2 = new Point(str[3], str[4]);
Point p3 = new Point(str[5], str[6]);
if(p1.isCoincide(p2) ) {
System.out.println("points coincide");
}else {
Line l1 = new Line(p1,p2);
System.out.println(l1.judgePointOnLine(p3));
}
}else if(len == 4) {
Point p1 = new Point(str[1], str[2]);
Point p2 = new Point(str[3], str[4]);
Point p3 = new Point(str[5], str[6]);
Point p4 = new Point(str[7], str[8]);
if(p1.isCoincide(p2) || p3.isCoincide(p4)) {
System.out.println("points coincide");
}else {
Line l1 = new Line(p1,p2);
Line l2 = new Line(p3,p4);
System.out.println(l1.judgeParallel(l2));
}
}else if(len == 5) {
Point p1 = new Point(str[1], str[2]);
Point p2 = new Point(str[3], str[4]);
Point p3 = new Point(str[5], str[6]);
Point p4 = new Point(str[7], str[8]);
if(p1.isCoincide(p2) || p3.isCoincide(p4)) {
System.out.println("points coincide");
}else {
Line l1 = new Line(p1,p2);
Line l2 = new Line(p3,p4);
if(l1.judgeParallel(l2)) {
System.out.println("is parallel lines,have no intersection point");
}else {
Point p = l1.calculateIntersection(l2);
System.out.println(p.getx()+","+p.gety()+" "+ (l1.judgePointInLine(p)||l2.judgePointInLine(p)) );
}
}
}
}
}
}
class Line {
private Point point1;
private Point point2;
// 构造函数
public Line(Point point1, Point point2) {
super();
this.point1 = point1;
this.point2 = point2;
}
// 得到点一
Point getPoint1() {
return this.point1;
}
// 得到点二
Point getPoint2() {
return this.point2;
}
// 得到x的系数A
double getA() {
return point1.gety()-point2.gety();
}
// 得到y的系数B
double getB() {
return point2.getx()-point1.getx();
}
// 得到常数C
double getC() {
return point1.getx() * point2.gety() - point2.getx() * point1.gety();
}
// 得到直线的斜率
double getK() {
return (point1.gety()-point2.gety())/(point1.getx()-point2.getx());
}
// 计算点到直线的距离
double calculateDistance( Point point) {
double a = Math.abs( this.getA()*point.getx() + this.getB()*point.gety() + this.getC());
double b = Math.sqrt(this.getA() * this.getA() + this.getB()*this.getB());
return a/b;
}
// 判断点是否在直线上
boolean judgePointOnLine( Point point ){
return this.getA()*point.getx()+this.getB()*point.gety()+this.getC() == 0;
}
// 判断两直线是否平行
boolean judgeParallel( Line line ) {
if(this.getB() != 0 && line.getB() !=0)
return this.getK() == line.getK() ;
else if(this.getB() == 0 && line.getB() ==0){
return true;
}else {
return false;
}
}
// 计算线与线的交点
Point calculateIntersection( Line line) {
double x = (line.getC()*this.getB()-this.getC()*line.getB())/(this.getA()*line.getB()-line.getA()*this.getB());
double y = (line.getC()*this.getA()-this.getC()*line.getA())/(line.getA()*this.getB()-this.getA()*line.getB());
if(x!=0 && y!=0 ) {
Point point = new Point(x,y);return point;
}
else if(x==0 && y==0 ) {
Point point = new Point(0,0);return point;
}
else if(x==0 && y!=0 ) {
Point point = new Point(0,y);return point;
}
else {
Point point = new Point(x,0);return point;
}
}
// 判断交点是否在线段的内部
boolean judgePointInLine( Point point ) {
if( point.getx() < Math.max( this.point1.getx(), this.point2.getx() ) && point.getx() > Math.min( this.point1.getx() , this.point2.getx() ) || point.gety() < Math.max( this.point1.gety(), this.point2.gety() ) && point.gety() > Math.min( this.point1.gety() , this.point2.gety() ))
return true;
else
return false;
}
}
class Point {
private double x;
private double y;
// 构造函数
public Point(String stringx, String stringy) {
this.x = Double.parseDouble(stringx) ;
this.y = Double.parseDouble(stringy) ;
}
// 构造函数
public Point(double x, double y) {
super();
this.x = x;
this.y = y;
}
//得到点的x坐标
double getx() {
return this.x;
}
//得到点的y坐标
double gety() {
return this.y;
}
//计算两点的距离
double calculateDistance( Point point) {
double num = (this.x - point.x)*(this.x - point.x) + (this.y - point.y)*(this.y - point.y);
return Math.sqrt(num);
}
//判断两点是否重合
boolean isCoincide( Point point) {
return this.x==point.x&&this.y==point.y;
}
}
- 源码分析



本题平均复杂度高达21.50,主要在于是TestPoint这个测试类,其中只含有main函数和isLegal函数。如果Point类和Line类单独看复杂度是不高的,但是对于测试类其中的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"
- 源码
import java.util.Scanner; public class Main { /*用于判断输入是否合法 * 合法就返回一个数组 * 不合法就返回空 */ static String[] isLegal( String string) { String[] str = string.split(",| |:"); if( !string.contains(":") || !string.contains(",") || !string.contains(" ")) { System.out.println("Wrong Format"); return null; } if(string.charAt(string.length()-1) ==' ' || string.charAt(string.length()-1) ==':' || string.charAt(string.length()-1) ==','|| !str[0].matches("[12345]") ) { System.out.println("Wrong Format"); return null; } for( int i = 1 ; i < str.length; i++) { if(!str[i].matches("[+-]?[1-9]\\d*(\\.\\d+)?|[+-]?[0](\\.\\d+)?")) { System.out.println("Wrong Format"); return null; } } int len = Integer.parseInt(str[0]) ; if( len == 1 || len == 2 || len == 3) { if(string.split(" ").length + string.split(":").length - string.split(",").length == 1) { if( str.length != 7) { System.out.println("wrong number of points"); return null; } }else { System.out.println("Wrong Format"); return null; } }else if( len == 5) { if(string.split(" ").length + string.split(":").length - string.split(",").length == 1) { if( str.length != 9) { System.out.println("wrong number of points"); return null; } }else { System.out.println("Wrong Format"); return null; } }else if( len == 4 ) { if(string.split(" ").length + string.split(":").length - string.split(",").length == 1) { if( str.length != 11) { System.out.println("wrong number of points"); return null; } }else { System.out.println("Wrong Format"); return null; } } return str; } static void print(double num) { if( num * 1000000 % 1 != 0) { System.out.printf("%.6f",num); }else { System.out.print(num); } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); String s = sc.nextLine(); if( isLegal(s) != null) { String[] str = isLegal(s) ; int len = Integer.parseInt(str[0]) ; if(len == 1) { Point p1 = new Point(str[1], str[2]); Point p2 = new Point(str[3], str[4]); Point p3 = new Point(str[5], str[6]); Line l12 = new Line(p1,p2); Line l13 = new Line(p1,p3); Line l23 = new Line(p2,p3); if( l12.judgePointOnLine(p3)|| p1.isCoincide(p2) || p1.isCoincide(p3) || p3.isCoincide(p2) ) { System.out.println("data error"); System.exit(0); }else { Triangle t = new Triangle(l12,l13,l23); System.out.println(t.isIsoscelesTriangle() +" "+ t.isRegularTriangle()); } }else if(len == 2) { Point p1 = new Point(str[1], str[2]); Point p2 = new Point(str[3], str[4]); Point p3 = new Point(str[5], str[6]); Line l12 = new Line(p1,p2); Line l13 = new Line(p1,p3); Line l23 = new Line(p2,p3); if( l12.judgePointOnLine(p3)|| p1.isCoincide(p2) || p1.isCoincide(p3) || p3.isCoincide(p2) ) { System.out.println("data error"); System.exit(0); }else { Triangle t = new Triangle(l12,l13,l23); print(t.calculatePerimeter()); System.out.print(" "); print(t.calculateArea()); System.out.print(" "); print(t.calculateCore().getx()); System.out.print(","); print(t.calculateCore().gety()); } }else if(len == 3) { Point p1 = new Point(str[1], str[2]); Point p2 = new Point(str[3], str[4]); Point p3 = new Point(str[5], str[6]); Line l12 = new Line(p1,p2); Line l13 = new Line(p1,p3); Line l23 = new Line(p2,p3); if( l12.judgePointOnLine(p3)|| p1.isCoincide(p2) || p1.isCoincide(p3) || p3.isCoincide(p2) ) { System.out.println("data error"); System.exit(0); }else { Triangle t = new Triangle(l12,l13,l23); System.out.println(t.isObtuseTriangle()+" "+t.isRightTriangle()+" "+t.isAcuteTriangle()); } }else if(len == 4) { Point p1 = new Point(str[1], str[2]); Point p2 = new Point(str[3], str[4]); Point p3 = new Point(str[5], str[6]); Point p4 = new Point(str[7], str[8]); Point p5 = new Point(str[9], str[10]); Line l12 = new Line(p1,p2); Line l34 = new Line(p3,p4); Line l35 = new Line(p3,p5); Line l45 = new Line(p4,p5); if(p1.isCoincide(p2)) { System.out.println("points coincide"); System.exit(0); } if( l34.judgePointOnLine(p5)|| p3.isCoincide(p4) || p3.isCoincide(p5) || p4.isCoincide(p5) ) { System.out.println("data error"); System.exit(0); }else { Triangle t = new Triangle(l34,l35,l45); System.out.print(t.calculateIntersectionCount(l12)); if(t.calculateIntersectionCount(l12) == 2) { //System.out.print(" "); //print(t.calculateArea()); System.out.print(" "); print(t.calculateCutArea(l12)); System.out.print(" "); print(t.calculateArea()-t.calculateCutArea(l12)); } } }else if(len == 5) { Point p1 = new Point(str[1], str[2]); Point p2 = new Point(str[3], str[4]); Point p3 = new Point(str[5], str[6]); Point p4 = new Point(str[7], str[8]); Line l23 = new Line(p2,p3); Line l24 = new Line(p2,p4); Line l34 = new Line(p3,p4); if( l23.judgePointOnLine(p4)|| p2.isCoincide(p3) || p2.isCoincide(p4) || p3.isCoincide(p4) ) { System.out.println("data error"); System.exit(0); }else { /* 当点p1在三角形边所在直线上时 * 不足以说明p1在边上,可能是延长线上 * 所以同时判断点的x,y处于在该线段内两端的x,y范围中 * 此时就在三角形边上 */ if( l23.judgePointOnLine(p1)&&l23.judgePointInLine(p1) || l24.judgePointOnLine(p1)&&l24.judgePointInLine(p1) || l34.judgePointOnLine(p1)&&l34.judgePointInLine(p1)) { System.out.println("on the triangle"); System.exit(0); }else { Triangle t = new Triangle(l23,l24,l34); if( t.judgePointPlace(p1)) { System.out.println("in the triangle"); }else { System.out.println("outof the triangle"); } } } } } } } class Triangle { private Line line12; // 点一 与 点二 构成 private Line line13; // 点一 与 点三 构成 private Line line23; // 点二 与 点三 构成 // 构造函数 public Triangle(Line line1, Line line2, Line line3) { super(); this.line12 = line1; this.line13 = line2; this.line23 = line3; } //判断三角形是否等腰 boolean isIsoscelesTriangle() { return line12.calculateLineLength() == line13.calculateLineLength() || line12.calculateLineLength() == line23.calculateLineLength() || line13.calculateLineLength() == line23.calculateLineLength() ; } //判断三角形是否等边 boolean isRegularTriangle() { return line12.calculateLineLength() == line13.calculateLineLength() && line12.calculateLineLength() == line23.calculateLineLength() ; } // 计算三角形周长 double calculatePerimeter() { return line12.calculateLineLength()+line13.calculateLineLength()+line23.calculateLineLength(); } /* * 根据三点计算三角形面积 * S=(1/2)*(x1y2+x2y3+x3y1-x1y3-x2y1-x3y2) 该公式存在方向性 A -> B -> C * 由于方向上的未知 输出时加上绝对值abs */ double calculateArea() { double num1 = line12.getPoint1().getx()*line12.getPoint2().gety() + line12.getPoint2().getx()*line13.getPoint2().gety() + line13.getPoint2().getx()*line13.getPoint1().gety() ; double num2 = line12.getPoint1().getx()*line13.getPoint2().gety() + line12.getPoint2().getx()*line13.getPoint1().gety() + line13.getPoint2().getx()*line12.getPoint2().gety() ; return Math.abs( (num1-num2)/2 ) ; } // 计算三角形的重心 Point calculateCore() { double x = ( line12.getPoint1().getx() + line12.getPoint2().getx() + line13.getPoint2().getx() ) / 3; double y = ( line12.getPoint1().gety() + line12.getPoint2().gety() + line13.getPoint2().gety() ) / 3; Point p = new Point(x,y); return p; } // 判断是否为钝角三角形 boolean isObtuseTriangle() { double a = line12.calculateLineLength2() ; double b = line13.calculateLineLength2() ; double c = line23.calculateLineLength2() ; if(a > b && a > c ) { return a > b + c ; }else if(b > a && b > c ) { return b > a + c ; }else { return c > b + a ; } } // 判断是否为直角三角形 boolean isRightTriangle() { double a = line12.calculateLineLength2() ; double b = line13.calculateLineLength2() ; double c = line23.calculateLineLength2() ; if(a > b && a > c ) { return a == b + c ; }else if(b > a && b > c ) { return b == a + c ; }else { return c == b + a ; } } // 判断是否为锐角三角形 boolean isAcuteTriangle() { double a = line12.calculateLineLength2() ; double b = line13.calculateLineLength2() ; double c = line23.calculateLineLength2() ; if(a > b && a > c ) { return a < b + c ; }else if(b > a && b > c ) { return b < a + c ; }else { return c < b + a ; } } /*判断线是否与三角形的边重合 * 先判断边是否与先平行 * 若平行,在判断该平行边上的三角形上的端点是否在线上 * 若在线上 则重合 */ boolean IsCoincideLine( Line line) { return this.line12.judgeParallel(line) && line.judgePointOnLine(this.line12.getPoint1()) || this.line13.judgeParallel(line) && line.judgePointOnLine(this.line13.getPoint1()) || this.line23.judgeParallel(line) && line.judgePointOnLine(this.line23.getPoint1()); } // 计算线与三角形交点数量 int calculateIntersectionCount( Line line) { int count = 0; if( !this.line12.judgeParallel(line) ) { if( this.line12.judgePointInLine( this.line12.calculateIntersection(line) ) ) { count++; } } if( !this.line13.judgeParallel(line) ) { if( this.line13.judgePointInLine( this.line13.calculateIntersection(line) ) ) { count++; } } if( !this.line23.judgeParallel(line) ) { if( this.line23.judgePointInLine( this.line23.calculateIntersection(line) ) ) { count++; } } if( line.judgePointOnLine(this.line12.getPoint1()) || line.judgePointOnLine(this.line12.getPoint2()) || line.judgePointOnLine(this.line13.getPoint2()) ) { count--; } return count; } // // 射线法计算线与三角形交点数量 // int calculateIntersectionCount2( Line line) { int count = 0; if( !this.line12.judgeParallel(line) ) { if( this.line12.judgePointInLine( this.line12.calculateIntersection(line) ) && this.line12.calculateIntersection(line).getx() > line.getPoint1().getx() ) { count++; } } if( !this.line13.judgeParallel(line) ) { if( this.line13.judgePointInLine( this.line13.calculateIntersection(line) ) && this.line13.calculateIntersection(line).getx() > line.getPoint1().getx() ) { count++; } } if( !this.line23.judgeParallel(line) ) { if( this.line23.judgePointInLine( this.line23.calculateIntersection(line) )&& this.line23.calculateIntersection(line).getx() > line.getPoint1().getx() ) { count++; } } if( line.judgePointOnLine(this.line12.getPoint1()) || line.judgePointOnLine(this.line12.getPoint2()) || line.judgePointOnLine(this.line13.getPoint2()) ) { count--; } return count; } /* 计算切割三角形后的两部分面积 * 把面积小的部分传回去 */ double calculateCutArea( Line line) { if( line.judgePointOnLine(this.line12.getPoint1() ) ) { Line l1 = new Line( line.calculateIntersection(line23),this.line12.getPoint1() ); Line l2 = new Line( line.calculateIntersection(line23), this.line13.getPoint2()); Line l3 = new Line( this.line12.getPoint1() , this.line13.getPoint2()); Triangle t = new Triangle(l1,l2,l3); return Math.min( t.calculateArea() , this.calculateArea()-t.calculateArea() ); } if( line.judgePointOnLine(this.line12.getPoint2() ) ) { Line l1 = new Line( line.calculateIntersection(line13),this.line12.getPoint2() ); Line l2 = new Line( line.calculateIntersection(line13), this.line13.getPoint2()); Line l3 = new Line( this.line12.getPoint2() , this.line13.getPoint2()); Triangle t = new Triangle(l1,l2,l3); return Math.min( t.calculateArea() , this.calculateArea()-t.calculateArea() ); } if( line.judgePointOnLine(this.line13.getPoint2() ) ) { Line l1 = new Line( line.calculateIntersection(line12),this.line13.getPoint2() ); Line l2 = new Line( line.calculateIntersection(line12), this.line12.getPoint2()); Line l3 = new Line( this.line13.getPoint2() , this.line12.getPoint2()); Triangle t = new Triangle(l1,l2,l3); return Math.min( t.calculateArea() , this.calculateArea()-t.calculateArea() ); } if( line.judgeParallel( this.line12 ) || !this.line12.judgePointInLine( this.line12.calculateIntersection(line) ) ) { Line l1 = new Line( line.calculateIntersection(line13), line.calculateIntersection(line23)); Line l2 = new Line( line.calculateIntersection(line13), this.line13.getPoint2()); Line l3 = new Line( line.calculateIntersection(line23), this.line13.getPoint2()); Triangle t = new Triangle(l1,l2,l3); return Math.min( t.calculateArea() , this.calculateArea()-t.calculateArea() ); }else if( line.judgeParallel( this.line13 ) || !this.line13.judgePointInLine( this.line13.calculateIntersection(line) ) ) { Line l1 = new Line( line.calculateIntersection(line12), line.calculateIntersection(line23)); Line l2 = new Line( line.calculateIntersection(line12), this.line12.getPoint2()); Line l3 = new Line( line.calculateIntersection(line23), this.line12.getPoint2()); Triangle t = new Triangle(l1,l2,l3); return Math.min( t.calculateArea() , this.calculateArea()-t.calculateArea() ); }else { // 23 Line l1 = new Line( line.calculateIntersection(line12), line.calculateIntersection(line13)); Line l2 = new Line( line.calculateIntersection(line12), this.line13.getPoint1()); Line l3 = new Line( line.calculateIntersection(line13), this.line13.getPoint1()); Triangle t = new Triangle(l1,l2,l3); return Math.min( t.calculateArea() , this.calculateArea()-t.calculateArea() ); } } /* 判断第四个点坐标是否在后三个点所构成的三角形的内部 * 内部返回true * 循环加数组产生八个不同方向的射线 * */ boolean judgePointPlace( Point point) { int sum = 0; Point p = new Point( point.getx()+1 , point.gety() ); Line l = new Line( point,p ); sum += this.calculateIntersectionCount2(l); if( sum % 2 == 1 ) return true; else return false; } } class Line { private Point point1; private Point point2; // 构造函数 public Line(Point point1, Point point2) { super(); this.point1 = point1; this.point2 = point2; } // 得到点一 Point getPoint1() { return this.point1; } // 得到点二 Point getPoint2() { return this.point2; } // 得到x的系数A double getA() { return point1.gety()-point2.gety(); } // 得到y的系数B double getB() { return point2.getx()-point1.getx(); } // 得到常数C double getC() { return point1.getx() * point2.gety() - point2.getx() * point1.gety(); } // 得到直线的斜率K double getK() { return (point1.gety()-point2.gety())/(point1.getx()-point2.getx()); } // 计算点到直线的距离 double calculateDistance( Point point) { double a = Math.abs( this.getA()*point.getx() + this.getB()*point.gety() + this.getC()); double b = Math.sqrt(this.getA() * this.getA() + this.getB()*this.getB()); return a/b; } /* 判断三点是否共线 * 或者判断点是否在直线上 */ boolean judgePointOnLine( Point point ){ return this.getA()*point.getx()+this.getB()*point.gety()+this.getC() == 0; } // 判断两直线是否平行 平行返回true boolean judgeParallel( Line line ) { if(this.getB() != 0 && line.getB() !=0) return this.getK() == line.getK() ; else if(this.getB() == 0 && line.getB() ==0){ return true; }else { return false; } } // 计算线与线的交点 Point calculateIntersection( Line line) { double x = (line.getC()*this.getB()-this.getC()*line.getB())/(this.getA()*line.getB()-line.getA()*this.getB()); double y = (line.getC()*this.getA()-this.getC()*line.getA())/(line.getA()*this.getB()-this.getA()*line.getB()); if(x!=0 && y!=0 ) { Point point = new Point(x,y);return point; } else if(x==0 && y==0 ) { Point point = new Point(0,0);return point; } else if(x==0 && y!=0 ) { Point point = new Point(0,y);return point; } else { Point point = new Point(x,0);return point; } } // 判断交点是否在线段的内部(包括端点,若不想包含端点删掉 = 号即可) boolean judgePointInLine( Point point ) { if( point.getx() <= Math.max( this.point1.getx(), this.point2.getx() ) && point.getx() >= Math.min( this.point1.getx() , this.point2.getx() ) && point.gety() <= Math.max( this.point1.gety(), this.point2.gety() ) && point.gety() >= Math.min( this.point1.gety() , this.point2.gety() )) return true; else return false; } // 计算线的长度 double calculateLineLength() { return this.point1.calculateDistance(this.point2); } // 计算线的长度的平方 double calculateLineLength2() { return this.point1.calculateDistance2(this.point2); } } class Point { private double x; private double y; // 构造函数 public Point(String stringx, String stringy) { this.x = Double.parseDouble(stringx) ; this.y = Double.parseDouble(stringy) ; } // 构造函数 public Point(double x, double y) { super(); this.x = x; this.y = y; } //得到点的x坐标 double getx() { return this.x; } //得到点的y坐标 double gety() { return this.y; } //计算两点的距离 double calculateDistance( Point point) { double num = (this.x - point.x)*(this.x - point.x) + (this.y - point.y)*(this.y - point.y); return Math.sqrt(num); } //计算两点的距离的平方 double calculateDistance2( Point point) { return (this.x - point.x)*(this.x - point.x) + (this.y - point.y)*(this.y - point.y); } //判断两点是否重合 boolean isCoincide( Point point) { return this.x==point.x&&this.y==point.y; } }
- 源码分析



和7-2一样超高的圈复杂度,还是由于测试类的mian方法和isLegal方法复杂度太高,不看测试类的话,Triangle和Line和Point类的平均复杂度基本都低于8,而我的测试类没有分开写很多的函数,而是一股脑全放在main中,导致main类的圈复杂度高达43,而我的判断输入语句是否合法的isLegal类由于不熟练正则表达式,导致圈复杂度很高。
踩坑心得
- 2-7-3 String的格式判断与内容提取
while( num < str.length() ){ str1 = str.substring(num,num+8); if( str1.substring(0,6).equals("202017") || str1.substring(0,6).equals("202061")){ if( num == str.length() - 8) System.out.print(str1.substring(4,8)); else System.out.print(str1.substring(4,8)+" "); } num += 8; }
if( str1.substring(0,6).equals("202017") || str1.substring(0,6).equals("202061"))该if语句不能使用contains来判断是否含有特定字符串,因为特定字符串规定了只能在前六位,如果在后六位的话是不合法的
可是contains语句会判定为合法,所以此处使用substring来切割得到前六个进行对比。
- 3-7-1 点线形系列1-计算两点之间的距离
public Point(String stringx, String stringy) { this.x = Double.parseDouble(stringx) ; this.y = Double.parseDouble(stringy) ; } // 构造函数 public Point(double x, double y) { super(); this.x = x; this.y = y; }
采用了两个构造函数,在面对不同传参时都能产生点。
- 3-7-2 点线形系列2-线的计算
// 判断两直线是否平行 boolean judgeParallel( Line line ) { if(this.getB() != 0 && line.getB() !=0) return this.getK() == line.getK() ; else if(this.getB() == 0 && line.getB() ==0){ return true; }else { return false; } }
此处不要使用斜率k来判断是否平行,因为当k不存在时考虑起来会特别麻烦。
// 判断交点是否在线段的内部 boolean judgePointInLine( Point point ) { if( point.getx() < Math.max( this.point1.getx(), this.point2.getx() ) && point.getx() > Math.min( this.point1.getx() , this.point2.getx() ) || point.gety() < Math.max( this.point1.gety(), this.point2.gety() ) && point.gety() > Math.min( this.point1.gety() , this.point2.gety() )) return true; else return false; }
进行判断时一定要同时判断在两点x值范围之间以及两点y值范围之间,不可单个考虑x或y,会有特殊情况导致过不去点。
3-7-3 点线形系列3-三角形的计算
/* * 根据三点计算三角形面积 * S=(1/2)*(x1y2+x2y3+x3y1-x1y3-x2y1-x3y2) 该公式存在方向性 A -> B -> C * 由于方向上的未知 输出时加上绝对值abs */ double calculateArea() { double num1 = line12.getPoint1().getx()*line12.getPoint2().gety() + line12.getPoint2().getx()*line13.getPoint2().gety() + line13.getPoint2().getx()*line13.getPoint1().gety() ; double num2 = line12.getPoint1().getx()*line13.getPoint2().gety() + line12.getPoint2().getx()*line13.getPoint1().gety() + line13.getPoint2().getx()*line12.getPoint2().gety() ; return Math.abs( (num1-num2)/2 ) ; }
谨慎使用海伦公式,因为我在前面求线长的时候已经开过根号求线长,海伦公式在开根号,可能会导致误差过大,测试点过不去的情况。
改进建议
- 首先可改进一下我的正则表达式的部分,看似我使用了正则表达式,但没有使用到正则表达式的精髓,可自己写一个完整的正则表达式,删减掉我那些 if 判断语句,降低圈复杂度。
- 在3-7-1点的计算中,可把后面线的计算和三角形计算中关于点的判断伊西俄,全都放到点类中。
- 在3-7-3三角形的计算中,可以把许多在方法中的与或非判断,整合到一个方法中,既可以降低圈复杂度,还可以提高代码的复用性,后期好维护。
- 在3-7-3三角形计算中 计算线与三角形交点数量的方法与 射线法计算线与三角形交点数量的方法我感觉可以整合成一个方法,可是我还没有想到怎么做。

浙公网安备 33010602011771号