前言:
四边形的计算和五边形的计算确实很复杂,尤其是五边形,挺多测试点的,
其中如何判断四边形和五边形大同小异,判断它们的凹凸性方法同根同源。
都用面积法来做。其他的点,虽然做法相似,比如一条直线分割四边形或
五边形,分割面积按从小到大输出,但是五边形的情况远比四边形复杂的
多。
期中测试的话,难度不大,但需要速度与细心。考的是在点与线类的基础
上增加父类、抽象类等考点。问题不大
第四次大作业:
7-2 点线形系列4-凸四边形的计算
分数 70
用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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"。
输入样例1:
选项1,点重合。例如:
1:-1,-1 -1,-1 1,2 1,-2
输出样例:
在这里给出相应的输出。例如:
points coincide
输入样例2:
不符合基本格式。例如:
1:-1,-1 1,2 -1,1 ++1,0
输出样例:
在这里给出相应的输出。例如:
Wrong Format
输入样例3:
选项1,输入点数量不对。例如:
1:-1,-1 -1,2
输出样例:
在这里给出相应的输出。例如:
wrong number of points
输入样例4:
选项1,正确输入判断。例如:
1:-1,-1 -1,1 1,2 1,-2
输出样例:
在这里给出相应的输出。例如:
true false
输入样例5:
选项2,输入点不构成四边形。例如:
2:10,10 1,1 0,0 1,20
输出样例:
在这里给出相应的输出。例如:
not a quadrilateral
输入样例6:
选项2,正方形。例如:
2:0,0 0,80 80,80 80,0
输出样例:
在这里给出相应的输出。例如:
true true true
输入样例7:
选项2。例如:
2:0,0 -10,80 0,160 -10,80
输出样例:
在这里给出相应的输出。例如:
not a quadrilateral
输入样例8:
选项3,凸四边形。例如:
3:-1,-1 -1,1 1,2 1,-2
输出样例:
在这里给出相应的输出。例如:
true 10.472 6.0
输入样例9:
选项3,。例如:
3:0,0 -10,100 0,99 10,100
输出样例:
在这里给出相应的输出。例如:
false 221.097 990.0
设计与分析:
我的代码:

