一、前言
1、题目集4、5
难度相比前几次有较大幅度的提升,难点在于算法的设计,如何设计能写出更简单易懂的代码,以及对于类的理解应用需要达到更高的水平。题目集4是对于四边形进行各种操作,而题目集5是对于五边形进行各种操作,本意是让在对于三角形的操作的基础上衍生出四边形,再升级为五边形,最后归类为多边形。
2、期中考试
难度适中,但融合了类、继承、多态等等知识点,适于全面考核,本次考试共三题,第一题属于打基础篇,即在第一题将大致的框架勾勒好,后面两题则是在第一题的基础上分别加上父类和抽象类以及多态的运用。
二、题目具体分析
1、题目集4/题目7-2:点线形系列4-凸四边形的计算
(1)题目详情
用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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"。
(2)设计
共有7个类,包括:
主类:包含一个静态主方法,其中主要有switch构成,作为情况选择的通道;
输入输出类:包含一个输入方法和一个输出方法,其中输出方法单指对于非法判断的结果输出;
格式判断类:对于输入的数据用正则表达式以及其他辅助手段进行合法性判断;
点类:包含点的横纵坐标属性x,y以及标记一个点是否真实存在的属性flag,点重合判断方法、计算两点间距离方法、两点计算斜率方法;
线类:包含作为属性的两个点dot1、dot2,线重合判断方法、两条直线的交点计算方法;
三角形类:包含作为属性的三个点A、B、C,构成三角形判断方法,点在三角形上判断方法,判断直线与三角形边重合方法,直线切割三角形方法,面积计算方法,点相对于三角形的位置判断方法;
四边形类:包含作为属性的四个点A、B、C、D和四条边AB、BC、CD、DA以及对角线交点在不在对角线上的标志flagAC,flagBD,
录入一个四边形信息的方法,构成四边形(凹、凸)判断方法,分别判断四边形的形状的一系列方法,周长计算方法......(有点多,不一 一列举)。
(3)源码
1 import java.util.Scanner; 2 3 public class Main{//主类 4 public static void main(String[] args){ 5 inOut inout = new inOut(); 6 String str = inout.input();//输入 7 int selectNum = (int)str.charAt(0) - (int)'0';//情况选择 8 int dex = 0, sign = 3;//dex为点的个数,sign应该取0,1,2以外的值 9 String[] tokens = str.split(":|,| "); 10 Verify ver = new Verify();//判非法对象 11 switch(selectNum){ 12 case 1: dex = 4; sign = ver.feifa(str,dex); 13 inout.output(sign); 14 if(sign == 1){//合法 15 Square sq = new Square(); 16 sq.creatSquare(1,tokens,sq);//四边形信息录入 17 if(sq.A.coincide(sq.B)==0 || sq.A.coincide(sq.C)==0 || sq.A.coincide(sq.D)==0 || sq.B.coincide(sq.C)==0 || sq.B.coincide(sq.D)==0 || sq.C.coincide(sq.D)==0){//有点重合 18 System.out.print("points coincide"); 19 break; 20 } 21 boolean flag = sq.sibianxingJudge(sq); 22 if(!flag){//无法构成四边形 23 System.out.print("false"+" "+"false"); 24 } 25 else{ 26 boolean flag1 = sq.pingxingJudge(sq); 27 if(flag1){//构成平行四边形 28 System.out.print("true"+" "+"true"); 29 } 30 else{//构成四边形 31 System.out.print("true"+" "+"false"); 32 } 33 } 34 } 35 break; 36 case 2: dex = 4; sign = ver.feifa(str,dex); 37 inout.output(sign); 38 if(sign == 1){//合法 39 Square sq = new Square(); 40 sq.creatSquare(1,tokens,sq);//四边形信息录入 41 /* if(sq.A.coincide(sq.B)==0 || sq.A.coincide(sq.C)==0 || sq.A.coincide(sq.D)==0 || sq.B.coincide(sq.C)==0 || sq.B.coincide(sq.D)==0 || sq.C.coincide(sq.D)==0){//有点重合 42 System.out.print("points coincide"); 43 break; 44 }*/ 45 if(!sq.sibianxingJudge(sq)){//无法构成四边形 46 System.out.print("not a quadrilateral"); 47 } 48 else{ 49 if(sq.pingxingJudge(sq) && sq.xianghuchuizhi(sq)){//平行四边形 + 对角线互相垂直 = 菱形 50 System.out.print("true"); 51 } 52 else{ 53 System.out.print("false"); 54 } 55 56 int flag = 0; 57 if(sq.pingxingJudge(sq) && sq.zhijiaoJudge(sq)){//平行四边形 + 有一个角是直角 = 矩形 58 flag = 1; 59 System.out.print(" true"); 60 } 61 else{ 62 System.out.print(" false"); 63 } 64 if(flag==0){//不是矩形,不可能是正方形 65 System.out.print(" false"); 66 } 67 else{//矩形 + 相邻边相等 = 正方形 68 if(sq.xianglinbianJudge(sq)){//相邻边相等判断 69 System.out.print(" true"); 70 } 71 else{ 72 System.out.print(" false"); 73 } 74 } 75 } 76 } 77 break; 78 case 3: dex = 4; sign = ver.feifa(str,dex); 79 inout.output(sign); 80 if(sign == 1){//合法 81 Square sq = new Square(); 82 sq.creatSquare(1,tokens,sq);//四边形信息录入 83 if(sq.A.coincide(sq.B)==0 || sq.A.coincide(sq.C)==0 || sq.A.coincide(sq.D)==0 || sq.B.coincide(sq.C)==0 || sq.B.coincide(sq.D)==0 || sq.C.coincide(sq.D)==0){//有点重合 84 System.out.print("points coincide"); 85 break; 86 } 87 88 if(sq.sibianxingJudge(sq)){//构成凸四边形 89 if(sq.aoJudeg(sq)){ 90 System.out.print("false"); 91 double zhouchang = sq.zhouchangCount(sq);//周长计算 92 double area = sq.areaCount2(sq);//面积计算 93 zhouchang = Math.round(zhouchang*1000)/1000.0; 94 area = Math.round(area*1000)/1000.0; 95 System.out.print(" "+zhouchang+" "+area); 96 } 97 else{ 98 System.out.print("true"); 99 double zhouchang = sq.zhouchangCount(sq);//周长计算 100 double area = sq.areaCount1(sq);//面积计算 101 zhouchang = Math.round(zhouchang*1000)/1000.0; 102 area = Math.round(area*1000)/1000.0; 103 System.out.print(" "+zhouchang+" "+area); 104 } 105 } 106 else if(sq.sibianxingJudge1(sq)){//构成凹四边形 107 System.out.print("false"); 108 double zhouchang = sq.zhouchangCount(sq);//周长计算 109 double area = sq.areaCount2(sq);//面积计算 110 zhouchang = Math.round(zhouchang*1000)/1000.0; 111 area = Math.round(area*1000)/1000.0; 112 System.out.print(" "+zhouchang+" "+area); 113 } 114 else{ 115 System.out.print("not a quadrilateral"); 116 } 117 118 /* 119 if(!sq.sibianJudge(sq)){ 120 System.out.print("not a quadrilateral"); 121 } 122 else{ 123 int flag = sq.aotuJudge(sq); 124 if(flag == 1){ 125 System.out.print("true"); 126 double zhouchang = sq.zhouchangCount(sq);//周长计算 127 double area = sq.areaCount1(sq);//面积计算 128 zhouchang = Math.round(zhouchang*1000)/1000.0; 129 area = Math.round(area*1000)/1000.0; 130 System.out.print(" "+zhouchang+" "+area); 131 } 132 else if(flag == 2){ 133 System.out.print("false"); 134 double zhouchang = sq.zhouchangCount(sq);//周长计算 135 double area = sq.areaCount2(sq);//面积计算 136 zhouchang = Math.round(zhouchang*1000)/1000.0; 137 area = Math.round(area*1000)/1000.0; 138 System.out.print(" "+zhouchang+" "+area); 139 } 140 else{ 141 System.out.print("not a quadrilateral"); 142 } 143 }*/ 144 } 145 break; 146 case 4: dex = 6; sign = ver.feifa(str,dex); 147 inout.output(sign); 148 if(sign == 1){//合法 149 Line l = new Line(); 150 Square sq = new Square(); 151 l.dot1.x = Double.valueOf(tokens[1]); l.dot1.y = Double.valueOf(tokens[2]); 152 l.dot2.x = Double.valueOf(tokens[3]); l.dot2.y = Double.valueOf(tokens[4]); 153 if(l.dot1.coincide(l.dot2) == 0){//两点重合 154 System.out.print("points coincide"); 155 break; 156 } 157 sq.creatSquare(5, tokens, sq);//四边形信息录入 158 Triangle t = new Triangle(); 159 if(sq.tJudge(sq,t)){//构成三角形 160 if(t.xianchongheJudge(t, l)){//线重合边 161 System.out.print("The line is coincide with one of the lines"); 162 break; 163 } 164 t.xianqiege(t, l, sq);//直线切割三角形 165 } 166 else if(sq.sibianxingJudge2(sq)){//构成凸四边形 167 if(sq.xianchongheJudge1(sq, l)){//线重合边 168 System.out.print("The line is coincide with one of the lines"); 169 break; 170 } 171 sq.xianqiege1(sq, l);//直线切割四边形 172 } 173 else{ 174 System.out.print("not a quadrilateral or triangle"); 175 } 176 } 177 break; 178 case 5: dex = 5; sign = ver.feifa(str,dex); 179 inout.output(sign); 180 if(sign == 1){//合法 181 Spot dot = new Spot(); 182 dot.x = Double.valueOf(tokens[1]); dot.y = Double.valueOf(tokens[2]); 183 Triangle t = new Triangle(); 184 Square sq = new Square(); 185 sq.creatSquare(3, tokens, sq);//四边形信息录入 186 if(sq.tJudge(sq,t)){//构成三角形 187 t.pointJudge1(t, dot, sq);//点的位置判断 188 } 189 else if(sq.sibianxingJudge2(sq)){//构成凸四边形 190 sq.pointJudge2(sq, dot, t);//点的位置判断 191 } 192 else{ 193 System.out.print("not a quadrilateral or triangle"); 194 } 195 } 196 break; 197 default: 198 System.out.print("Wrong Format"); 199 }//switch 200 }//main 201 }//Main 202 203 class Spot{//点 204 double x, y;//横纵坐标 205 boolean flag = false;//点的状态 206 public int coincide(Spot dot){//判断两点是否重合 207 if((this.x == dot.x) && (this.y == dot.y)){ 208 return 0;//两点重合 209 } 210 return 1;//不重合 211 } 212 213 public double distance(Spot dot){//两点间距离计算 214 return Math.sqrt((this.x-dot.x)*(this.x-dot.x) + (this.y-dot.y)*(this.y-dot.y)); 215 } 216 217 public double xielv(Spot dot1, Spot dot2){//斜率 218 return (dot1.y - dot2.y) / (dot1.x - dot2.x); 219 } 220 }//Spot 221 222 class Line{//线 223 Spot dot1 = new Spot(); 224 Spot dot2 = new Spot();//两点确定一条直线 225 226 public boolean xianchonghe(Line l, Spot A, Spot B){//判断两线是否重合 227 if(l.dot1.x == l.dot2.x){//l斜率不存在 228 if(A.x == B.x){//直线斜率不存在 229 if(A.x == l.dot1.x) 230 return true; 231 else 232 return false; 233 } 234 else{ 235 return false; 236 } 237 } 238 else{//l斜率存在 239 if(A.x == B.x){//直线斜率不存在 240 return false; 241 } 242 else{//y = k * x + b 243 double lk = l.dot1.xielv(l.dot1, l.dot2); 244 double lb = l.dot1.y - lk * l.dot1.x; 245 double k = A.xielv(A, B); 246 double b = A.y - k * A.x; 247 if(lk==k && lb== b) 248 return true; 249 else 250 return false; 251 } 252 } 253 } 254 255 public void xianjiaodian(Spot dot1, Spot dot2, Line l, Spot dot){//求两直线的交点,dot1和dot2所构成直线与l的交点dot 256 if(l.dot1.x == l.dot2.x){//l斜率不存在 257 if(dot1.x == dot2.x){//直线斜率不存在,无交点 258 dot.flag = false; 259 } 260 else{//直线斜率存在,有交点 261 dot.x = l.dot1.x; 262 //y = k * x + b 263 double k = dot1.xielv(dot1, dot2); 264 double b = dot1.y - k * dot1.x; 265 dot.y = k * dot.x + b; 266 dot.flag = true; 267 } 268 } 269 else{//l斜率存在 270 if(dot1.x == dot2.x){//直线斜率不存在,有交点 271 dot.x = dot1.x; 272 //y = k * x + b 273 double lk = l.dot1.xielv(l.dot1, l.dot2); 274 double lb = l.dot1.y - lk * l.dot1.x; 275 dot.y = lk * dot.x + lb; 276 dot.flag = true; 277 } 278 else{//直线斜率存在 279 double lk = l.dot1.xielv(l.dot1, l.dot2); 280 double lb = l.dot1.y - lk * l.dot1.x; 281 double k = dot1.xielv(dot1, dot2); 282 double b = dot1.y - k * dot1.x; 283 if(lk==lb){//两直线平行,无交点 284 dot.flag = false; 285 } 286 else{ 287 dot.x = (lb-b)/(k-lk); 288 dot.y = k * dot.x + b; 289 dot.flag = true; 290 } 291 } 292 } 293 } 294 295 }//Line 296 297 class Square{//四边形 298 Spot A = new Spot(); 299 Spot B = new Spot(); 300 Spot C = new Spot(); 301 Spot D = new Spot();//构成四边形的四个点 302 Line AB = new Line(); 303 Line BC = new Line(); 304 Line CD = new Line(); 305 Line DA = new Line();//构成四边形的四条边 306 int flagAC = 0; 307 int flagBD = 0; 308 309 public void creatSquare(int start, String[] a, Square sq){//输入四边形信息 310 sq.A.x = Double.valueOf(a[start]); sq.A.y = Double.valueOf(a[++start]); 311 sq.B.x = Double.valueOf(a[++start]); sq.B.y = Double.valueOf(a[++start]); 312 sq.C.x = Double.valueOf(a[++start]); sq.C.y = Double.valueOf(a[++start]); 313 sq.D.x = Double.valueOf(a[++start]); sq.D.y = Double.valueOf(a[++start]); 314 sq.AB.dot1 = A; sq.AB.dot2 = B; 315 sq.BC.dot1 = B; sq.BC.dot2 = C; 316 sq.CD.dot1 = C; sq.CD.dot2 = D; 317 sq.DA.dot1 = D; sq.DA.dot2 = A; 318 } 319 320 public boolean sibianxingJudge(Square sq){//判断是否构成凸四边形 321 if((sq.A.x-sq.B.x)*(sq.B.y-sq.C.y) == (sq.B.x-sq.C.x)*(sq.A.y-sq.B.y)) 322 return false; 323 else if((sq.A.x-sq.B.x)*(sq.A.y-sq.D.y) == (sq.A.x-sq.D.x)*(sq.A.y-sq.B.y)) 324 return false; 325 else if((sq.D.x-sq.C.x)*(sq.A.y-sq.D.y) == (sq.A.x-sq.D.x)*(sq.D.y-sq.C.y)) 326 return false; 327 else if((sq.C.x-sq.D.x)*(sq.B.y-sq.C.y) == (sq.B.x-sq.C.x)*(sq.C.y-sq.D.y)) 328 return false; 329 else if(tongceJudeg1(sq) && tongceJudeg2(sq))//且C、D在AB同侧,A、D在BC同侧 330 return true; 331 else 332 return false; 333 } 334 335 public boolean tongceJudeg1(Square sq){//判断构成四边形的C、D两点是否在直线AB同侧 336 if(sq.A.x == sq.B.x){//AB斜率不存在 337 if(sq.C.x>sq.A.x && sq.D.x>sq.A.x)//在同侧 338 return true; 339 else if(sq.C.x<sq.A.x && sq.D.x<sq.A.x) 340 return true; 341 else 342 return false; 343 } 344 else{ 345 double k = sq.A.xielv(sq.A, sq.B);//y = k*x+b; 346 double b = sq.A.y - k*sq.A.x; 347 if((sq.C.y - k*sq.C.x - b)>0 && (sq.D.y - k*sq.D.x - b)>0) 348 return true;//在同侧 349 else if((sq.C.y - k*sq.C.x - b)<0 && (sq.D.y - k*sq.D.x - b)<0) 350 return true; 351 else 352 return false; 353 } 354 } 355 356 public boolean tongceJudeg2(Square sq){//判断构成四边形的A、D两点是否在直线BC同侧 357 if(sq.B.x == sq.C.x){//BC斜率不存在 358 if(sq.A.x>sq.B.x && sq.D.x>sq.B.x)//在同侧 359 return true; 360 else if(sq.A.x<sq.B.x && sq.D.x<sq.B.x) 361 return true; 362 else 363 return false; 364 } 365 else{ 366 double k = sq.B.xielv(sq.B, sq.C);//y = k*x+b; 367 double b = sq.B.y - k*sq.B.x; 368 if((sq.A.y - k*sq.A.x - b)>0 && (sq.D.y - k*sq.D.x - b)>0) 369 return true;//在同侧 370 else if((sq.A.y - k*sq.A.x - b)<0 && (sq.D.y - k*sq.D.x - b)<0) 371 return true; 372 else 373 return false; 374 } 375 } 376 377 public boolean pingxingJudge(Square sq){//判断是否为平行四边形 378 //判断两组对边平行则为平行四边形,AB和CD,BC和DA 379 if(((sq.A.x-sq.B.x)*(sq.C.y-sq.D.y) == (sq.C.x-sq.D.x)*(sq.A.y-sq.B.y)) && (sq.D.x-sq.A.x)*(sq.B.y-sq.C.y) == (sq.B.x-sq.C.x)*(sq.D.y-sq.A.y)) 380 return true;//构成平行四边形 381 else 382 return false; 383 } 384 385 public boolean xianghuchuizhi(Square sq){//判断四边形对角线是否相互垂直,AC与BD 386 if((sq.C.x-sq.A.x)*(sq.B.x-sq.D.x) == (sq.A.y-sq.C.y)*(sq.B.y-sq.D.y)){ 387 return true;//相互垂直 388 } 389 else{ 390 return false; 391 } 392 } 393 394 public boolean zhijiaoJudge(Square sq){//判断四边形中有一个角为直角 395 double AB = sq.A.distance(sq.B); 396 double BC = sq.B.distance(sq.C); 397 double AC = sq.A.distance(sq.C); 398 if(Math.abs(AB*AB + BC*BC - AC*AC) < 0.000001){ 399 return true; 400 } 401 else{ 402 return false; 403 } 404 } 405 406 public boolean xianglinbianJudge(Square sq){//判断矩形任意一组相邻边是否相等 407 double AB = sq.A.distance(sq.B); 408 double BC = sq.B.distance(sq.C); 409 if(AB == BC){ 410 return true; 411 } 412 else{ 413 return false; 414 } 415 } 416 417 public double zhouchangCount(Square sq){//周长 418 return ((sq.A.distance(sq.B)) + (sq.B.distance(sq.C)) + (sq.C.distance(sq.D)) + (sq.D.distance(sq.A))); 419 } 420 421 public double areaCount1(Square sq){//凸四边形面积,任意对角线切割 422 //AC切割 423 double AB = sq.A.distance(sq.B); 424 double BC = sq.B.distance(sq.C); 425 double AC = sq.A.distance(sq.C); 426 double CD = sq.C.distance(sq.D); 427 double DA = sq.D.distance(sq.A); 428 double ABC = (AB+BC+AC)/2; 429 double ACD = (AC+CD+DA)/2; 430 return (Math.sqrt(ABC*(ABC-AB)*(ABC-BC)*(ABC-AC)) + Math.sqrt(ACD*(ACD-AC)*(ACD-CD)*(ACD-DA))); 431 } 432 433 public boolean aoJudeg(Square sq){//D点为凹入点 434 Spot dot = new Spot(); 435 sq.jiaodianCount(sq,dot); 436 if(!sq.dianxianJudge(dot, sq.B, sq.D) && sq.dianxianJudge(dot, sq.A, sq.C)){//点不在线段BD上 437 sq.flagAC = 1; 438 return true; 439 } 440 else 441 return false; 442 } 443 444 public boolean sibianxingJudge2(Square sq){//判断能否构成凸四边形 445 if((sq.A.x-sq.B.x)*(sq.B.y-sq.C.y) == (sq.B.x-sq.C.x)*(sq.A.y-sq.B.y)) 446 return false; 447 else if((sq.A.x-sq.B.x)*(sq.A.y-sq.D.y) == (sq.A.x-sq.D.x)*(sq.A.y-sq.B.y)) 448 return false; 449 else if((sq.D.x-sq.C.x)*(sq.A.y-sq.D.y) == (sq.A.x-sq.D.x)*(sq.D.y-sq.C.y)) 450 return false; 451 else if((sq.C.x-sq.D.x)*(sq.B.y-sq.C.y) == (sq.B.x-sq.C.x)*(sq.C.y-sq.D.y)) 452 return false; 453 else if(sq.jiaodian(sq)==2)//且对角线的交点在两条对角线上 454 return true; 455 else 456 return false; 457 } 458 459 public boolean sibianxingJudge1(Square sq){//判断能否构成凹四边形 460 if((sq.A.x-sq.B.x)*(sq.B.y-sq.C.y) == (sq.B.x-sq.C.x)*(sq.A.y-sq.B.y)) 461 return false; 462 else if((sq.A.x-sq.B.x)*(sq.A.y-sq.D.y) == (sq.A.x-sq.D.x)*(sq.A.y-sq.B.y)) 463 return false; 464 else if((sq.D.x-sq.C.x)*(sq.A.y-sq.D.y) == (sq.A.x-sq.D.x)*(sq.D.y-sq.C.y)) 465 return false; 466 else if((sq.C.x-sq.D.x)*(sq.B.y-sq.C.y) == (sq.B.x-sq.C.x)*(sq.C.y-sq.D.y)) 467 return false; 468 else if(sq.jiaodian(sq)==1)//且对角线的交点只在其中任意一条对角线上 469 return true; 470 else 471 return false; 472 } 473 474 public int jiaodian(Square sq){//判断对角线交点在不在对角线上 475 Spot jiaodian = new Spot(); 476 sq.jiaodianCount(sq, jiaodian); 477 if(sq.dianxianJudge(jiaodian, sq.A, sq.C)){//点在线段AC上 478 sq.flagAC = 1; 479 } 480 if(sq.dianxianJudge(jiaodian, sq.B, sq.D)){//点在线段BD上 481 sq.flagBD = 1; 482 } 483 if((sq.flagAC==1 && sq.flagBD==0) || (sq.flagAC==0 && sq.flagBD==1)) 484 return 1; 485 else if(sq.flagAC==1 && sq.flagBD==1) 486 return 2; 487 else 488 return 0; 489 } 490 491 public boolean dianxianJudge(Spot dot, Spot dot1, Spot dot2){//判断点是否在线段上 492 double dotA = dot.distance(dot1); 493 double dotB = dot.distance(dot2); 494 double AB = dot1.distance(dot2); 495 if(dotA+dotB-AB < 0.000001){//在线段上 496 return true; 497 } 498 else{ 499 return false; 500 } 501 } 502 503 public void jiaodianCount(Square sq, Spot dot){//计算交点坐标 504 if(sq.A.x == sq.C.x){//AC斜率不存在 505 double k2 = sq.B.xielv(sq.B,sq.D); 506 double b2 = sq.B.y - k2 * sq.B.x; 507 dot.x = sq.A.x; 508 dot.y = k2 * dot.x + b2; 509 } 510 else if(sq.B.x == sq.D.x){//BD斜率不存在 511 double k1 = sq.A.xielv(sq.A,sq.C); 512 double b1 = sq.A.y - k1 * sq.A.x; 513 dot.x = sq.B.x; 514 dot.y = k1 * dot.x + b1; 515 } 516 else{ 517 //y1 = k1 * x1 + b1, AC 518 double k1 = sq.A.xielv(sq.A,sq.C); 519 double b1 = sq.A.y - k1 * sq.A.x; 520 //y2 = k2 * x2 + b2, BD 521 double k2 = sq.B.xielv(sq.B,sq.D); 522 double b2 = sq.B.y - k2 * sq.B.x; 523 dot.x = (b2-b1)/(k1-k2); 524 dot.y = k1 * dot.x + b1; 525 } 526 } 527 /* 528 public boolean sibianJudge(Square sq){ 529 if((sq.A.x-sq.B.x)*(sq.B.y-sq.C.y) == (sq.B.x-sq.C.x)*(sq.A.y-sq.B.y)) 530 return false; 531 else if((sq.A.x-sq.B.x)*(sq.A.y-sq.D.y) == (sq.A.x-sq.D.x)*(sq.A.y-sq.B.y)) 532 return false; 533 else if((sq.D.x-sq.C.x)*(sq.A.y-sq.D.y) == (sq.A.x-sq.D.x)*(sq.D.y-sq.C.y)) 534 return false; 535 else if((sq.C.x-sq.D.x)*(sq.B.y-sq.C.y) == (sq.B.x-sq.C.x)*(sq.C.y-sq.D.y)) 536 return false; 537 else 538 return true; 539 } 540 541 public int aotuJudge(Square sq){//判断四边形凹凸情况 542 double BD = sq.B.distance(sq.D); 543 double DA = sq.D.distance(sq.A); 544 double AB = sq.A.distance(sq.B); 545 double BC = sq.B.distance(sq.C); 546 double CD = sq.C.distance(sq.D); 547 double AC = sq.A.distance(sq.C); 548 549 //S,BD 550 double BDA = (BD+DA+AB)/2; 551 double BDC = (BD+BC+CD)/2; 552 double S1 = (Math.sqrt(BDA*(BDA-BD)*(BDA-DA)*(BDA-AB)) + Math.sqrt(BDC*(BDC-BD)*(BDC-BC)*(BDC-CD))); 553 554 //S,AC 555 double ACD = (AC+CD+DA)/2; 556 double ACB = (AC+AB+BC)/2; 557 double S2 = (Math.sqrt(ACD*(ACD-AC)*(ACD-CD)*(ACD-DA)) + Math.sqrt(ACB*(ACB-AC)*(ACB-AB)*(ACB-BC))); 558 if(S1 == S2){//凸四边形 559 return 1; 560 } 561 else{ 562 if(S1>S2){ 563 sq.flagBD = 1; 564 } 565 else{ 566 sq.flagAC = 1; 567 } 568 return 2; 569 } 570 }*/ 571 572 public double areaCount2(Square sq){//凹四边形面积 573 double S = 0; 574 if(sq.flagAC == 1){//交点在AC上,BD切割 575 double BD = sq.B.distance(sq.D); 576 //BDA 577 double DA = sq.D.distance(sq.A); 578 double AB = sq.A.distance(sq.B); 579 double BDA = (BD+DA+AB)/2; 580 //BDC 581 double BC = sq.B.distance(sq.C); 582 double CD = sq.C.distance(sq.D); 583 double BDC = (BD+BC+CD)/2; 584 //S 585 S = (Math.sqrt(BDA*(BDA-BD)*(BDA-DA)*(BDA-AB)) + Math.sqrt(BDC*(BDC-BD)*(BDC-BC)*(BDC-CD))); 586 } 587 else if(sq.flagBD == 1){//交点在BD上,AC切割 588 double AC = sq.A.distance(sq.C); 589 //ACD 590 double CD = sq.C.distance(sq.D); 591 double DA = sq.D.distance(sq.A); 592 double ACD = (AC+CD+DA)/2; 593 //ACB 594 double AB = sq.A.distance(sq.B); 595 double BC = sq.B.distance(sq.C); 596 double ACB = (AC+AB+BC)/2; 597 S = (Math.sqrt(ACD*(ACD-AC)*(ACD-CD)*(ACD-DA)) + Math.sqrt(ACB*(ACB-AC)*(ACB-AB)*(ACB-BC))); 598 } 599 return S; 600 } 601 602 public boolean tJudge(Square sq, Triangle t){//判断是否构成三角形 603 if(t.dianONxian(sq, t)){//有一个点在一条边线上 604 return true; 605 } 606 else{ 607 return false; 608 } 609 /* if(sq.A.coincide(sq.B)==0 && t.goucheng(sq.A, sq.C, sq.D, t)){//AB重合,ACD三点构成三角形 610 return true; 611 } 612 else if(sq.A.coincide(sq.C)==0 && t.goucheng(sq.A, sq.B, sq.D, t)){//AC重合,ABD三点构成三角形 613 return true; 614 } 615 else if(sq.A.coincide(sq.D)==0 && t.goucheng(sq.A, sq.B, sq.C, t)){//AD重合,ABC三点构成三角形 616 return true; 617 } 618 else if(sq.B.coincide(sq.C)==0 && t.goucheng(sq.A, sq.B, sq.D, t)){//BC重合,ABD三点构成三角形 619 return true; 620 } 621 else if(sq.B.coincide(sq.D)==0 && t.goucheng(sq.A, sq.B, sq.C, t)){//BD重合,ABC三点构成三角形 622 return true; 623 } 624 else if(sq.C.coincide(sq.D)==0 && t.goucheng(sq.A, sq.B, sq.C, t)){//CD重合,ABC三点构成三角形 625 return true; 626 } 627 else if(sq.A.coincide(sq.B)==1 && sq.A.coincide(sq.C)==1 && sq.A.coincide(sq.D)==1 && sq.B.coincide(sq.C)==1 && sq.B.coincide(sq.D)==1 && sq.C.coincide(sq.D)==1){//不存在点重合,但有一个点在一条边线上 628 if(t.dianONxian(sq, t)){//有一个点在一条边线上 629 return true; 630 } 631 else{ 632 return false; 633 } 634 } 635 else{ 636 return false; 637 }*/ 638 } 639 640 public boolean xianchongheJudge1(Square sq, Line l){//判断线与四边形的边是否重合 641 if(l.xianchonghe(l, sq.A, sq.B) || l.xianchonghe(l, sq.B, sq.C) || l.xianchonghe(l, sq.C, sq.D) || l.xianchonghe(l, sq.D, sq.A)){//l与AB重合||l与BC重合||l与CD重合||l与DA重合 642 return true; 643 } 644 else{ 645 return false; 646 } 647 } 648 649 public void xianqiege1(Square sq, Line l){//直线切割四边形求面积 650 //l与AB相交 651 Spot ABdot = new Spot(); 652 int dotnum = 0;//记录点的个数 653 l.xianjiaodian(sq.A, sq.B, l, ABdot); 654 if(ABdot.flag==true){//交点存在 655 if(sq.dianxianJudge(ABdot, sq.A, sq.B)){//点在AB线段上 656 dotnum++; 657 } 658 else{ 659 ABdot.flag = false; 660 } 661 662 }//if 663 //l与BC相交 664 Spot BCdot = new Spot(); 665 l.xianjiaodian(sq.B, sq.C, l, BCdot); 666 if(BCdot.flag==true){//交点存在 667 if(sq.dianxianJudge(BCdot, sq.B, sq.C)){//点在BC线段上 668 if(ABdot.flag==false){//ABdot不存在 669 dotnum++; 670 } 671 else if(ABdot.flag==true && BCdot.coincide(ABdot)==1){//ABdot存在但两点不重合 672 dotnum++; 673 } 674 else{ 675 BCdot.flag = false; 676 } 677 } 678 else{ 679 BCdot.flag = false; 680 } 681 }//if 682 //l与CD相交 683 Spot CDdot = new Spot(); 684 l.xianjiaodian(sq.C, sq.D, l, CDdot); 685 if(CDdot.flag==true){//交点存在 686 if(sq.dianxianJudge(CDdot, sq.C, sq.D)){//点在CD线段上 687 if(ABdot.flag==false && BCdot.flag==false){//ABdot、BCdot均不存在 688 dotnum++; 689 } 690 else if(ABdot.flag==true && BCdot.flag==false && CDdot.coincide(ABdot)==1){//ABdot存在、BCdot不存在,且ABdot与CDdot不重合 691 dotnum++; 692 } 693 else if(ABdot.flag==false && BCdot.flag==true && CDdot.coincide(BCdot)==1){//ABdot不存在、BCdot存在,且BCdot与CDdot不重合 694 dotnum++; 695 } 696 else{ 697 CDdot.flag = false; 698 } 699 } 700 else{ 701 CDdot.flag = false; 702 } 703 }//if 704 //l与DA相交 705 Spot DAdot = new Spot(); 706 l.xianjiaodian(sq.D, sq.A, l, DAdot); 707 if(DAdot.flag==true){//交点存在 708 if(sq.dianxianJudge(DAdot, sq.D, sq.A)){//点在DA线段上 709 if(ABdot.flag==false && BCdot.flag==false && CDdot.flag==false){//ABdot、BCdot、CDdot均不存在 710 dotnum++; 711 } 712 else if(ABdot.flag==true && BCdot.flag==false && CDdot.flag==false && DAdot.coincide(ABdot)==1){//ABdot存在,BCdot、CDdot均不存在,且DAdot与ABdot不重合 713 dotnum++; 714 } 715 else if(ABdot.flag==false && BCdot.flag==true && CDdot.flag==false && DAdot.coincide(BCdot)==1){//BCdot存在,ABdot、CDdot均不存在,且DAdot与BCdot不重合 716 dotnum++; 717 } 718 else if(ABdot.flag==false && BCdot.flag==false && CDdot.flag==true && DAdot.coincide(CDdot)==1){//CDdot存在,ABdot、BCdot均不存在,且DAdot与CDdot不重合 719 dotnum++; 720 } 721 else{ 722 DAdot.flag = false; 723 } 724 } 725 else{ 726 DAdot.flag = false; 727 } 728 }//if 729 System.out.print(dotnum); 730 //四边形总面积 731 double S = sq.areaCount1(sq); 732 double S1 = 0; 733 //用于三角形面积计算方法调用 734 Triangle t1 = new Triangle(); 735 if(dotnum==2){//有两个交点,成功切割 736 if(ABdot.flag==true && BCdot.flag==true){//两个点在AB和BC上,计算B、ABdot、BCdot构成三角形的面积 737 S1 = t1.mianjiCount(sq.B, ABdot, BCdot); 738 } 739 else if(BCdot.flag==true && CDdot.flag==true){//两个点在BC和CD上,计算C、BCdot、CDdot构成三角形的面积 740 S1 = t1.mianjiCount(sq.C, BCdot, CDdot); 741 } 742 else if(CDdot.flag==true && DAdot.flag==true){//两个点在CD和DA上,计算D、CDdot、DAdot构成三角形的面积 743 S1 = t1.mianjiCount(sq.D, CDdot, DAdot); 744 } 745 else if(ABdot.flag==true && DAdot.flag==true){//两个点在AB和DA上,计算A、ABdot、DAdot构成三角形的面积 746 S1 = t1.mianjiCount(sq.A, ABdot, DAdot); 747 } 748 else if(ABdot.flag==true && CDdot.flag==true){//两个点在AB和CD上,计算S(A、D、CDdot)+ S(A、ABdot、CDdot) 749 S1 = t1.mianjiCount(sq.A, sq.D, CDdot) + t1.mianjiCount(sq.A, ABdot, CDdot); 750 } 751 else if(DAdot.flag==true && BCdot.flag==true){//两个点在DA和BC上,计算S(A、B、BCdot)+ S(A、BCdot、DAdot) 752 S1 = t1.mianjiCount(sq.A, sq.B, BCdot) + t1.mianjiCount(sq.A, BCdot, DAdot); 753 } 754 }//if 755 double S2 = S - S1; 756 if(S1 > S2){ 757 double temp = 0; 758 temp = S1; 759 S1 = S2; 760 S2 = temp; 761 } 762 S1 = Math.round(S1*1000)/1000.0; 763 S2 = Math.round(S2*1000)/1000.0; 764 System.out.print(" "+S1+" "+S2); 765 } 766 767 public void pointJudge2(Square sq, Spot dot, Triangle t){//点相对于四边形位置的判断 768 if(sq.dianxianJudge(dot, sq.A, sq.B) || sq.dianxianJudge(dot, sq.B, sq.C) || sq.dianxianJudge(dot, sq.C, sq.D) || sq.dianxianJudge(dot, sq.D, sq.A)){//点在四边形上,dot在AB或BC或CD或DA上 769 System.out.print("on the quadrilateral"); 770 } 771 else{//面积法判断 772 double Sabcd = sq.areaCount1(sq);//四边形A、B、C、D的面积 773 double Sab = t.mianjiCount(sq.A, sq.B, dot);//三角形A、B、dot的面积 774 double Sbc = t.mianjiCount(sq.B, sq.C, dot);//三角形B、C、dot的面积 775 double Scd = t.mianjiCount(sq.C, sq.D, dot);//三角形C、D、dot的面积 776 double Sda = t.mianjiCount(sq.D, sq.A, dot);//三角形D、A、dot的面积 777 if(Math.abs(Sab + Sbc + Scd + Sda - Sabcd) < (2e-10)){//在四边形内部 778 System.out.print("in the quadrilateral"); 779 } 780 else{//在四边形外部 781 System.out.print("outof the quadrilateral"); 782 } 783 } 784 } 785 786 }//Square 787 788 class Triangle{//三角形 789 Spot A = new Spot(); 790 Spot B = new Spot(); 791 Spot C = new Spot();//三角形三点 792 793 public boolean goucheng(Spot dot1, Spot dot2, Spot dot3, Triangle t){//判构是否成三角形 794 if(dot1.coincide(dot2)==0 || dot1.coincide(dot3)==0 || dot2.coincide(dot3)==0){//三个点中存在重合点 795 return false; 796 } 797 else{ 798 double l12 = dot1.distance(dot2); 799 double l13 = dot1.distance(dot3); 800 double l23 = dot2.distance(dot3); 801 if((l12-l13-l23<0) && (l13-l12-l23<0) && (l23-l12-l13<0)){//构成三角形 802 t.A = dot1; 803 t.B = dot2; 804 t.C = dot3; 805 return true; 806 } 807 else{ 808 return false; 809 } 810 } 811 } 812 813 public boolean dianONxian(Square sq, Triangle t){//判断四点是否有一点在三角形的边线上 814 if(t.goucheng(sq.A, sq.B, sq.C, t) && (sq.dianxianJudge(sq.D, sq.A, sq.C) || sq.D.coincide(sq.B)==0)){//ABC构成三角形,D在AC线上,或D与B重合 815 return true; 816 } 817 else if(t.goucheng(sq.A, sq.B, sq.D, t) && (sq.dianxianJudge(sq.C, sq.B, sq.D) || sq.C.coincide(sq.A)==0)){//ABD构成三角形,C在BD线上,或C与A重合 818 return true; 819 } 820 else if(t.goucheng(sq.A, sq.C, sq.D, t) && (sq.dianxianJudge(sq.B, sq.A, sq.C) || sq.B.coincide(sq.D)==0)){//ACD构成三角形,B在AC线上,或B与D重合 821 return true; 822 } 823 else if(t.goucheng(sq.B, sq.C, sq.D, t) && (sq.dianxianJudge(sq.A, sq.B, sq.D) || sq.A.coincide(sq.C)==0)){//BCD构成三角形,A在BD线上,或A与C重合 824 return true; 825 } 826 else{ 827 return false; 828 } 829 } 830 831 public boolean xianchongheJudge(Triangle t, Line l){//线与三角形的边重合 832 if(l.xianchonghe(l, t.A, t.B) || l.xianchonghe(l, t.A, t.C) || l.xianchonghe(l, t.B, t.C)){//l重合AB或AC或BC 833 return true; 834 } 835 else{ 836 return false; 837 } 838 } 839 840 public void xianqiege(Triangle t, Line l, Square sq){//直线l切割三角形求面积 841 //l与AB交点 842 Spot ABdot = new Spot(); 843 int dotnum = 0;//记录点的个数 844 l.xianjiaodian(t.A, t.B, l, ABdot); 845 if(ABdot.flag==true){//交点存在 846 if(sq.dianxianJudge(ABdot, t.A, t.B)){//点在线段上 847 dotnum++; 848 } 849 else{//点不在线段上 850 ABdot.flag = false; 851 } 852 }//if 853 //l与AC交点 854 Spot ACdot = new Spot(); 855 l.xianjiaodian(t.A, t.C, l, ACdot); 856 if(ACdot.flag==true){//交点存在 857 if(sq.dianxianJudge(ACdot, t.A, t.C)){//点在线段上 858 if(ABdot.flag==false){//ABdot不存在 859 dotnum++; 860 } 861 else if(ABdot.flag==true && ACdot.coincide(ABdot)==1){//ABdot存在但两点不重合 862 dotnum++; 863 } 864 else{ 865 ACdot.flag = false; 866 } 867 } 868 else{ 869 ACdot.flag = false; 870 } 871 }//if 872 //l与BC交点 873 Spot BCdot = new Spot(); 874 l.xianjiaodian(t.B, t.C, l, BCdot); 875 if(BCdot.flag==true){//交点存在 876 if(sq.dianxianJudge(BCdot, t.B, t.C)){//点在线段上 877 if(ABdot.flag==false && ACdot.flag==false){//ABdot、ACdot均不存在 878 dotnum++; 879 } 880 else if(ABdot.flag==true && ACdot.flag==false && BCdot.coincide(ABdot)==1){//ABdot存在、ACdot不存在,且BCdot与ABdot不重合 881 dotnum++; 882 } 883 else if(ABdot.flag==false && ACdot.flag==true && BCdot.coincide(ACdot)==1){//ABdot不存在、ACdot存在,且BCdot与ACdot不重合 884 dotnum++; 885 } 886 else{ 887 BCdot.flag = false; 888 } 889 } 890 else{ 891 BCdot.flag = false; 892 } 893 }//if 894 System.out.print(dotnum); 895 if(dotnum==2){//有两个交点,成功切割 896 double S = t.mianjiCount(t.A, t.B, t.C);//总面积 897 double S2 = 0; 898 if(ABdot.flag==true && ACdot.flag==true){//两个点在AB和AC上,计算三角形A、ABdot、ACdot的面积 899 S2 = t.mianjiCount(t.A, ABdot, ACdot); 900 } 901 else if(ABdot.flag==true && BCdot.flag==true){//两个点在AB和BC上,计算三角形B、ABdot、BCdot的面积 902 S2 = t.mianjiCount(t.B, ABdot, BCdot); 903 } 904 else if(BCdot.flag==true && ACdot.flag== true){//两个点在BC和AC上,计算三角形C、BCdot、ACdot的面积 905 S2 = t.mianjiCount(t.C, BCdot, ACdot); 906 } 907 double S1 = S - S2; 908 if(S1 > S2){ 909 double temp = 0; 910 temp = S1; 911 S1 = S2; 912 S2 = temp; 913 } 914 S1 = Math.round(S1*1000)/1000.0; 915 S2 = Math.round(S2*1000)/1000.0; 916 System.out.print(" "+S1+" "+S2); 917 } 918 } 919 920 public double mianjiCount(Spot A, Spot B, Spot C){//计算三角形面积 921 double AB = A.distance(B); 922 double AC = A.distance(C); 923 double BC = B.distance(C); 924 double p = (AB+AC+BC)/2; 925 return Math.sqrt(p*(p-AB)*(p-AC)*(p-BC)); 926 } 927 928 public void pointJudge1(Triangle t, Spot dot, Square sq){//点相对于三角形位置的判断 929 if(sq.dianxianJudge(dot, t.A, t.B) || sq.dianxianJudge(dot, t.B, t.C) || sq.dianxianJudge(dot, t.A, t.C)){//点在三角形上,dot在AB或BC或AC上 930 System.out.print("on the triangle"); 931 } 932 else{//面积法判断 933 double Sabc = t.mianjiCount(t.A, t.B, t.C);////三角形A,B,C 934 double Sab = t.mianjiCount(t.A, t.B, dot);//三角形A,B,dot 935 double Sbc = t.mianjiCount(t.B, t.C, dot);//三角形B,C,dot 936 double Sac = t.mianjiCount(t.A, t.C, dot);//三角形A,C,dot 937 if(Math.abs(Sab + Sbc + Sac - Sabc) < (2e-10)){//在三角形内 938 System.out.print("in the triangle"); 939 } 940 else{//在三角形外 941 System.out.print("outof the triangle"); 942 } 943 } 944 } 945 946 }//Triangle 947 948 class inOut{//输入输出 949 public String input(){//输入 950 Scanner in = new Scanner(System.in); 951 String s = in.nextLine(); 952 return s; 953 } 954 public void output(int a){//输出格式判断结果 955 if(a == 0) 956 System.out.print("Wrong Format"); 957 if(a == 2) 958 System.out.print("wrong number of points"); 959 } 960 961 }//inOut 962 963 class Verify{//格式验证 964 public int feifa(String s, int dex){ 965 String[] tokens = s.split(" "); 966 int i = 0, sign = 1; 967 boolean flag = true; 968 for(i=0;i<tokens.length;i++) { 969 if(i==0){ 970 flag = tokens[i].matches("^[1-5]:[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"); 971 } 972 else{ 973 flag = tokens[i].matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"); 974 } 975 if (!flag){//flag = flase 976 sign = 0; 977 break; 978 } 979 } 980 if(flag && tokens.length!=(dex)){//flag = true 981 sign = 2; 982 } 983 // System.out.println(sign); 984 return sign;//为1输入合法,为0输入格式错误,为2输入个数错误 985 } 986 }View Code
(4)代码分析
测试如下:
分析:类和方法的设置适中,深度和复杂度越界,感觉是因为算法的设计出现了漏洞然后不好修改只能填补或重写供后面使用,以及对于类的用法并不是很熟练,并未用上父类、子类、继承等这些可以让代码更加简洁的办法。
(5)踩坑心得
一开始判断是否构成四边形遗漏了情况,会将一种凹四边形判成不构成四边形,但又引用了其进行其他判断,导致不好修改,后面又直接写了一个可判凹、凸、构成非法的方法(在四个点能构成四边形的前提下,求对角线的交点,判断交点是否在两条对角线线段上,如果同时在两条上,则四边形为凸四边形,若只在其中一条上,则四边形为凹四边形,若同时不在两条上,则为非法的四边形,即不符合题目要求的四边形)。所以说在动手敲码前,要先将大致的思路构思好,并且确立一个恰当的正确的算法,并且应该尽量一个一个测试点过完整,不然容易返工。(回炉重造是真的难受!!!)
(6)改进建议
添加父类,有好几个地方都是相同的方法写两遍,原因是因为传的参数不同。
2、题目集5/7-1:点线形系列5-凸五边形的计算-1
(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
(2)设计
共有8个类,包括:
主类:包含一个静态主方法,其中主要有switch构成,作为情况选择的通道;
输入输出类:包含一个输入方法和一个输出方法,其中输出方法单指对于非法判断的结果输出;
格式判断类:对于输入的数据用正则表达式以及其他辅助手段进行合法性判断;
点类:包含点的横纵坐标属性x,y以及标记一个点是否真实存在的属性flag,点重合判断方法、计算两点间距离方法、两点计算斜率方法,三点共线判断方法;
线类:包含作为属性的两个点dot1、dot2,线重合判断方法、两条直线的交点计算方法,四点共线判断方法,点在线段上判断方法......;
三角形类:包含作为属性的三个点A、B、C,构成三角形判断方法(构成与合法),判断直线与三角形边重合方法,直线切割三角形方法,面积计算方法;
四边形类:包含作为属性的四个点A、B、C、D,构成四边形(凸)判断方法(构成与合法),判断直线与四边形边重合方法,直线切割四边形方法;
五边形类:包含作为属性的五个点A、B、C、D、E和五条边AB、BC、CD、DE、EA,
录入五边形信息方法,构成五边形判断方法(构成与合法),凸五边形判断方法,周长计算方法,面积计算方法,判断直线与五边形边重合方法,直线切割五边形方法。
(3)源码
1 import java.util.Scanner; 2 import java.util.ArrayList; 3 4 class Input{//输入输出类 5 public String input(){//输入数据 6 Scanner input = new Scanner(System.in); 7 String s = input.nextLine(); 8 return s; 9 } 10 public void output(int a){//输出格式判断结果 11 if(a == 0) 12 System.out.print("Wrong Format"); 13 if(a == 2) 14 System.out.print("wrong number of points"); 15 } 16 } 17 18 class Verify{//输入格式判断 19 public int feifa(String s, int dex){ 20 String[] tokens = s.split(" "); 21 int i = 0, sign = 1; 22 boolean flag = true; 23 for(i=0;i<tokens.length;i++) { 24 if(i==0){ 25 flag = tokens[i].matches("^[1-5]:[+-]?(0|aaa(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"); 26 } 27 else{ 28 flag = tokens[i].matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"); 29 } 30 if (!flag){//flag = flase 31 sign = 0; 32 break; 33 } 34 } 35 if(flag && tokens.length!=(dex)){//flag = true 36 sign = 2; 37 } 38 // System.out.println(sign); 39 return sign;//为1输入合法,为0输入格式错误,为2输入个数错误 40 } 41 } 42 43 class Spot{//点类 44 double x; 45 double y;//横纵坐标 46 boolean flag = false;//点的状态,不存在 47 48 public boolean coincide(Spot dot){//点重合判断 49 return (this.x == dot.x && this.y == dot.y) ? true : false; 50 } 51 52 public double xielv(Spot dot){//计算斜率 53 return (this.y - dot.y) / (this.x - dot.x); 54 } 55 56 public double distance(Spot dot){//两点间计算距离 57 return Math.sqrt((this.x-dot.x)*(this.x-dot.x) + (this.y-dot.y)*(this.y-dot.y)); 58 } 59 60 public boolean dianOnXian1(Spot A, Spot B, Spot dot){//三点共线 61 return ((dot.x - B.x)*(B.y - A.y) == (B.x - A.x)*(dot.y - B.y)) ? true : false; 62 } 63 64 }//Spot 65 66 class Line{//线类 67 Spot dot1 = new Spot(); 68 Spot dot2 = new Spot();//两点确定一条直线 69 70 public boolean dianGongXian(Spot A, Spot B, Spot C, Spot D){//四点共线问题(两直线重合) 71 if(A.x == B.x){//l1斜率不存在 72 if(C.x == D.x){//l2斜率不存在 73 if(A.x == C.x) 74 return true; 75 else 76 return false; 77 } 78 else{ 79 return false; 80 } 81 } 82 else{//l1斜率存在 83 if(C.x == D.x){//l2斜率不存在 84 return false; 85 } 86 else{//y = k * x + b 87 double k1 = A.xielv(B); 88 double b1 = A.y - k1 * A.x; 89 double k2 = C.xielv(D); 90 double b2 = C.y - k2 * C.x; 91 if(k1==k2 && b1==b2) 92 return true; 93 else 94 return false; 95 } 96 } 97 } 98 99 public boolean jiaoDianOnXianDuan(Line l){//两条线段所在直线交点是否在两条线段上 100 Spot dot = new Spot();//交点 101 l.jiaoDianCount(this, l, dot); 102 if(dot.flag){//交点存在 103 if(!this.dianOnXianDuan1(this.dot1, this.dot2, dot) && !l.dianOnXianDuan1(l.dot1, l.dot2, dot)){//交点不在两条线段上 104 return false; 105 } 106 else{ 107 return true; 108 } 109 } 110 else{ 111 return true; 112 } 113 } 114 115 public void jiaoDianCount(Line l1, Line l2, Spot dot){//计算两条直线交点 116 if(l1.dot1.x == l1.dot2.x){//l1斜率不存在 117 if(l2.dot1.x == l2.dot2.x){//l2斜率不存在,无交点 118 dot.flag = false; 119 } 120 else{//l2斜率存在,有交点 121 dot.x = l1.dot1.x; 122 //y = k * x + b 123 double k2 = l2.dot1.xielv(l2.dot2); 124 double b2 = l2.dot1.y - k2 * l2.dot1.x; 125 dot.y = k2 * dot.x + b2; 126 dot.flag = true; 127 } 128 } 129 else{//l1斜率存在 130 if(l2.dot1.x == l2.dot2.x){//l2斜率不存在,有交点 131 dot.x = l2.dot1.x; 132 //y = k * x + b 133 double k1 = l1.dot1.xielv(l1.dot2); 134 double b1 = l1.dot1.y - k1 * l1.dot1.x; 135 dot.y = k1 * dot.x + b1; 136 dot.flag = true; 137 } 138 else{//l2斜率存在 139 double k1 = l1.dot1.xielv(l1.dot2); 140 double b1 = l1.dot1.y - k1 * l1.dot1.x; 141 double k2 = l2.dot1.xielv(l2.dot2); 142 double b2 = l2.dot1.y - k2 * l2.dot1.x; 143 if(k1==k2){//两直线平行,无交点 144 dot.flag = false; 145 } 146 else{ 147 dot.x = (b2-b1)/(k1-k2); 148 dot.y = k1 * dot.x + b1; 149 dot.flag = true; 150 } 151 } 152 } 153 } 154 155 public boolean dianOnXianDuan1(Spot A, Spot B, Spot dot){//判断点dot是否在线段上 156 double dotA = dot.distance(A); 157 double dotB = dot.distance(B); 158 double AB = A.distance(B); 159 if(dotA+dotB-AB < 0.000001){//在线段上 160 return true; 161 } 162 else{ 163 return false; 164 } 165 } 166 167 public double chaCheng(Line l){//两线段所在向量的叉乘 168 double x1 = this.dot2.x - this.dot1.x; 169 double y1 = this.dot2.y - this.dot1.y; 170 double x2 = l.dot2.x - l.dot1.x; 171 double y2 = l.dot2.y - l.dot1.y; 172 return (x1 * y2) - (x2 * y1); 173 } 174 175 public boolean dianOnXian(Spot dot){//点在线上判断(三点共线) 176 return ((dot.x - this.dot2.x)*(this.dot2.y - this.dot1.y) == (this.dot2.x - this.dot1.x)*(dot.y - this.dot2.y)) ? true : false; 177 } 178 179 }//Line 180 181 class Triangle{//三角形类 182 Spot A = new Spot(); 183 Spot B = new Spot(); 184 Spot C = new Spot(); 185 boolean flag = false;//三角形状态 186 187 public double area3(Spot A, Spot B, Spot C){//计算三角形面积 188 double AB = A.distance(B); 189 double AC = A.distance(C); 190 double BC = B.distance(C); 191 double p = (AB+AC+BC)/2; 192 return Math.sqrt(p*(p-AB)*(p-AC)*(p-BC)); 193 } 194 195 public boolean gouChenSanJiaoXing(Spot dot1, Spot dot2, Spot dot3, Triangle t){//判断三点是否构成三角形 196 if(dot1.coincide(dot2) || dot1.coincide(dot3) || dot2.coincide(dot3)){//三个点中存在重合点 197 return false; 198 } 199 else{ 200 double l12 = dot1.distance(dot2); 201 double l13 = dot1.distance(dot3); 202 double l23 = dot2.distance(dot3); 203 if((l12-l13-l23<0) && (l13-l12-l23<0) && (l23-l12-l13<0)){//构成三角形 204 t.A = dot1; 205 t.B = dot2; 206 t.C = dot3; 207 return true; 208 } 209 else{ 210 return false; 211 } 212 } 213 } 214 215 public boolean sanJiaoXingJudge(Pentagon p, Triangle t){//判断是否构成三角形 216 Line l = new Line(); 217 if(t.gouChenSanJiaoXing(p.A, p.B, p.C, t)){//ABC构成三角形 218 if(p.B.coincide(p.D) && p.C.coincide(p.E)){//B、D重合,C、E重合 219 t.flag = true; 220 return true; 221 } 222 else if(l.dianOnXianDuan1(p.A, p.C, p.E) && l.dianOnXianDuan1(p.A, p.C, p.D) && (p.C.distance(p.D)<=p.C.distance(p.E))){//E、D在AC上,且CD<=CE 223 t.flag = true; 224 return true; 225 } 226 else{//不合法 227 t.flag = false; 228 } 229 } 230 if(t.gouChenSanJiaoXing(p.A, p.B, p.D, t)){//ABD构成三角形 231 if(p.C.coincide(p.A) && p.E.coincide(p.B)){//C、A重合,E、B重合 232 t.flag = true; 233 return true; 234 } 235 else if(l.dianOnXianDuan1(p.B, p.D, p.C) && l.dianOnXianDuan1(p.A, p.D, p.E)){//C在BD上,E在AD上 236 t.flag = true; 237 return true; 238 } 239 else{//不合法 240 t.flag = false; 241 } 242 } 243 if(t.gouChenSanJiaoXing(p.A, p.B, p.E, t)){//ABE构成三角形 244 if(p.C.coincide(p.A) && p.D.coincide(p.B)){//C、A重合,D、B重合 245 t.flag = true; 246 return true; 247 } 248 else if(l.dianOnXianDuan1(p.B, p.E, p.C) && l.dianOnXianDuan1(p.B, p.E, p.D) && (p.B.distance(p.C)<=p.B.distance(p.D))){//C、D在BE上,且BC<=BD 249 t.flag = true; 250 return true; 251 } 252 else{//不合法 253 t.flag = false; 254 } 255 } 256 if(t.gouChenSanJiaoXing(p.A, p.C, p.D, t)){//ACD构成三角形 257 if(p.B.coincide(p.D) && p.E.coincide(p.C)){//B、D重合,E、C重合 258 t.flag = true; 259 return true; 260 } 261 else if(l.dianOnXianDuan1(p.A, p.C, p.B) && l.dianOnXianDuan1(p.A, p.D, p.E)){//B在AC上,E在AD上 262 t.flag = true; 263 return true; 264 } 265 else{//不合法 266 t.flag = false; 267 } 268 } 269 if(t.gouChenSanJiaoXing(p.A, p.C, p.E, t)){//ACE构成三角形 270 if(p.B.coincide(p.E) && p.D.coincide(p.A)){//B、E重合,D、A重合 271 t.flag = true; 272 return true; 273 } 274 else if(l.dianOnXianDuan1(p.A, p.C, p.B) && l.dianOnXianDuan1(p.C, p.E, p.D)){//B在AC上,D在CE上 275 t.flag = true; 276 return true; 277 } 278 else{//不合法 279 t.flag = false; 280 } 281 } 282 if(t.gouChenSanJiaoXing(p.A, p.D, p.E, t)){//ADE构成三角形 283 if(p.B.coincide(p.E) && p.C.coincide(p.A)){//B、E重合,C、A重合 284 t.flag = true; 285 return true; 286 } 287 else if(l.dianOnXianDuan1(p.A, p.D, p.B) && l.dianOnXianDuan1(p.A, p.D, p.C) && (p.A.distance(p.B)<=p.A.distance(p.C))){//B、C在AD上,且AB<=AC 288 t.flag = true; 289 return true; 290 } 291 else{//不合法 292 t.flag = false; 293 } 294 } 295 if(t.gouChenSanJiaoXing(p.B, p.C, p.D, t)){//BCD构成三角形 296 if(p.A.coincide(p.D) && p.E.coincide(p.C)){//A、D重合,E、C重合 297 t.flag = true; 298 return true; 299 } 300 else if(l.dianOnXianDuan1(p.B, p.D, p.A) && l.dianOnXianDuan1(p.B, p.D, p.E) && (p.D.distance(p.E)<=p.D.distance(p.A))){//A、E在BD上,且DE<=DA 301 t.flag = true; 302 return true; 303 } 304 else{//不合法 305 t.flag = false; 306 } 307 } 308 if(t.gouChenSanJiaoXing(p.B, p.C, p.E, t)){//BCE构成三角形 309 if(p.A.coincide(p.C) && p.D.coincide(p.B)){//A、C重合,D、B重合 310 t.flag = true; 311 return true; 312 } 313 else if(l.dianOnXianDuan1(p.B, p.E, p.A) && l.dianOnXianDuan1(p.C, p.E, p.D)){//A在BE上,D在CE上 314 t.flag = true; 315 return true; 316 } 317 else{//不合法 318 t.flag = false; 319 } 320 } 321 if(t.gouChenSanJiaoXing(p.B, p.D, p.E, t)){//BDE构成三角形 322 if(p.A.coincide(p.D) && p.C.coincide(p.E)){//A、D重合,C、E重合 323 t.flag = true; 324 return true; 325 } 326 else if(l.dianOnXianDuan1(p.B, p.E, p.A) && l.dianOnXianDuan1(p.B, p.D, p.C)){//A在BE上,C在BD上 327 t.flag = true; 328 return true; 329 } 330 else{//不合法 331 t.flag = false; 332 } 333 } 334 if(t.gouChenSanJiaoXing(p.C, p.D, p.E, t)){//CDE构成三角形 335 if(p.A.coincide(p.D) && p.B.coincide(p.E)){//A、D重合,B、E重合 336 t.flag = true; 337 return true; 338 } 339 else if(l.dianOnXianDuan1(p.C, p.E, p.A) && l.dianOnXianDuan1(p.C, p.E, p.B) && (p.E.distance(p.A)<=p.E.distance(p.B))){//A、B在CE上,且EA<=EB 340 t.flag = true; 341 return true; 342 } 343 else{//不合法 344 t.flag = false; 345 } 346 } 347 return t.flag; 348 } 349 350 public boolean xianChongHe3(Triangle t, Line l){//判断直线l与三角形各边是否重合 351 if(l.dianGongXian(l.dot1, l.dot2, t.A, t.B) || l.dianGongXian(l.dot1, l.dot2, t.B, t.C) || l.dianGongXian(l.dot1, l.dot2, t.C, t.A)){//l与AB、BC、CA重合 352 return true; 353 } 354 else{ 355 return false; 356 } 357 } 358 359 public void qieGeSanJiaoXing(Triangle t, Line l){//直线切割三角形 360 Line AB = new Line(); AB.dot1 = t.A; AB.dot2 = t.B; 361 Line BC = new Line(); BC.dot1 = t.B; BC.dot2 = t.C; 362 Line CA = new Line(); CA.dot1 = t.C; CA.dot2 = t.A; 363 int dotnum = 0;//记录点的个数 364 //l与AB相交 365 Spot ABdot = new Spot(); 366 l.jiaoDianCount(AB, l, ABdot); 367 if(ABdot.flag==true){//交点存在 368 if(l.dianOnXianDuan1(t.A, t.B, ABdot)){//点在AB线段上 369 dotnum++; 370 } 371 else{ 372 ABdot.flag = false; 373 } 374 }//if 375 //l与BC相交 376 Spot BCdot = new Spot(); 377 l.jiaoDianCount(BC, l, BCdot); 378 if(BCdot.flag==true){//交点存在 379 if(l.dianOnXianDuan1(t.B, t.C, BCdot)){//点在线段上 380 if(ABdot.flag==false){//ABdot不存在 381 dotnum++; 382 } 383 else if(ABdot.flag==true && !BCdot.coincide(ABdot)){//ABdot存在,且BCdot不与ABdot重合 384 dotnum++; 385 } 386 else{ 387 BCdot.flag = false; 388 } 389 } 390 else{//点不在线段上 391 BCdot.flag = false; 392 } 393 } 394 //l与CA相交 395 Spot CAdot = new Spot(); 396 l.jiaoDianCount(CA, l, CAdot); 397 if(CAdot.flag==true){//交点存在 398 if(l.dianOnXianDuan1(t.C, t.A, CAdot)){//点在CA线段上 399 if(ABdot.flag==false && BCdot.flag==false){//ABdot、BCdot均不存在 400 dotnum++; 401 } 402 else if(ABdot.flag==true && BCdot.flag==false && !CAdot.coincide(ABdot)){//ABdot存在、BCdot不存在,且ABdot与CAdot不重合 403 dotnum++; 404 } 405 else if(ABdot.flag==false && BCdot.flag==true && !CAdot.coincide(BCdot)){//ABdot不存在、BCdot存在,且BCdot与CAdot不重合 406 dotnum++; 407 } 408 else{ 409 CAdot.flag = false; 410 } 411 } 412 else{ 413 CAdot.flag = false; 414 } 415 }//if 416 System.out.print(dotnum); 417 double S = t.area3(t.A, t.B, t.C);//三角形总面积 418 double S1 = 0; 419 if(dotnum==2){//切割成功 420 if(ABdot.flag==true && BCdot.flag==true){//B,ABdot,BCdot 421 S1 = t.area3(t.B, ABdot, BCdot); 422 } 423 else if(BCdot.flag==true && CAdot.flag==true){//C,BCdot,CAdot 424 S1 = t.area3(t.C, BCdot, CAdot); 425 } 426 else if(ABdot.flag==true && CAdot.flag==true){//A,ABdot,CAdot 427 S1 = t.area3(t.A, ABdot, CAdot); 428 } 429 } 430 double S2 = S - S1; 431 if(S1 > S2){ 432 double temp = 0; 433 temp = S1; 434 S1 = S2; 435 S2 = temp; 436 } 437 S1 = Math.round(S1*1000)/1000.0; 438 S2 = Math.round(S2*1000)/1000.0; 439 System.out.print(" "+S1+" "+S2); 440 } 441 442 }//Triangle 443 444 class Square{//四边形类 445 Spot A = new Spot(); 446 Spot B = new Spot(); 447 Spot C = new Spot(); 448 Spot D = new Spot(); 449 450 public boolean siBianXingJudge(Pentagon p, Square s){//判断能否构成四边形 451 if(s.siBianXing(p.A, p.B, p.C, p.D, s) && p.AB.dianOnXianDuan1(p.A, p.D, p.E)){//ABCD构成四边形,E在AD上 452 return true; 453 } 454 else if(s.siBianXing(p.A, p.B, p.C, p.E, s) && p.AB.dianOnXianDuan1(p.C, p.E, p.D)){//ABCE构成四边形,D在CE上 455 return true; 456 } 457 else if(s.siBianXing(p.A, p.B, p.D, p.E, s) && p.AB.dianOnXianDuan1(p.B, p.D, p.C)){//ABDE构成四边形,C在BD上 458 return true; 459 } 460 else if(s.siBianXing(p.A, p.C, p.D, p.E, s) && p.AB.dianOnXianDuan1(p.A, p.C, p.B)){//ACDE构成四边形,B在AC上 461 return true; 462 } 463 else if(s.siBianXing(p.B, p.C, p.D, p.E, s) && p.AB.dianOnXianDuan1(p.E, p.B, p.A)){//BCDE构成四边形,A在EB上 464 return true; 465 } 466 else{ 467 return false; 468 } 469 } 470 471 public boolean siBianXing(Spot A, Spot B, Spot C, Spot D, Square s){//四个点构成四边形 472 Spot dot = new Spot(); 473 Line l1 = new Line(); l1.dot1 = A; l1.dot2 = C; 474 Line l2 = new Line(); l2.dot1 = B; l2.dot2 = D; 475 l1.jiaoDianCount(l1, l2, dot); 476 if(A.coincide(B) || A.coincide(C) || A.coincide(D) || B.coincide(C) || B.coincide(D) || C.coincide(D)){ 477 //任意两点重合,无法构成 478 return false; 479 } 480 else if(A.dianOnXian1(A, B, C) || A.dianOnXian1(A, B, D) || A.dianOnXian1(A, C, D) || A.dianOnXian1(B, C, D) ){ 481 //任意三点共线,无法构成 482 return false; 483 } 484 else{//构成四边形 485 if(dot.flag){ 486 if(l1.dianOnXianDuan1(l1.dot1, l1.dot2, dot) || l2.dianOnXianDuan1(l2.dot1, l2.dot2, dot)){ 487 s.A = A; s.B = B; s.C = C; s.D = D; 488 return true; 489 } 490 else{ 491 return false; 492 } 493 } 494 else{ 495 return false; 496 } 497 } 498 } 499 500 public boolean xianChongHe4(Square s, Line l){//判断直线l与四边形各边是否重合 501 if(l.dianGongXian(l.dot1, l.dot2, s.A, s.B) || l.dianGongXian(l.dot1, l.dot2, s.B, s.C) || l.dianGongXian(l.dot1, l.dot2, s.C, s.D) || l.dianGongXian(l.dot1, l.dot2, s.D, s.A)){//l与AB,BC,CD,DA重合 502 return true; 503 } 504 else{ 505 return false; 506 } 507 } 508 509 public void qieGeSiBianXing(Square s, Line l){//直线切割凸四边形 510 Line AB = new Line(); AB.dot1 = s.A; AB.dot2 = s.B; 511 Line BC = new Line(); BC.dot1 = s.B; BC.dot2 = s.C; 512 Line CD = new Line(); CD.dot1 = s.C; CD.dot2 = s.D; 513 Line DA = new Line(); DA.dot1 = s.D; DA.dot2 = s.A; 514 //l与AB相交 515 Spot ABdot = new Spot(); 516 int dotnum = 0;//记录点的个数 517 l.jiaoDianCount(AB, l, ABdot); 518 if(ABdot.flag==true){//交点存在 519 if(l.dianOnXianDuan1(s.A, s.B, ABdot)){//点在AB线段上 520 dotnum++; 521 } 522 else{ 523 ABdot.flag = false; 524 } 525 526 }//if 527 //l与BC相交 528 Spot BCdot = new Spot(); 529 l.jiaoDianCount(BC, l, BCdot); 530 if(BCdot.flag==true){//交点存在 531 if(l.dianOnXianDuan1(s.B, s.C, BCdot)){//点在BC线段上 532 if(ABdot.flag==false){//ABdot不存在 533 dotnum++; 534 } 535 else if(ABdot.flag==true && !BCdot.coincide(ABdot)){//ABdot存在但两点不重合 536 dotnum++; 537 } 538 else{ 539 BCdot.flag = false; 540 } 541 } 542 else{ 543 BCdot.flag = false; 544 } 545 }//if 546 //l与CD相交 547 Spot CDdot = new Spot(); 548 l.jiaoDianCount(CD, l, CDdot); 549 if(CDdot.flag==true){//交点存在 550 if(l.dianOnXianDuan1(s.C, s.D, CDdot)){//点在CD线段上 551 if(ABdot.flag==false && BCdot.flag==false){//ABdot、BCdot均不存在 552 dotnum++; 553 } 554 else if(ABdot.flag==true && BCdot.flag==false && !CDdot.coincide(ABdot)){//ABdot存在、BCdot不存在,且ABdot与CDdot不重合 555 dotnum++; 556 } 557 else if(ABdot.flag==false && BCdot.flag==true && !CDdot.coincide(BCdot)){//ABdot不存在、BCdot存在,且BCdot与CDdot不重合 558 dotnum++; 559 } 560 else{ 561 CDdot.flag = false; 562 } 563 } 564 else{ 565 CDdot.flag = false; 566 } 567 }//if 568 //l与DA相交 569 Spot DAdot = new Spot(); 570 l.jiaoDianCount(DA, l, DAdot); 571 if(DAdot.flag==true){//交点存在 572 if(l.dianOnXianDuan1(s.D, s.A, DAdot)){//点在DA线段上 573 if(ABdot.flag==false && BCdot.flag==false && CDdot.flag==false){//ABdot、BCdot、CDdot均不存在 574 dotnum++; 575 } 576 else if(ABdot.flag==true && BCdot.flag==false && CDdot.flag==false && !DAdot.coincide(ABdot)){//ABdot存在,BCdot、CDdot均不存在,且DAdot与ABdot不重合 577 dotnum++; 578 } 579 else if(ABdot.flag==false && BCdot.flag==true && CDdot.flag==false && !DAdot.coincide(BCdot)){//BCdot存在,ABdot、CDdot均不存在,且DAdot与BCdot不重合 580 dotnum++; 581 } 582 else if(ABdot.flag==false && BCdot.flag==false && CDdot.flag==true && !DAdot.coincide(CDdot)){//CDdot存在,ABdot、BCdot均不存在,且DAdot与CDdot不重合 583 dotnum++; 584 } 585 else{ 586 DAdot.flag = false; 587 } 588 } 589 else{ 590 DAdot.flag = false; 591 } 592 }//if 593 System.out.print(dotnum); 594 //四边形总面积 595 Triangle t1 = new Triangle(); 596 double S = t1.area3(s.A, s.B, s.C) + t1.area3(s.A, s.C, s.D);//总面积,ABC+ACD 597 double S1 = 0; 598 if(dotnum==2){//有两个交点,成功切割 599 if(ABdot.flag==true && BCdot.flag==true){//两个点在AB和BC上,计算B、ABdot、BCdot构成三角形的面积 600 S1 = t1.area3(s.B, ABdot, BCdot); 601 } 602 else if(BCdot.flag==true && CDdot.flag==true){//两个点在BC和CD上,计算C、BCdot、CDdot构成三角形的面积 603 S1 = t1.area3(s.C, BCdot, CDdot); 604 } 605 else if(CDdot.flag==true && DAdot.flag==true){//两个点在CD和DA上,计算D、CDdot、DAdot构成三角形的面积 606 S1 = t1.area3(s.D, CDdot, DAdot); 607 } 608 else if(ABdot.flag==true && DAdot.flag==true){//两个点在AB和DA上,计算A、ABdot、DAdot构成三角形的面积 609 S1 = t1.area3(s.A, ABdot, DAdot); 610 } 611 else if(ABdot.flag==true && CDdot.flag==true){//两个点在AB和CD上,计算S(A、D、CDdot)+ S(A、ABdot、CDdot) 612 S1 = t1.area3(s.A, s.D, CDdot) + t1.area3(s.A, ABdot, CDdot); 613 } 614 else if(DAdot.flag==true && BCdot.flag==true){//两个点在DA和BC上,计算S(A、B、BCdot)+ S(A、BCdot、DAdot) 615 S1 = t1.area3(s.A, s.B, BCdot) + t1.area3(s.A, BCdot, DAdot); 616 } 617 }//if 618 double S2 = S - S1; 619 if(S1 > S2){ 620 double temp = 0; 621 temp = S1; 622 S1 = S2; 623 S2 = temp; 624 } 625 S1 = Math.round(S1*1000)/1000.0; 626 S2 = Math.round(S2*1000)/1000.0; 627 System.out.print(" "+S1+" "+S2); 628 } 629 630 }//Square 631 632 class Pentagon{//五边形类 633 Spot A = new Spot(); 634 Spot B = new Spot(); 635 Spot C = new Spot(); 636 Spot D = new Spot(); 637 Spot E = new Spot(); 638 Line AB = new Line(); 639 Line BC = new Line(); 640 Line CD = new Line(); 641 Line DE = new Line(); 642 Line EA = new Line(); 643 644 public void setWuBianXing(int start, String[] a, Pentagon p){//五边形信息录入 645 p.A.x = Double.valueOf(a[start]); p.A.y = Double.valueOf(a[++start]); 646 p.B.x = Double.valueOf(a[++start]); p.B.y = Double.valueOf(a[++start]); 647 p.C.x = Double.valueOf(a[++start]); p.C.y = Double.valueOf(a[++start]); 648 p.D.x = Double.valueOf(a[++start]); p.D.y = Double.valueOf(a[++start]); 649 p.E.x = Double.valueOf(a[++start]); p.E.y = Double.valueOf(a[++start]); 650 p.AB.dot1 = A; p.AB.dot2 = B; 651 p.BC.dot1 = B; p.BC.dot2 = C; 652 p.CD.dot1 = C; p.CD.dot2 = D; 653 p.DE.dot1 = D; p.DE.dot2 = E; 654 p.EA.dot1 = E; p.EA.dot2 = A; 655 } 656 657 public boolean wuBianXingJudge(Pentagon p){//判断能否构成五边形 658 if(A.coincide(B) || A.coincide(C) || A.coincide(D) || A.coincide(E) || B.coincide(C) || B.coincide(D) || B.coincide(E) || C.coincide(D) || C.coincide(E) || D.coincide(E)){ 659 //任意两点重合,无法构成 660 return false; 661 } 662 else if(p.AB.dianGongXian(A,B,C,D) || p.AB.dianGongXian(A,B,C,E) || p.AB.dianGongXian(A,B,D,E) || p.AB.dianGongXian(A,C,D,E)|| p.AB.dianGongXian(B,C,D,E)){ 663 //任意四点共线,无法构成 664 return false; 665 } 666 else if(p.AB.dianOnXian(C) || p.BC.dianOnXian(D) || p.CD.dianOnXian(E) || p.EA.dianOnXian(B) || p.DE.dianOnXian(A)){ 667 //连续的三个点共线,无法构成 668 return false; 669 } 670 else{//构成五边形,包括合法和不合法 671 if(!p.wuBianHeFaJudge(p)){//不合法 672 return false; 673 } 674 else{//合法 675 return true; 676 } 677 } 678 } 679 680 public boolean wuBianHeFaJudge(Pentagon p){//判断构成的五边形合不合法 681 Line AC = new Line(); AC.dot1 = A; AC.dot2 = C; 682 Line AD = new Line(); AD.dot1 = A; AD.dot2 = D; 683 Line BD = new Line(); BD.dot1 = B; BD.dot2 = D; 684 Line BE = new Line(); BE.dot1 = B; BE.dot2 = E; 685 Line CE = new Line(); CE.dot1 = C; CE.dot2 = E;//五条对角线 686 ArrayList<Line> list = new ArrayList<>(); 687 list.add(AC); list.add(AD); list.add(BD); 688 list.add(BE); list.add(CE); 689 int i = 0; 690 for(i=1;i<=4;i++){ 691 if(!list.get(0).jiaoDianOnXianDuan(list.get(i))){//0和1,2,3,4对角线交点不在两条对角线上,非法 692 return false; 693 } 694 } 695 for(i=2;i<=4;i++){ 696 if(!list.get(1).jiaoDianOnXianDuan(list.get(i))){//1和2,3,4对角线交点不在两条对角线上,非法 697 return false; 698 } 699 } 700 for(i=3;i<=4;i++){ 701 if(!list.get(2).jiaoDianOnXianDuan(list.get(i))){//2和3,4对角线交点不在两条对角线上,非法 702 return false; 703 } 704 } 705 if(!list.get(3).jiaoDianOnXianDuan(list.get(4))){//3和4对角线交点不在两条对角线上,非法 706 return false; 707 } 708 return true; 709 } 710 711 public boolean tuWuBianXingJudge(Pentagon p){//判断五边形是否为凸五边形 712 if(p.AB.chaCheng(BC) > 0 && p.BC.chaCheng(CD) > 0 && p.CD.chaCheng(DE) > 0 && p.DE.chaCheng(EA) > 0 && p.EA.chaCheng(AB) > 0){ 713 return true; 714 } 715 else if(p.AB.chaCheng(BC) < 0 && p.BC.chaCheng(CD) < 0 && p.CD.chaCheng(DE) < 0 && p.DE.chaCheng(EA) < 0 && p.EA.chaCheng(AB) < 0){ 716 return true; 717 } 718 else{ 719 return false; 720 } 721 } 722 723 public double zhouChangCount(Pentagon p){//计算凸五边形周长 724 return (p.A.distance(B) + p.B.distance(C) + p.C.distance(D) + p.D.distance(E) + p.E.distance(A)); 725 } 726 727 public double areaCount(Pentagon p){//计算凸五边形面积,AC和AD切割,ABC+ACD+ADE 728 Triangle t = new Triangle(); 729 return t.area3(p.A, p.B, p.C) + t.area3(p.A, p.C, p.D) + t.area3(p.A, p.D, p.E); 730 } 731 732 public boolean xianChongHe5(Pentagon p, Line l){//判断直线l与五边形各边是否重合 733 if(l.dianGongXian(l.dot1, l.dot2, p.A, p.B) || l.dianGongXian(l.dot1, l.dot2, p.B, p.C) ||l.dianGongXian(l.dot1, l.dot2, p.C, p.D) || l.dianGongXian(l.dot1, l.dot2, p.D, p.E) || l.dianGongXian(l.dot1, l.dot2, p.E, p.A) ){//l与AB或BC或CD或DE或EA重合 734 return true; 735 } 736 else{ 737 return false; 738 } 739 } 740 741 public void qieGeWuBianXing(Pentagon p, Line l){//直线切割凸五边形 742 Line AB = new Line(); AB.dot1 = p.A; AB.dot2 = p.B; 743 Line BC = new Line(); BC.dot1 = p.B; BC.dot2 = p.C; 744 Line CD = new Line(); CD.dot1 = p.C; CD.dot2 = p.D; 745 Line DE = new Line(); DE.dot1 = p.D; DE.dot2 = p.E; 746 Line EA = new Line(); EA.dot1 = p.E; EA.dot2 = p.A; 747 int dotnum = 0; 748 //l与AB交点 749 Spot ABdot = new Spot(); 750 l.jiaoDianCount(AB, l, ABdot); 751 if(ABdot.flag==true){//交点存在 752 if(l.dianOnXianDuan1(p.A, p.B, ABdot)){//点在AB线段上 753 dotnum++; 754 } 755 else{ 756 ABdot.flag = false; 757 } 758 }//if 759 //l与BC交点 760 Spot BCdot = new Spot(); 761 l.jiaoDianCount(BC, l, BCdot); 762 if(BCdot.flag==true){//交点存在 763 if(l.dianOnXianDuan1(p.B, p.C, BCdot)){//点在BC线段上 764 if(ABdot.flag==false){//ABdot不存在 765 dotnum++; 766 } 767 else if(ABdot.flag==true && !BCdot.coincide(ABdot)){//ABdot存在但两点不重合 768 dotnum++; 769 } 770 else{ 771 BCdot.flag = false; 772 } 773 } 774 else{ 775 BCdot.flag = false; 776 } 777 }//if 778 //l与CD交点 779 Spot CDdot = new Spot(); 780 l.jiaoDianCount(CD, l, CDdot); 781 if(CDdot.flag==true){//交点存在 782 if(l.dianOnXianDuan1(p.C, p.D, CDdot)){//点在CD线段上 783 if(ABdot.flag==false && BCdot.flag==false){//ABdot、BCdot均不存在 784 dotnum++; 785 } 786 else if(ABdot.flag==true && BCdot.flag==false && !CDdot.coincide(ABdot)){//ABdot存在、BCdot不存在,且ABdot与CDdot不重合 787 dotnum++; 788 } 789 else if(ABdot.flag==false && BCdot.flag==true && !CDdot.coincide(BCdot)){//ABdot不存在、BCdot存在,且BCdot与CDdot不重合 790 dotnum++; 791 } 792 else{ 793 CDdot.flag = false; 794 } 795 } 796 else{ 797 CDdot.flag = false; 798 } 799 }//if 800 //l与DE交点 801 Spot DEdot = new Spot(); 802 l.jiaoDianCount(DE, l, DEdot); 803 if(DEdot.flag==true){//交点存在 804 if(l.dianOnXianDuan1(p.D, p.E, DEdot)){//点在DE线段上 805 if(ABdot.flag==false && BCdot.flag==false && CDdot.flag==false){//ABdot、BCdot、CDdot均不存在 806 dotnum++; 807 } 808 else if(ABdot.flag==true && BCdot.flag==false && CDdot.flag==false && !DEdot.coincide(ABdot)){//ABdot存在、BCdot和CDdot不存在,且ABdot与DEdot不重合 809 dotnum++; 810 } 811 else if(ABdot.flag==false && BCdot.flag==true && CDdot.flag==false && !DEdot.coincide(BCdot)){//BCdot存在、ABdot和CDdot不存在,且BCdot与DEdot不重合 812 dotnum++; 813 } 814 else if(ABdot.flag==false && BCdot.flag==false && CDdot.flag==true && !DEdot.coincide(CDdot)){//BCdot存在、ABdot和CDdot不存在,且BCdot与DEdot不重合 815 dotnum++; 816 } 817 else{ 818 DEdot.flag = false; 819 } 820 } 821 else{ 822 DEdot.flag = false; 823 } 824 }//if 825 //l与EA交点 826 Spot EAdot = new Spot(); 827 l.jiaoDianCount(EA, l, EAdot); 828 if(EAdot.flag==true){//交点存在 829 if(l.dianOnXianDuan1(p.E, p.A, EAdot)){//点在EA线段上 830 if(ABdot.flag==false && BCdot.flag==false && CDdot.flag==false && DEdot.flag==false){//ABdot、BCdot、CDdot、DEdot均不存在 831 dotnum++; 832 } 833 else if(ABdot.flag==true && BCdot.flag==false && CDdot.flag==false && DEdot.flag==false && !EAdot.coincide(ABdot)){//ABdot存在、BCdot、CDdot和DEdot不存在,且ABdot与EAdot不重合 834 dotnum++; 835 } 836 else if(ABdot.flag==false && BCdot.flag==true && CDdot.flag==false && DEdot.flag==false && !EAdot.coincide(BCdot)){//BCdot存在、ABdot、CDdot和DEdot不存在,且BCdot与EAdot不重合 837 dotnum++; 838 } 839 else if(ABdot.flag==false && BCdot.flag==false && CDdot.flag==true && DEdot.flag==false && !EAdot.coincide(CDdot)){//CDdot存在、ABdot、BCdot和DEdot不存在,且CDdot与EAdot不重合 840 dotnum++; 841 } 842 else if(ABdot.flag==false && BCdot.flag==false && CDdot.flag==false && DEdot.flag==true && !EAdot.coincide(DEdot)){//DEdot存在、ABdot、BCdot和CDdot不存在,且DEdot与EAdot不重合 843 dotnum++; 844 } 845 else{ 846 EAdot.flag = false; 847 } 848 } 849 else{ 850 EAdot.flag = false; 851 } 852 }//if 853 System.out.print(dotnum); 854 //五边形总面积 855 Triangle t1 = new Triangle(); 856 double S = t1.area3(p.A, p.B, p.C) + t1.area3(p.A, p.C, p.D) + t1.area3(p.A, p.D, p.E);//总面积,ABC+ACD+ADE 857 double S1 = 0; 858 if(dotnum==2){//切割成功 859 if(ABdot.flag && BCdot.flag){//AB、BC上,三角形B,ABdot,BCdot 860 S1 = t1.area3(p.B, ABdot, BCdot); 861 } 862 else if(BCdot.flag && CDdot.flag){//BC、CD上,三角形C,BCdot,CDdot 863 S1 = t1.area3(p.C, BCdot, CDdot); 864 } 865 else if(CDdot.flag && DEdot.flag){//CD、DE上,三角形D,CDdot,DEdot 866 S1 = t1.area3(p.D, CDdot, DEdot); 867 } 868 else if(DEdot.flag && EAdot.flag){//DE、EA上,三角形E,DEdot,EAdot 869 S1 = t1.area3(p.E, DEdot, EAdot); 870 } 871 else if(EAdot.flag && ABdot.flag){//EA、AB上,三角形A,EAdot,ABdot 872 S1 = t1.area3(p.A, EAdot, ABdot); 873 } 874 else if(ABdot.flag && DEdot.flag){//AB、DE上,A,ABdot,DEdot + A,E,DEdot 875 S1 = t1.area3(p.A, ABdot, DEdot) + t1.area3(p.A, p.E, DEdot); 876 } 877 else if(ABdot.flag && CDdot.flag){//AB、CD上,B,ABdot,CDdot + B,C,CDdot 878 S1 = t1.area3(p.B, ABdot, CDdot) + t1.area3(p.B, p.C, CDdot); 879 } 880 else if(BCdot.flag && EAdot.flag){//BC、EA上,A,BCdot,EAdot + A,B,BCdot 881 S1 = t1.area3(p.A, BCdot, EAdot) + t1.area3(p.A, p.B, BCdot); 882 } 883 else if(BCdot.flag && DEdot.flag){//BC、DE上,C,BCdot,DEdot + C,D,DEdot 884 S1 = t1.area3(p.C, BCdot, DEdot) + t1.area3(p.C, p.D, DEdot); 885 } 886 else if(CDdot.flag && EAdot.flag){//CD、EA上,D,CDdot,EAdot + D,E,EAdot 887 S1 = t1.area3(p.D, CDdot, EAdot) + t1.area3(p.D, p.E, EAdot); 888 } 889 else if(ABdot.flag && CDdot.flag){//AB、CD上,B,ABdot,CDdot + B,C,CDdot 890 S1 = t1.area3(p.B, ABdot, CDdot) + t1.area3(p.B, p.C, CDdot); 891 } 892 }//if 893 double S2 = S - S1; 894 if(S1 > S2){ 895 double temp = 0; 896 temp = S1; 897 S1 = S2; 898 S2 = temp; 899 } 900 S1 = Math.round(S1*1000)/1000.0; 901 S2 = Math.round(S2*1000)/1000.0; 902 System.out.print(" "+S1+" "+S2); 903 } 904 905 }//Pentagon 906 907 public class Main{ 908 public static void main(String[] args){ 909 Input in = new Input(); 910 String str = in.input();//输入 911 int selectNum = (int)str.charAt(0) - (int)'0';//情况选择 912 int dex = 0, sign = 3;//dex为点的个数,sign应该取0,1,2以外的值 913 String[] tokens = str.split(":|,| "); 914 Verify ver = new Verify();//创建引用判非法的对象 915 switch(selectNum){ 916 case 1: dex = 5; sign = ver.feifa(str, dex); 917 in.output(sign); 918 if(sign==1){//输入格式合法 919 Pentagon p = new Pentagon(); 920 p.setWuBianXing(1, tokens, p);//五边形信息录入 921 if(p.wuBianXingJudge(p)){//判断是否构成五边形 922 System.out.println("true"); 923 } 924 else{ 925 System.out.print("false"); 926 } 927 } 928 break; 929 case 2: dex = 5; sign = ver.feifa(str, dex); 930 in.output(sign); 931 if(sign==1){//输入格式合法 932 Pentagon p = new Pentagon(); 933 p.setWuBianXing(1, tokens, p);//五边形信息录入 934 if(p.wuBianXingJudge(p)){//判断是否构成五边形 935 if(p.tuWuBianXingJudge(p)){//判断是否为凸五边形 936 System.out.print("true "); 937 double zhouchang = p.zhouChangCount(p); 938 double area = p.areaCount(p); 939 zhouchang = Math.round(zhouchang*1000)/1000.0; 940 area = Math.round(area*1000)/1000.0; 941 System.out.print(zhouchang+" "+area); 942 } 943 else{//为凹五边形 944 System.out.print("false"); 945 } 946 } 947 else{//不构成五边形 948 System.out.print("not a pentagon"); 949 } 950 } 951 break; 952 case 3: dex = 7; sign = ver.feifa(str, dex); 953 in.output(sign); 954 if(sign==1){//输入格式合法 955 Line l = new Line(); 956 l.dot1.x = Double.valueOf(tokens[1]); l.dot1.y = Double.valueOf(tokens[2]); 957 l.dot2.x = Double.valueOf(tokens[3]); l.dot2.y = Double.valueOf(tokens[4]); 958 Pentagon p = new Pentagon(); 959 Square s = new Square(); 960 Triangle t = new Triangle(); 961 if(l.dot1.coincide(l.dot2)){//l两端点重合 962 System.out.print("points coincide"); 963 break; 964 } 965 p.setWuBianXing(5, tokens, p);//五边形信息录入 966 if(p.wuBianXingJudge(p)){//构成五边形 967 if(p.xianChongHe5(p, l)){ 968 System.out.print("The line is coincide with one of the lines"); 969 break; 970 } 971 p.qieGeWuBianXing(p, l); 972 } 973 else if(s.siBianXingJudge(p, s)){//构成四边形 974 if(s.xianChongHe4(s, l)){ 975 System.out.print("The line is coincide with one of the lines"); 976 break; 977 } 978 s.qieGeSiBianXing(s, l); 979 } 980 else if(t.sanJiaoXingJudge(p, t)){//构成三角形 981 if(t.xianChongHe3(t, l)){ 982 System.out.print("The line is coincide with one of the lines"); 983 break; 984 } 985 t.qieGeSanJiaoXing(t, l); 986 } 987 else{//不构成多边形 988 System.out.print("not a polygon"); 989 } 990 } 991 break; 992 default: 993 System.out.print("Wrong Format"); 994 break; 995 }//seitch 996 }//main 997 }//MainView Code
(4)代码分析
分析:类和方法的设置适中,复杂度越界,未用父类、子类、继承等这些可以让代码更加简洁的办法。
(5)踩坑心得
没遇上啥大坑,就是一如既往地接着“复杂化”我的代码,后悔没先好好学习父子类和继承。
3、题目集5/7-2:点线形系列5-凸五边形的计算-2
(1)题目详情
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
(2)设计
共有9个类,包括:
主类:包含一个静态主方法,其中主要有switch构成,作为情况选择的通道;
输入输出类:包含一个输入方法和一个输出方法,其中输出方法单指对于非法判断的结果输出;
格式判断类:对于输入的数据用正则表达式以及其他辅助手段进行合法性判断;
点类:包含点的横纵坐标属性x,y以及标记一个点是否真实存在的属性flag,点重合判断方法、计算两点间距离方法、两点计算斜率方法,三点共线判断方法;
线类:包含作为属性的两个点dot1、dot2,线重合判断方法、两条直线的交点计算方法,四点共线判断方法,点在线段上判断方法......;
三角形类:包含作为属性的三个点A、B、C,三条边AB、BC、CA,点集合dotList,线集合lineList,
录入三角形信息方法,构成三角形判断方法(构成与合法),三角形面积计算方法,点在三角形内判断方法,点在三角形外判断方法;
四边形类:包含作为属性的四个点A、B、C、D,四条边AB、BC、CD、DA,点集合dotList,线集合lineList,
录入四边形信息方法,构成四边形判断方法(构成与合法),点在四边形内判断方法,点在四边形外判断方法;
五边形类:包含作为属性的五个点A、B、C、D、E,五条边AB、BC、CD、DE、EA,点集合dotList,线集合lineList,
录入五边形信息方法,构成五边形判断方法(构成与合法),点在五边形内判断方法,点在五边形外判断方法;
多边形位置关系类:全部均是多边形位置判断的方法
(3)源码
1 import java.util.Scanner; 2 import java.util.ArrayList; 3 4 class Input{//输入输出类 5 public String input(){//输入数据 6 Scanner input = new Scanner(System.in); 7 String s = input.nextLine(); 8 return s; 9 } 10 public void output(int a){//输出格式判断结果 11 if(a == 0) 12 System.out.print("Wrong Format"); 13 if(a == 2) 14 System.out.print("wrong number of points"); 15 } 16 } 17 18 class Verify{//输入格式判断 19 public int feifa(String s, int dex){ 20 String[] tokens = s.split(" "); 21 int i = 0, sign = 1; 22 boolean flag = true; 23 for(i=0;i<tokens.length;i++) { 24 if(i==0){ 25 flag = tokens[i].matches("^[4-6]:[+-]?(0|aaa(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"); 26 } 27 else{ 28 flag = tokens[i].matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"); 29 } 30 if (!flag){//flag = flase 31 sign = 0; 32 break; 33 } 34 } 35 if(flag && tokens.length!=(dex)){//flag = true 36 sign = 2; 37 } 38 // System.out.println(sign); 39 return sign;//为1输入合法,为0输入格式错误,为2输入个数错误 40 } 41 } 42 43 class Spot{//点类 44 double x; 45 double y;//横纵坐标 46 boolean flag = false;//点的状态,不存在 47 48 public boolean coincide(Spot dot){//点重合判断 49 return (this.x == dot.x && this.y == dot.y) ? true : false; 50 } 51 52 public double xielv(Spot dot){//计算斜率 53 return (this.y - dot.y) / (this.x - dot.x); 54 } 55 56 public double distance(Spot dot){//两点间计算距离 57 return Math.sqrt((this.x-dot.x)*(this.x-dot.x) + (this.y-dot.y)*(this.y-dot.y)); 58 } 59 60 public boolean dianOnXian1(Spot A, Spot B, Spot dot){//三点共线 61 return ((dot.x - B.x)*(B.y - A.y) == (B.x - A.x)*(dot.y - B.y)) ? true : false; 62 } 63 64 }//Spot 65 66 class Line{//线类 67 Spot dot1 = new Spot(); 68 Spot dot2 = new Spot();//两点确定一条直线 69 70 public boolean dianGongXian(Spot A, Spot B, Spot C, Spot D){//四点共线问题(两直线重合) 71 if(A.x == B.x){//l1斜率不存在 72 if(C.x == D.x){//l2斜率不存在 73 if(A.x == C.x) 74 return true; 75 else 76 return false; 77 } 78 else{ 79 return false; 80 } 81 } 82 else{//l1斜率存在 83 if(C.x == D.x){//l2斜率不存在 84 return false; 85 } 86 else{//y = k * x + b 87 double k1 = A.xielv(B); 88 double b1 = A.y - k1 * A.x; 89 double k2 = C.xielv(D); 90 double b2 = C.y - k2 * C.x; 91 if(k1==k2 && b1==b2) 92 return true; 93 else 94 return false; 95 } 96 } 97 } 98 99 public boolean jiaoDianOnXianDuan(Line l){//两条线段所在直线交点是否在两条线段上 100 Spot dot = new Spot();//交点 101 l.jiaoDianCount(this, l, dot); 102 if(dot.flag){//交点存在 103 if(!this.dianOnXianDuan1(this.dot1, this.dot2, dot) && !l.dianOnXianDuan1(l.dot1, l.dot2, dot)){//交点不在两条线段上 104 return false; 105 } 106 else{ 107 return true; 108 } 109 } 110 else{ 111 return true; 112 } 113 } 114 115 public void jiaoDianCount(Line l1, Line l2, Spot dot){//计算两条直线交点 116 if(l1.dot1.x == l1.dot2.x){//l1斜率不存在 117 if(l2.dot1.x == l2.dot2.x){//l2斜率不存在,无交点 118 dot.flag = false; 119 } 120 else{//l2斜率存在,有交点 121 dot.x = l1.dot1.x; 122 //y = k * x + b 123 double k2 = l2.dot1.xielv(l2.dot2); 124 double b2 = l2.dot1.y - k2 * l2.dot1.x; 125 dot.y = k2 * dot.x + b2; 126 dot.flag = true; 127 } 128 } 129 else{//l1斜率存在 130 if(l2.dot1.x == l2.dot2.x){//l2斜率不存在,有交点 131 dot.x = l2.dot1.x; 132 //y = k * x + b 133 double k1 = l1.dot1.xielv(l1.dot2); 134 double b1 = l1.dot1.y - k1 * l1.dot1.x; 135 dot.y = k1 * dot.x + b1; 136 dot.flag = true; 137 } 138 else{//l2斜率存在 139 double k1 = l1.dot1.xielv(l1.dot2); 140 double b1 = l1.dot1.y - k1 * l1.dot1.x; 141 double k2 = l2.dot1.xielv(l2.dot2); 142 double b2 = l2.dot1.y - k2 * l2.dot1.x; 143 if(k1==k2){//两直线平行,无交点 144 dot.flag = false; 145 } 146 else{ 147 dot.x = (b2-b1)/(k1-k2); 148 dot.y = k1 * dot.x + b1; 149 dot.flag = true; 150 } 151 } 152 } 153 } 154 155 public boolean dianOnXianDuan1(Spot A, Spot B, Spot dot){//判断点dot是否在线段上 156 double dotA = dot.distance(A); 157 double dotB = dot.distance(B); 158 double AB = A.distance(B); 159 if(dotA+dotB-AB < 0.000001){//在线段上 160 return true; 161 } 162 else{ 163 return false; 164 } 165 } 166 167 public double chaCheng(Line l){//两线段所在向量的叉乘 168 double x1 = this.dot2.x - this.dot1.x; 169 double y1 = this.dot2.y - this.dot1.y; 170 double x2 = l.dot2.x - l.dot1.x; 171 double y2 = l.dot2.y - l.dot1.y; 172 return (x1 * y2) - (x2 * y1); 173 } 174 175 public boolean dianOnXian(Spot dot){//点在线上判断(三点共线) 176 return ((dot.x - this.dot2.x)*(this.dot2.y - this.dot1.y) == (this.dot2.x - this.dot1.x)*(dot.y - this.dot2.y)) ? true : false; 177 } 178 179 }//Line 180 181 class Triangle{//三角形类 182 Spot A = new Spot(); 183 Spot B = new Spot(); 184 Spot C = new Spot(); 185 Line AB = new Line(); 186 Line BC = new Line(); 187 Line CA = new Line(); 188 ArrayList<Spot> dotList = new ArrayList<>(); 189 ArrayList<Line> lineList = new ArrayList<>(); 190 boolean flag = false;//三角形状态 191 192 public void sanJiaoXingCreat(Triangle t){//三角形信息完善 193 t.AB.dot1 = A; t.AB.dot2 = B; 194 t.BC.dot1 = B; t.BC.dot2 = C; 195 t.CA.dot1 = C; t.CA.dot2 = A; 196 t.dotList.add(t.A); t.dotList.add(t.B); t.dotList.add(t.C); 197 t.lineList.add(t.AB); t.lineList.add(t.BC); t.lineList.add(t.CA); 198 } 199 200 public double area3(Spot A, Spot B, Spot C){//计算三角形面积 201 double AB = A.distance(B); 202 double AC = A.distance(C); 203 double BC = B.distance(C); 204 double p = (AB+AC+BC)/2; 205 return Math.sqrt(p*(p-AB)*(p-AC)*(p-BC)); 206 } 207 208 public boolean gouChenSanJiaoXing(Spot dot1, Spot dot2, Spot dot3, Triangle t){//判断三点是否构成三角形 209 if(dot1.coincide(dot2) || dot1.coincide(dot3) || dot2.coincide(dot3)){//三个点中存在重合点 210 return false; 211 } 212 else{ 213 double l12 = dot1.distance(dot2); 214 double l13 = dot1.distance(dot3); 215 double l23 = dot2.distance(dot3); 216 if((l12-l13-l23<0) && (l13-l12-l23<0) && (l23-l12-l13<0)){//构成三角形 217 t.A = dot1; 218 t.B = dot2; 219 t.C = dot3; 220 return true; 221 } 222 else{ 223 return false; 224 } 225 } 226 } 227 228 public boolean sanJiaoXingJudge(Pentagon p, Triangle t){//判断是否构成三角形 229 Line l = new Line(); 230 if(t.gouChenSanJiaoXing(p.A, p.B, p.C, t)){//ABC构成三角形 231 if(p.B.coincide(p.D) && p.C.coincide(p.E)){//B、D重合,C、E重合 232 t.flag = true; 233 return true; 234 } 235 else if(l.dianOnXianDuan1(p.A, p.C, p.E) && l.dianOnXianDuan1(p.A, p.C, p.D) && (p.C.distance(p.D)<=p.C.distance(p.E))){//E、D在AC上,且CD<=CE 236 t.flag = true; 237 return true; 238 } 239 else{//不合法 240 t.flag = false; 241 } 242 } 243 if(t.gouChenSanJiaoXing(p.A, p.B, p.D, t)){//ABD构成三角形 244 if(p.C.coincide(p.A) && p.E.coincide(p.B)){//C、A重合,E、B重合 245 t.flag = true; 246 return true; 247 } 248 else if(l.dianOnXianDuan1(p.B, p.D, p.C) && l.dianOnXianDuan1(p.A, p.D, p.E)){//C在BD上,E在AD上 249 t.flag = true; 250 return true; 251 } 252 else{//不合法 253 t.flag = false; 254 } 255 } 256 if(t.gouChenSanJiaoXing(p.A, p.B, p.E, t)){//ABE构成三角形 257 if(p.C.coincide(p.A) && p.D.coincide(p.B)){//C、A重合,D、B重合 258 t.flag = true; 259 return true; 260 } 261 else if(l.dianOnXianDuan1(p.B, p.E, p.C) && l.dianOnXianDuan1(p.B, p.E, p.D) && (p.B.distance(p.C)<=p.B.distance(p.D))){//C、D在BE上,且BC<=BD 262 t.flag = true; 263 return true; 264 } 265 else{//不合法 266 t.flag = false; 267 } 268 } 269 if(t.gouChenSanJiaoXing(p.A, p.C, p.D, t)){//ACD构成三角形 270 if(p.B.coincide(p.D) && p.E.coincide(p.C)){//B、D重合,E、C重合 271 t.flag = true; 272 return true; 273 } 274 else if(l.dianOnXianDuan1(p.A, p.C, p.B) && l.dianOnXianDuan1(p.A, p.D, p.E)){//B在AC上,E在AD上 275 t.flag = true; 276 return true; 277 } 278 else{//不合法 279 t.flag = false; 280 } 281 } 282 if(t.gouChenSanJiaoXing(p.A, p.C, p.E, t)){//ACE构成三角形 283 if(p.B.coincide(p.E) && p.D.coincide(p.A)){//B、E重合,D、A重合 284 t.flag = true; 285 return true; 286 } 287 else if(l.dianOnXianDuan1(p.A, p.C, p.B) && l.dianOnXianDuan1(p.C, p.E, p.D)){//B在AC上,D在CE上 288 t.flag = true; 289 return true; 290 } 291 else{//不合法 292 t.flag = false; 293 } 294 } 295 if(t.gouChenSanJiaoXing(p.A, p.D, p.E, t)){//ADE构成三角形 296 if(p.B.coincide(p.E) && p.C.coincide(p.A)){//B、E重合,C、A重合 297 t.flag = true; 298 return true; 299 } 300 else if(l.dianOnXianDuan1(p.A, p.D, p.B) && l.dianOnXianDuan1(p.A, p.D, p.C) && (p.A.distance(p.B)<=p.A.distance(p.C))){//B、C在AD上,且AB<=AC 301 t.flag = true; 302 return true; 303 } 304 else{//不合法 305 t.flag = false; 306 } 307 } 308 if(t.gouChenSanJiaoXing(p.B, p.C, p.D, t)){//BCD构成三角形 309 if(p.A.coincide(p.D) && p.E.coincide(p.C)){//A、D重合,E、C重合 310 t.flag = true; 311 return true; 312 } 313 else if(l.dianOnXianDuan1(p.B, p.D, p.A) && l.dianOnXianDuan1(p.B, p.D, p.E) && (p.D.distance(p.E)<=p.D.distance(p.A))){//A、E在BD上,且DE<=DA 314 t.flag = true; 315 return true; 316 } 317 else{//不合法 318 t.flag = false; 319 } 320 } 321 if(t.gouChenSanJiaoXing(p.B, p.C, p.E, t)){//BCE构成三角形 322 if(p.A.coincide(p.C) && p.D.coincide(p.B)){//A、C重合,D、B重合 323 t.flag = true; 324 return true; 325 } 326 else if(l.dianOnXianDuan1(p.B, p.E, p.A) && l.dianOnXianDuan1(p.C, p.E, p.D)){//A在BE上,D在CE上 327 t.flag = true; 328 return true; 329 } 330 else{//不合法 331 t.flag = false; 332 } 333 } 334 if(t.gouChenSanJiaoXing(p.B, p.D, p.E, t)){//BDE构成三角形 335 if(p.A.coincide(p.D) && p.C.coincide(p.E)){//A、D重合,C、E重合 336 t.flag = true; 337 return true; 338 } 339 else if(l.dianOnXianDuan1(p.B, p.E, p.A) && l.dianOnXianDuan1(p.B, p.D, p.C)){//A在BE上,C在BD上 340 t.flag = true; 341 return true; 342 } 343 else{//不合法 344 t.flag = false; 345 } 346 } 347 if(t.gouChenSanJiaoXing(p.C, p.D, p.E, t)){//CDE构成三角形 348 if(p.A.coincide(p.D) && p.B.coincide(p.E)){//A、D重合,B、E重合 349 t.flag = true; 350 return true; 351 } 352 else if(l.dianOnXianDuan1(p.C, p.E, p.A) && l.dianOnXianDuan1(p.C, p.E, p.B) && (p.E.distance(p.A)<=p.E.distance(p.B))){//A、B在CE上,且EA<=EB 353 t.flag = true; 354 return true; 355 } 356 else{//不合法 357 t.flag = false; 358 } 359 } 360 return t.flag; 361 } 362 363 public boolean dianOnSanJiaoXing(Triangle t, Spot dot){//点在三角形上 364 Line l = new Line(); 365 return (l.dianOnXianDuan1(t.A, t.B, dot) || l.dianOnXianDuan1(t.B, t.C, dot) || l.dianOnXianDuan1(t.C, t.A, dot)) ? true : false; 366 } 367 368 public boolean dianInSanJiaoXing(Triangle t, Spot dot){//点在三角形内 369 if(Math.abs(t.area3(t.A, t.B, dot) + t.area3(t.B, t.C, dot) + t.area3(t.C, t.A, dot) - t.area3(t.A, t.B, t.C)) < 0.000001){ 370 return true; 371 } 372 else{ 373 return false; 374 } 375 } 376 377 }//Triangle 378 379 class Square{//四边形类 380 Spot A = new Spot(); 381 Spot B = new Spot(); 382 Spot C = new Spot(); 383 Spot D = new Spot(); 384 Line AB = new Line(); 385 Line BC = new Line(); 386 Line CD = new Line(); 387 Line DA = new Line(); 388 ArrayList<Spot> dotList = new ArrayList<>(); 389 ArrayList<Line> lineList = new ArrayList<>(); 390 391 public void siBianXingCreat(Square s){//四边形信息完善 392 s.AB.dot1 = A; s.AB.dot2 = B; 393 s.BC.dot1 = B; s.BC.dot2 = C; 394 s.CD.dot1 = C; s.CD.dot2 = D; 395 s.DA.dot1 = D; s.DA.dot2 = A; 396 s.dotList.add(s.A); s.dotList.add(s.B); s.dotList.add(s.C); s.dotList.add(s.D); 397 s.lineList.add(s.AB); s.lineList.add(s.BC); s.lineList.add(s.CD); s.lineList.add(s.DA); 398 } 399 400 public boolean siBianXingJudge(Pentagon p, Square s){//判断能否构成四边形 401 if(s.siBianXing(p.A, p.B, p.C, p.D, s) && p.AB.dianOnXianDuan1(p.A, p.D, p.E)){//ABCD构成四边形,E在AD上 402 return true; 403 } 404 else if(s.siBianXing(p.A, p.B, p.C, p.E, s) && p.AB.dianOnXianDuan1(p.C, p.E, p.D)){//ABCE构成四边形,D在CE上 405 return true; 406 } 407 else if(s.siBianXing(p.A, p.B, p.D, p.E, s) && p.AB.dianOnXianDuan1(p.B, p.D, p.C)){//ABDE构成四边形,C在BD上 408 return true; 409 } 410 else if(s.siBianXing(p.A, p.C, p.D, p.E, s) && p.AB.dianOnXianDuan1(p.A, p.C, p.B)){//ACDE构成四边形,B在AC上 411 return true; 412 } 413 else if(s.siBianXing(p.B, p.C, p.D, p.E, s) && p.AB.dianOnXianDuan1(p.E, p.B, p.A)){//BCDE构成四边形,A在EB上 414 return true; 415 } 416 else{ 417 return false; 418 } 419 } 420 421 public boolean siBianXing(Spot A, Spot B, Spot C, Spot D, Square s){//四个点构成四边形 422 Spot dot = new Spot(); 423 Line l1 = new Line(); l1.dot1 = A; l1.dot2 = C; 424 Line l2 = new Line(); l2.dot1 = B; l2.dot2 = D; 425 l1.jiaoDianCount(l1, l2, dot); 426 if(A.coincide(B) || A.coincide(C) || A.coincide(D) || B.coincide(C) || B.coincide(D) || C.coincide(D)){ 427 //任意两点重合,无法构成 428 return false; 429 } 430 else if(A.dianOnXian1(A, B, C) || A.dianOnXian1(A, B, D) || A.dianOnXian1(A, C, D) || A.dianOnXian1(B, C, D) ){ 431 //任意三点共线,无法构成 432 return false; 433 } 434 else{//构成四边形 435 if(dot.flag){ 436 if(l1.dianOnXianDuan1(l1.dot1, l1.dot2, dot) || l2.dianOnXianDuan1(l2.dot1, l2.dot2, dot)){ 437 s.A = A; s.B = B; s.C = C; s.D = D; 438 return true; 439 } 440 else{ 441 return false; 442 } 443 } 444 else{ 445 return false; 446 } 447 } 448 } 449 450 public boolean dianOnSiBianXing(Square s, Spot dot){//点在四边形上 451 Line l = new Line(); 452 return (l.dianOnXianDuan1(s.A, s.B, dot) || l.dianOnXianDuan1(s.B, s.C, dot) || l.dianOnXianDuan1(s.C, s.D, dot) || l.dianOnXianDuan1(s.D, s.A, dot)) ? true : false; 453 } 454 455 public boolean dianInSiBianXing(Square s, Spot dot){//点在凸四边形内 456 Triangle t2 = new Triangle(); 457 //四边形总面积 458 double S = t2.area3(s.A, s.B, s.C) + t2.area3(s.A, s.C, s.D);//ABC+ACD 459 if(Math.abs(t2.area3(s.A, s.B, dot) + t2.area3(s.B, s.C, dot) + t2.area3(s.C, s.D, dot) + t2.area3(s.D, s.A, dot) - S) < 0.000001){ 460 return true; 461 } 462 else{ 463 return false; 464 } 465 } 466 467 }//Square 468 469 class Pentagon{//五边形类 470 Spot A = new Spot(); 471 Spot B = new Spot(); 472 Spot C = new Spot(); 473 Spot D = new Spot(); 474 Spot E = new Spot(); 475 Line AB = new Line(); 476 Line BC = new Line(); 477 Line CD = new Line(); 478 Line DE = new Line(); 479 Line EA = new Line(); 480 ArrayList<Spot> dotList = new ArrayList<>(); 481 ArrayList<Line> lineList = new ArrayList<>(); 482 483 public void setWuBianXing(int start, String[] a, Pentagon p){//五边形信息录入 484 p.A.x = Double.valueOf(a[start]); p.A.y = Double.valueOf(a[++start]); 485 p.B.x = Double.valueOf(a[++start]); p.B.y = Double.valueOf(a[++start]); 486 p.C.x = Double.valueOf(a[++start]); p.C.y = Double.valueOf(a[++start]); 487 p.D.x = Double.valueOf(a[++start]); p.D.y = Double.valueOf(a[++start]); 488 p.E.x = Double.valueOf(a[++start]); p.E.y = Double.valueOf(a[++start]); 489 p.AB.dot1 = A; p.AB.dot2 = B; 490 p.BC.dot1 = B; p.BC.dot2 = C; 491 p.CD.dot1 = C; p.CD.dot2 = D; 492 p.DE.dot1 = D; p.DE.dot2 = E; 493 p.EA.dot1 = E; p.EA.dot2 = A; 494 p.dotList.add(p.A); p.dotList.add(p.B); p.dotList.add(p.C); p.dotList.add(p.D); p.dotList.add(p.E); 495 p.lineList.add(p.AB); p.lineList.add(p.BC); p.lineList.add(p.CD); p.lineList.add(p.DE); p.lineList.add(p.EA); 496 } 497 498 public boolean wuBianXingJudge(Pentagon p){//判断能否构成五边形 499 if(A.coincide(B) || A.coincide(C) || A.coincide(D) || A.coincide(E) || B.coincide(C) || B.coincide(D) || B.coincide(E) || C.coincide(D) || C.coincide(E) || D.coincide(E)){ 500 //任意两点重合,无法构成 501 return false; 502 } 503 else if(p.AB.dianGongXian(A,B,C,D) || p.AB.dianGongXian(A,B,C,E) || p.AB.dianGongXian(A,B,D,E) || p.AB.dianGongXian(A,C,D,E)|| p.AB.dianGongXian(B,C,D,E)){ 504 //任意四点共线,无法构成 505 return false; 506 } 507 else if(p.AB.dianOnXian(C) || p.BC.dianOnXian(D) || p.CD.dianOnXian(E) || p.EA.dianOnXian(B) || p.DE.dianOnXian(A)){ 508 //连续的三个点共线,无法构成 509 return false; 510 } 511 else{//构成五边形,包括合法和不合法 512 if(!p.wuBianHeFaJudge(p)){//不合法 513 return false; 514 } 515 else{//合法 516 return true; 517 } 518 } 519 } 520 521 public boolean wuBianHeFaJudge(Pentagon p){//判断构成的五边形合不合法 522 Line AC = new Line(); AC.dot1 = A; AC.dot2 = C; 523 Line AD = new Line(); AD.dot1 = A; AD.dot2 = D; 524 Line BD = new Line(); BD.dot1 = B; BD.dot2 = D; 525 Line BE = new Line(); BE.dot1 = B; BE.dot2 = E; 526 Line CE = new Line(); CE.dot1 = C; CE.dot2 = E;//五条对角线 527 ArrayList<Line> list = new ArrayList<>(); 528 list.add(AC); list.add(AD); list.add(BD); 529 list.add(BE); list.add(CE); 530 int i = 0; 531 for(i=1;i<=4;i++){ 532 if(!list.get(0).jiaoDianOnXianDuan(list.get(i))){//0和1,2,3,4对角线交点不在两条对角线上,非法 533 return false; 534 } 535 } 536 for(i=2;i<=4;i++){ 537 if(!list.get(1).jiaoDianOnXianDuan(list.get(i))){//1和2,3,4对角线交点不在两条对角线上,非法 538 return false; 539 } 540 } 541 for(i=3;i<=4;i++){ 542 if(!list.get(2).jiaoDianOnXianDuan(list.get(i))){//2和3,4对角线交点不在两条对角线上,非法 543 return false; 544 } 545 } 546 if(!list.get(3).jiaoDianOnXianDuan(list.get(4))){//3和4对角线交点不在两条对角线上,非法 547 return false; 548 } 549 return true; 550 } 551 552 public boolean dianOnWuBianXing(Pentagon p, Spot dot){//判断点在五边形上 553 if(p.AB.dianOnXianDuan1(p.A, p.B, dot) || p.AB.dianOnXianDuan1(p.B, p.C, dot) || p.AB.dianOnXianDuan1(p.C, p.D, dot) || p.AB.dianOnXianDuan1(p.D, p.E, dot) || p.AB.dianOnXianDuan1(p.E, p.A, dot)){ 554 return true; 555 } 556 else{ 557 return false; 558 } 559 } 560 561 public boolean dianInWuBianXing(Pentagon p, Spot dot){//判断点在凸五边形内 562 //五边形总面积 563 Triangle t1 = new Triangle(); 564 double S = t1.area3(p.A, p.B, p.C) + t1.area3(p.A, p.C, p.D) + t1.area3(p.A, p.D, p.E);//总面积,ABC+ACD+ADE 565 if(Math.abs(t1.area3(p.A, p.B, dot) + t1.area3(p.B, p.C, dot) + t1.area3(p.C, p.D, dot) + t1.area3(p.D, p.E, dot) + t1.area3(p.E, p.A, dot) - S) < 0.000001){ 566 return true; 567 } 568 else{ 569 return false; 570 } 571 } 572 573 }//Pentagon 574 575 class weiZhiGuangXi{ 576 public void weiZhiGuangXi(Pentagon p1, Pentagon p2, Square s1, Square s2, Triangle t1, Triangle t2){//判断两个多边形的位置关系 577 if(p1.wuBianXingJudge(p1)){//构成五边形p1 578 if(p2.wuBianXingJudge(p2)){//构成五边形p2 579 weiZhiGuangXi55(p1, p2); 580 } 581 else if(s2.siBianXingJudge(p2, s2)){//构成四边形s2 582 s2.siBianXingCreat(s2); 583 weiZhiGuangXi54(p1, s2); 584 } 585 else if(t2.sanJiaoXingJudge(p2, t2)){//构成三角形t2 586 t2.sanJiaoXingCreat(t2); 587 weiZhiGuangXi53(p1, t2); 588 } 589 else{//不构成多边形 590 System.out.print("2 not a polygon"); 591 } 592 } 593 else if(s1.siBianXingJudge(p1, s1)){//构成四边形s1 594 s1.siBianXingCreat(s1); 595 if(p2.wuBianXingJudge(p2)){//构成五边形p2 596 weiZhiGuangXi45(s1, p2); 597 } 598 else if(s2.siBianXingJudge(p2, s2)){//构成四边形s2 599 s2.siBianXingCreat(s2); 600 weiZhiGuangXi44(s1, s2); 601 } 602 else if(t2.sanJiaoXingJudge(p2, t2)){//构成三角形t2 603 t2.sanJiaoXingCreat(t2); 604 weiZhiGuangXi43(s1, t2); 605 } 606 else{//不构成多边形 607 System.out.print("2 not a polygon"); 608 } 609 } 610 else if(t1.sanJiaoXingJudge(p1, t1)){//构成三角形t1 611 t1.sanJiaoXingCreat(t1); 612 if(p2.wuBianXingJudge(p2)){//构成五边形p2 613 weiZhiGuangXi35(t1, p2); 614 } 615 else if(s2.siBianXingJudge(p2, s2)){//构成四边形s2 616 s2.siBianXingCreat(s2); 617 weiZhiGuangXi34(t1, s2); 618 } 619 else if(t2.sanJiaoXingJudge(p2, t2)){//构成三角形t2 620 t2.sanJiaoXingCreat(t2); 621 weiZhiGuangXi33(t1, t2); 622 } 623 else{//不构成多边形 624 System.out.print("not a polygon"); 625 } 626 } 627 else{//不构成多边形 628 System.out.print("not a polygon"); 629 } 630 } 631 632 public void weiZhiGuangXi33(Triangle t1, Triangle t2){//三角形和三角形 633 if(wanquanchonghe33(t1, t2)){//重合 634 System.out.print("the previous triangle coincides with the following triangle"); 635 } 636 else if(baoHan33(t1,t2)){//包含 637 System.out.print("the previous triangle contains the following triangle"); 638 } 639 else if(baoHan33(t2,t1)){//被包含 640 System.out.print("the previous triangle is inside the following triangle"); 641 } 642 } 643 644 public void weiZhiGuangXi34(Triangle t, Square s){//三角形和四边形 645 if(baoHan34(t, s)){//三角形包含四边形 646 System.out.print("the previous triangle contains the following quadrilateral"); 647 } 648 else if(baoHan43(s, t)){//三角形被包含于四边形 649 System.out.print("the previous triangle is inside the following quadrilateral"); 650 } 651 } 652 653 public boolean baoHan34(Triangle t, Square s){//三角形包含四边形 654 for(int i=0;i<4;i++){ 655 if(!t.dianInSanJiaoXing(t, s.dotList.get(i))){//有一个点不在三角形内 656 return false; 657 } 658 } 659 return true; 660 } 661 662 public boolean baoHan43(Square s, Triangle t){//三角形被包含于四边形 663 for(int i=0;i<3;i++){ 664 if(!s.dianInSiBianXing(s, t.dotList.get(i))){//有一个点不在三角形内 665 return false; 666 } 667 } 668 return true; 669 } 670 671 public void weiZhiGuangXi35(Triangle t, Pentagon p){//三角形和五边形 672 if(baoHan35(t, p)){//三角形包含五边形 673 System.out.print("the previous triangle contains the following pentagon"); 674 } 675 else if(baoHan53(p, t)){//三角形被包含于五边形 676 System.out.print("the previous triangle is inside the following pentagon"); 677 } 678 } 679 680 public boolean baoHan35(Triangle t, Pentagon p){//三角形包含五边形 681 for(int i=0;i<5;i++){ 682 if(!t.dianInSanJiaoXing(t, p.dotList.get(i))){//有一个点不在三角形内 683 return false; 684 } 685 } 686 return true; 687 } 688 689 public boolean baoHan53(Pentagon p, Triangle t){//三角形被包含于五边形 690 for(int i=0;i<3;i++){ 691 if(!p.dianInWuBianXing(p, t.dotList.get(i))){//有一个点不在五边形内 692 return false; 693 } 694 } 695 return true; 696 } 697 698 public boolean wanquanchonghe33(Triangle t1, Triangle t2){//三角形完全重合 699 for(int i=0;i<3;i++){ 700 if(t1.A.coincide(t2.dotList.get(i))){//A点 701 if(t1.B.coincide(t2.dotList.get((i+1)%3))){//B点 702 if(t1.C.coincide(t2.dotList.get((i+2)%3))){//C点 703 return true; 704 } 705 } 706 else if(t1.B.coincide(t2.dotList.get((i+3-1)%3))){//B点 707 if(t1.C.coincide(t2.dotList.get((i+3-2)%3))){//C点 708 return true; 709 } 710 } 711 } 712 } 713 return false; 714 } 715 716 public boolean baoHan33(Triangle t1, Triangle t2){//两个三角形的包含关系,t1包含t2,t2的点均在t1内 717 for(int i=0;i<3;i++){ 718 if(!t1.dianInSanJiaoXing(t1, t2.dotList.get(i))){//有一个点不在三角形内 719 return false; 720 } 721 } 722 return true; 723 } 724 725 public void weiZhiGuangXi43(Square s, Triangle t){//四边形和三角形 726 if(baoHan43(s, t)){//四边形包含三角形 727 System.out.print("the previous quadrilateral contains the following triangle"); 728 } 729 else if(baoHan34(t, s)){//四边形被包含于三角形 730 System.out.print("the previous quadrilateral is inside the following triangle"); 731 } 732 } 733 734 public void weiZhiGuangXi44(Square s1, Square s2){//四边形和四边形 735 if(wanquanchonghe44(s1, s2)){//四边形完全重合 736 System.out.print("the previous quadrilateral coincides with the following quadrilateral"); 737 } 738 else if(baoHan44(s1, s2)){//包含 739 System.out.print("the previous quadrilateral contains the following quadrilateral"); 740 } 741 else if(baoHan44(s2, s1)){//被包含 742 System.out.print("the previous quadrilateral is inside the following quadrilateral"); 743 } 744 } 745 746 public boolean baoHan44(Square s1, Square s2){//四边形包含四边形,s2的点均在s1内 747 for(int i=0;i<4;i++){ 748 if(!s1.dianInSiBianXing(s1, s2.dotList.get(i))){//有一个点不在四边形内 749 return false; 750 } 751 } 752 return true; 753 } 754 755 public boolean wanquanchonghe44(Square s1, Square s2){//四边形完全重合 756 for(int i=0;i<4;i++){ 757 if(s1.A.coincide(s2.dotList.get(i))){//A点 758 if(s1.B.coincide(s2.dotList.get((i+1)%4))){//B点 759 if(s1.C.coincide(s2.dotList.get((i+2)%4))){//C点 760 if(s1.D.coincide(s2.dotList.get((i+3)%4))){//D点 761 return true; 762 } 763 } 764 } 765 else if(s1.B.coincide(s2.dotList.get((i+4-1)%4))){//B点 766 if(s1.C.coincide(s2.dotList.get((i+4-2)%4))){//C点 767 if(s1.D.coincide(s2.dotList.get((i+4-3)%4))){//D点 768 return true; 769 } 770 } 771 } 772 } 773 } 774 return false; 775 } 776 777 public void weiZhiGuangXi45(Square s, Pentagon p){//四边形和五边形 778 if(baoHan45(s, p)){//四边形包含五边形 779 System.out.print("the previous quadrilateral contains the following pentagon"); 780 } 781 else if(baoHan54(p, s)){//四边形被包含于五边形内 782 System.out.print("the previous quadrilateral is inside the following pentagon"); 783 } 784 } 785 786 public boolean baoHan45(Square s, Pentagon p){//四边形包含五边形 787 for(int i=0;i<5;i++){ 788 if(!s.dianInSiBianXing(s, p.dotList.get(i))){//有一个点不在五边形内 789 return false; 790 } 791 } 792 return true; 793 } 794 795 public boolean baoHan54(Pentagon p, Square s){//四边形被包含于五边形内 796 for(int i=0;i<4;i++){ 797 if(!p.dianInWuBianXing(p, s.dotList.get(i))){//有一个点不在五边形内 798 return false; 799 } 800 } 801 return true; 802 } 803 804 public void weiZhiGuangXi53(Pentagon p, Triangle t){//五边形和三角形 805 if(baoHan53(p, t)){//五边形包含三角形 806 System.out.print("the previous pentagon contains the following triangle"); 807 } 808 else if(baoHan35(t, p)){//五边形被包含于三角形内 809 System.out.print("the previous pentagon is inside the following triangle"); 810 } 811 } 812 813 public void weiZhiGuangXi54(Pentagon p, Square s){//五边形和四边形 814 if(baoHan54(p, s)){//五边形包含四边形 815 System.out.print("the previous pentagon contains the following quadrilateral"); 816 } 817 else if(baoHan45(s, p)){//五边形包被包含于四边形内 818 System.out.print("the previous pentagon is inside the following quadrilateral"); 819 } 820 } 821 822 public void weiZhiGuangXi55(Pentagon p1, Pentagon p2){//五边形和五边形 823 if(wanquanchonghe55(p1, p2)){ 824 System.out.print("the previous pentagon coincides with the following pentagon"); 825 } 826 else if(baoHan55(p1, p2)){//包含 827 System.out.print("the previous pentagon contains the following pentagon"); 828 } 829 else if(baoHan55(p2, p1)){//被包含 830 System.out.print("the previous pentagon is inside the following pentagon"); 831 } 832 } 833 834 public boolean baoHan55(Pentagon p1, Pentagon p2){//p1包含p2,p2的点均在p1内 835 for(int i=0;i<5;i++){ 836 if(!p1.dianInWuBianXing(p1, p2.dotList.get(i))){//有一个点不在四边形内 837 return false; 838 } 839 } 840 return true; 841 } 842 843 public boolean wanquanchonghe55(Pentagon p1, Pentagon p2){//五边形完全重合 844 for(int i=0;i<5;i++){ 845 if(p1.A.coincide(p2.dotList.get(i))){//A点 846 if(p1.B.coincide(p2.dotList.get((i+1)%5))){//B点 847 if(p1.C.coincide(p2.dotList.get((i+2)%5))){//C点 848 if(p1.D.coincide(p2.dotList.get((i+3)%5))){//D点 849 if(p1.E.coincide(p2.dotList.get((i+4)%5))){//E点 850 return true; 851 } 852 } 853 } 854 } 855 else if(p1.B.coincide(p2.dotList.get((i+5-1)%5))){//B点 856 if(p1.C.coincide(p2.dotList.get((i+5-2)%5))){//C点 857 if(p1.D.coincide(p2.dotList.get((i+5-3)%5))){//D点 858 if(p1.E.coincide(p2.dotList.get((i+5-4)%5))){//E点 859 return true; 860 } 861 } 862 } 863 } 864 } 865 } 866 return false; 867 } 868 869 }//weiZhiGuangXi 870 871 public class Main{ 872 public static void main(String[] args){ 873 Input in = new Input(); 874 String str = in.input();//输入 875 int selectNum = (int)str.charAt(0) - (int)'0';//情况选择 876 int dex = 0, sign = 3;//dex为点的个数,sign应该取0,1,2以外的值 877 String[] tokens = str.split(":|,| "); 878 Verify ver = new Verify();//创建引用判非法的对象 879 switch(selectNum){ 880 case 4: dex = 10; sign = ver.feifa(str, dex); 881 in.output(sign); 882 if(sign==1){//输入合法 883 Pentagon p1 = new Pentagon(); Square s1 = new Square(); Triangle t1 = new Triangle(); 884 Pentagon p2 = new Pentagon(); Square s2 = new Square(); Triangle t2 = new Triangle(); 885 p1.setWuBianXing(1, tokens, p1);//五边形p1信息录入 886 p2.setWuBianXing(11, tokens, p2);//五边形p1信息录入 887 weiZhiGuangXi gx = new weiZhiGuangXi(); 888 gx.weiZhiGuangXi(p1, p2, s1, s2, t1, t2); 889 } 890 break; 891 case 5: dex = 10; sign = ver.feifa(str, dex); 892 in.output(sign); 893 if(sign==1){//输入合法 894 Pentagon p1 = new Pentagon(); Square s1 = new Square(); Triangle t1 = new Triangle(); 895 Pentagon p2 = new Pentagon(); Square s2 = new Square(); Triangle t2 = new Triangle(); 896 p1.setWuBianXing(1, tokens, p1);//五边形p1信息录入 897 p2.setWuBianXing(11, tokens, p2);//五边形p1信息录入 898 899 } 900 break; 901 case 6: dex = 6; sign = ver.feifa(str, dex); 902 in.output(sign); 903 if(sign==1){//输入合法 904 Spot dot = new Spot(); 905 dot.x = Double.valueOf(tokens[1]); dot.y = Double.valueOf(tokens[2]); 906 Pentagon p = new Pentagon(); 907 Square s = new Square(); 908 Triangle t = new Triangle(); 909 p.setWuBianXing(3, tokens, p);//五边形信息录入 910 if(p.wuBianXingJudge(p)){//构成五边形 911 if(p.dianOnWuBianXing(p, dot)){//点在五边形上 912 System.out.print("on the pentagon"); 913 } 914 else if(p.dianInWuBianXing(p, dot)){//点在五边形内 915 System.out.print("in the pentagon"); 916 } 917 else{//点在五边形外 918 System.out.print("outof the pentagon"); 919 } 920 } 921 else if(s.siBianXingJudge(p, s)){//构成四边形 922 if(s.dianOnSiBianXing(s, dot)){//点在四边形上 923 System.out.print("on the quadrilateral"); 924 } 925 else if(s.dianInSiBianXing(s, dot)){//点在四边形内 926 System.out.print("in the quadrilateral"); 927 } 928 else{//点在四边形外 929 System.out.print("outof the quadrilateral"); 930 } 931 } 932 else if(t.sanJiaoXingJudge(p, t)){//构成三角形 933 if(t.dianOnSanJiaoXing(t, dot)){//点在三角形上 934 System.out.print("on the triangle"); 935 } 936 else if(t.dianInSanJiaoXing(t, dot)){//点在三角形内 937 System.out.print("in the triangle"); 938 } 939 else{//点在三角形外 940 System.out.print("outof the triangle"); 941 } 942 } 943 else{//不构成多边形 944 System.out.print("not a polygon"); 945 } 946 } 947 break; 948 default: 949 System.out.print("Wrong Format"); 950 break; 951 }//switch 952 }//main 953 }//MainView Code
(4)代码分析
这次的复杂度真是离谱!
(5)踩坑心得
没写完,就写了两个大测试点,好吧,错估了时间,以为蔡蔡会延时,呜呜呜。但我思考了一下整体实现,数组加父子类、继承、多态这些会给你带来惊喜,吐槽一下判断三角形的时候10种情况我差点没怀疑人生,绝对不要直接硬写,想象一下没有父子类和继承,两个多边形的位置关系判断会有多少种情况,每次传参不一样又要重写一个方法,yue了,好好学习吧......
4、期中考试-1:点与线(类设计)
(1)题目详情
-
设计一个类表示平面直角坐标系上的点Point,私有属性分别为横坐标x与纵坐标y,数据类型均为实型数,除构造方法以及属性的getter与setter方法外,定义一个用于显示信息的方法display(),用来输出该坐标点的坐标信息,格式如下:
(x,y)
,数值保留两位小数。为简化题目,其中,坐标点的取值范围设定为(0,200]
。若输入有误,系统则直接输出Wrong Format
-
设计一个类表示平面直角坐标系上的线Line,私有属性除了标识线段两端的点point1、point2外,还有一个字符串类型的color,用于表示该线段的颜色,同样,除构造方法以及属性的getter与setter方法外,定义一个用于计算该线段长度的方法getDistance(),还有一个用于显示信息的方法display(),用来输出线段的相关信息,输出格式如下:
``` The line's color is:颜色值 The line's begin point's Coordinate is: (x1,y1) The line's end point's Coordinate is: (x2,y2) The line's length is:长度值 ```
其中,所有数值均保留两位小数,建议可用
String.format("%.2f", data)
方法。设计类图如下图所示。
** 题目要求:在主方法中定义一条线段对象,从键盘输入该线段的起点坐标与终点坐标以及颜色,然后调用该线段的display()方法进行输出。**
- 以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
输入格式:
分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。
输出格式:
The line's color is:颜色值
The line's begin point's Coordinate is:
(x1,y1)
The line's end point's Coordinate is:
(x2,y2)
The line's length is:长度值
(2)设计
共三个类:
主类:包含一个静态主方法,用来将点类和线类联系在一起;
点类:包含两个私有的属性x和y,两个构造方法(方法的重载,参数不同)以及一个展示点的细节的输出方法;
线类:包含四个私有的属性:两个点point1、point2,颜色color和长度distance,两个构造方法(方法的重载,参数不同)以及一个展示线的细节的输出方法。
(3)源码
1 import java.util.Scanner; 2 3 class Point{//点类 4 private double x; 5 private double y; 6 7 public Point(){} 8 9 public Point(double x, double y){ 10 this.x = x; 11 this.y = y; 12 } 13 14 public double getX(){ 15 return x; 16 } 17 18 public void setX(double x){ 19 this.x = x; 20 } 21 22 public double getY(){ 23 return y; 24 } 25 26 public void setY(double y){ 27 this.y = y; 28 } 29 30 public void display(){ 31 32 } 33 }//Point 34 35 class Line{//线类 36 private Point point1; 37 private Point point2; 38 private String color; 39 40 public Line(){} 41 42 public Line(Point p1, Point p2, String color){ 43 this.point1 = p1; 44 this.point2 = p2; 45 this.color = color; 46 } 47 48 public Point getPoint1(){ 49 return point1; 50 } 51 52 public void setPoint1(Point point1){ 53 this.point1 = point1; 54 } 55 56 public Point getPoint2(){ 57 return point2; 58 } 59 60 public void setPoint2(Point point2){ 61 this.point2 = point2; 62 } 63 64 public String getColor(){ 65 return color; 66 } 67 68 public void setColor(String color){ 69 this.color = color; 70 } 71 72 public double getDistance(){ 73 double d = (this.point2.getY()-this.point1.getY())*(this.point2.getY()-this.point1.getY())+(this.point2.getX()-this.point1.getX())*(this.point2.getX()-this.point1.getX()); 74 return Math.sqrt(d); 75 } 76 77 public void display(){ 78 System.out.println("The line's color is:"+color); 79 System.out.println("The line's begin point's Coordinate is:"); 80 System.out.println("("+String.format("%.2f", this.point1.getX())+","+String.format("%.2f", this.point1.getY())+")"); 81 System.out.println("The line's end point's Coordinate is:"); 82 System.out.println("("+String.format("%.2f", this.point2.getX())+","+String.format("%.2f", this.point2.getY())+")"); 83 System.out.println("The line's length is:"+String.format("%.2f", getDistance())); 84 } 85 }//Line 86 87 public class Main{ 88 public static void main(String[] args){ 89 Scanner input = new Scanner(System.in); 90 double x1 = input.nextDouble(); 91 double y1 = input.nextDouble(); 92 double x2 = input.nextDouble(); 93 double y2 = input.nextDouble(); 94 if((x1<=0 || x1>200) || (y1<=0 || y1>200) ||(x2<=0 || x2>200) || (y2<=0 || y2>200)){ 95 System.out.print("Wrong Format"); 96 } 97 else{ 98 Point point1 = new Point(x1, y1); 99 Point point2 = new Point(x2, y2); 100 String s = input.next(); 101 Line l = new Line(point1, point2, s); 102 103 l.display(); 104 } 105 }//main 106 }//MainView Code
(4)代码分析
复杂度,深度,类的设计都很nice!主要是代码比较简单。
(5)踩坑心得
没啥问题,就是敲的有点慢......
5、期中考试-2:点线面问题重构(继承与多态)
(1)题目详情
在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。
- 对题目中的点Point类和线Line类进行进一步抽象,定义一个两个类的共同父类Element(抽象类),将display()方法在该方法中进行声明(抽象方法),将Point类和Line类作为该类的子类。
- 再定义一个Element类的子类面Plane,该类只有一个私有属性颜色color,除了构造方法和属性的getter、setter方法外,display()方法用于输出面的颜色,输出格式如下:
The Plane's color is:颜色
- 在主方法内,定义两个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();
其中,所有数值均保留两位小数,建议可用String.format("%.2f", data)
方法。
- 以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
输入格式:
分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。
输出格式:
(x1,y1)
(x2,y2)
The line's color is:颜色值
The line's begin point's Coordinate is:
(x1,y1)
The line's end point's Coordinate is:
(x2,y2)
The line's length is:长度值
The Plane's color is:颜色值
(2)设计
共五个类:
Element(父类):一个抽象类,包含展示细节方法(空方法);
主类:包含一个静态主方法,用来将点类、面类和线类联系在一起;
点类(Element的子类):包含两个私有的属性x和y,两个构造方法(方法的重载,参数不同)以及一个展示点的细节的输出方法(父类方法重写);
线类(Element的子类):包含四个私有的属性:两个点point1、point2,颜色color和长度distance,两个构造方法(方法的重载,参数不同)以及一个展示线的细节的输出方法(父类方法重写);
面类(Element的子类):包含一个私有属性颜色color,两个构造方法(方法的重载,参数不同)以及一个展示面的细节的输出方法(父类方法重写)。
(3)源码
1 import java.util.Scanner; 2 3 abstract class Element{ 4 public void display(){ 5 6 } 7 }//Element 8 9 class Point extends Element{//点类 10 private double x; 11 private double y; 12 13 public Point(){} 14 15 public Point(double x, double y){ 16 this.x = x; 17 this.y = y; 18 } 19 20 public double getX(){ 21 return x; 22 } 23 24 public void setX(double x){ 25 this.x = x; 26 } 27 28 public double getY(){ 29 return y; 30 } 31 32 public void setY(double y){ 33 this.y = y; 34 } 35 @Override 36 public void display(){ 37 System.out.println("("+String.format("%.2f", this.x)+","+String.format("%.2f", this.y)+")"); 38 } 39 }//Point 40 41 class Line extends Element{//线类 42 private Point point1; 43 private Point point2; 44 private String color; 45 46 public Line(){} 47 48 public Line(Point p1, Point p2, String color){ 49 this.point1 = p1; 50 this.point2 = p2; 51 this.color = color; 52 } 53 54 public Point getPoint1(){ 55 return point1; 56 } 57 58 public void setPoint1(Point point1){ 59 this.point1 = point1; 60 } 61 62 public Point getPoint2(){ 63 return point2; 64 } 65 66 public void setPoint2(Point point2){ 67 this.point2 = point2; 68 } 69 70 public String getColor(){ 71 return color; 72 } 73 74 public void setColor(String color){ 75 this.color = color; 76 } 77 78 public double getDistance(){ 79 double d = (this.point2.getY()-this.point1.getY())*(this.point2.getY()-this.point1.getY())+(this.point2.getX()-this.point1.getX())*(this.point2.getX()-this.point1.getX()); 80 return Math.sqrt(d); 81 } 82 @Override 83 public void display(){ 84 System.out.println("The line's color is:"+color); 85 System.out.println("The line's begin point's Coordinate is:"); 86 System.out.println("("+String.format("%.2f", this.point1.getX())+","+String.format("%.2f", this.point1.getY())+")"); 87 System.out.println("The line's end point's Coordinate is:"); 88 System.out.println("("+String.format("%.2f", this.point2.getX())+","+String.format("%.2f", this.point2.getY())+")"); 89 System.out.println("The line's length is:"+String.format("%.2f", getDistance())); 90 } 91 }//Line 92 93 class Plane extends Element{ 94 private String color; 95 96 public Plane(){} 97 98 public Plane(String color){ 99 this.color = color; 100 } 101 102 public String getColor(){ 103 return color; 104 } 105 106 public void setColor(String color){ 107 this.color = color; 108 } 109 @Override 110 public void display(){ 111 System.out.print("The Plane's color is:"+color); 112 } 113 } 114 115 public class Main{ 116 public static void main(String[] args){ 117 Scanner input = new Scanner(System.in); 118 double x1 = input.nextDouble(); 119 double y1 = input.nextDouble(); 120 double x2 = input.nextDouble(); 121 double y2 = input.nextDouble(); 122 if((x1<=0 || x1>200) || (y1<=0 || y1>200) ||(x2<=0 || x2>200) || (y2<=0 || y2>200)){ 123 System.out.print("Wrong Format"); 124 } 125 else{ 126 Point point1 = new Point(x1, y1); 127 Point point2 = new Point(x2, y2); 128 String s = input.next(); 129 Line l = new Line(point1, point2, s); 130 Plane p = new Plane(s); 131 Element element; 132 element = point1;//起点Point 133 element.display(); 134 135 element = point2;//终点Point 136 element.display(); 137 138 element = l;//线段 139 element.display(); 140 141 element = p;//面 142 element.display(); 143 } 144 } 145 }View Code
(4)代码分析
和上一题一样,复杂度,深度,类的设计都很nice!主要是代码比较简单。
(5)踩坑心得
总是忘记属性是私有的,不过报个编译错误很快就能解决,其他没啥问题。在第一题的基础上,这题很快就能完成。
6、期中考试-3:点线面问题再重构(容器类)
(1)题目详情
在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。
- 在原有类设计的基础上,增加一个GeometryObject容器类,其属性为
ArrayList<Element>
类型的对象(若不了解泛型,可以不使用<Element>
) - 增加该类的
add()
方法及remove(int index)
方法,其功能分别为向容器中增加对象及删除第index - 1
(ArrayList中index>=0)个对象 - 在主方法中,用户循环输入要进行的操作(choice∈[0,4]),其含义如下:
- 1:向容器中增加Point对象
- 2:向容器中增加Line对象
- 3:向容器中增加Plane对象
- 4:删除容器中第index - 1个数据,若index数据非法,则无视此操作
- 0:输入结束
输入结束后,按容器中的对象顺序分别调用每个对象的choice = input.nextInt(); while(choice != 0) { switch(choice) { case 1://insert Point object into list ... break; case 2://insert Line object into list ... break; case 3://insert Plane object into list ... break; case 4://delete index - 1 object from list int index = input.nextInt(); ... } choice = input.nextInt(); }
display()
方法进行输出。
类图如下所示:
- 以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
输入格式:
switch(choice) {
case 1://insert Point object into list
输入“点”对象的x,y值
break;
case 2://insert Line object into list
输入“线”对象两个端点的x,y值
break;
case 3://insert Plane object into list
输入“面”对象的颜色值
break;
case 4://delete index - 1 object from list
输入要删除的对象位置(从1开始)
...
}
输出格式:
- Point、Line、Plane的输出参考题目2
- 删除对象时,若输入的index超出合法范围,程序自动忽略该操作
(2)设计
共六个类:
Element(父类):一个抽象类,包含展示细节方法(空方法);
GeometryObject:容器类,包含一个私有的数组属性,数组类型为Element类,一个空的构造方法,添加对象方法,删除对象方法;
主类:包含一个静态主方法,用来将点类、面类和线类联系在一起;
点类(Element的子类):包含两个私有的属性x和y,两个构造方法(方法的重载,参数不同)以及一个展示点的细节的输出方法(父类方法重写);
线类(Element的子类):包含四个私有的属性:两个点point1、point2,颜色color和长度distance,两个构造方法(方法的重载,参数不同)以及一个展示线的细节的输出方法(父类方法重写);
面类(Element的子类):包含一个私有属性颜色color,两个构造方法(方法的重载,参数不同)以及一个展示面的细节的输出方法(父类方法重写)。
(3)源码
1 import java.util.Scanner; 2 import java.util.ArrayList; 3 4 class GeometryObject{ 5 private ArrayList<Element> list = new ArrayList<>(); 6 7 public GeometryObject(){} 8 9 public void add(Element element){ 10 this.add(element); 11 } 12 13 public void remove(int index){ 14 15 } 16 17 public ArrayList<Element> getList(){ 18 return list; 19 } 20 }//GeometryObject 21 22 abstract class Element{ 23 public void display(){ 24 25 } 26 }//Element 27 28 class Point extends Element{//点类 29 private double x; 30 private double y; 31 32 public Point(){} 33 34 public Point(double x, double y){ 35 this.x = x; 36 this.y = y; 37 } 38 39 public double getX(){ 40 return x; 41 } 42 43 public void setX(double x){ 44 this.x = x; 45 } 46 47 public double getY(){ 48 return y; 49 } 50 51 public void setY(double y){ 52 this.y = y; 53 } 54 @Override 55 public void display(){ 56 System.out.println("("+String.format("%.2f", this.x)+","+String.format("%.2f", this.y)+")"); 57 } 58 }//Point 59 60 class Line extends Element{//线类 61 private Point point1; 62 private Point point2; 63 private String color; 64 65 public Line(){} 66 67 public Line(Point p1, Point p2, String color){ 68 this.point1 = p1; 69 this.point2 = p2; 70 this.color = color; 71 } 72 73 public Point getPoint1(){ 74 return point1; 75 } 76 77 public void setPoint1(Point point1){ 78 this.point1 = point1; 79 } 80 81 public Point getPoint2(){ 82 return point2; 83 } 84 85 public void setPoint2(Point point2){ 86 this.point2 = point2; 87 } 88 89 public String getColor(){ 90 return color; 91 } 92 93 public void setColor(String color){ 94 this.color = color; 95 } 96 97 public double getDistance(){ 98 double d = (this.point2.getY()-this.point1.getY())*(this.point2.getY()-this.point1.getY())+(this.point2.getX()-this.point1.getX())*(this.point2.getX()-this.point1.getX()); 99 return Math.sqrt(d); 100 } 101 @Override 102 public void display(){ 103 System.out.println("The line's color is:"+color); 104 System.out.println("The line's begin point's Coordinate is:"); 105 System.out.println("("+String.format("%.2f", this.point1.getX())+","+String.format("%.2f", this.point1.getY())+")"); 106 System.out.println("The line's end point's Coordinate is:"); 107 System.out.println("("+String.format("%.2f", this.point2.getX())+","+String.format("%.2f", this.point2.getY())+")"); 108 System.out.println("The line's length is:"+String.format("%.2f", getDistance())); 109 } 110 }//Line 111 112 class Plane extends Element{ 113 private String color; 114 115 public Plane(){} 116 117 public Plane(String color){ 118 this.color = color; 119 } 120 121 public String getColor(){ 122 return color; 123 } 124 125 public void setColor(String color){ 126 this.color = color; 127 } 128 @Override 129 public void display(){ 130 System.out.print("The Plane's color is:"+color); 131 } 132 } 133 134 public class Main{ 135 public static void main(String[] args){ 136 Scanner input = new Scanner(System.in); 137 int choice = input.nextInt(); 138 GeometryObject g = new GeometryObject(); 139 while(choice!=0){ 140 choice = input.nextInt(); 141 switch(choice) { 142 case 1://insert Point object into list 143 double x = input.nextDouble(); 144 double y = input.nextDouble(); 145 if((x<=0 || x>200) || (y<=0 || y>200)){ 146 System.out.print("Wrong Format"); 147 } 148 else{ 149 Point point = new Point(x, y); 150 g.add(point); 151 } 152 break; 153 case 2://insert Line object into list 154 double x1 = input.nextDouble(); 155 double y1 = input.nextDouble(); 156 double x2 = input.nextDouble(); 157 double y2 = input.nextDouble(); 158 if((x1<=0 || x1>200) || (y1<=0 || y1>200) ||(x2<=0 || x2>200) || (y2<=0 || y2>200)){ 159 System.out.print("Wrong Format"); 160 } 161 else{ 162 Point point1 = new Point(x1, y1); 163 Point point2 = new Point(x2, y2); 164 String s = input.next(); 165 Line l = new Line(point1, point2, s); 166 g.add(l); 167 } 168 break; 169 case 3://insert Plane object into list 170 String s = input.next(); 171 Plane p = new Plane(s); 172 g.add(p); 173 break; 174 case 4://delete index - 1 object from list 175 176 break; 177 default: break; 178 } 179 } 180 } 181 }View Code
(4)代码分析
类的设计合理,但在最大复杂度和平均深度上略微有点超标。
(5)踩坑心得
没写完。
三、总结
通过这几次的练习和考核,我对于类的理解得到了加深,也让我意识到自己的问题所在,需要用到的知识点没有好好学习,导致写码过程中绕了很多大弯,很多时候会造成虽然勉强能写出码来,但敲码的效率不够高,以及码的整体效果、复杂度都不太理想,出现错误时找错还得重新理解一遍自己的码,主要是可能还找不出来;类的封装度不够高,类与类之间联系过于紧密,像我在上面提到的一个问题就是一个东西出现了遗漏,而与其牵连的东西过多,导致我不想去修改,直接选择再加方法单独拎出来考虑,但这样做会使得程序的可读性下降。
标签:java,double,sq,五边形,else,flag,&&,四边形,false From: https://www.cnblogs.com/jjbokey/p/16838405.html