前言:这两次的pta题目也是多边形系列的,题目要求复杂,测试点多,难度高,虽然题目数量少了,但所需时间更多。知识点涉及的其实主要还是类的运用,只是为实现功能所需的各种算法难度较大,需要借鉴网上的方法。由于之前就没能跟上,这两次作业很完成度都低。相比之下期中考试就简单很多了,主要考察的是基础知识,题目不仅给出了类图,还有部分所需代码可以使用。
7-2 点线形系列4-凸四边形的计算
用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入四个点坐标,判断是否是四边形、平行四边形,判断结果输出true/false,结果之间以一个英文空格符分隔。
2:输入四个点坐标,判断是否是菱形、矩形、正方形,判断结果输出true/false,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
3:输入四个点坐标,判断是凹四边形(false)还是凸四边形(true),输出四边形周长、面积,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
4:输入六个点坐标,前两个点构成一条直线,后四个点构成一个四边形或三角形,输出直线与四边形(也可能是三角形)相交的交点数量。如果交点有两个,再按面积从小到大输出四边形(或三角形)被直线分割成两部分的面积(不换行)。若直线与四边形或三角形的一条边线重合,输出"The line is coincide with one of the lines"。若后四个点不符合四边形或三角形的输入,输出"not a quadrilateral or triangle"。
后四个点构成三角形的情况:假设三角形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
1)符合要求的输入:顶点重复或者z与xy都相邻,如x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
2) 不符合要求的输入:z 不与xy都相邻,如z x y s、x z s y、x s z y
5:输入五个点坐标,输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形(判定方法见选项4)的内部(若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。如果点在多边形的某条边上,输出"on the triangle或者on the quadrilateral"。若后四个点不符合四边形或三角形,输出"not a quadrilateral or triangle"。
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
选项1、2、3中,若四边形四个点中有重合点,输出"points coincide"。
选项4中,若前两个输入线的点重合,输出"points coincide"。
设计与分析:用变量存点坐标,创建线类和四边形类,由于对类的操作不熟悉,将各种功能实现放在四边形类的方法中。
import java.text.DecimalFormat; import java.util.Scanner; public class Main { public static void main(String[] args) { // TODO 自动生成的方法存根 Scanner in = new Scanner(System.in); String str; str = in.nextLine(); int i = (int)str.charAt(0)-48; str=str.substring(2); if((!str.matches("((-|[+])?((([1-9]\\d*)|[0])(\\.\\d+)?),(-|[+])?((([1-9]\\d*)|[0])(\\.\\d+)?))((\\s)(-|[+])?((([1-9]\\d*)|[0])(\\.\\d+)?),(-|[+])?((([1-9]\\d*)|[0])(\\.\\d+)?))*\\s?"))) { System.out.println("Wrong Format"); System.exit(0); } switch(i) { case 1:{ if(str.matches("((-|[+])?(([1-9]\\d*|[0])(\\.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(\\.\\d+)?))((\\s)(-|[+])?(([1-9]\\d*|[0])(.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(.\\d+)?)){3}")) { String[] a = str.split(",|\\s"); Quadrilateral q = new Quadrilateral(Float.parseFloat(a[0]),Float.parseFloat(a[1]),Float.parseFloat(a[2]),Float.parseFloat(a[3]),Float.parseFloat(a[4]),Float.parseFloat(a[5]),Float.parseFloat(a[6]),Float.parseFloat(a[7])); if(q.isCoincide()) { System.out.println("points coincide"); System.exit(0); } else System.out.println(q.isQuadrilateral()+" "+q.isParallelogram()); } break; } case 2:{ if(str.matches("((-|[+])?(([1-9]\\d*|[0])(.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(.\\d+)?))((\\s)(-|[+])?(([1-9]\\d*|[0])(.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(.\\d+)?)){3}")) { String[] a = str.split(",|\\s"); Quadrilateral q = new Quadrilateral(Float.parseFloat(a[0]),Float.parseFloat(a[1]),Float.parseFloat(a[2]),Float.parseFloat(a[3]),Float.parseFloat(a[4]),Float.parseFloat(a[5]),Float.parseFloat(a[6]),Float.parseFloat(a[7])); if(q.isCoincide()) System.out.println("points coincide"); else if(!q.isQuadrilateral()) System.out.println("not a quadrilateral"); else System.out.println(q.isDiamond()+" "+q.isRectangle()+" "+q.isSquare()); } break; } case 3:{ if(str.matches("((-|[+])?(([1-9]\\d*|[0])(.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(.\\d+)?))((\\s)(-|[+])?(([1-9]\\d*|[0])(.\\d+)?),(-|[+])?(([1-9]\\d*|[0])(.\\d+)?)){3}")) { String[] a = str.split(",|\\s"); Quadrilateral q = new Quadrilateral(Float.parseFloat(a[0]),Float.parseFloat(a[1]),Float.parseFloat(a[2]),Float.parseFloat(a[3]),Float.parseFloat(a[4]),Float.parseFloat(a[5]),Float.parseFloat(a[6]),Float.parseFloat(a[7])); if(q.isCoincide()) { System.out.println("points coincide"); System.exit(0); }else if(!q.isQuadrilateral()) System.out.println("not a quadrilateral"); else { if(q.isBump()) System.out.println(q.isBump()+" "+q.format(q.circumference())+" "+q.format(q.Area1())); else System.out.println(q.isBump()+" "+q.format(q.circumference())+" "+q.format(q.Area2())); } } break; } } } } //四边形判断类 class Quadrilateral{ private float x1,y1,x2,y2,x3,y3,x4,y4; //点坐标 public Quadrilateral() { super(); // TODO 自动生成的构造函数存根 } public Quadrilateral(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { super(); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.x3 = x3; this.y3 = y3; this.x4 = x4; this.y4 = y4; } public boolean isCoincide(){//是否重合 if((x1==x2&&y1==y2)||(x2==x3&&y2==y3)||(x3==x4&&y3==y4)||(x4==x1&&y4==y1)) return true; return false; } public boolean isQuadrilateral() {//是否是四边形 Line a1 = new Line(x2,y2,x3,y3,x1,y1,x4,y4); Line a2 = new Line(x4,y4,x3,y3,x1,y1,x2,y2); if((x1==x3&&y1==y3)||(x2==x4&&y2==y4)||(x1==x2&&y1==y2)||(x4==x3&&y4==y3)||a1.isDot3()||a2.isDot3()) return false; else if((x1==x2&&x1==x3)||(x1==x2&&x1==x4)||(x1==x3&&x1==x4)||(x3==x2&&x3==x4)) return false; else if(Math.abs((y1-y2)/(x1-x2)-(y1-y3)/(x1-x3))<0.01||Math.abs((y1-y2)/(x1-x2)-(y1-y4)/(x1-x4))<0.01||Math.abs((y1-y4)/(x1-x4)-(y1-y3)/(x1-x3))<0.01||Math.abs((y3-y2)/(x3-x2)-(y2-y4)/(x2-x4))<0.01) return false; else return true; } public boolean isParallelogram() {//是否是平行四边形 if(isQuadrilateral()) { if((x1==x2&&x3==x4||(y1-y2)/(x1-x2)==(y4-y3)/(x4-x3))&&(x3==x2&&x1==x4||(y3-y2)/(x3-x2)==(y4-y1)/(x4-x1))) return true; else return false; } else return false; } public boolean isDiamond() {//是否是菱形 if(isParallelogram()) { if(((y1==y3&&x2==x4)||(y2==y4&&x1==x3))||(((y1-y3)/(x1-x3))*((y4-y2)/(x4-x2))==-1)) return true; else return false; } else return false; } public boolean isRectangle() {//是否是矩形 if(isParallelogram()) { if((x1==x2&&y2==y3)||(y1==y2&&x2==x3)||((y1-y2)/(x1-x2))*((y3-y2)/(x3-x2))==-1) return true; else return false; } else return false; } public boolean isSquare() {//是否是正方形 if(isRectangle()&&isDiamond()) return true; else return false; } public boolean isBump() {//凹为false 凸为true double x = -((x2-x4)*(x3*y1-x1*y3)-(x1-x3)*(x4*y2-x2*y4))/((y2-y4)*(x1-x3)-(y1-y3)*(x2-x4)); double y = -((y2-y4)*(y3*x1-y1*x3)-(y1-y3)*(y4*x2-y2*x4))/((x2-x4)*(y1-y3)-(x1-x3)*(y2-y4)); if ((((x>=x3&&x<=x1)||(x<=x3&&x>=x1))&&((y>=y3&&y<=y1)||(y<=y3&&y>=y1)))&&(((x>=x2&&x<=x4)||(x<=x2&&x>=x4))&&((y>=y2&&y<=y4)||(y<=y2&&y>=y4)))) return true; else return false; } public boolean isComposition() {//是否为三角形和四边形 if(isQuadrilateral()) return true; if((x1==x2&&y1==y2&&x3==x2&&y3==y2)||(x1==x2&&y1==y2&&x4==x2&&y4==y2)||(x1==x4&&y1==y4&&x3==x4&&y3==y4)||(x4==x2&&y4==y2&&x3==x4&&y3==y4)) return false; if((x1==x2&&x2==x3&&x3==x4)||(y1-y3)/(x1-x3)==(y2-y4)/(x2-x4)) return false; if((x1==x2&&y1==y2)||(x4==x2&&y4==y2)||(x3==x4&&y3==y4)||(x4==x1&&y4==y1)) return true; if((x1==x2&&x2==x3||Math.abs((y1-y2)/(x1-x2)-(y2-y3)/(x2-x3))<0.01)&&((x1>=x2&&x2>=x3)||x3>=x2&&x2>=x1)&&((y1>=y2&&y2>=y3)||y3>=y2&&y2>=y1)) return true; if((x1==x2&&x2==x4||Math.abs((y1-y2)/(x1-x2)-(y2-y4)/(x2-x4))<0.01)&&((x4>=x1&&x1>=x2)||x1>=x2&&x2>=x4)&&((y4>=y1&&y1>=y2)||y2>=y1&&y1>=y4)) return true; if((x4==x2&&x2==x3||Math.abs((y4-y2)/(x4-x2)-(y2-y3)/(x2-x3))<0.01)&&((x4>=x3&&x3>=x2)||x2>=x3&&x3>=x4)&&((y4>=y3&&y3>=y2)||y2>=y3&&y3>=y4)) return true; if((x1==x4&&x4==x3||Math.abs((y1-y4)/(x1-x4)-(y4-y3)/(x4-x3))<0.01)&&((x1>=x4&&x4>=x3)||x3>=x4&&x4>=x1)&&((y1>=y4&&y4>=y3)||y3>=y4&&y4>=y1)) return true; return false; } public boolean isDCoincide(float x5,float y5) {//是否三点共线 if((x1==x2&&x5==x1&&((x5>=x1&&x5<=x2)||(x5<=x1&&x5>=x2))&&((y5>=y1&&y5<=y2)||(y5<=y1&&y5>=y2)))||(x3==x2&&x5==x2&&((x5>=x3&&x5<=x2)||(x5<=x3&&x5>=x2))&&((y5>=y3&&y5<=y2)||(y5<=y3&&y5>=y2)))||(x3==x4&&x5==x3&&((x5>=x3&&x5<=x4)||(x5<=x3&&x5>=x4))&&((y5>=y3&&y5<=y4)||(y5<=y3&&y5>=y4)))||(x1==x4&&x5==x4&&((x5>=x1&&x5<=x4)||(x5<=x1&&x5>=x4))&&((y5>=y1&&y5<=y4)||(y5<=y1&&y5>=y4)))) return true; if((x1!=x2&&y1!=y2&&(y1-y2)/(x1-x2)==(y5-y1)/(x5-x1)&&((x5>=x1&&x5<=x2)||(x5<=x1&&x5>=x2))&&((y5>=y1&&y5<=y2)||(y5<=y1&&y5>=y2)))||(x3!=x2&&y3!=y2&&(y3-y2)/(x3-x2)==(y5-y2)/(x5-x2)&&((x5>=x3&&x5<=x2)||(x5<=x3&&x5>=x2))&&((y5>=y3&&y5<=y2)||(y5<=y3&&y5>=y2)))||(x3!=x4&&y3!=y4&&(y3-y4)/(x3-x4)==(y5-y3)/(x5-x3)&&((x5>=x3&&x5<=x4)||(x5<=x3&&x5>=x4))&&((y5>=y3&&y5<=y4)||(y5<=y3&&y5>=y4)))||(x1!=x4&&y1!=y4&&(y1-y4)/(x1-x4)==(y5-y4)/(x5-x4)&&((x5>=x1&&x5<=x4)||(x5<=x1&&x5>=x4))&&((y5>=y1&&y5<=y4)||(y5<=y1&&y5>=y4)))) return true; return false; } public String format(double a) {//格式化 return new DecimalFormat("0.0##").format(a); } public double Area(float x1, float y1, float x2, float y2, float x3, float y3) {//三角形面积 return 0.5 * Math.abs(x1 * y3 + x2 * y1 + x3 * y2 - x1 * y2 - x2 * y3 -x3 * y1); } public double Area1() {//凸形面积 return 0.5*Math.abs((x3-x1)*(y4-y2)-(y3-y1)*(x4-x2)); } public double Area2() {//凹形面积 return 0.5*Math.abs((x3-x1)*(y4-y2)-(y3-y1)*(x4-x2)); } public boolean Area3(float x5,float y5) {//面积是否相等 面积法 double a = 0.5 * Math.abs(x1 * y3 + x2 * y1 + x3 * y2 - x1 * y2 - x2 * y3 -x3 * y1) + 0.5 * Math.abs(x1 * y3 + x4 * y1 + x3 * y4 - x1 * y4 - x4 * y3 -x3 * y1); double b = 0.5 * Math.abs(x1 * y5 + x2 * y1 + x5 * y2 - x1 * y2 - x2 * y5 -x5 * y1) + 0.5 * Math.abs(x2 * y3 + x5 * y2 + x3 * y5 - x2 * y5 - x5 * y3 -x3 * y2) + 0.5 * Math.abs(x4 * y3 + x5 * y4 + x3 * y5 - x4 * y5 - x5 * y3 -x3 * y4) + 0.5 * Math.abs(x1 * y4 + x5 * y1 + x4 * y5 - x1 * y5 - x5 * y4 -x4 * y1); if(Math.abs(a-b)<0.01) return true; return false; } public double circumference() {//四边形周长 return Math.pow((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2),0.5) + Math.pow((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2),0.5) + Math.pow((x3-x4)*(x3-x4)+(y3-y4)*(y3-y4),0.5) +Math.pow((x1-x4)*(x1-x4)+(y1-y4)*(y1-y4),0.5); } } //线类 class Line{ private float x1,x2,x3,x4,y1,y2,y3,y4; public Line(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4) { super(); this.x1 = x1; this.x2 = x2; this.x3 = x3; this.x4 = x4; this.y1 = y1; this.y2 = y2; this.y3 = y3; this.y4 = y4; } public Line() { super(); // TODO 自动生成的构造函数存根 } boolean isDot() { double x = -((x3-x4)*(x2*y1-x1*y2)-(x1-x2)*(x4*y3-x3*y4))/((y3-y4)*(x1-x2)-(y1-y2)*(x3-x4)); double y = -((y3-y4)*(y2*x1-y1*x2)-(y1-y2)*(y4*x3-y3*x4))/((x3-x4)*(y1-y2)-(x1-x2)*(y3-y4)); if(Math.abs((y1-y2)/(x1-x2)-(y3-y4)/(x3-x4))<0.01) return false; else if (((x>=x3&&x<=x4)||(x<=x3&&x>=x4))&&((y>=y3&&y<=y4)||(y<=y3&&y>=y4))) return true; else return false; } boolean isDot3() { double x = -((x3-x4)*(x2*y1-x1*y2)-(x1-x2)*(x4*y3-x3*y4))/((y3-y4)*(x1-x2)-(y1-y2)*(x3-x4)); double y = -((y3-y4)*(y2*x1-y1*x2)-(y1-y2)*(y4*x3-y3*x4))/((x3-x4)*(y1-y2)-(x1-x2)*(y3-y4)); if(Math.abs((y1-y2)/(x1-x2)-(y3-y4)/(x3-x4))<0.01) return false; else if (((x>=x3&&x<=x4)||(x<=x3&&x>=x4))&&((y>=y3&&y<=y4)||(y<=y3&&y>=y4))&&((x>=x1&&x<=x2)||(x<=x1&&x>=x2))&&((y>=y1&&y<=y2)||(y<=y1&&y>=y2))) return true; else return false; } boolean isCoincide(){ if(Math.abs((y4-y3)*x1+(x3-x4)*y1+x4*y3-y4*x3)/Math.sqrt((y4-y3)*(y4-y3)+(x4-x3)*(x4-x3))<0.01&&(Math.abs((y1-y2)/(x1-x2)-(y3-y4)/(x3-x4))<0.01||((x1==x2)&&(x3==x4)))) return true; else return false; } float getxValue(){ return -((x3-x4)*(x2*y1-x1*y2)-(x1-x2)*(x4*y3-x3*y4))/((y3-y4)*(x1-x2)-(y1-y2)*(x3-x4)); } float getyValue(){ return -((y3-y4)*(y2*x1-y1*x2)-(y1-y2)*(y4*x3-y3*x4))/((x3-x4)*(y1-y2)-(x1-x2)*(y3-y4)); } }
改进建议:功能四和五没能实现,后续需要补完。可以构造更多的类,将部分的方法放在类中,减少单个类的复杂度。
7-1 点线形系列5-凸五边形的计算-1
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入五个点坐标,判断是否是五边形,判断结果输出true/false。
2:输入五个点坐标,判断是凹五边形(false)还是凸五边形(true),如果是凸五边形,则再输出五边形周长、面积,结果之间以一个英文空格符分隔。 若五个点坐标无法构成五边形,输出"not a pentagon"
3:输入七个点坐标,前两个点构成一条直线,后五个点构成一个凸五边形、凸四边形或凸三角形,输出直线与五边形、四边形或三角形相交的交点数量。如果交点有两个,再按面积从小到大输出被直线分割成两部分的面积(不换行)。若直线与多边形形的一条边线重合,输出"The line is coincide with one of the lines"。若后五个点不符合五边形输入,若前两点重合,输出"points coincide"。
以上3选项中,若输入的点无法构成多边形,则输出"not a polygon"。输入的五个点坐标可能存在冗余,假设多边形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
1)符合要求的输入:顶点重复或者z与xy都相邻,如:x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
2) 不符合要求的输入:z不与xy都相邻,如:z x y s、x z s y、x s z y
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
输入样例1:
选项1,点重合。例如:
1:-1,-1 1,2 -1,1 1,0
输出样例:
在这里给出相应的输出。例如:
wrong number of points
设计与分析:构造点线类,主要判断直接放在主函数中,调用类方法实现功能。
import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { Scanner in =new Scanner(System.in); String s =in.nextLine(); if(s.charAt(0)=='1') { String regrex1 = "[1-5]{1}\\:(([+-]?(0|[1-9](\\d+)?)(\\.\\d+)?,[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?[\\s])*)[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?,[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?"; boolean flag = s.matches(regrex1); if(flag){ int o = 2; int m = 0; for(o=2;o<s.length();o++){ if(s.charAt(o)==','){ m++; } } if(m==5){ Matcher matcher = Pattern.compile("(-?\\d*)\\.?\\d+").matcher(s); double[] num = new double[20]; int n=0; while(matcher.find()){ num[n] = Double.valueOf(matcher.group().toString()); n++; } Point p1 = new Point(); Point p2 = new Point(); Point p3 = new Point(); Point p4 = new Point(); Point p5 = new Point(); p1.setX(num[1]); p1.setY(num[2]); p2.setX(num[3]); p2.setY(num[4]); p3.setX(num[5]); p3.setY(num[6]); p4.setX(num[7]); p4.setY(num[8]); p5.setX(num[9]); p5.setY(num[10]); Line l1 = new Line(p1,p2); Line l2 = new Line(p2,p3); Line l3 = new Line(p3,p4); Line l4 = new Line(p4,p5); Line l5 = new Line(p5,p1); if(l1.isParallel(l2)||l2.isParallel(l3)||l3.isParallel(l4)||l4.isParallel(l5)||l5.isParallel(l1)){ System.out.println("false"); } else{ if(java.awt.geom.Line2D.linesIntersect(p1.getX(), p1.getY(),p2.getX(), p2.getY(),p3.getX(), p3.getY(),p4.getX(), p4.getY())||java.awt.geom.Line2D.linesIntersect(p1.getX(), p1.getY(),p2.getX(), p2.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY())||java.awt.geom.Line2D.linesIntersect(p2.getX(), p2.getY(),p3.getX(), p3.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY())||java.awt.geom.Line2D.linesIntersect(p2.getX(), p2.getY(),p3.getX(), p3.getY(),p5.getX(), p5.getY(),p1.getX(), p1.getY()) ||java.awt.geom.Line2D.linesIntersect(p3.getX(), p3.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY(),p1.getX(), p1.getY())){ System.out.println("false"); } else{ System.out.println("true"); } } } else{ System.out.println("wrong number of points"); } } else{ System.out.println("Wrong Format"); }} if(s.charAt(0)=='2') { String regrex2 = "[1-5]{1}\\:(([+-]?(0|[1-9](\\d+)?)(\\.\\d+)?,[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?[\\s])*)[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?,[+-]?(0|[1-9](\\d+)?)(\\.\\d+)?"; boolean flag = s.matches(regrex2); if(flag){ int o = 2; int m = 0; for(o=2;o<s.length();o++){ if(s.charAt(o)==','){ m++; } } if(m==5) { Matcher matcher = Pattern.compile("(-?\\d*)\\.?\\d+").matcher(s); double[] num = new double[20]; int n=0; while(matcher.find()){ num[n] = Double.valueOf(matcher.group().toString()); n++; } Point p1 = new Point(); Point p2 = new Point(); Point p3 = new Point(); Point p4 = new Point(); Point p5 = new Point(); p1.setX(num[1]); p1.setY(num[2]); p2.setX(num[3]); p2.setY(num[4]); p3.setX(num[5]); p3.setY(num[6]); p4.setX(num[7]); p4.setY(num[8]); p5.setX(num[9]); p5.setY(num[10]); Line l1 = new Line(p1,p2); Line l2 = new Line(p2,p3); Line l3 = new Line(p3,p4); Line l4 = new Line(p4,p5); Line l5 = new Line(p5,p1); int t = -1; if(l1.isParallel(l2)||l2.isParallel(l3)||l3.isParallel(l4)||l4.isParallel(l5)||l5.isParallel(l1)) { t =0; } else { if(java.awt.geom.Line2D.linesIntersect(p1.getX(), p1.getY(),p2.getX(), p2.getY(),p3.getX(), p3.getY(),p4.getX(), p4.getY())||java.awt.geom.Line2D.linesIntersect(p1.getX(), p1.getY(),p2.getX(), p2.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY())||java.awt.geom.Line2D.linesIntersect(p2.getX(), p2.getY(),p3.getX(), p3.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY())||java.awt.geom.Line2D.linesIntersect(p2.getX(), p2.getY(),p3.getX(), p3.getY(),p5.getX(), p5.getY(),p1.getX(), p1.getY()) ||java.awt.geom.Line2D.linesIntersect(p3.getX(), p3.getY(),p4.getX(), p4.getY(),p5.getX(), p5.getY(),p1.getX(), p1.getY())) { t=0; } else { t = 1; } } if(t == 0) { System.out.println("not a pentagon"); } if(t == 1) { System.out.println("false"); } } else { System.out.println("wrong number of points"); } } else { System.out.println("Wrong Format"); } } } } class Point { public double x; public double y; public Point() { } public Point(double x,double y) { this.x=x; this.y=y; } /* 设置坐标x,将输入参数赋值给属性x */ public void setX(double x) { this.x = x; } /* 设置坐标y,将输入参数赋值给属性y */ public void setY(double y) { this.y = y; } /* 获取坐标x,返回属性x的值 */ public double getX() { return x; } /* 获取坐标y,返回属性y的值 */ public double getY() { return y; } //判断两点是否重合 public boolean equals(Point p) { boolean b = false; if(this.x==p.getX()&&this.y==p.getY()) { b=true; } return b; } /* 计算当前点和输入点p之间的距离 */ public double getDistance(Point p) { return 0; } } class Line { private Point p1;//线上的第一个点 private Point p2;//线上的第二个点 public Line(double x1, double y1, double x2, double y2) { Point p1 = new Point(x1, y1); Point p2 = new Point(x2, y2); LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出 this.p1 = p1; this.p2 = p2; } public Line(Point p1, Point p2) { LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出 this.p1 = p1; this.p2 = p2; } /* 获取线条的斜率 */ public Double getSlope() { // (x1-x2=0)注意考虑斜率不存在即返回double类型无穷大"Infinite" return (p2.getY() - p1.getY()) / (p2.getX() - p1.getX()); } /* 判断x是否在线上 */ public boolean isOnline(Point x) { //System.out.println("isOnline"); //System.out.println(p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y + " "); // 点重合 if ((x.getX() == p1.getX() && x.getY() == p1.getY()) || (x.getX() == p2.getX() && x.getY() == p2.getY())) { return true; } Line l = new Line(p1, x); if (l.getSlope().isInfinite() && this.getSlope().isInfinite()) { return true; } // 此点与线上任意一点构成的线的斜率相等则此点在线上 double b1 = l.getSlope(), b2 = this.getSlope(); //System.out.println(b1 + " " + b2 + " " + (b1- b2) + " " + (Math.abs(b1 - b2) < 0.00000000001)); return Math.abs(b1 - b2) < 0.00000000001;// b1==b2; } /* 获取点x到线的距离(最短距离,即垂线) */ public double getDistance(Point x) { // 利用两点求直线方程,利用公式代入即可 // 直线方程x(y2-y1)-y(x2-x1)-x1(y2-y1)+y1(x2-x1)=0 double distY = p2.getY() - p1.getY(); double distX = p2.getX() - p1.getX(); return Math.abs(x.getX() * distY - x.getY() * distX - p1.getX() * distY + p1.getY() * distX) / p1.getDistance(p2); } /* 判断x是否在线上且在两点之间 */ public boolean isBetween(Point x) { //System.out.println("isBetween" + " " + this.p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y); if (!this.isOnline(x)) { return false; } // 与端点重合,认为不在在两点之间, if (x.equals(p1) || x.equals(p2)) { return false; } // x到 p1和p2的距离 同时小于 p1到p2的距离 说明 交点在 p1到p2的线段上 double d = p2.getDistance(p1); boolean b = x.getDistance(p2) < d && x.getDistance(p1) < d; //System.out.println("isBetween" + b); return b; } /* 判断p1、p2是否在x的同一侧 */ public boolean isSameSide(Point x) { // 点在线上且不在点之间 return isOnline(x) && !isBetween(x); } /* 获取p1、p2之间的中点 */ public Point getMiddlePoint() { Point p = new Point(); p.setX((p1.getX() + p2.getX()) / 2); p.setY((p1.getY() + p2.getY()) / 2); return p; } /* 获取线段的第一个坐标点 */ public Point getPointA() { return p1; } /* 获取线段的第二个坐标点 */ public Point getPointB() { return p2; } /* 获取与线条l之间的夹角,若两条线段交叉(交叉点位于其中一条线的两点之间),取较小的夹角 */ public double getAngle(Line l) { // 利用公式θ=arctan∣(k2- k1)/(1+ k1k2)∣,此时求较小的夹角 double k2 = getSlope(); double k1 = l.getSlope(); return (double) (Math.atan(Math.abs((k2 - k1) / (1 + k1 * k2))) * 180.0 / Math.PI);// 返回值为角度 } // 是否平行,平行返回true,否则false。 public boolean isParallel(Line l) { Double b1 = this.getSlope(); Double b2 = l.getSlope(); if ((b1.isInfinite()) && (b2.isInfinite())) { return true; } else { return (this.getSlope().doubleValue() == l.getSlope().doubleValue()); } } // 两条线是否重合,重合返回true,否则false。 public boolean isCoincide(Line l) { if (!this.isParallel(l)) { return false; } if (this.isOnline(l.p1)) { return true; } return false; } // 获取交叉点,若两条线平行,返回null。 public Point getIntersection(Line l) { if (this.isParallel(l)) { return null; } if (p1.equals(l.p1) || p1.equals(l.p2)) { return p1; } if (p2.equals(l.p1) || p2.equals(l.p2)) { return p2; } Point p3 = l.p1, p4 = l.p2; double x_member, x_denominator, y_member, y_denominator; Point cross_point = new Point(); x_denominator = p4.x * p2.y - p4.x * p1.y - p3.x * p2.y + p3.x * p1.y - p2.x * p4.y + p2.x * p3.y + p1.x * p4.y - p1.x * p3.y; x_member = p3.y * p4.x * p2.x - p4.y * p3.x * p2.x - p3.y * p4.x * p1.x + p4.y * p3.x * p1.x - p1.y * p2.x * p4.x + p2.y * p1.x * p4.x + p1.y * p2.x * p3.x - p2.y * p1.x * p3.x; if (x_denominator == 0) cross_point.x = 0; else cross_point.x = x_member / x_denominator; y_denominator = p4.y * p2.x - p4.y * p1.x - p3.y * p2.x + p1.x * p3.y - p2.y * p4.x + p2.y * p3.x + p1.y * p4.x - p1.y * p3.x; y_member = -p3.y * p4.x * p2.y + p4.y * p3.x * p2.y + p3.y * p4.x * p1.y - p4.y * p3.x * p1.y + p1.y * p2.x * p4.y - p1.y * p2.x * p3.y - p2.y * p1.x * p4.y + p2.y * p1.x * p3.y; if (y_denominator == 0) cross_point.y = 0; else cross_point.y = y_member / y_denominator; return cross_point; // 平行返回(0,0) } } //处理异常提示。 class LineInputError { public static void pointsCoincideError(Point p1, Point p2) { if ((p1.getX() == p2.getX()) && p1.getY() == p2.getY()) { System.out.println("points coincide"); System.exit(0); } } }
采坑心得:功能判断的算法太难了想不出来,只好借鉴网上代码了。
改进建议:功能未实现完,后续需要补足。还是添加更多的类,减少单个类的复杂度,后续水平增强后优化代码
7-2 点线形系列5-凸五边形的计算-2
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
4:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),判断它们两个之间是否存在包含关系(一个多边形有一条或多条边与另一个多边形重合,其他部分都包含在另一个多边形内部,也算包含)。
两者存在六种关系:1、分离(完全无重合点) 2、连接(只有一个点或一条边重合) 3、完全重合 4、被包含(前一个多边形在后一个多边形的内部)5、交错 6、包含(后一个多边形在前一个多边形的内部)。
各种关系的输出格式如下:
1、no overlapping area between the previous triangle/quadrilateral/ pentagon and the following triangle/quadrilateral/ pentagon
2、the previous triangle/quadrilateral/ pentagon is connected to the following triangle/quadrilateral/ pentagon
3、the previous triangle/quadrilateral/ pentagon coincides with the following triangle/quadrilateral/ pentagon
4、the previous triangle/quadrilateral/ pentagon is inside the following triangle/quadrilateral/ pentagon
5、the previous triangle/quadrilateral/ pentagon is interlaced with the following triangle/quadrilateral/ pentagon
6、the previous triangle/quadrilateral/ pentagon contains the following triangle/quadrilateral/ pentagon
5:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),输出两个多边形公共区域的面积。注:只考虑每个多边形被另一个多边形分割成最多两个部分的情况,不考虑一个多边形将另一个分割成超过两个区域的情况。
6:输入六个点坐标,输出第一个是否在后五个点所构成的多边形(限定为凸多边形,不考虑凹多边形),的内部(若是五边形输出in the pentagon/outof the pentagon,若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。输入入错存在冗余点要排除,冗余点的判定方法见选项5。如果点在多边形的某条边上,输出"on the triangle/on the quadrilateral/on the pentagon"。
以上4、5、6选项输入的五个点坐标可能存在冗余,假设多边形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
1)符合要求的输入:顶点重复或者z与xy都相邻,如:x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
2) 不符合要求的输入:z不与xy都相邻,如:z x y s、x z s y、x s z y
设计与分析:这题难度太大,时间不够,没能完成,后续有时间再写吧。
期中考试
7-1 点与线(类设计)
设计与分析:
根据题目中已给出类图,根据类图设计类、变量和方法即可。重点在于用getDistance()的算法计算长度和display()方法的构造和使用。
部分代码(点类和线类):
//点类 class Point{ private double x,y; public Point(double x,double y){ this.x = x; this.y = y; } 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 void display(){ System.out.println("("+String.format("%.2f", x)+","+String.format("%.2f",y)+")"); } } //线类 class Line{ Point point1; Point point2; String color; public Line(Point point1,Point point2,String color){ this.point1 = point1; this.point2 = point2; this.color = color; } public void setPoint1(Point point1){ this.point1 = point1; } public void setPoint2(Point point2){ this.point2 = point2; } public void setColor(String color){ this.color = color; } public Point getPoint1(){ return point1; } public Point getPoint2(){ return point2; } public String getColor(){ return color; } public double getDistance(){ double distance=Math.sqrt((point1.getX()-point2.getX())*(point1.getX()-point2.getX())+(point1.getY()-point2.getY())*(point1.getY()-point2.getY())); return distance; } public void display(){ System.out.println("The line's color is:"+color); System.out.println("The line's begin point's Coordinate is:"); point1.display(); System.out.println("The line's end point's Coordinate is:"); point2.display(); System.out.println("The line's length is:"+String.format("%.2f",getDistance())); } }
采坑心得:仔细审题,注意输入范围的判断(其实是别人踩的坑,借用一下)
改进建议:暂无
7-2 点线面问题重构(继承与多态)
在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。
在主方法内,定义两个Point(线段的起点和终点)对象、一个Line对象和一个Plane对象,依次从键盘输入两个Point对象的起点、终点坐标和颜色值(Line对象和Plane对象颜色相同),然后定义一个Element类的引用,分别使用该引用调用以上四个对象的display()方法,从而实现多态特性。示例代码如下:
element = p1;//起点Point
element.display();
element = p2;//终点Point
element.display();
element = line;//线段
element.display();
element = plane;//面
element.display();
设计与分析:
这题就是在第一题基础上加上继承,所需的类方法也都已给出,主类中所需修改的代码题目也已经给出,按类图修改就行啦。
部分代码(主类和新建的两个类)
import java.util.*; //主类 public class Main { public static void main(String args[]){ Scanner input = new Scanner(System.in); double x1=input.nextDouble(); double y1=input.nextDouble(); double x2=input.nextDouble(); double y2=input.nextDouble(); String color=input.next(); if(x1>0&&x1<=200&&x2>0&&x2<=200&&y1>0&&y1<=200&&y2>0&&y2<=200){ //设定范围 Point p1=new Point(x1,y1); Point p2=new Point(x2,y2); Line line=new Line(p1,p2,color); Element element = new Element(); Plane plane = new Plane(color); element = p1;//起点Point element.display(); element = p2;//终点Point element.display(); element = line;//线段 element.display(); element = plane;//面 element.display(); } else System.out.print("Wrong Format"); } } //共同父类 class Element{ public void display(){ } } //颜色类 class Plane extends Element{ String color; public Plane(String color){ this.color = color; } public String getColor(){ return color; } public void setColor(String color){ this.color = color; } @Override public void display(){ System.out.println("The Plane's color is:"+color); } }
采坑心得:用题目给的代码注意变量名统一
改进建议:暂无
7-3 点线面问题再重构(容器类)
由于在补前面的知识,容器没有学好,这题也没拿什么分。
总结:这几周的学习状态一直都不好,再加之要补前面落下的知识,作业的完成情况不太好。类和方法的知识有了一定的进步,但仍需写一些练习题完善。继承只后的知识还没怎么学,需要加快进度了。在算法方面遇到了很多困难,要多加练习,多学习网上的算法来提高自己。正则表达式也是用的网上的,需要更深入的学习才能自己写出需要的正则表达式解决问题。不会就多问,多看网课多练习,上课不能再划水摸鱼了,努力追上进度。
标签:总结性,y2,期中考试,Blog,&&,x2,x3,x1,x4 From: https://www.cnblogs.com/cdpr/p/16839242.html