1 import java.util.*; 2 import java.text.DecimalFormat; 3 public class Main{ 4 //控制小数点 5 public static void main(String[] args){ 6 //Point p1=new Point(); 7 8 Scanner input=new Scanner(System.in); 9 String x=input.nextLine();//输入点 10 String coor[]=x.split(" |[,]|[:]");//提出每个点的坐标x,y 11 String coor1[]=x.split(" |,"); 12 String coor2[]=x.split(" |:"); 13 //判断格式是否合法,不合法则结束 14 if(!x.matches("^[1-5][:](([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))[,]([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))\\s?)+$")){ 15 System.out.println("Wrong Format"); 16 return; 17 } 18 19 if(coor[0].equalsIgnoreCase("1")||coor[0].equalsIgnoreCase("2")||coor[0].equalsIgnoreCase("3")){ 20 if(coor.length!=9){ 21 System.out.println("wrong number of points"); 22 return; 23 } 24 } 25 if(coor[0].equalsIgnoreCase("4")){ 26 if(coor.length!=13){ 27 System.out.println("wrong number of points"); 28 return; 29 } 30 } 31 if(coor[0].equalsIgnoreCase("5")){ 32 if(coor.length!=11){ 33 System.out.println("wrong number of points"); 34 return; 35 } 36 } 37 double x1=Double.valueOf(coor[1]); 38 double y1=Double.valueOf(coor[2]); 39 double x2=Double.valueOf(coor[3]); 40 double y2=Double.valueOf(coor[4]); 41 double x3=Double.valueOf(coor[5]); 42 double y3=Double.valueOf(coor[6]); 43 double x4=Double.valueOf(coor[7]); 44 double y4=Double.valueOf(coor[8]); 45 Point a=new Point(x1,y1); 46 Point b=new Point(x2,y2); 47 Point c=new Point(x3,y3); 48 Point d=new Point(x4,y4); 49 // Line l1=new Line(a,b); 50 // Line l2=new Line(b,c); 51 // Line l3=new Line(c,d); 52 // Line l4=new Line(d,a); 53 // Quadrilateral q = new Quadrilateral(a,b,c,d); 54 if(coor[0].equalsIgnoreCase("1")){ 55 56 try{ 57 Quadrilateral q = new Quadrilateral(a,b,c,d); 58 if(q.isCoincide()){ 59 System.out.println("points coincide"); 60 return; 61 } 62 System.out.printf("true %s\n",q.isParallelQuadrilateral()); 63 }catch (Exception e){ 64 if(e.getMessage().equals("not a quadrilateral")) 65 System.out.println("false false"); 66 else System.out.println(e.getMessage()); 67 } 68 } 69 70 71 if(coor[0].equalsIgnoreCase("2")){ 72 73 try{ 74 Quadrilateral q = new Quadrilateral(a,b,c,d); 75 if(q.isCoincide()){ 76 System.out.println("points coincide"); 77 return; 78 } 79 System.out.printf("%s %s %s\n",q.isDiamond(),q.isRectangle(),q.isSquare()); 80 }catch (Exception e){ 81 System.out.println("not a quadrilateral"); 82 } 83 } 84 85 86 if(coor[0].equalsIgnoreCase("3")){ 87 try{ 88 Quadrilateral q = new Quadrilateral(a,b,c,d); 89 if(q.isCoincide()){ 90 System.out.println("points coincide"); 91 return; 92 } 93 System.out.printf("%s ",q.isConvexQuadrilateral()); 94 change(q.sideLength()); 95 System.out.print(" "); 96 change(q.area()); 97 98 }catch (Exception e){ 99 System.out.println(e.getMessage()); 100 } 101 } 102 103 if(coor[0].equalsIgnoreCase("4")){ 104 double x5=Double.valueOf(coor[9]); 105 double y5=Double.valueOf(coor[10]); 106 double x6=Double.valueOf(coor[11]); 107 double y6=Double.valueOf(coor[12]); 108 Point f=new Point(x5,y5); 109 Point g=new Point(x6,y6); 110 Line l=null; 111 Quadrilateral q=null; 112 try{ 113 l=new Line(a,b); 114 }catch (Exception e){ //不构成直线 115 System.out.println(e.getMessage()); 116 return; 117 } 118 try{ 119 q = new Quadrilateral(c,d,f,g); 120 solve(l,q); 121 122 return; 123 }catch (Exception e){ //可能构成三角形 124 try{ //保证以下代码正确,捕获异常并吞并 125 126 //以g号点作为顶点 127 if(!c.isSameTo(f)){ //c,f点不重合 128 Line ll = new Line(c,f); 129 //d在ll之上,g在ll之外 130 if(d.inLineSegment_close(ll) && !g.inLineSegment_close(ll)){ 131 Trianges tr = new Trianges(c,f,g); 132 solve(l,tr); 133 return; 134 } 135 } 136 else{ //c,f点重合 137 if(!c.isSameTo(d)){ //但是c,d点不重合 138 Line ll = new Line(c,d); 139 if(!g.inLineSegment_close(ll)){ //g点在ll线之外 140 Trianges tr = new Trianges(c,d,g); 141 solve(l,tr); 142 return; 143 } 144 } 145 } 146 //以c点作为顶点 147 if(!d.isSameTo(g)){//d,g点不重合 148 Line ll = new Line(d,g); 149 if(f.inLineSegment_close(ll) && !c.inLine(ll)){ 150 Trianges tr = new Trianges(c,d,g); 151 solve(l,tr); 152 return; 153 } 154 } 155 else{ 156 if(!d.isSameTo(f)){ 157 Line ll = new Line(d,f); 158 if(!c.inLineSegment_close(ll)){ 159 Trianges tr = new Trianges(c,d,f); 160 solve(l,tr); 161 return; 162 } 163 } 164 } 165 166 //以f点作为顶点 167 if(!d.isSameTo(g)){ 168 Line ll = new Line(d,g); 169 if(c.inLineSegment_close(ll) && !f.inLine(ll)){ 170 Trianges tr = new Trianges(d,f,g); 171 172 solve(l,tr); 173 return; 174 } 175 } 176 else{ 177 if(!d.isSameTo(c)){ 178 Line ll = new Line(d,c); 179 if(!f.inLineSegment_close(ll)){ 180 Trianges tr = new Trianges(c,d,f); 181 solve(l,tr); 182 return; 183 } 184 } 185 } 186 //以d点作为顶点 187 if(!c.isSameTo(f)){ 188 Line ll = new Line(c,f); 189 if(g.inLineSegment_close(ll) && !d.inLine(ll)){ 190 Trianges tr = new Trianges(c,d,f); 191 solve(l,tr); 192 return; 193 } 194 } 195 else{ 196 if(!g.isSameTo(f)){ 197 Line ll = new Line(g,f); 198 if(!d.inLineSegment_close(ll)){ 199 Trianges tr = new Trianges(f,d,g); 200 solve(l,tr); 201 return; 202 } 203 } 204 } 205 206 207 208 //不构成三角形 209 System.out.println("not a quadrilateral or triangle"); 210 211 212 }catch(Exception ee){} 213 214 215 } 216 217 } 218 if(coor[0].equalsIgnoreCase("5")){ 219 double x5=Double.valueOf(coor[9]); 220 double y5=Double.valueOf(coor[10]); 221 Point f=new Point(x5,y5); 222 try{ 223 Quadrilateral q = new Quadrilateral(b,c,d,f); 224 int flag=q.isContainPoint(a); 225 if(flag==0) 226 System.out.println("in the quadrilateral"); 227 else if(flag==1) 228 System.out.println("on the quadrilateral"); 229 else 230 System.out.println("outof the quadrilateral"); 231 return; 232 }catch(Exception e){ //不构成四边形,待确定是否构成三角形 233 try{ 234 //以b点作为顶点 235 if(!c.isSameTo(f)){ //c,f点不重合 236 Line Lcf = new Line(c,f); 237 if(d.inLineSegment_close(Lcf)&&!b.inLineSegment_close(Lcf)){ //d在Lcf之上,b在Lcf之外 238 Trianges tr=new Trianges(b,c,f); 239 isInTriangle(tr,a); 240 return; 241 } 242 } 243 else{ 244 //c,f点重合 245 if(!d.isSameTo(c)){ //但是c,d点不重合 246 Line Lcd = new Line(d,c); 247 if(!b.inLineSegment_close(Lcd)){ //b点在Lcd线之外 248 Trianges tr=new Trianges(b,c,d); 249 isInTriangle(tr,a); 250 return; 251 } 252 } 253 } 254 //以f点作为顶点 255 if(!b.isSameTo(d)){ //b,d点不重合 256 Line Lbd = new Line(b,d); 257 if(c.inLineSegment_close(Lbd)&&!f.inLineSegment_close(Lbd)){ //c在Lbd之上,f在Lbd之外 258 Trianges tr=new Trianges(b,d,f); 259 isInTriangle(tr,a); 260 return; 261 } 262 } 263 else{ 264 //b,d点重合 265 if(!b.isSameTo(c)){ //但是b,c点不重合 266 Line Lbc = new Line(b,c); 267 if(!f.inLineSegment_close(Lbc)){ //f点在Lbc线之外 268 Trianges tr=new Trianges(b,c,f); 269 isInTriangle(tr,a); 270 return; 271 } 272 } 273 } 274 //以c点作为顶点 275 if(!b.isSameTo(d)){ //b,d点不重合 276 Line Lbd=new Line(b,d); 277 if(f.inLineSegment_close(Lbd)&&!c.inLineSegment_close(Lbd)){ //f在Lbd之上,c在Lbd之外 278 Trianges tr=new Trianges(b,c,d); 279 isInTriangle(tr,a); 280 return; 281 } 282 } 283 else{ 284 //b,d点重合 285 if(!f.isSameTo(d)){ //但是f,d点不重合 286 Line Ldf=new Line(f,d); 287 if(!c.inLineSegment_close(Ldf)){ //d点在Ldf线之外 288 Trianges tr=new Trianges(f,c,d); 289 isInTriangle(tr,a); 290 return; 291 } 292 } 293 } 294 //以d点作为顶点 295 if(!c.isSameTo(f)){ //c,f点不重合 296 Line Lcf = new Line(c,f); 297 if(b.inLineSegment_close(Lcf)&&!d.inLineSegment_close(Lcf)){ //d在Lbd之上,b在Lbd之外 298 Trianges tr=new Trianges(d,c,f); 299 isInTriangle(tr,a); 300 return; 301 } 302 } 303 else{ 304 //c,f点重合 305 if(!b.isSameTo(c)){ //但是b,c点不重合 306 Line Lbc=new Line(b,c); 307 if(!d.inLineSegment_close(Lbc)){ //d点在Lbc线之外 308 Trianges tr=new Trianges(b,c,d); 309 isInTriangle(tr,a); 310 return; 311 } 312 } 313 } 314 System.out.println("not a quadrilateral or triangle"); 315 }catch(Exception ee){} 316 317 } 318 319 } 320 } 321 public static void change(double num){ 322 // if((num*1000)%10<0.0001)//这里不能写==0,double的精度问题 323 // System.out.printf("%.1f",num); 324 // else 325 // System.out.printf("%.3f",num); 326 DecimalFormat d=new DecimalFormat(); 327 String style="#.###"; 328 d.applyPattern(style); 329 System.out.print(Double.parseDouble(d.format((Double)num))); 330 331 } 332 public static void isInTriangle(Trianges tr,Point a){ 333 int flag=tr.isContainPoint(a); 334 if(flag==0) 335 System.out.println("in the triangle"); 336 else if(flag==1) 337 System.out.println("on the triangle"); 338 else 339 System.out.println("outof the triangle"); 340 return; 341 } 342 public static void pr_ans(Trianges t, Point a,Point b,Point c){ 343 double[] ans = new double[2]; 344 ans[0] = Trianges.area(a,b,c); 345 ans[1] = t.getArea() - ans[0]; 346 Arrays.sort(ans); 347 System.out.printf("2 "); 348 change(ans[0]); 349 System.out.print(" "); 350 change(ans[1]); 351 System.out.println(); 352 } 353 public static void pr_ans(Quadrilateral q,Point a,Point b,Point c){ 354 double[] ans = new double[2]; 355 ans[0] = Trianges.area(a,b,c); 356 ans[1] = q.area() - ans[0]; 357 Arrays.sort(ans); 358 System.out.printf("2 "); 359 change(ans[0]); 360 System.out.print(" "); 361 change(ans[1]); 362 } 363 364 //三角形交点情况 365 public static void solve(Line l,Trianges t){ 366 367 //与任意一条边重合 368 if(l.isSameTo(t.L1) || l.isSameTo(t.L2) || l.isSameTo(t.L3)){ 369 System.out.println("The line is coincide with one of the lines"); 370 return; 371 } 372 373 //与三条边的交点(值可能为null,即平行) 374 Point p_ab = l.getIntersection(t.L1); 375 Point p_ac = l.getIntersection(t.L3); 376 Point p_bc = l.getIntersection(t.L2); 377 378 379 //三交点是否位于边之内 380 boolean p_ab_in=false, p_ac_in =false, p_bc_in=false; 381 if(p_ab != null) p_ab_in = p_ab.inLineSegment(t.L1); 382 if(p_ac != null) p_ac_in = p_ac.inLineSegment(t.L3); 383 if(p_bc != null) p_bc_in = p_bc.inLineSegment(t.L2); 384 385 386 //任一角在直线之上(特判三角形的角) 387 if(t.p1.inLine(l)){ 388 //与另一条边无交点或者交点在边之外 389 if(p_bc == null || !p_bc.inLineSegment_close(t.L2)){ 390 System.out.println("1"); 391 } 392 else pr_ans(t,t.p1,t.p2,p_bc); 393 return; 394 } 395 if(t.p2.inLine(l)){ 396 if(p_ac == null || !p_ac.inLineSegment_close(t.L3)){ 397 System.out.println("1"); 398 } 399 else pr_ans(t,t.p1,t.p2,p_ac); 400 return; 401 } 402 if(t.p3.inLine(l)){ 403 if(p_ab == null || !p_ab.inLineSegment_close(t.L1)){ 404 System.out.println("1"); 405 } 406 else pr_ans(t,t.p1,t.p3,p_ab); 407 return; 408 } 409 410 //两个交点 411 if(p_ab_in && p_bc_in){ pr_ans(t,t.p2,p_ab,p_bc);return;} 412 if(p_ab_in && p_ac_in){ pr_ans(t,t.p1,p_ab,p_ac);return;} 413 if(p_bc_in && p_ac_in){ pr_ans(t,t.p3,p_bc,p_ac);return;} 414 //无交点 415 System.out.println("0"); 416 417 } 418 419 //四边形交点情况 420 public static void solve(Line l,Quadrilateral q){ 421 //与任意一条边重合 422 if(l.isSameTo(q.l1)||l.isSameTo(q.l2)||l.isSameTo(q.l3)||l.isSameTo(q.l4)){ 423 System.out.println("The line is coincide with one of the lines"); 424 return; 425 } 426 //与四条边的交点,可能为null; 427 Point pt0 = l.getIntersection(q.l1); 428 Point pt1 = l.getIntersection(q.l2); 429 Point pt2 = l.getIntersection(q.l3); 430 Point pt3 = l.getIntersection(q.l4); 431 432 //判断交点是否在边之上 433 boolean p0_in = false,p1_in = false,p2_in = false,p3_in = false; 434 if(pt0 != null) p0_in = pt0.inLineSegment(q.l1); 435 if(pt1 != null) p1_in = pt1.inLineSegment(q.l2); 436 if(pt2 != null) p2_in = pt2.inLineSegment(q.l3); 437 if(pt3 != null) p3_in = pt3.inLineSegment(q.l4); 438 439 //任一角在直线l之上 440 if(q.p1.inLine(l)){ 441 //它的对角也在边之上 442 if(q.p3.inLine(l)){ 443 pr_ans(q,q.p1,q.p2,q.p3); 444 } 445 //对角的邻边任一与直线有交点 446 else if (p2_in){ //邻边之一 447 pr_ans(q,q.p1,pt2,q.p4); 448 } 449 else if (p1_in){ //邻边之二 450 pr_ans(q,q.p1,pt1,q.p2); 451 } 452 else{ 453 System.out.println("1"); 454 } 455 return; 456 } 457 else if(q.p2.inLine(l)){ 458 //它的对角也在边之上 459 if(q.p4.inLine(l)){ 460 pr_ans(q,q.p2,q.p3,q.p4); 461 } 462 //对角的邻边任一与直线有交点 463 else if (p2_in){ //邻边之一 464 pr_ans(q,q.p2,pt2,q.p3); 465 } 466 else if (p3_in){ //邻边之二 467 pr_ans(q,q.p2,pt3,q.p1); 468 } 469 else{ 470 System.out.println("1"); 471 } 472 return; 473 } 474 else if (q.p3.inLine(l)) { 475 //它的对角也在边之上 476 if(q.p1.inLine(l)){ 477 pr_ans(q,q.p3,q.p4,q.p1); 478 } 479 //对角的邻边任一与直线有交点 480 else if (p3_in){ //邻边之一 481 pr_ans(q,q.p3,pt3,q.p4); 482 } 483 else if (p0_in){ //邻边之二 484 pr_ans(q,q.p3,pt0,q.p2); 485 } 486 else{ 487 System.out.println("1"); 488 } 489 return; 490 } 491 else if (q.p4.inLine(l)) { 492 //它的对角也在边之上 493 if(q.p2.inLine(l)){ 494 pr_ans(q,q.p4,q.p1,q.p2); 495 } 496 //对角的邻边任一与直线有交点 497 else if (p0_in){ //邻边之一 498 pr_ans(q,q.p4,pt0,q.p1); 499 } 500 else if (p1_in){ //邻边之二 501 pr_ans(q,q.p4,pt1,q.p3); 502 } 503 else{ 504 System.out.println("1"); 505 } 506 return; 507 } 508 509 //两个交点(邻边) 510 if(p0_in && p1_in){pr_ans(q,pt0,pt1,q.p2);return;} 511 if(p1_in && p2_in){pr_ans(q,pt1,pt2,q.p3);return;} 512 if(p2_in && p3_in){pr_ans(q,pt2,pt3,q.p4);return;} 513 if(p3_in && p0_in){pr_ans(q,pt3,pt0,q.p1);return;} 514 //对边 515 if(p0_in && p2_in){ 516 double[] ans = new double[2]; 517 ans[0] = Trianges.area(q.p1,pt0,pt2) + Trianges.area(pt0,pt2,q.p4); 518 ans[1] = Trianges.area(q.p2,pt0,pt2) + Trianges.area(pt0,pt2,q.p3); 519 Arrays.sort(ans); 520 System.out.printf("2 "); 521 change(ans[0]); 522 System.out.print(" "); 523 change(ans[1]); 524 return; 525 } 526 if(p1_in && p3_in){ 527 double[] ans = new double[2]; 528 ans[0] = Trianges.area(q.p2,pt1,pt3) + Trianges.area(pt1,pt3,q.p1); 529 ans[1] = Trianges.area(q.p3,pt1,pt3) + Trianges.area(pt1,pt3,q.p4); 530 Arrays.sort(ans); 531 System.out.printf("2 "); 532 change(ans[0]); 533 System.out.print(" "); 534 change(ans[1]); 535 return; 536 } 537 //0交点 538 System.out.println("0"); 539 540 } 541 542 543 544 } 545 class Point{ 546 double x; 547 double y; 548 public Point(){ 549 this.x = 0; 550 this.y = 0; 551 } 552 public Point(double x,double y){ 553 this.x=x; 554 this.y=y; 555 } 556 //斜率是否存在 557 public boolean vertical(Point b){ 558 if((this.x==b.x)&&(this.y!=b.y)) 559 return true;//不存在 560 else 561 return false; 562 } 563 //两点的斜率 564 public double getSlope(Point b){ 565 return (this.y-b.y)/(this.x-b.x); 566 } 567 //两点坐标相同 568 public boolean isSameTo(Point a){ 569 return (this.x == a.x)&&(this.y == a.y); 570 } 571 //计算两点距离 572 public double getDistance(Point b){ 573 return Math.sqrt(Math.pow(b.x-this.x,2)+Math.pow(b.y-this.y,2)); 574 } 575 //判断是否在直线之上 576 public boolean inLine(Line l){ 577 return Math.abs(l.A*this.x + l.B*this.y + l.C) < 0.000001; 578 } 579 //判断是否在线段之内(包括端点) 580 public boolean inLineSegment_close(Line l){ 581 if(!this.inLine(l)) 582 return false; 583 else{ 584 double res = this.getDistance(l.a) + this.getDistance(l.b)-l.GetLength(); 585 return Math.abs(res) < 0.000001; 586 } 587 } 588 //判断是否在线段之内(不包括端点) 589 public boolean inLineSegment(Line l){ 590 return this.inLineSegment_close(l) && 591 (!this.isSameTo(l.a)) && 592 (!this.isSameTo(l.b)); 593 } 594 } 595 class Line{ 596 Point a; 597 Point b; 598 double A,B,C; 599 public Line(Point m,Point n){ 600 this.a=m; 601 this.b=n; 602 603 this.A = this.b.y-this.a.y; 604 this.B = this.a.x-this.b.x; 605 // this.C = this.b.x*this.a.y-this.a.x*this.b.y; 606 this.C = (-this.A*this.a.x-this.B*this.a.y); 607 608 609 } 610 611 //斜率是否存在 612 public boolean vertical(){ 613 614 return (this.a.x != this.b.x) || (this.a.y == this.b.y); 615 } 616 617 //线的斜率 618 public double getSlope(){ 619 return (this.a.y-this.b.y)/(this.a.x-this.b.x); 620 } 621 //判断两直线是否平行 622 public boolean isParallelTo(Line l){ 623 if(this.B==0 || l.B==0){ 624 return (this.B == 0 && l.B == 0); 625 } 626 return ((this.A / this.B) == (l.A / l.B)); 627 } 628 //判断两直线是否重合 629 public boolean isSameTo(Line another){ 630 return this.isParallelTo(another) && (this.C==another.C); 631 } 632 //判断两直线是否垂直 633 public boolean isVerticalTo(Line another){ 634 return this.A * another.A + this.B * another.B == 0; 635 } 636 //点到直线的距离 637 public double distance(Point a){ 638 return Math.abs((this.a.y-this.b.y)*a.x+(this.b.x-this.a.x)*a.y+this.a.x*this.b.y-this.a.y*this.b.x)/Math.sqrt((this.a.y-this.b.y)*(this.a.y-this.b.y)+(this.a.x-this.b.x)*(this.a.x-this.b.x)); 639 } 640 //判断三点是否一线 641 boolean threeline(Point c) { 642 return this.distance(c) == 0; 643 } 644 645 //线段长度 646 public double GetLength(){ 647 return Math.sqrt(Math.pow(this.b.x-this.a.x,2)+Math.pow(this.b.y-this.a.y,2)); 648 } 649 //判断两线长度是否相等 650 public boolean isEqulength(Line l){ 651 if(this.GetLength()==l.GetLength()) 652 return true; 653 else 654 return false; 655 } 656 //求两条直线交点 657 public Point getIntersection(Line another){ 658 if(this.isParallelTo(another)) return null; 659 Point res = new Point(); 660 res.y = (another.A*this.C-this.A*another.C) / (this.A*another.B-another.A*this.B); 661 res.x = (this.B*another.C-another.B*this.C) / (this.A*another.B-another.A*this.B); 662 return res; 663 } 664 665 666 } 667 class Trianges 668 { 669 Point p1,p2,p3; 670 Line L1,L2,L3; 671 double J1,J2,J3; 672 public Trianges(Point point1,Point point2,Point point3)throws Exception 673 { 674 try{ 675 this.p1 = point1; 676 this.p2 = point2; 677 this.p3 = point3; 678 this.L1 = new Line(point1,point2); 679 this.L2 = new Line(point2,point3); 680 this.L3 = new Line(point1,point3); 681 if(this.L1.isParallelTo(this.L2)){ 682 throw new Exception("not a triangle"); 683 } 684 }catch(Exception e){ 685 throw e; 686 } 687 } 688 //是否等边三角形,返回(true/false) 689 public boolean isDengbian() 690 { 691 return (this.L1.GetLength() == this.L2.GetLength()&&this.L2.GetLength() == this.L3.GetLength()); 692 } 693 //是否等腰三角形,返回(true/false) 694 public boolean isDengyao() 695 { 696 return (this.L1.GetLength() == this.L2.GetLength()||this.L2.GetLength() == this.L3.GetLength()||this.L1.GetLength() == this.L3.GetLength()); 697 } 698 //计算三角形周长,返回三角形周长(double) 699 public double getGirth() 700 { 701 return (this.L1.GetLength()+this.L2.GetLength()+this.L3.GetLength()); 702 } 703 //计算三角形面积,返回三角形面积(double) 704 public double getArea() 705 { 706 return (this.L1.GetLength()*this.L1.distance(this.p3))/2; 707 } 708 //求三个点围成的图形面积(三点可能共线,面积为0) 709 public static double area(Point a,Point b,Point c){ 710 double l1 = a.getDistance(b); 711 double l2 = b.getDistance(c); 712 double l3 = a.getDistance(c); 713 double p = (l1+l2+l3)/2; 714 return Math.sqrt(p*(p-l1)*(p-l2)*(p-l3)); 715 } 716 //求三角形的重心,返回重心点(Points) 717 public Point getCenter() 718 { 719 Point Z = new Point((this.p1.x+this.p2.x+this.p3.x)/3,(this.p1.y+this.p2.y+this.p3.y)/3); 720 return Z; 721 } 722 //是否是钝角三角形,,返回(true/false) 723 public boolean isDunjiao() 724 { 725 double l12 = this.L1.GetLength()*this.L1.GetLength(); 726 double l22 = this.L2.GetLength()*this.L2.GetLength(); 727 double l32 = this.L3.GetLength()*this.L3.GetLength(); 728 return ((l12+l22-l32+1e-6<0)||(l12+l32-l22+1e-6<0)||(l22+l32-l12+1e-6<0)); 729 } 730 //是否是直角三角形,返回(true/false) 731 public boolean isZhijiao() 732 { 733 return (Math.abs(J1-90)<=1e-6||Math.abs(J2-90)<=1e-6||Math.abs(J3-90)<=1e-6); 734 } 735 //是否是锐角三角形,返回(true/false) 736 public boolean isRuijiao() 737 { 738 return (!(this.isDunjiao()||this.isZhijiao())); 739 } 740 //线是否与三角形的其中一条边重合 741 public boolean LineEquTriangesLine(Line l) 742 { 743 return ((L1.distance(l.a)==0&&L1.distance(l.b)==0)||(L2.distance(l.a)==0)&&L2.distance(l.b)==0||(L3.distance(l.a)==0&&L3.distance(l.b)==0)); 744 } 745 746 // 判断某点是否在三角形之内,(0内,1边,2外); 747 //面积法 748 public int isContainPoint(Point p){ 749 //特判在边上的情况 750 if(p.inLineSegment_close(this.L1) || p.inLineSegment_close(this.L2) 751 || p.inLineSegment_close(this.L3)){ 752 return 1; 753 } 754 double a1 = Trianges.area(p,this.p1,this.p2); 755 double a2 = Trianges.area(p,this.p2,this.p3); 756 double a3 = Trianges.area(p,this.p3,this.p1); 757 double res = a1+a2+a3 - this.getArea(); 758 if(Math.abs(res) < 0.000001) 759 return 0; 760 return 2; 761 } 762 763 } 764 class Quadrilateral{ 765 Point p1,p2,p3,p4; 766 Line l1,l2,l3,l4,diagonaL1,diagonaL2; 767 public Quadrilateral(Point a,Point b,Point c,Point d)throws Exception{ 768 try{ 769 this.p1 = a; 770 this.p2 = b; 771 this.p3 = c; 772 this.p4 = d; 773 this.l1 = new Line(a,b); 774 this.l2 = new Line(b,c); 775 this.l3 = new Line(c,d); 776 this.l4 = new Line(d,a); 777 diagonaL1 = new Line(this.p1,this.p3); 778 diagonaL2 = new Line(this.p2,this.p4); 779 if(this.l1.isParallelTo(this.l2) || this.l1.isParallelTo(this.l4)){ 780 throw new Exception("not a quadrilateral"); 781 } 782 if(this.l3.isParallelTo(this.l2) || this.l3.isParallelTo(this.l4)){ 783 throw new Exception("not a quadrilateral"); 784 } 785 Point P1 = this.l1.getIntersection(this.l3); 786 Point P2 = this.l2.getIntersection(this.l4); 787 if(P1 != null && P1.inLineSegment_close(this.l1) && P1.inLineSegment_close(this.l3)) throw new Exception("not a quadrilateral"); 788 if(P2 != null && P2.inLineSegment_close(this.l2) && P2.inLineSegment_close(this.l4)) throw new Exception("not a quadrilateral"); 789 }catch (Exception e){ 790 throw e; 791 } 792 } 793 //判断是否是四边形 794 public boolean isQuadrilateral1(){ 795 if((this.l1.isParallelTo(this.l2))||(this.l2.isParallelTo(this.l3))) 796 return false; 797 else if((this.l3.isParallelTo(this.l4))||(this.l4.isParallelTo(this.l1))) 798 return false; 799 else 800 return true; 801 } 802 public boolean isQuadrilateral2(){ 803 Point P1 = this.l1.getIntersection(this.l3); 804 Point P2 = this.l2.getIntersection(this.l4); 805 if(P1 != null && P1.inLineSegment_close(this.l1) && P1.inLineSegment_close(this.l3)) 806 return false; 807 else if(P2 != null && P2.inLineSegment_close(this.l2) && P2.inLineSegment_close(this.l4)) 808 return false; 809 else 810 return true; 811 } 812 813 //判断是否是平行四边形 814 public boolean isParallelQuadrilateral(){ 815 if((this.l1.isParallelTo(this.l3))&&(this.l2.isParallelTo(this.l4))) 816 return true; 817 else 818 return false; 819 } 820 //判断是否为菱形(平行四边形 + 四边长度相等) 821 public boolean isDiamond(){ 822 boolean H = this.l1.GetLength() == this.l2.GetLength()&& 823 this.l2.GetLength() == this.l3.GetLength()&& 824 this.l3.GetLength() == this.l4.GetLength(); 825 return this.isParallelQuadrilateral() && H; 826 } 827 //判断是否是矩形 828 public boolean isRectangle(){ 829 if(this.diagonaL1.isEqulength(this.diagonaL2)) 830 return true; 831 else 832 return false; 833 } 834 //判断是否为正方形(菱形 + 矩形) 835 public boolean isSquare(){ 836 return this.isDiamond() && this.isRectangle(); 837 } 838 //判断四个点是否有重合 839 public boolean isCoincide(){ 840 if((this.p1.x==this.p2.x)&&(this.p1.y==this.p2.y)) 841 return true; 842 else if((this.p1.x==this.p3.x)&&(this.p1.y==this.p3.y)) 843 return true; 844 else if((this.p1.x==this.p4.x)&&(this.p1.y==this.p4.y)) 845 return true; 846 else if((this.p2.x==this.p3.x)&&(this.p2.y==this.p3.y)) 847 return true; 848 else if((this.p2.x==this.p4.x)&&(this.p2.y==this.p4.y)) 849 return true; 850 else if((this.p3.x==this.p4.x)&&(this.p3.y==this.p4.y)) 851 return true; 852 else 853 return false; 854 } 855 //判断是否为凸四边形(面积公式) 856 public boolean isConvexQuadrilateral(){ 857 double s1 = Trianges.area(p1,p2,p3); 858 double s2 = Trianges.area(p1,p3,p4); 859 double s3 = Trianges.area(p2,p4,p3); 860 double s4 = Trianges.area(p2,p4,p1); 861 double res = s1+s2-s3-s4; 862 return Math.abs(res) < 0.000001; 863 } 864 //四边形周长 865 public double sideLength(){ 866 return this.l1.GetLength() + this.l2.GetLength() +this.l3.GetLength() +this.l4.GetLength(); 867 } 868 869 //四边形面积(切分为两个三角形) 870 public double area(){ 871 double s1 = Trianges.area(this.p1, this.p2, this.p3); 872 double s2 = Trianges.area(this.p1, this.p3, this.p4); 873 874 875 double s3 = Trianges.area(this.p2, this.p4, this.p1); 876 double s4 = Trianges.area(this.p2, this.p4, this.p3); 877 878 879 return Math.min(s1+s2, s3+s4); 880 } 881 882 //判断一个点是否落在(凸)四边形内部(0内,1边,2外)面积法 883 public int isContainPoint(Point p){ 884 if(p.inLineSegment_close(this.l1) || p.inLineSegment_close(this.l2)) 885 return 1; 886 else if(p.inLineSegment_close(this.l3) || p.inLineSegment_close(this.l4)) 887 return 1; 888 else{ 889 double s1 = Trianges.area(p,this.p1,this.p2); 890 double s2 = Trianges.area(p,this.p2,this.p3); 891 double s3 = Trianges.area(p,this.p3,this.p4); 892 double s4 = Trianges.area(p,this.p4,this.p1); 893 double res = s1+s2+s3+s4-this.area(); 894 if(Math.abs(res) < 0.000001) 895 return 0; 896 return 2; 897 } 898 } 899 900 901 }
圈复杂度分析图:
由上图可知:Max complexity(最大复杂度)过大,原因是某个函数(最复杂的函数)设计中if-else语句用的太多。还有Avg Depth过大,说明我的函数中分支嵌套的层数过多,导致平均其值过大。
踩坑心得:
(1)注意异常四边形、凹四边形和凸四边形。异常四边形:不相邻的两条边交叉(不算四边形哦,判断是否为四边形时候记得不要漏掉此情况)。凹凸四边形大家都认识,我就不说了,懂得都懂。
(2)判断凹凸四边形建议用面积法,就是用对角线分割成两个三角形求面积和,看两条对角线分割后求的四边形面积是否相等。相等为凸四边形,否则为凹四边形。
(3)判断输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形的内部。建议这里使用面积法。假设为m点,判断m分别与四边形的每条边组成的三角形面积之和是否等于该四边形。相等即在内部,否则在外部。前提是判断m点不在四边形上。
改进建议:
把那些if-else判断语句还是写成一个函数吧,太复杂了,减少圈复杂度。
第五次大作业:
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入五个点坐标,判断是否是五边形,判断结果输出true/false。
2:输入五个点坐标,判断是凹五边形(false)还是凸五边形(true),如果是凸五边形,则再输出五边形周长、面积,结果之间以一个英文空格符分隔。 若五个点坐标无法构成五边形,输出"not a pentagon"
3:输入七个点坐标,前两个点构成一条直线,后五个点构成一个凸五边形、凸四边形或凸三角形,输出直线与五边形、四边形或三角形相交的交点数量。如果交点有两个,再按面积从小到大输出被直线分割成两部分的面积(不换行)。若直线与多边形形的一条边线重合,输出"The line is coincide with one of the lines"。若后五个点不符合五边形输入,若前两点重合,输出"points coincide"。
以上3选项中,若输入的点无法构成多边形,则输出"not a polygon"。输入的五个点坐标可能存在冗余,假设多边形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
1)符合要求的输入:顶点重复或者z与xy都相邻,如:x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
2) 不符合要求的输入:z不与xy都相邻,如:z x y s、x z s y、x s z y
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
输入样例1:
选项1,点重合。例如:
1:-1,-1 1,2 -1,1 1,0
输出样例:
在这里给出相应的输出。例如:
wrong number of points
之前的就不再重复写,主要贴出五边形的类和判断五边形的交点情况。
设计与分析:
这里我就不给全部代码了,太冗长了
五边形的类:

