JAVA PTA第二次总结
- 前言
(1)前言:经过了前面的作业感觉后面的作业都没有像前面的那么折磨,可能已经习惯了折磨的感觉,写起来特别顺手。

(2)设计与分析:
7-2 点线形系列4-凸四边形的计算
用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入四个点坐标,判断是否是四边形、平行四边形,判断结果输出true/false,结果之间以一个英文空格符分隔。
2:输入四个点坐标,判断是否是菱形、矩形、正方形,判断结果输出true/false,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
3:输入四个点坐标,判断是凹四边形(false)还是凸四边形(true),输出四边形周长、面积,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
4:输入六个点坐标,前两个点构成一条直线,后四个点构成一个四边形或三角形,输出直线与四边形(也可能是三角形)相交的交点数量。如果交点有两个,再按面积从小到大输出四边形(或三角形)被直线分割成两部分的面积(不换行)。若直线与四边形或三角形的一条边线重合,输出"The line is coincide with one of the lines"。若后四个点不符合四边形或三角形的输入,输出"not a quadrilateral or triangle"。
后四个点构成三角形的情况:假设三角形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
1)符合要求的输入:顶点重复或者z与xy都相邻,如x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
2) 不符合要求的输入:z 不与xy都相邻,如z x y s、x z s y、x s z y
5:输入五个点坐标,输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形(判定方法见选项4)的内部(若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。如果点在多边形的某条边上,输出"on the triangle或者on the quadrilateral"。若后四个点不符合四边形或三角形,输出"not a quadrilateral or triangle"。
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
选项1、2、3中,若四边形四个点中有重合点,输出"points coincide"。
选项4中,若前两个输入线的点重合,输出"points coincide"。
首先是input类 ,判断是否格式正确,返回点的集合的功能。
查看代码
static class input{
String ss;
input(String ss){
this.ss=ss;
}
boolean islegal(){
String s="[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)";
return this.ss.matches(s + "," + s + "(\\s" + s +","+ s + ")+" + "[\\s]*");
}
int diannum( ){
return this.ss.split("\\s").length;
}
String [] dian(){
return ss.split(" ");
}
dian [] getPoint(){
dian a[] = new dian[20];
String[] s1=ss.split(" ");
for(int i=0;i<this.dian().length;++i){
String [ ] ss1=s1[i].split(",");
double x1=Double.parseDouble(ss1[0]);
double y1=Double.parseDouble(ss1[1]);
a[i]= new dian(x1,y1);
}
return a;
}
}
这是四边形的类,写的有点辣鸡,大部分功能是枚举情况,没有什么好看的,可以看后面第五次作业优化的版本。
static class Quad {
dian p1, p2, p3, p4;
jian ab,ac,ad,bc,cd,bd;
Quad(dian x1, dian x2, dian x3, dian x4){
this.p1=x1;
this.p2=x2;
this.p3=x3;
this.p4=x4;
ab=new jian(p1,p2);
ad = new jian(p1,p4);
bc= new jian(p2,p3);
cd = new jian(p3,p4);
ac= new jian(p1,p3);
bd= new jian(p2,p4);
}
double getCircumference(){
return p1.distance(p2)+p2.distance(p3)+p3.distance(p4)+p4.distance(p1);
}
public int istri() //判断是否为三角形,并判断哪三点共线
{
//判断是三角形的条件为有且只有一种三点共线的情况
if(p1.isequlity(p2)||p1.isequlity(p3)||p1.isequlity(p4))
{
if(p2.isequlity(p3)||p2.isequlity(p4)||p3.isequlity(p4))
{
return 0;
}
else return 1;
}
if(p2.isequlity(p3)||p2.isequlity(p4))
{
if(p1.isequlity(p2)||p1.isequlity(p3)||p1.isequlity(p4)
||p3.isequlity(p4))
return 0;
else return 2;
}
if(p3.isequlity(p4))
{
if(p1.isequlity(p2)||p1.isequlity(p3)||p1.isequlity(p4)
||p2.isequlity(p3)||p2.isequlity(p4))
return 3;
else return 0;
}
int count=0;
if(ac.onxianduan(p2))//1 3 quad.bd.onxianduan(quad.p1)
{
tri sanjiaoxing1=new tri(p1,p3,p4);
if(sanjiaoxing1.istri()) count=2;
}
if(bd.onxianduan(p3))//2 4
{
if(count!=0) return 0;
else
{
tri sanjiaoxing1=new tri(p1,p2,p4);
if(sanjiaoxing1.istri()) count=3;
}
}
if(ac.onxianduan(p4))//
{
if(count!=0) return 0;
else
{
tri sanjiaoxing1=new tri(p1,p2,p3);
if(sanjiaoxing1.istri()) count=4;
}
}
if(bd.onxianduan(p1))
{
if(count!=0) return 0;
else
{
tri sanjiaoxing1=new tri(p2,p3,p4);
if(sanjiaoxing1.istri()) count=1;
}
}
return count;
}
double getArea(){
tri t1= new tri(p1,p2,p3);
tri t2= new tri(p1,p3,p4);
tri t3= new tri(p1,p2,p4);
tri t4= new tri(p4,p2,p3);
return min(t1.mianji()+t2.mianji(),t3.mianji()+t4.mianji());
}
boolean isQuad(){
if(cd.jiaodiannum_2xianduan(ab)==1||bc.jiaodiannum_2xianduan(ad)==1) return false;
return !(ab.tongxian(p3)||ab.tongxian(p4)||bc.tongxian(p4)||ad.tongxian(p3));
}
boolean isParallelogram(){
if(!this.isQuad()) return false;
return (ab.pingxing(cd)&&ad.pingxing(bc));
}
boolean isDiamond(){
return p1.distance(p2)==p1.distance(p4)&&this.isParallelogram();
}
boolean isSquare(){
return this.isRectangular()&&this.isDiamond();
}
boolean isRectangular(){
if(!this.isQuad()) return false;
if(mul(sub(p1,p2),sub(p1,p4))==0)
return true;
return false;
}
boolean isConvex_Quadrilateral(){
//叉乘法
// double t1 = (p4.x-p1.x)*(p2.y-p1.y)-(p4.y-p1.y)*(p2.x-p1.x);
// double t2 = (p1.x-p2.x)*(p3.y-p2.y)-(p1.y-p2.y)*(p3.x-p2.x);
// double t3 = (p2.x-p3.x)*(p4.y-p3.y)-(p2.y-p3.y)*(p4.x-p3.x);
// double t4 = (p3.x-p4.x)*(p1.y-p4.y)-(p3.y-p4.y)*(p1.x-p4.x);
// return t1 * t2 * t3 * t4 > 0;
//面积法
tri s1= new tri(p1,p2,p3);
tri s2= new tri(p3,p4,p1);
tri s3 =new tri(p2,p3,p4 );
tri s4 = new tri(p4,p1,p2);
return doubleequal(s1.mianji()+s2.mianji(),s3.mianji()+s4.mianji());
}
public void inpoint(dian a){
dian [] w={this.p1,this.p2,this.p3,this.p4};
jian x1=new jian(this.p1,this.p2);
jian x2=new jian(this.p2,this.p3);
jian x3 =new jian (this.p3,this.p4);
jian x4 =new jian (this.p4,this.p1);
if( x1.tongxian(a)){
if((a.x>=min(x1.x.x,x1.y.x)&&a.x<=max(x1.x.x,x1.y.x))&&(a.y<=max(x1.x.y,x1.y.y)&&a.y>=min(x1.x.y,x1.y.y))){
System.out.println("on the quadrilateral");return ;
}
}
if( x2.tongxian(a)){
if((a.x>=min(x2.x.x,x2.y.x)&&a.x<=max(x2.x.x,x2.y.x))&&(a.y<=max(x2.x.y,x2.y.y)&&a.y>=min(x2.x.y,x2.y.y))){
System.out.println("on the quadrilateral");return ;
}
}
if( x3.tongxian(a)){
if((a.x>=min(x3.x.x,x3.y.x)&&a.x<=max(x3.x.x,x3.y.x))&&(a.y<=max(x3.x.y,x3.y.y)&&a.y>=min(x3.x.y,x3.y.y))){
System.out.println("on the quadrilateral");return ;
}
}
if( x4.tongxian(a)){
if((a.x>=min(x4.x.x,x4.y.x)&&a.x<=max(x4.x.x,x4.y.x))&&(a.y<=max(x4.x.y,x4.y.y)&&a.y>=min(x4.x.y,x4.y.y))){
System.out.println("on the quadrilateral");return ;
}
}
int i;
int count=0;
for(i=0;i<4;++i){
dian p1=w[i];
dian p2=w[(i+1)%4];
if(p1.y==p2.y) continue;
if(a.y<=min(p1.y,p2.y))continue;
if(a.y>=max(p1.y,p2.y))continue;
double tep=(a.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
if(tep>a.x) count++;
}
if((count&1)==1) System.out.println("in the quadrilateral");
else System.out.println("outof the quadrilateral");
}
void jiaodiannum_quad(jian a){
if(a.isequality(ab)||a.isequality(bc)||a.isequality(cd)||a.isequality(ad))
{
System.out.println("The line is coincide with one of the lines");
return;
}
int sum = ab.jiaodiannum(a)+bc.jiaodiannum(a)+cd.jiaodiannum(a)+ad.jiaodiannum(a);
if(sum==0){
System.out.println(sum);
return;
}
if(sum==3){
System.out.print("2 ");
if(a.jiaodiannum(ab)==0){
if(ad.jiaodian(a).isequlity(cd.jiaodian(a))){
dian tep= a.jiaodian(bc);
tri t=new tri(tep,p3,p4);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
else {
dian tep= a.jiaodian(ad);
tri t=new tri(tep,p3,p4);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
}
else if(a.jiaodiannum(bc)==0){
System.out.print("2 ");
if(ad.jiaodian(a).isequlity(ab.jiaodian(a))){
dian tep= a.jiaodian(cd);
tri t=new tri(tep,p1,p4);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
else {
dian tep= a.jiaodian(ab);
tri t=new tri(tep,p1,p4);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
}
else if(a.jiaodiannum(cd)==0){
System.out.print("2 ");
if(bc.jiaodian(a).isequlity(ab.jiaodian(a))){
dian tep= a.jiaodian(ad);
tri t=new tri(tep,p1,p2);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
else {
dian tep= a.jiaodian(bc);
tri t=new tri(tep,p1,p2);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
}
else {
System.out.print("2 ");
if(bc.jiaodian(a).isequlity(cd.jiaodian(a))){
dian tep= a.jiaodian(ab);
tri t=new tri(tep,p2,p3);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
else {
dian tep= a.jiaodian(cd);
tri t=new tri(tep,p2,p3);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
}
}
else if(sum==4){
System.out.print("2 ");
if((bc.jiaodian(a).isequlity(cd.jiaodian(a)))&&(ad.jiaodian(a).isequlity(ab.jiaodian(a)))){
tri t1= new tri(p1,p2,p3);
System.out.println(data(min(t1.mianji(),this.getArea()-t1.mianji()))+" "+data(max(t1.mianji(),this.getArea()-t1.mianji())));
}
else {
tri t1= new tri(p1,p2,p4);
System.out.println(data(min(t1.mianji(),this.getArea()-t1.mianji()))+" "+data(max(t1.mianji(),this.getArea()-t1.mianji())));
}
}
else if(sum==2){
System.out.print("2 ");
if(ab.jiaodiannum(a)==1&&cd.jiaodiannum(a)==1){
dian d1= ab.jiaodian(a);
dian d2= cd.jiaodian(a);
Quad q1= new Quad(d1,d2,p1,p4);
Quad q2= new Quad(d1,d2,p2,p3);
System.out.println(data(min(q1.getArea(), q2.getArea()))+" "+data(max(q1.getArea(), q2.getArea())));
}
else if(ad.jiaodiannum(a)==1&&bc.jiaodiannum(a)==1){
dian d1= ad.jiaodian(a);
dian d2= bc.jiaodian(a);
Quad q1= new Quad(d1,d2,p1,p4);
Quad q2= new Quad(d1,d2,p2,p3);
System.out.println(data(min(q1.getArea(), q2.getArea()))+" "+data(max(q1.getArea(), q2.getArea())));
}
if(ab.jiaodiannum(a)==1&&bc.jiaodiannum(a)==1){
dian d1= ab.jiaodian(a);
dian d2= bc.jiaodian(a);
tri t= new tri(d1,d2,p2);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
else if(ab.jiaodiannum(a)==1&&ad.jiaodiannum(a)==1){
dian d1= ab.jiaodian(a);
dian d2= ad.jiaodian(a);
tri t= new tri(d1,d2,p1);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
else if(bc.jiaodiannum(a)==1&&cd.jiaodiannum(a)==1){
dian d1= cd.jiaodian(a);
dian d2= bc.jiaodian(a);
tri t= new tri(d1,d2,p3);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
else if(cd.jiaodiannum(a)==1&&ad.jiaodiannum(a)==1){
dian d1= ad.jiaodian(a);
dian d2= cd.jiaodian(a);
tri t= new tri(d1,d2,p4);
System.out.println(data(min(t.mianji(),this.getArea()-t.mianji()))+" "+data(max(t.mianji(),this.getArea()-t.mianji())));
}
}
}
}
类图: 这类图就像面向过程一样,相互之间没有关联,后面的继承就可以链接起来了。

SourceMonitor生成报表内容如下:

点线形系列5-凸五边形的计算
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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
用户输入一组选项和数据,进行与五边形有关的计算。
以下五边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
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
这二道题可以写在一起,至于为什么分开来,可能是怕行数超过限制吧。

这道题写的代码我写了好久,把前面的代码都重构了一遍,呜呜呜,真的累,不过效果还是很好的。
首先是多边形的类:几乎把三边行和四边形的方法和属性都放在了里面。比如点和线,周长,面积,多边形的分割面积等等。
查看代码 public class Graph{
Point[] point;
Line[] line;
int side;
Graph() {}
Graph(Point[] point, int n) {
this.point= new Point[n];
this.line= new Line[n];
side=n;
for (int i = 0; i < n; i++)
this.point[i] = new Point(point[i].x, point[i].y);
for (int i = 0; i < n; i++)
line[i] = new Line(point[i], point[(i + 1) % point.length]);
}
// boolean isGraph(){
// for (int i = 0; i < side; i++) {
// Line tep = new Line()
// if()
// }
// }
/**
*
* @param tep 线
* @return 是否线与多边形重复
*/
boolean EdgeCoincidence(Line tep){
for(Line a:line)
if(a.isequality_xianduan(tep))
return true;
return false;
}
/**
*
* @param tep 点
* @return 是否点与多边形重复
*/
boolean PointCoincidence(Point tep){
for(Point a:point)
if(a.isequlity(tep))
return true;
return false;
}
/**
*
* @param tep
* @return 点是否在多边形边上
*/
boolean Point_onedge(Point tep){
for(Line a:line)
if(a.onxianduan(tep))
return true;
return false;
}
/**
*
* @return 周长
*/
double getCircumference() {
double ans = 0;
for (int i = 0; i < side; i++)
ans += point[i].distance(point[(i + 1) % point.length]);
return ans;
}
/**
*
* @return 面积
*/
double getArea() {
if(side<3) return 0;
Point[] point=ClockwiseSortPoints(this.point,side);//排序
double area = 0;
for (int i=1;i<side-1;i++)
area += cross(sub(point[i],point[0]),sub(point[i+1],point[0]));
area /= 2; return(area < 0 ? -area : area);
}
/**
*
* @param a 多边形
* @return 多边形与多边形的公共面积
*/
double Public_Area(Graph a){
Point[] s= new Point[10];
Point tep =new Point();
int count=0;
for(Line a1:line)
for(Line a2:a.line)
if(a1.jiaodian(a2)!=null){
if(a1.jiaodiannum_2xianduan(a2)==1)
s[count++] = a1.jiaodian(a2);
}
s=tep.Coincidentpoints(s,count);
int sum =tep.len(s);
for(int i = 0;i <side;i++)
if (a.Point_In_Graph(point[i]))
s[sum++]= point[i];
for (int i = 0;i < a.side;i++)
if (this.Point_In_Graph(a.point[i]))
s[sum++]= a.point[i];
Graph graph= new Graph(s,sum);
System.out.println(data(graph.getArea()));
return graph.getArea();
}
/**
*
* @param a 线
* 分割多边形
*/
void Division_Graph(Line a){
if(this.EdgeCoincidence(a))
{
System.out.println("The line is coincide with one of the lines");
return;
}
int sum =0,count=0,count1=0;
Point [] x = new Point[10];
Line [] k = new Line[10];
for(Line l: line){
if(l.jiaodiannum(a)!=0){
sum+=l.jiaodiannum(a);
x[count++]=l.jiaodian(a);
k[count1++]= l;
}
}
Point s =new Point();
x= s.Coincidentpoints(x,count);
if(s.len(x)==0||s.len(x)==1){
System.out.println(x.length);
return;
}
System.out.print("2 ");
int i = 0,j;
Point [] tep =a.Line_MinPoint(point);
for ( i = 2; i < 2+s.len(tep); i++)
x[i]=tep[i-2];
Graph graph = new Graph(x,s.len(x));
System.out.println(data(min(this.getArea() - graph.getArea(), graph.getArea())) + " " + data(max(this.getArea() - graph.getArea(), graph.getArea())));
}
/**
*
* @param a 多边形
* @return 是否多边形与多边形分离
*/
boolean Separate(Graph a ){
boolean flag =false;
for(Line a1:this.line)
for(Line a2:a.line){
if(a1.jiaodiannum_2xianduan(a2)==1)
flag= true;
}
return !flag;
}
/**
*
* @param a
* @return 是否连接
*/
boolean Connection(Graph a){
int flag1= 0,flag2 =0;
for(Line a2:a.line){
if(this.EdgeCoincidence(a2))
flag1++;
}
for(Point a1:a.point){
if(this.PointCoincidence(a1))
flag2++ ;
}
boolean flag= false;
for (Line a1:line )
for(Line a2:a.line)
if(a1.jiaodiannum_2xianduan(a2)==1)
if(!this.PointCoincidence(a1.jiaodian(a2)))
flag= true;
if(flag) return false;
return flag1==1||flag2==1;
}
/**
*
* @param a
* @return 是否重合
*/
boolean Coincides (Graph a){
if(this.side!=a.side) return false;
int sum=0;
for(Point a1:point)
for(Point a2:a.point)
if(a1.isequlity(a2))
sum++;
return sum==side;
}
/**
*
* @param a
* @return 是否包含
*/
boolean Contains(Graph a){// a在this中
boolean flag= false;
for(Point a2:a.point){
if(!this.Point_In_Graph(a2)&&!this.Point_onedge(a2))
flag =true;
}
return !flag;
}
/**
*
* @param a
* @return 是否交错
*/
boolean Interlaced(Graph a){
if(this.Coincides(a)) return false;
boolean flag= false;
for (Line a1:line )
for(Line a2:a.line)
if(a1.jiaodiannum_2xianduan(a2)==1)
flag= true;
return flag;
}
/**
*
* @param a
* @return 是否被包含
*/
boolean Inside(Graph a){// this在a中
boolean flag= false;
for(Point a2:this.point)
if(!a.Point_In_Graph(a2)&&!a.Point_onedge(a2))
flag =true;
return !flag;
}
/**
*
* @param a
* @output 输出关系
*/
void Relationship(Graph a){
String [] ss= new String[8];
ss[3]="triangle";
ss[4]="quadrilateral";
ss[5]="pentagon";
if(this.Separate(a)){//no overlapping area between the previous triangle/quadrilateral/ pentagon and the following triangle/quadrilateral/ pentagon
System.out.print("no overlapping area between the previous "+ss[side]+" and the following "+ss[a.side]);
}
else if(this.Connection(a)){
System.out.print("the previous "+ss[side]+" is connected to the following "+ss[a.side]);
}
else if(this.Coincides(a)){
System.out.print("the previous "+ss[side]+" coincides with the following "+ss[a.side]);
}
else if(this.Inside(a)){
System.out.print("the previous "+ss[side]+" is inside the following "+ss[a.side]);
}
else if(this.Contains(a)){
System.out.print("the previous "+ss[side]+" contains the following "+ss[a.side]);
}
else if(this.Interlaced(a)){
System.out.print("the previous "+ss[side]+" is interlaced with the following "+ss[a.side]);
}
}
// void Point_In_Graph(Point a) {
// for (Line l : line)
// if (l.tongxian(a))
// if ((a.x >= min(l.x.x, l.y.x) && a.x <= max(l.x.x, l.y.x)) && (a.y <= max(l.x.y, l.y.y) && a.y >= min(l.x.y, l.y.y))) {
// System.out.println("on the quadrilateral");
// return;
// }
// int count = 0;
// for (int i = 0; i < side; ++i) {
// Point p1 = point[i];
// Point p2 = point[(i + 1) % side];
// if (p1.y == p2.y) continue;
// if (a.y <= min(p1.y, p2.y)) continue;
// if (a.y >= max(p1.y, p2.y)) continue;
// double tep = (a.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
// if (tep > a.x) count++;
// }
// if ((count & 1) == 1) System.out.println("in the quadrilateral");
// else System.out.println("outof the quadrilateral");
// }
/**
*
* @param a
* @return 是否在多边形中 在边上return false
*/
boolean Point_In_Graph(Point a) {
for (Line l : line)
if (l.tongxian(a))
if ((a.x >= min(l.x.x, l.y.x) && a.x <= max(l.x.x, l.y.x)) && (a.y <= max(l.x.y, l.y.y) && a.y >= min(l.x.y, l.y.y)))
return false;
int count = 0;
for (int i = 0; i < side; ++i) {
Point p1 = point[i];
Point p2 = point[(i + 1) % side];
if (p1.y == p2.y) continue;
if (a.y < min(p1.y, p2.y)) continue;
if (a.y >= max(p1.y, p2.y)) continue;
double tep = (a.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
//if(doubleequal(tep,a.x)) continue;
if (tep > a.x) count++;
}
return (count & 1) == 1;
}
/**
*
* @return 是否凹凸多边形
*/
boolean isConvex_Quadrilateral(){
int len = side;
double ans = 1;
for(int i=0;i<len;i++) {
double t = (point[i%len].x-point[(i+1)%len].x)*(point[(i+2)%len].y-point[(i+1)%len].y)-(point[i%len].y-point[(i+1)%len].y)*(point[(i+2)%len].x-point[(i+1)%len].x);
ans = ans*t;
}
return ans < 0.000001;
}
}
我来介绍一下分割面积和求面积吧:
分割面积:
分割面积 void Division_Graph(Line a){
if(this.EdgeCoincidence(a))
{
System.out.println("The line is coincide with one of the lines");
return;
}
int sum =0,count=0,count1=0;
Point [] x = new Point[10];
Line [] k = new Line[10];
for(Line l: line){
if(l.jiaodiannum(a)!=0){
sum+=l.jiaodiannum(a);
x[count++]=l.jiaodian(a);
k[count1++]= l;
}
}
Point s =new Point();
x= s.Coincidentpoints(x,count);
if(s.len(x)==0||s.len(x)==1){
System.out.println(x.length);
return;
}
System.out.print("2 ");
int i = 0,j;
Point [] tep =a.Line_MinPoint(point);
for ( i = 2; i < 2+s.len(tep); i++)
x[i]=tep[i-2];
Graph graph = new Graph(x,s.len(x));
System.out.println(data(min(this.getArea() - graph.getArea(), graph.getArea())) + " " + data(max(this.getArea() - graph.getArea(), graph.getArea())));
}
得到线一边最少的点
public Point[] Line_MinPoint(Point [] a){
Point[] ans1 = new Point[8];
Point[] ans2 = new Point[8];
int count=0,count1=0;
for(Point i :a)
if(!this.onxianduan(i))
if((this.x.x-i.x)*(this.y.y-i.y)-(this.x.y-i.y)*(this.y.x-i.x)>0)
ans1[count++] = i;
else
ans2[count1++]=i;
if(min(count,count1)==count)
return ans1;
else
return ans2;
}
求面积时要先对点进行排序:
点排序 static boolean PointCmp(Point a, Point b, Point center) {
if (a.x >= 0 && b.x < 0)
return true;
if (a.x == 0 && b.x == 0)
return a.y > b.y;
//向量OA和向量OB的叉积
double det = (a.x - center.x) * (b.y - center.y) - (b.x - center.x) * (a.y - center.y);
if (det < 0)
return true;
if (det > 0)
return false;
//向量OA和向量OB共线,以距离判断大小
double d1 = (a.x - center.x) * (a.x - center.x) + (a.y - center.y) * (a.y - center.y);
double d2 = (b.x - center.x) * (b.x - center.y) + (b.y - center.y) * (b.y - center.y);
return d1 > d2;
}
static Point[] ClockwiseSortPoints(Point[] vPoints, int n) {
//计算重心
double x = 0, y = 0;
for (int i = 0; i < n; i++) {
x += vPoints[i].x;
y += vPoints[i].y;
}
Point center = new Point(x / n, y / n);
//冒泡排序
for (int i = 0; i < n - 1; i++)
for (int j = 0; j < n - i - 1; j++)
if (PointCmp(vPoints[j], vPoints[j + 1], center)) {
Point tmp = vPoints[j];
vPoints[j] = vPoints[j + 1];
vPoints[j + 1] = tmp;
}
return vPoints;
}
求面积
double getArea() {
if(side<3) return 0;
Point[] point=ClockwiseSortPoints(this.point,side);//排序
double area = 0;
for (int i=1;i<side-1;i++)
area += cross(sub(point[i],point[0]),sub(point[i+1],point[0]));
area /= 2; return(area < 0 ? -area : area);
}
接下来的是五边形的类:
五边形 public class Pentagon extends Graph{
Pentagon(Point [] points){
super(points,5);
}
boolean isPentagon(){
if((line[0].jiaodiannum_2xianduan(line[3])!=0)||(line[0].jiaodiannum_2xianduan(line[2])!=0)
||(line[1].jiaodiannum_2xianduan(line[4])!=0)
||(line[2].jiaodiannum_2xianduan(line[4])!=0)||(line[1].jiaodiannum_2xianduan(line[3])!=0))
return false;
//三点共线
Line[] ll= { new Line(point[0],point[2]),new Line(point[1],point[3]),new Line(point[2],point[4]),
new Line(point[3],point[0]),new Line(point[1],point[4])} ;
if(ll[0].onxianduan(point[1])||ll[1].onxianduan(point[2])||ll[2].onxianduan(point[3])||ll[3].onxianduan(point[4])||ll[4].onxianduan(point[0]))
return false;
return true;
}
Point[] jugde( ){
if(this.isPentagon()) return point;
Point a = new Point();
Point[] ans =a.Coincidentpoints(point,5);
if(ans.length == 3) return ans;
if(ans.length == 4){
Quad quad = new Quad(ans[0],ans[1],ans[2],ans[3]);
if(quad.isQuad())
return ans;
else if(quad.line[4].onxianduan(quad. point[1])){
Point [] tep = {ans[0],ans[2],ans[3]};
return tep;
}
else if(quad.line[4].onxianduan(quad.point[3])){
Point [] tep = {ans[0],ans[1],ans[2]};
return tep;
}
else if(quad.line[5].onxianduan(quad.point[2])){
Point [] tep = {ans[0],ans[1],ans[3]};
return tep;
}
else if(quad.line[5].onxianduan(quad.point[0])){
Point [] tep = {ans[1],ans[2],ans[3]};
return tep;
}
}
int count=0;
int sum=0;
Point [] l= new Point[10];
for (int i = 0; i < line.length; i++)
for (int j = i+1; j < line.length; j++)
if(line[i].isequality(line[j])){
count ++;
if(line[i].jiaodian_tongxainxianduan(line[j])!=null)
l[sum++] =(line[i].jiaodian_tongxainxianduan(line[j]));
}
Point x= new Point();
l=x.Coincidentpoints(l,sum);
l= x.Delete(point,5,l,x.len(l));
return l;
}
}
其中最重要的是jugde方法,判断是什么形状,并返回点的集合。
类图:

SourceMonitor生成报表内容如下:

额额,这复杂度还是蛮高的,写的时候还没有觉得自己写这样的高,自我感觉良好。
点与线(类设计)
-
设计一个类表示平面直角坐标系上的点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或者回车分隔。
-
import java.util.Scanner;
import static java.lang.Math.sqrt;
public class Main
{
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
double x1,x2,y1,y2;
int num;
int index;
String color;
x1=sc.nextDouble();
y1=sc.nextDouble();
x2=sc.nextDouble();
y2=sc.nextDouble();
if(x1>0&&x1<=200&&y1>0&&y1<=200&&x2>0&&x2<=200&&y2>0&&y2<=200)
{
Point point1=new Point(x1,y1);
Point point2=new Point(x2,y2);
color=sc.next();
Line line1=new Line(point1,point2,color);
line1.display();
}
else
{
System.out.println("Wrong Format");
}
}
}
class Line
{
private Point point1,point2;
private String color;
public Line() {
}
public Line(Point point1, Point point2, String color) {
this.point1 = point1;
this.point2 = point2;
this.color = color;
}
public Point getPoint1() {
return point1;
}
public void setPoint1(Point point1) {
this.point1 = point1;
}
public Point getPoint2() {
return point2;
}
public void setPoint2(Point point2) {
this.point2 = point2;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getDistance()
{
return sqrt((point1.getX()-point2.getX())*(point1.getX()-point2.getX())+(point1.getY()-point2.getY())*(point1.getY()-point2.getY()));
}
public void display()
{
System.out.println("The line's color is:"+color);
System.out.println("The line's begin point's Coordinate is:");
point1.display();
System.out.println("The line's end point's Coordinate is:");
point2.display();
System.out.println("The line's length is:"+String.format("%.2f",getDistance()));
}
}
class Point
{
private double x,y;
public Point()
{
}
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public void display()
{
System.out.println("("+String.format("%.2f",this.x)+","+String.format("%.2f",this.y)+")");
}
}
照着类图写就行了,基本操作都可以快捷键自动生成生成,就一个display()要自己写,不过一开始的我以为要写正则表达式,导致我浪费了好久时间。
点线面问题重构(继承与多态)
在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。
- 对题目中的点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)方法。
- 以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
import java.util.Scanner;
import static java.lang.Math.sqrt;
public class Main
{
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
double x1,x2,y1,y2;
int num;
int index;
String color;
x1=sc.nextDouble();
y1=sc.nextDouble();
x2=sc.nextDouble();
y2=sc.nextDouble();
if(x1>0&&x1<=200&&y1>0&&y1<=200&&x2>0&&x2<=200&&y2>0&&y2<=200)
{
Point point1=new Point(x1,y1);
Point point2=new Point(x2,y2);
color=sc.next();
Line line1=new Line(point1,point2,color);
Plane plane=new Plane(color);
Element element;
element = point1;//起点Point
element.display();
element = point2;//终点Point
element.display();
element = line1;//线段
element.display();
element = plane;//面
element.display();
}
else
{
System.out.println("Wrong Format");
}
}
}
abstract class Element
{
public abstract void display();
}
class Line extends Element
{
private Point point1,point2;
private String color;
public Line() {
}
public Line(Point point1, Point point2, String color) {
this.point1 = point1;
this.point2 = point2;
this.color = color;
}
public Point getPoint1() {
return point1;
}
public void setPoint1(Point point1) {
this.point1 = point1;
}
public Point getPoint2() {
return point2;
}
public void setPoint2(Point point2) {
this.point2 = point2;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getDistance()
{
return sqrt((point1.getX()-point2.getX())*(point1.getX()-point2.getX())+(point1.getY()-point2.getY())*(point1.getY()-point2.getY()));
}
@Override
public void display()
{
System.out.println("The line's color is:"+color);
System.out.println("The line's begin point's Coordinate is:");
point1.display();
System.out.println("The line's end point's Coordinate is:");
point2.display();
System.out.println("The line's length is:"+String.format("%.2f",getDistance()));
}
}
class Plane extends Element
{
private String color;
public Plane() {
}
public Plane(String color) {
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public void display()
{
System.out.println("The Plane's color is:"+color);
}
}
class Point extends Element
{
private double x,y;
public Point()
{
}
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public void display()
{
System.out.println("("+String.format("%.2f",this.x)+","+String.format("%.2f",this.y)+")");
}
}
相较前一题多定义了一个抽象父类和一个plane类,再用一下多态就可以啦。
点线面问题再重构(容器类)
在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。
- 在原有类设计的基础上,增加一个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()方法进行输出。
类图如下所示:

- 以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
查看代码
import java.util.ArrayList;
import java.util.Scanner;
import static java.lang.Math.sqrt;
public class Main
{
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
double x1,x2,y1,y2;
int num;
int index;
String color;
GeometryObject g=new GeometryObject();
num=sc.nextInt();
while(num!=0)
{
switch(num)
{
case 1:{
x1=sc.nextDouble();
y1=sc.nextDouble();
point p = new point(x1,y1);
g.add(p);
}
break;
case 2:{
x1=sc.nextDouble();
y1=sc.nextDouble();
point p1 = new point(x1,y1);
x2=sc.nextDouble();
y2=sc.nextDouble();
point p2 = new point(x2,y2);
color = sc.next();
line l = new line(p1,p2,color);
g.add(l);
}
break;
case 3:
{
color = sc.next();
plane p = new plane(color);
g.add(p);
}
break;
case 4:
{
index = sc.nextInt();
if(g.getList().size()>=index)
g.remove(index-1);
}
}
num = sc.nextInt();
}
ArrayList<element> list = g.getList();
for(int i=0;i<list.size();i++)
{
list.get(i).display();
}
}
}
abstract class element
{
public abstract void display();
}
class GeometryObject
{
ArrayList<element> list=new ArrayList<>();
public GeometryObject()
{
}
public GeometryObject(ArrayList<element> list) {
this.list = list;
}
public ArrayList<element> getList() {
return list;
}
public void setList(ArrayList<element> list) {
this.list = list;
}
public void add(element e)
{
list.add(e);
}
public void remove(int n)
{
list.remove(n);
}
}
class line extends element
{
private point point1,point2;
private String color;
public line()
{
}
public line(point point1, point point2, String color)
{
this.point1 = point1;
this.point2 = point2;
this.color = color;
}
public point getPoint1() {
return point1;
}
public void setPoint1(point point1) {
this.point1 = point1;
}
public point getPoint2() {
return point2;
}
public void setPoint2(point point2) {
this.point2 = point2;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double distance()
{
return sqrt((point1.getX()-point2.getX())*(point1.getX()-point2.getX())+(point1.getY()-point2.getY())*(point1.getY()-point2.getY()));
}
@Override
public void display()
{
System.out.println("The line's color is:"+color);
System.out.println("The line's begin point's Coordinate is:");
point1.display();
System.out.println("The line's end point's Coordinate is:");
point2.display();
System.out.println("The line's length is:"+String.format("%.2f",distance()));
}
}
class plane extends element
{
private String color;
public plane() {
}
public plane(String color) {
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public void display()
{
System.out.println("The Plane's color is:"+color);
}
}
class point extends element
{
private double x,y;
public point()
{
}
public point(double x, double y)
{
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
@Override
public void display()
{
System.out.println("("+String.format("%.2f",this.x)+","+String.format("%.2f",this.y)+")");
}
}
没什么,就是简单容器的使用,就和c++的动态数组一样的。
(3)采坑心得:
说说做这几次作业踩的坑,有的题目有的bug debug了二天,硬测试出来的测试点,呜,太菜了。
1.在写数组时调用数组的length()函数时,返回的是初始化时设置的长度,而不是数组中实际的元素个数,可以函数入口加一个n 表示个数,也可以写一个函数判断有几个,比如:
查看代码 static int len(Point[] a){
int ss=0;
for(Point s: a)
if(s!=null)
ss++;
return ss;
}
2.求四边形的面积时,把四边形分割为两个三角形,但是因为有凹四边形的存在,最后结果要取两次分割得到的结果的较小值。
3.在计算多边形的面积时,点必须按顺序存储,要不然就会矢量相消。
4在四边形的计算中,就是这个bug我de了二天。这就是第1和第3个点重合的情况,应该在判断之前先进行点的去重操作。在后面的五边形的时候我就先去重了,就没有出现类似的问题。

5.射线法的时候,有一个边界问题,将>=改为>就可以了

(4)改进建议:感觉多边形可以变成抽象类,就可以使用多态,而不是用多边形对象了。
可以把主函数的一些方法放进类里面封装起来,一些类里面的方法是不需要的。
其实判断是不是多边形也可以封装。
(5)总结:总的来说,通过这几次作业,我学到了很多,学会了继承,抽象,多态等等。写的类也是一点一点的改进,一点一点的进步,从只会写类,到封装,到继承,到后面就感觉自己真的nb。
bug总是改完一个又出现另一个,有时候真的想放弃,但还是耐心debug,学到了更多的debug的技巧。


浙公网安备 33010602011771号