1 class Pentagon{ 2 public Point[] p; 3 public Point p1,p2,p3,p4,p5; 4 public Line[] l; 5 public Line l1,l2,l3,l4,l5; 6 7 public String message = "init"; 8 public Pentagon ( Point p1,Point p2,Point p3,Point p4,Point p5){ 9 this.p = new Point[5]; 10 this.l = new Line[5]; 11 this.p[0] = p1; 12 this.p[1] = p2; 13 this.p[2] = p3; 14 this.p[3] = p4; 15 this.p[4] = p5; 16 this.l[0] = new Line(p1,p2); 17 this.l[1] = new Line(p2,p3); 18 this.l[2] = new Line(p3,p4); 19 this.l[3] = new Line(p4,p5); 20 this.l[4] = new Line(p5,p1); 21 this.p1 = p1; 22 this.p2 = p2; 23 this.p3 = p3; 24 this.p4 = p4; 25 this.p5 = p5; 26 this.l1 = new Line(p1,p2); 27 this.l2 = new Line(p2,p3); 28 this.l3 = new Line(p3,p4); 29 this.l4 = new Line(p4,p5); 30 this.l5 = new Line(p5,p1); 31 32 } 33 34 public boolean isxj(){ 35 Point P1 = this.l[0].getIntersection(this.l[2]); 36 Point P2 = this.l[0].getIntersection(this.l[3]); 37 Point P3 = this.l[1].getIntersection(this.l[3]); 38 Point P4 = this.l[1].getIntersection(this.l[4]); 39 Point P5 = this.l[2].getIntersection(this.l[4]); 40 if(P1 != null && P1.inLineSegment_close(this.l[0]) && P1.inLineSegment_close(this.l[2])) 41 return true; 42 else if(P2 != null && P2.inLineSegment_close(this.l[0]) && P2.inLineSegment_close(this.l[3])) 43 return true; 44 else if(P3 != null && P3.inLineSegment_close(this.l[1]) && P3.inLineSegment_close(this.l[3])) 45 return true; 46 else if(P4 != null && P4.inLineSegment_close(this.l[1]) && P1.inLineSegment_close(this.l[4])) 47 return true; 48 else if(P5 != null && P5.inLineSegment_close(this.l[2]) && P1.inLineSegment_close(this.l[4])) 49 return true; 50 else 51 return false; 52 } 53 public boolean isThree(){ 54 if(this.l[0].isParallelTo(this.l[1]) || this.l[1].isParallelTo(this.l[2])){ 55 return true; 56 } 57 else if(this.l[2].isParallelTo(this.l[3]) || this.l[3].isParallelTo(this.l[4])){ 58 return true; 59 } 60 else if(this.l[4].isParallelTo(this.l[0])){ 61 return true; 62 } 63 else 64 return false; 65 } 66 public boolean isCoincide(){ 67 if((this.p[0].x==this.p[1].x)&&(this.p[0].y==this.p[1].y)) 68 return true; 69 else if((this.p[0].x==this.p[2].x)&&(this.p[0].y==this.p[2].y)) 70 return true; 71 else if((this.p[0].x==this.p[3].x)&&(this.p[0].y==this.p[3].y)) 72 return true; 73 else if((this.p[0].x==this.p[4].x)&&(this.p[0].y==this.p[4].y)) 74 return true; 75 else if((this.p[1].x==this.p[2].x)&&(this.p[1].y==this.p[2].y)) 76 return true; 77 else if((this.p[1].x==this.p[3].x)&&(this.p[1].y==this.p[3].y)) 78 return true; 79 else if((this.p[1].x==this.p[4].x)&&(this.p[1].y==this.p[4].y)) 80 return true; 81 else if((this.p[2].x==this.p[3].x)&&(this.p[2].y==this.p[3].y)) 82 return true; 83 else if((this.p[2].x==this.p[4].x)&&(this.p[2].y==this.p[4].y)) 84 return true; 85 else if((this.p[3].x==this.p[4].x)&&(this.p[3].y==this.p[4].y)) 86 return true; 87 else 88 return false; 89 } 90 91 public boolean isPentagon(){ 92 if(this.isCoincide()){ 93 return false; 94 }else{ 95 if(this.isThree()){ 96 return false; 97 }else{ 98 if(this.isxj()){ 99 return false; 100 }else{ 101 return true; 102 } 103 } 104 105 } 106 107 } 108 //判断是凹五边形还是凸五边形 109 public boolean checkConvex(){ 110 int flag=0; 111 for(int i=0;i<4;){ 112 if(l[i].Chacheng(l[i+1])>0){ 113 i++; 114 flag++; 115 }else 116 flag=0; 117 } 118 if(l[4].Chacheng(l[1])>0) 119 flag++; 120 else 121 flag=0; 122 if(flag==0) 123 return false; 124 else 125 return true; 126 } 127 //判断是否为凸五边形(面积公式) 128 public boolean isConvexQuadrilateral(){ 129 double s1 = Trianges.area(this.p[0], this.p[1], this.p[2]); 130 double s2 = Trianges.area(this.p[0], this.p[2], this.p[3]); 131 double s3 = Trianges.area(this.p[0], this.p[3], this.p[4]); 132 double s4 = Trianges.area(this.p[1], this.p[2], this.p[3]); 133 double s5 = Trianges.area(this.p[1], this.p[3], this.p[4]); 134 double s6 = Trianges.area(this.p[1], this.p[0], this.p[4]); 135 double res = s1+s2+s3-(s4+s5+s6); 136 return Math.abs(res) < 0.000001; 137 } 138 //五边形面积 139 public double area(){ 140 double s1 = Trianges.area(this.p[0], this.p[1], this.p[2]); 141 double s2 = Trianges.area(this.p[0], this.p[2], this.p[3]); 142 double s3 = Trianges.area(this.p[0], this.p[3], this.p[4]); 143 return s1+s2+s3; 144 } 145 //五边形周长 146 public double sideLength(){ 147 return this.l[0].GetLength() + this.l[1].GetLength() +this.l[2].GetLength() +this.l[3].GetLength()+this.l[4].GetLength(); 148 } 149 150 151 }
判断五边形的交点情况的方法:

//五边形交点情况 public static void solve(Line l,Pentagon q){ //与任意一条边重合 if(l.isSameTo(q.l1)||l.isSameTo(q.l2)||l.isSameTo(q.l3)||l.isSameTo(q.l4)||l.isSameTo(q.l5)){ System.out.println("The line is coincide with one of the lines"); return; } //与五条边的交点,可能为null; Point pt0 = l.getIntersection(q.l1); Point pt1 = l.getIntersection(q.l2); Point pt2 = l.getIntersection(q.l3); Point pt3 = l.getIntersection(q.l4); Point pt4 = l.getIntersection(q.l5); //判断交点是否在边之上 boolean p0_in = false,p1_in = false,p2_in = false,p3_in = false,p4_in = false; if(pt0 != null) p0_in = pt0.inLineSegment(q.l1); if(pt1 != null) p1_in = pt1.inLineSegment(q.l2); if(pt2 != null) p2_in = pt2.inLineSegment(q.l3); if(pt3 != null) p3_in = pt3.inLineSegment(q.l4); if(pt4 != null) p4_in = pt4.inLineSegment(q.l5); //任一角在直线l之上 if(q.p1.inLine(l)){ //它的不相邻对角也在边之上 if(q.p3.inLine(l)){ pr_ans(q,q.p1,q.p2,q.p3); } //它的另不相邻对角也在边之上 else if(q.p4.inLine(l)){ pr_ans(q,q.p1,q.p4,q.p5); } //对角的邻边任一与直线有交点 else if (p3_in){ //邻边之一 pr_ans(q,q.p1,pt3,q.p5); } else if (p1_in){ //邻边之二 pr_ans(q,q.p1,pt1,q.p2); } else if (p2_in){ //对边 double[] ans = new double[2]; ans[0]=Trianges.area(q.p1,q.p2,q.p3)+Trianges.area(q.p1,pt2,q.p3); ans[1] = q.area() - ans[0]; Arrays.sort(ans); System.out.printf("2 "); change(ans[0]); System.out.print(" "); change(ans[1]); // pr_ans(q,q.p1,pt2,q.p3); // pr_ans(q,q.p1,q.p3,q.p2); } else{ System.out.println("1"); } return; } else if(q.p2.inLine(l)){ //它的对角也在边之上 if(q.p4.inLine(l)){ pr_ans(q,q.p2,q.p3,q.p4); } //它的另一不相邻对角也在边之上 else if(q.p5.inLine(l)){ pr_ans(q,q.p2,q.p4,q.p5); } //对角的邻边任一与直线有交点 else if (p2_in){ //邻边之一 pr_ans(q,q.p2,pt2,q.p3); } else if (p4_in){ //邻边之二 pr_ans(q,q.p2,pt4,q.p1); } else if (p3_in){ //对边 double[] ans = new double[2]; ans[0]=Trianges.area(q.p2,q.p3,q.p4)+Trianges.area(q.p2,pt3,q.p4); ans[1] = q.area() - ans[0]; Arrays.sort(ans); System.out.printf("2 "); change(ans[0]); System.out.print(" "); change(ans[1]); } else{ System.out.println("1"); } return; } else if (q.p3.inLine(l)) { //它的对角也在边之上 if(q.p1.inLine(l)){ pr_ans(q,q.p3,q.p2,q.p1); } //它的另一不相邻对角也在边之上 else if(q.p5.inLine(l)){ pr_ans(q,q.p3,q.p4,q.p5); } //对角的邻边任一与直线有交点 else if (p3_in){ //邻边之一 pr_ans(q,q.p3,pt3,q.p4); } else if (p0_in){ //邻边之二 pr_ans(q,q.p3,pt0,q.p2); } else if (p4_in){ //对边 double[] ans = new double[2]; ans[0]=Trianges.area(q.p3,q.p4,q.p5)+Trianges.area(q.p3,pt4,q.p5); ans[1] = q.area() - ans[0]; Arrays.sort(ans); System.out.printf("2 "); change(ans[0]); System.out.print(" "); change(ans[1]); } else{ System.out.println("1"); } return; } else if (q.p4.inLine(l)) { //它的对角也在边之上 if(q.p2.inLine(l)){ pr_ans(q,q.p4,q.p3,q.p2); } //它的另一不相邻对角也在边之上 else if(q.p1.inLine(l)){ pr_ans(q,q.p4,q.p5,q.p1); } //对角的邻边任一与直线有交点 else if (p4_in){ //邻边之一 pr_ans(q,q.p4,pt4,q.p5); } else if (p1_in){ //邻边之二 pr_ans(q,q.p4,pt1,q.p3); } else if (p0_in){ //对边 double[] ans = new double[2]; ans[0]=Trianges.area(q.p4,q.p5,q.p1)+Trianges.area(q.p4,pt0,q.p1); ans[1] = q.area() - ans[0]; Arrays.sort(ans); System.out.printf("2 "); change(ans[0]); System.out.print(" "); change(ans[1]); } else{ System.out.println("1"); } return; } else if (q.p5.inLine(l)) { //它的对角也在边之上 if(q.p3.inLine(l)){ pr_ans(q,q.p5,q.p4,q.p3); } //它的另一不相邻对角也在边之上 else if(q.p2.inLine(l)){ pr_ans(q,q.p5,q.p1,q.p2); } //对角的邻边任一与直线有交点 else if (p0_in){ //邻边之一 pr_ans(q,q.p5,pt0,q.p1); } else if (p2_in){ //邻边之二 pr_ans(q,q.p5,pt2,q.p4); } else if (p1_in){ //对边 double[] ans = new double[2]; ans[0]=Trianges.area(q.p5,q.p1,q.p2)+Trianges.area(q.p5,pt1,q.p2); ans[1] = q.area() - ans[0]; Arrays.sort(ans); System.out.printf("2 "); change(ans[0]); System.out.print(" "); change(ans[1]); } else{ System.out.println("1"); } return; } //两个交点(邻边) if(p0_in && p1_in){pr_ans(q,pt0,pt1,q.p2);return;} if(p1_in && p2_in){pr_ans(q,pt1,pt2,q.p3);return;} if(p2_in && p3_in){pr_ans(q,pt2,pt3,q.p4);return;} if(p3_in && p4_in){pr_ans(q,pt3,pt4,q.p5);return;} if(p4_in && p0_in){pr_ans(q,pt4,pt0,q.p1);return;} //对边 if(p0_in && p2_in){ double[] ans = new double[2]; ans[0] = Trianges.area(q.p3,pt0,pt2) + Trianges.area(pt0,q.p2,q.p3); ans[1] = q.area() - ans[0]; Arrays.sort(ans); System.out.printf("2 "); change(ans[0]); System.out.print(" "); change(ans[1]); return; } if(p0_in && p3_in){ double[] ans = new double[2]; ans[0] = Trianges.area(q.p5,pt0,pt3) + Trianges.area(pt0,q.p1,q.p5); ans[1] = q.area() - ans[0]; Arrays.sort(ans); System.out.printf("2 "); change(ans[0]); System.out.print(" "); change(ans[1]); return; } if(p1_in && p3_in){ double[] ans = new double[2]; ans[0] = Trianges.area(q.p4,pt1,pt3) + Trianges.area(pt1,q.p3,q.p4); ans[1] = q.area() - ans[0]; Arrays.sort(ans); System.out.printf("2 "); change(ans[0]); System.out.print(" "); change(ans[1]); return; } if(p1_in && p4_in){ double[] ans = new double[2]; ans[0] = Trianges.area(q.p1,pt1,pt4) + Trianges.area(pt1,q.p1,q.p2); ans[1] = q.area() - ans[0]; Arrays.sort(ans); System.out.printf("2 "); change(ans[0]); System.out.print(" "); change(ans[1]); return; } if(p2_in && p4_in){ double[] ans = new double[2]; ans[0] = Trianges.area(q.p5,pt2,pt4) + Trianges.area(pt2,q.p5,q.p4); ans[1] = q.area() - ans[0]; Arrays.sort(ans); System.out.printf("2 "); change(ans[0]); System.out.print(" "); change(ans[1]); return; } //0交点 System.out.println("0"); }
圈复杂度分析图:
由上图可知:Avg Depth过大,很大的原因是部分函数中if-else语句(分支嵌套层数)用的太多。而Avg Stmts/Method过大,说明我的函数有部分语句过多,导致平均每个函数包含的语句数过大。
踩坑心得:
这道题很难,我是菜狗,我没做出来,部分正确。判断凹凸四边形建议用面积法。
(1)注意异常五边形、凹四边形和凸四边形。非五边形的情况:异常五边形:不相邻的两条边交叉、三点共线、任意两点重合。
(2)判断凹凸五边形建议用面积法,就是选定任意两个顶点分别将五边形分割成三个三角形求面积和,看二者分割后求的五边形面积是否相等。相等为凸五边形,否则为凹五边形。
(3)判断输出第一个是否在后五个点所构成的四边形(限定为凸五边形,不考虑凹五边形)或三角形的内部。建议这里使用面积法。假设为m点,判断m分别与四边形的每条边组成的三角形面积之和是否等于该四边形。相等即在内部,否则在外部。前提是判断m点不在四边形上。
改进建议:
同上一题一样,把那些if-else判断语句还是写成一个函数吧,太复杂了,减少圈复杂度。
7-2 点线形系列5-凸五边形的计算-2
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
4:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),判断它们两个之间是否存在包含关系(一个多边形有一条或多条边与另一个多边形重合,其他部分都包含在另一个多边形内部,也算包含)。
两者存在六种关系:1、分离(完全无重合点) 2、连接(只有一个点或一条边重合) 3、完全重合 4、被包含(前一个多边形在后一个多边形的内部)5、交错 6、包含(后一个多边形在前一个多边形的内部)。
各种关系的输出格式如下:
1、no overlapping area between the previous triangle/quadrilateral/ pentagon and the following triangle/quadrilateral/ pentagon
2、the previous triangle/quadrilateral/ pentagon is connected to the following triangle/quadrilateral/ pentagon
3、the previous triangle/quadrilateral/ pentagon coincides with the following triangle/quadrilateral/ pentagon
4、the previous triangle/quadrilateral/ pentagon is inside the following triangle/quadrilateral/ pentagon
5、the previous triangle/quadrilateral/ pentagon is interlaced with the following triangle/quadrilateral/ pentagon
6、the previous triangle/quadrilateral/ pentagon contains the following triangle/quadrilateral/ pentagon
5:输入十个点坐标,前、后五个点分别构成一个凸多边形(三角形、四边形、五边形),输出两个多边形公共区域的面积。注:只考虑每个多边形被另一个多边形分割成最多两个部分的情况,不考虑一个多边形将另一个分割成超过两个区域的情况。
6:输入六个点坐标,输出第一个是否在后五个点所构成的多边形(限定为凸多边形,不考虑凹多边形),的内部(若是五边形输出in the pentagon/outof the pentagon,若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。输入入错存在冗余点要排除,冗余点的判定方法见选项5。如果点在多边形的某条边上,输出"on the triangle/on the quadrilateral/on the pentagon"。
以上4、5、6选项输入的五个点坐标可能存在冗余,假设多边形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
1)符合要求的输入:顶点重复或者z与xy都相邻,如:x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
2) 不符合要求的输入:z不与xy都相邻,如:z x y s、x z s y、x s z y
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
输入样例:
在这里给出一组输入。例如:
4:0,0 6,0 7,1 8,3 6,6 0,0 6,0 7,1 8,3 6,6
输出样例:
在这里给出相应的输出。例如:
the previous pentagon coincides with the following pentagon
设计与分析:
父类:Grahical类

1 class Graphical { 2 public int len=0,status=1; //多边形边数,状态 3 public Point[] points; 4 public Line[] lines; 5 public double sideLength = 0,area = 0; //边长,面积 6 public boolean isConvexGraphical = true; 7 public String message = "init"; //信息 8 9 public Graphical(Point[] points){ 10 this.points = new Point[points.length]; 11 12 points = this.removeMulti(points); //去除重复点 13 if(points.length <=2 ){ 14 this.status = -1; 15 this.message = "Not enough points"; 16 return; 17 } 18 19 //相邻边夹角0则去除中间点,夹角180则status:-1 20 for(int i=0;i<points.length;i++){ 21 int first = i , second = (i+1)%points.length, third = (i+2)%points.length; 22 try{ 23 Line l1 = new Line(points[first],points[second]); 24 Line l2 = new Line(points[second],points[third]); 25 if( Math.abs(l1.vectorAngle(l2) - Math.PI) < 0.000001 ){ //夹角180 26 this.status = -1; 27 this.message = "lines reverse coincidence"; 28 return; 29 } 30 else if(Math.abs(l1.vectorAngle(l2)) > 0.000001){ //夹角不为0 31 this.points[this.len++] = points[second].deepCopy(); 32 } 33 }catch (Exception e){} 34 } 35 36 this.points = Arrays.copyOf(this.points,this.len); 37 this.lines = new Line[this.len]; 38 39 //初始化边 40 for(int i=0;i<this.len;i++){ 41 try { 42 int first = i, second = (i+1)%this.len; 43 this.lines[i] = new Line(this.points[first], this.points[second]); 44 }catch (Exception e){} 45 } 46 47 //判断任意不相邻边(线段交点)是否有交点 48 checkEdge(); 49 50 Graphical.area(this); 51 Graphical.sideLength(this); 52 Graphical.checkConvex(this); 53 } 54 public void print(){ 55 if(this.status == -1){ 56 System.out.println(this.message); 57 return; 58 } 59 System.out.println("点数为:"+this.len); 60 for(int i=0;i<this.len;i++){ 61 this.points[i].print(); 62 } 63 for(int i=0;i<this.len;i++){ 64 this.lines[i].print(); 65 } 66 System.out.println("周长为:"+this.sideLength); 67 System.out.println("面积为:"+this.area); 68 System.out.println("凹凸性:"+this.isConvexGraphical); 69 } 70 //判断图形是否包含某个点返回值-1,0,1 (内部,边缘,外部) 71 //由于只考虑凸多边形,用面积法就行 72 public int isContainPoint(Point p){ 73 for(int i=0;i<this.len;i++){ //位于边之上 74 if(p.inLineSegment_close(this.lines[i])) return 0; 75 } 76 77 double s = 0; 78 for(int i=0;i<this.len;i++){ 79 s += Triangle.area(p,this.points[i], this.points[(i+1)%this.len]); 80 } 81 return Math.abs(s-this.area) < 0.000001 ? -1:1; 82 } 83 //判断两个图形类之间的关系() 84 public String relationshipWith(Graphical g){ 85 String[] name = new String[]{"triangle", "quadrilateral", "pentagon"}; 86 //分离 87 if(this.isSeparatedFrom(g)){ 88 return "no overlapping area between the previous "+name[this.len-3]+ " and the following "+name[g.len-3]; 89 } 90 //完全重合 91 if(this.isSameTo(g)) 92 return "the previous "+name[this.len-3]+ " coincides with the following "+name[g.len-3]; 93 //包含 94 if(this.isContainGra(g)){ 95 return "the previous "+name[this.len-3]+ " contains the following "+name[g.len-3]; 96 } 97 //被包含 98 if(g.isContainGra(this)){ 99 return "the previous "+name[this.len-3]+ " is inside the following "+name[g.len-3]; 100 } 101 102 //连接 103 if(this.overlappingArea(g) == 0){ 104 return "the previous "+name[this.len-3]+ " is connected to the following "+name[g.len-3]; 105 } 106 107 //交错 108 return "the previous "+name[this.len-3]+ " is interlaced with the following "+name[g.len-3]; 109 110 } 111 112 //判断和另一个图形完全分离(重叠面积为0,并且任意点都在this之外) 113 public boolean isSeparatedFrom(Graphical g){ 114 boolean ok = true; 115 int[] check2 = new int[g.len]; 116 for(int i=0;i<g.len;i++){ 117 check2[i] = this.isContainPoint(g.points[i]); 118 } 119 for(int item:check2){ 120 if(item != 1) ok = false; 121 } 122 if(this.overlappingArea(g) !=0) ok = false; 123 return ok; 124 } 125 //判断完全包含另一个图形(任意点都在this之内) 126 public boolean isContainGra(Graphical g){ 127 boolean ok = true; 128 int[] check2 = new int[g.len]; 129 for(int i=0;i<g.len;i++){ 130 check2[i] = this.isContainPoint(g.points[i]); 131 } 132 for(int item:check2){ 133 if(item == 1) ok = false; 134 } 135 return ok; 136 } 137 138 //判断两个图形是否一模一样(点完全重合) 139 public boolean isSameTo(Graphical g){ 140 if(this.len != g.len) return false; 141 for(int i=0;i<this.len;i++){ 142 boolean ok = false; 143 for(int j=0;j<g.len;j++){ 144 if(this.points[i].isSameTo(g.points[j])) ok = true; 145 } 146 if(!ok) return false; 147 } 148 return true; 149 } 150 151 //计算两个图形的重叠面积(交点加内部顶点构成重叠多边形) 152 public double overlappingArea(Graphical g){ 153 Point[] intersection = new Point[100]; 154 int intersection_len = 0; 155 156 157 for(Line item1:this.lines){ //求出两多边形的交点 158 for(Line item2: g.lines){ 159 Point tmp = item1.lsi(item2); 160 if(tmp != null){ 161 intersection[intersection_len++] = tmp.deepCopy(); 162 } 163 } 164 } 165 166 167 for(Point item:g.points){ //顶点包含在内部 168 if(this.isContainPoint(item) == -1) intersection[intersection_len++] = item.deepCopy(); 169 } 170 for(Point item:this.points){ //顶点包含在内部 171 if(g.isContainPoint(item) == -1) intersection[intersection_len++] = item.deepCopy(); 172 } 173 174 //if(intersection_len == 0) return 0; //交点为0,分离 175 //-2分 176 177 /*排序交点数组*/ 178 intersection = Arrays.copyOf(intersection,intersection_len); 179 intersection = this.removeMulti(intersection); 180 Point focus = Point.focusPoint(intersection); 181 Point sta = intersection[0].deepCopy(); 182 183 Arrays.sort(intersection,1,intersection.length, new Comparator<Point>() { 184 @Override 185 public int compare(Point o1, Point o2) { 186 try{ 187 Line origin =new Line(focus,sta); 188 Line l1 = new Line(focus,o1); 189 Line l2 = new Line(focus,o2); 190 double angle1 = origin.vectorAngle(l1); 191 double angle2 = origin.vectorAngle(l2); 192 if(origin.vectorCrossMul(l1) < 0) angle1 = 2*Math.PI - angle1; 193 if(origin.vectorCrossMul(l2) < 0) angle2 = 2*Math.PI - angle2; 194 if(angle1-angle2 > 0.000001) return 1; 195 if(Math.abs(angle1-angle2) < 0.000001) return 0; 196 return -1; 197 }catch (Exception reason){} 198 return 0; 199 } 200 }); 201 202 Graphical graphical = new Graphical(intersection); 203 return graphical.area; 204 205 } 206 207 //去除所有重复点 208 private Point[] removeMulti(Point[] points){ 209 Point[] tmp_points = new Point[points.length]; 210 int tmp_len = 0; 211 212 for(int i=0;i<points.length;i++){ 213 boolean ok = true; 214 for(int j=0;j<tmp_len;j++){ 215 if(points[i].isSameTo(tmp_points[j])){ 216 this.message = "points coincide"; 217 ok = false; 218 break; 219 } 220 } 221 if(ok) tmp_points[tmp_len++] = points[i].deepCopy(); 222 } 223 return Arrays.copyOf(tmp_points,tmp_len); 224 } 225 //判断不相邻边是否有交点 226 private void checkEdge(){ 227 for(int i=0;i<this.len;i++){ 228 for(int j=i+2;j<this.len;j++){ 229 if(i==0&&j==this.len-1) continue; 230 Point p = this.lines[i].getIntersection(this.lines[j]); 231 if(p==null) continue; 232 233 if(p.inLineSegment_close(this.lines[i]) && p.inLineSegment_close(this.lines[j])){ 234 this.status = -1; 235 this.message = "Non adjacent edges have intersections"; 236 return; 237 } 238 } 239 } 240 } 241 //多边形面积 242 private static void area(Graphical e){ 243 double res = 0; 244 Point origin = new Point(0,0); 245 for(int i=0;i<e.len;i++){ 246 try{ 247 Line l1 = new Line(origin,e.points[i]); 248 Line l2 = new Line(origin,e.points[(i+1)%e.len]); 249 res += 0.5 * l1.vectorCrossMul(l2); 250 }catch (Exception reason){} 251 252 } 253 e.area = Math.abs(res); 254 } 255 //多边形周长 256 private static void sideLength(Graphical e){ 257 double res = 0; 258 for(int i=0;i<e.len;i++){ 259 res += e.points[i].disToPoint(e.points[(i+1)%e.len]); 260 } 261 e.sideLength = res; 262 } 263 //多边形凹凸性 264 private static void checkConvex(Graphical e){ 265 if(e.len == 3) return; 266 int v = 0; 267 for(int i=0;i<e.len;i++){ 268 int first = i, second = (i+1)%e.len, thrid = (i+2)%e.len; 269 try{ 270 Line l1 = new Line(e.points[first], e.points[second]); 271 Line l2 = new Line(e.points[first], e.points[thrid]); 272 if(v==0){ 273 if(l1.vectorCrossMul(l2) > 0) v = 1; 274 else v = -1; 275 } 276 if(v == 1 && l1.vectorCrossMul(l2) < 0) e.isConvexGraphical = false; 277 if(v == -1 && l1.vectorCrossMul(l2) > 0) e.isConvexGraphical = false; 278 }catch (Exception reason){} 279 } 280 } 281 //是否一样 282 283 }
圈复杂度分析图:
由上图可知:Max complexity(最大复杂度)过大,原因是某个函数(最复杂的函数)设计中if-else语句用的太多。不用说,这几道题我都是if-else语句过多,真是头大,能力不够。
踩坑心得:
这道题很难,我是菜狗,我没做出来,部分正确。
(1)判断输出第一个是否在后五个点所构成的四边形(限定为凸五边形,不考虑凹五边形)或四边形或三角形的内部。判断是否在五边形内部建议这里使用面积法。假设为m点,判断m分别与五边形的每条边组成的三角形面积之和是否等于该五边形。相等即在内部,否则在外部。前提是判断m点不在五边形上。
改进建议:
没写完,速度太慢了,下次写快点。嵌套层次太多了,想办法改进吧。还是多用用类吧。
7-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:长度值
输入样例1:
在这里给出一组输入。例如:
5
9.4
12.3
84
Red
输出样例1:
在这里给出相应的输出。例如:
The line's color is:Red
The line's begin point's Coordinate is:
(5.00,9.40)
The line's end point's Coordinate is:
(12.30,84.00)
The line's length is:74.96
输入样例2:
在这里给出一组输入。例如:
80.2356
352.12
24.5
100
Black
输出样例2:
在这里给出相应的输出。例如:
Wrong Format
我的代码:

1 import java.util.*; 2 import java.text.DecimalFormat; 3 public class Main{ 4 //控制小数点 5 public static void main(String[] args){ 6 //Point p1=new Point(); 7 8 Scanner input=new Scanner(System.in); 9 double x1=input.nextDouble(); 10 double y1=input.nextDouble(); 11 double x2=input.nextDouble(); 12 double y2=input.nextDouble(); 13 String color=input.next(); 14 Point p1=new Point(x1,y1); 15 Point p2=new Point(x2,y2); 16 Line L=new Line(p1,p2,color); 17 if((x1<=0||x1>200)||(y1<=0||y1>200)||(x2<=0||x2>200)||(y2<=0||y2>200)){ 18 System.out.println("Wrong Format"); 19 return; 20 } 21 else{ 22 L.display(); 23 } 24 25 } 26 } 27 class Point{ 28 private double x; 29 private double y; 30 public Point(){ 31 this.x = 0; 32 this.y = 0; 33 } 34 public Point(double x,double y){ 35 this.x=x; 36 this.y=y; 37 } 38 public double getX(){ 39 return this.x; 40 } 41 public void setX(double x){ 42 this.x=x; 43 } 44 public double getY(){ 45 return this.y; 46 } 47 public void setY(double y){ 48 this.x=y; 49 } 50 public void display(){ 51 System.out.print("("); 52 System.out.printf("%.2f",this.x); 53 System.out.print(","); 54 System.out.printf("%.2f",this.y); 55 System.out.println(")"); 56 } 57 } 58 class Line{ 59 private Point point1; 60 private Point point2; 61 String color; 62 public Line(){ 63 this.point1=point1; 64 this.point2=point2; 65 this.color=""; 66 } 67 public Line(Point point1,Point point2,String color){ 68 this.point1=point1; 69 this.point2=point2; 70 this.color=color; 71 } 72 public Point getPoint1() { 73 return point1; 74 } 75 public void setPoint1(Point point1) { 76 this.point1=point1; 77 } 78 public Point getPoint2() { 79 return point2; 80 } 81 public void setPoint2(Point point2) { 82 this.point2=point2; 83 } 84 public String getColor() { 85 return color; 86 } 87 public void setColor(String color) { 88 this.color=color; 89 } 90 //线段长度 91 public double getDistance(){ 92 return Math.sqrt(Math.pow(this.point2.getX()-this.point1.getX(),2)+Math.pow(this.point2.getY()-this.point1.getY(),2)); 93 } 94 public void display(){ 95 System.out.println("The line's color is:"+this.color); 96 System.out.println("The line's begin point's Coordinate is:"); 97 this.point1.display(); 98 System.out.println("The line's end point's Coordinate is:"); 99 this.point2.display(); 100 System.out.print("The line's length is:"); 101 System.out.printf("%.2f",getDistance()); 102 } 103 }
圈复杂分析图:
由上图可得:圈复杂度在合理范围之内
踩坑心得:
这里注意Point类中的x,y是private,在Line类的方法不能直接调用x,y,需要使用getX(),getY()的方法。其次注意输入值范围设定为(0,200]。
改进建议:
Point类中dispalay()中的输出方法可以简化为:
System.out.printf("(%.2f,%.2f)\n",this.x,this.y);
7-2 点线面问题重构(继承与多态)
在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。
- 对题目中的点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:颜色值
输入样例1:
在这里给出一组输入。例如:
5
9.4
12.3
84
Red
输出样例1:
在这里给出相应的输出。例如:
(5.00,9.40)
(12.30,84.00)
The line's color is:Red
The line's begin point's Coordinate is:
(5.00,9.40)
The line's end point's Coordinate is:
(12.30,84.00)
The line's length is:74.96
The Plane's color is:Red
输入样例2:
在这里给出一组输入。例如:
5
9.4
12.3
845
Black
输出样例2:
在这里给出相应的输出。例如:
Wrong Format
我的代码:

1 import java.util.*; 2 import java.text.DecimalFormat; 3 public class Main{ 4 //控制小数点 5 public static void main(String[] args){ 6 //Point p1=new Point(); 7 8 Scanner input=new Scanner(System.in); 9 double x1=input.nextDouble(); 10 double y1=input.nextDouble(); 11 double x2=input.nextDouble(); 12 double y2=input.nextDouble(); 13 String color=input.next(); 14 Point p1=new Point(x1,y1); 15 Point p2=new Point(x2,y2); 16 Line L=new Line(p1,p2,color); 17 Plane P=new Plane(color); 18 Element element; 19 if((x1<=0||x1>200)||(y1<=0||y1>200)||(x2<=0||x2>200)||(y2<=0||y2>200)){ 20 System.out.println("Wrong Format"); 21 return; 22 } 23 else{ 24 25 element = p1;//起点Point 26 element.display(); 27 28 element = p2;//终点Point 29 element.display(); 30 31 element = L;//线段 32 element.display(); 33 34 element = P;//面 35 element.display(); 36 37 } 38 39 } 40 } 41 class Element{ 42 public void display(){ 43 } 44 } 45 class Point extends Element{ 46 private double x; 47 private double y; 48 public Point(){ 49 this.x = 0; 50 this.y = 0; 51 } 52 public Point(double x,double y){ 53 this.x=x; 54 this.y=y; 55 } 56 public double getX(){ 57 return this.x; 58 } 59 public void setX(double x){ 60 this.x=x; 61 } 62 public double getY(){ 63 return this.y; 64 } 65 public void setY(double y){ 66 this.x=y; 67 } 68 public void display(){ 69 System.out.print("("); 70 System.out.printf("%.2f",this.x); 71 System.out.print(","); 72 System.out.printf("%.2f",this.y); 73 System.out.println(")"); 74 } 75 } 76 class Line extends Element{ 77 private Point point1; 78 private Point point2; 79 String color; 80 public Line(){ 81 this.point1=point1; 82 this.point2=point2; 83 this.color=""; 84 } 85 public Line(Point point1,Point point2,String color){ 86 this.point1=point1; 87 this.point2=point2; 88 this.color=color; 89 } 90 public Point getPoint1() { 91 return point1; 92 } 93 public void setPoint1(Point point1) { 94 this.point1=point1; 95 } 96 public Point getPoint2() { 97 return point2; 98 } 99 public void setPoint2(Point point2) { 100 this.point2=point2; 101 } 102 public String getColor() { 103 return color; 104 } 105 public void setColor(String color) { 106 this.color=color; 107 } 108 //线段长度 109 public double getDistance(){ 110 return Math.sqrt(Math.pow(this.point2.getX()-this.point1.getX(),2)+Math.pow(this.point2.getY()-this.point1.getY(),2)); 111 } 112 public void display(){ 113 System.out.println("The line's color is:"+this.color); 114 System.out.println("The line's begin point's Coordinate is:"); 115 this.point1.display(); 116 System.out.println("The line's end point's Coordinate is:"); 117 this.point2.display(); 118 System.out.print("The line's length is:"); 119 System.out.printf("%.2f\n",getDistance()); 120 } 121 } 122 class Plane extends Element{ 123 private String color; 124 public Plane(String color) { 125 super(); 126 this.color=color; 127 } 128 public String getColor() { 129 return color; 130 } 131 132 public void setColor(String color) { 133 this.color=color; 134 } 135 136 public void display() { 137 System.out.println("The Plane's color is:"+this.color); 138 139 } 140 }

由上图可得:圈复杂度在合理范围之内
踩坑心得:
这道题是在上一题的基础上,加了一个抽象类,注意在抽象父类中的display()方法也要用抽象方法来实现。这道题比较简单,注意格式就行。
改进建议:
同上一题一样,输出可以改进一下,这道题比较简单,不需要花费太大的心思。
7-3 点线面问题再重构(容器类)
在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。
- 在原有类设计的基础上,增加一个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超出合法范围,程序自动忽略该操作
输入样例:
在这里给出一组输入。例如:
1
3.4
5.6
2
4.4
8.0
0.98
23.888
Red
3
Black
1
9.8
7.5
3
Green
4
3
0
输出样例:
在这里给出相应的输出。例如:
(3.40,5.60)
The line's color is:Red
The line's begin point's Coordinate is:
(4.40,8.00)
The line's end point's Coordinate is:
(0.98,23.89)
The line's length is:16.25
(9.80,7.50)
The Plane's color is:Green
设计与分析:
我的代码:

1 import java.util.*; 2 import java.text.DecimalFormat; 3 public class Main{ 4 //控制小数点 5 public static void main(String[] args){ 6 //Point p1=new Point(); 7 8 Scanner input=new Scanner(System.in); 9 10 GeometryObject ge = new GeometryObject(); 11 while(true) { 12 13 int choice = input.nextInt(); 14 if(choice==0) { 15 break; 16 } 17 switch(choice) { 18 case 1://insert Point object into list 19 double x1=input.nextDouble(); 20 double y1=input.nextDouble(); 21 Point p1=new Point(x1,y1); 22 ge.add(new Point(x1,y1)); 23 break; 24 case 2://insert Line object into list 25 double x2=input.nextDouble(); 26 double y2=input.nextDouble(); 27 double x3=input.nextDouble(); 28 double y3=input.nextDouble(); 29 String color=input.next(); 30 Point p2=new Point(x2,y2); 31 Point p3=new Point(x2,y2); 32 Line L=new Line(p2,p3,color); 33 if((x2<=0||x2>200)||(y2<=0||y2>200)||(x3<=0||x3>200)||(y3<=0||y3>200)){ 34 System.out.println("Wrong Format"); 35 ge.add(L); 36 return; 37 } 38 break; 39 case 3://insert Plane object into list 40 String plcolor = input.next(); 41 Plane plane = new Plane(plcolor); 42 ge.add(plane); 43 break; 44 case 4://delete index - 1 object from list 45 int index = input.nextInt(); 46 ge.remove(index); 47 default: 48 break; 49 } 50 for(Element element:ge.getList()){ 51 element.display(); 52 } 53 } 54 55 56 57 } 58 } 59 class Element{ 60 public void display(){ 61 } 62 } 63 class Point extends Element{ 64 private double x; 65 private double y; 66 public Point(){ 67 this.x = 0; 68 this.y = 0; 69 } 70 public Point(double x,double y){ 71 this.x=x; 72 this.y=y; 73 } 74 public double getX(){ 75 return this.x; 76 } 77 public void setX(double x){ 78 this.x=x; 79 } 80 public double getY(){ 81 return this.y; 82 } 83 public void setY(double y){ 84 this.x=y; 85 } 86 public void display(){ 87 System.out.print("("); 88 System.out.printf("%.2f",this.x); 89 System.out.print(","); 90 System.out.printf("%.2f",this.y); 91 System.out.println(")"); 92 } 93 } 94 class Line extends Element{ 95 private Point point1; 96 private Point point2; 97 String color; 98 public Line(){ 99 this.point1=point1; 100 this.point2=point2; 101 this.color=""; 102 } 103 public Line(Point point1,Point point2,String color){ 104 this.point1=point1; 105 this.point2=point2; 106 this.color=color; 107 } 108 public Point getPoint1() { 109 return point1; 110 } 111 public void setPoint1(Point point1) { 112 this.point1=point1; 113 } 114 public Point getPoint2() { 115 return point2; 116 } 117 public void setPoint2(Point point2) { 118 this.point2=point2; 119 } 120 public String getColor() { 121 return color; 122 } 123 public void setColor(String color) { 124 this.color=color; 125 } 126 //线段长度 127 public double getDistance(){ 128 return Math.sqrt(Math.pow(this.point2.getX()-this.point1.getX(),2)+Math.pow(this.point2.getY()-this.point1.getY(),2)); 129 } 130 public void display(){ 131 System.out.println("The line's color is:"+this.color); 132 System.out.println("The line's begin point's Coordinate is:"); 133 this.point1.display(); 134 System.out.println("The line's end point's Coordinate is:"); 135 this.point2.display(); 136 System.out.print("The line's length is:"); 137 System.out.printf("%.2f\n",getDistance()); 138 } 139 } 140 class Plane extends Element{ 141 private String color; 142 public Plane(String color) { 143 super(); 144 this.color=color; 145 } 146 public String getColor() { 147 return color; 148 } 149 150 public void setColor(String color) { 151 this.color=color; 152 } 153 154 public void display() { 155 System.out.println("The Plane's color is:"+this.color); 156 157 } 158 } 159 class GeometryObject { 160 private ArrayList<Element> list=new ArrayList<>(); 161 public void add(Element element){ 162 list.add(element); 163 } 164 public void remove(int index){ 165 if(index<=list.size()) 166 list.remove(index-1); 167 } 168 public ArrayList<Element> getList(){ 169 return list; 170 } 171 172 }
圈复杂分析图:
由上图可得知:圈复杂度在合理范围之内,没啥好说的。
踩坑心得:
这一题是在前两题的基础上做了修改。这里需要定义一个ArrayList<Element>的容器(不会的小伙伴记得找相关资料搞定),要通过add()和remove()进行添加和删除的工作。还有注意每一种情况都要判断输入值是否合法,
改进建议:
我没有每一种情况都判断输入值是否合法,没得满分,这里需要改进。
总结:
通过这几次实验,对于类的运用更加熟练,也学会的使用继承关系来简化代码。但是速度太慢,思考也不够深度,总感觉浮于表面,感觉有些地方似懂非懂。第五次大作业完成的不是很好,很多点没有想到或者想到了,写出来的代码却又问题,找bug又找不出来,很难受。只能说还需要加强练习。