前言:
很快就来到了第二次blog的作业总结了,在前面的三角形的基础打好之后迎来了四边形和五边形的PTA作业,后续在java课程中学习了面向对象的三个基本特征中的封装、继承和多态。以及Exception的处理等等。然后便是期中考试,考试还是比较简单的。接下来对面向对象的三个基本特征给出我自己的理解以及对PTA和期中考试进行分析与总结。PTA当中还是有不少坑的,蔡科你坏事做尽呀!!
关于面向对象的三个基本特征
对于面向对象的三个基本特征,书上的概念对封装,继承,多态的理解也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。接下来谈谈自己的看法与理解。
封装:
1.封装从表面的字意就可以理解是把东西封装起来,到底是把什么封装起来呢?也就是把数据给封装起来。
2.封装的意义或者说是优点在哪里,我认为是可以将数据保护起来,防止代码被无意间的破坏。
3.不让类以外的程序直接访问或修改,只能通过提供的公共接口访问。
4.类似于if中的判断条件只给一个接口,将里面的判断条件给封装起来,既可以方便与读者理解,也可以使得代码更加精简。
继承:
1.继承我最初的理解就是把一个或多个有共同属性或方法的几个类创建一个公共父类来方便其使用,后来才发现继承实际上更多是为多态进行服务的。
2.继承是在已有类的基础上创建新类的过程,已有类称为基类(父类),新类称为派生类(子类)。
3.子类拥有父类的全部变量与方法,继承上还能继承,如:多边形继承颜色类,四边形再继承到多边形。也称为继承中的传递。
4.在java中所有的类都继承与Object类,将Object类称为最高父类。
多态:
1.对于多态,简单来说,就是在同一个类或继承体系结构的基类与派生类中,用同名函数来实现各种不同的功能。
2.在这点上一般用abstarct抽象类来完成,或者使用接口interface完成。
3.多态的好处也是很多的,其中比较突出的就是可扩展性,新增的子类不会对现有类的各种属性。
PTA和期中考试中遇到的bug和问题
此处就类举一下写作业中碰到的问题与bug
PTA4(四边形) :
1.使用Pattern和Matcher中遇到的使用方法错误。
2.精度问题。
3.对于四边形的第四种情况需要除去冗余点,所以acad等等情况需要除去重复点,不考虑不构成三角形的这种情况,也需要计算面积。(我de这个bug滴了两天,后面把点找出来了是ac重合的情况,ck!!)
PTA5(五边形) :
1.删除点后的点的排序问题。
2.点在五边形内的精度问题。
3.条件判断遗漏。
4.五边形格式判断的更新。
期中考试:
1.点的大小范围判断的错写。
2.复制输出结果时候的多复制导致的答案错误。
总结: bug来源主要来自以下四点: 1.对继承改写的陌生,导致出现了一些错误。 2.考虑不周到,很多情况没有考虑到。 3.自己对题目的观察理解不够透彻,导致健壮性的不完善。 4.不小心写错。补:蔡科出的题目阴险和我玩文字游戏。
代码分析
(代码量太大这里不给出全代码,部分题目给出关键的代码,只给出类图和耦合度以及对题目的分析)
PTA47-2 点线形系列4-凸四边形的计算
类图: 耦合度:
分析:
四边形的前两题跟前面的三角形还是有些类似的,只要判断是不是四边形和判断菱形矩形正方形即可,第三问也只要计算相应公式即可。第四问经典的求交点问题,这里其实可以把这种求交点问题的方法写入多边形之中,但这里我还没有学到继承,所以还是用的求交点交点边的方法来求,通过判断交点是否在线上,设置flag1和flag2通过int类型来判断交的那一条边上(ab,bc,cd,da)。在那两条边上就可以将其公共的顶点和两个交点来构造一个三角形求出面积并用总面积前去三角形的面积得到另外一个图形的面积输出即可。第五问判断是否在三角形内依旧沿用面积法,将两两顶点和点构成数个三角形将三角形的面积相加比较总面积,精度小于一定数值即可判断点在四边形内。在通过点到直线的距离是否为零判断是否在直线上即可。
PTA57-1&7-2 凸五边形的计算
类图:
耦合度:
分析:
第五题前面几题和前面的图形类题一致不做多余分析,主要说一下我是怎么去构造多边形的类以及重构类的。我构造了一个不是抽象类的多边形类,这样可能不是很好,但确实帮助了不少忙,我可以直接通过创建多边形来直接求出对应多边形的面积,对于我将各种题目中经常出现的问题存入多边形类中起到了帮助,比如交点问题,通过flag1和flag2的判断和多边形的面积,我将其写入了多边形的类方法中,这样以后需要求对应边形的交点问题时候就可以直接调用,另外我还把其中其多边形还原成正确的几边形构造了方法,中途要注意点的排序问题,不然之后的求面积及会有问题,比较复杂的第6种情况其实在做完第7问的求公共面积后就能很好的解决,通过求公共面积来实现判断两个多边形间的相交问题。最后的点在多边形内只要注意一下精度问题即可。下面给出我自己的多边形类的代码
多边形类的代码:
class duobianxing {
Dian[] dians;
Xian[] bians;
int side;
public duobianxing() {
// TODO 自动生成的构造函数存根
}
public duobianxing(Dian[] dians,int len) {
this.dians = new Dian[len];
this.bians = new Xian[len];
side = len;
if(len!=dians.length)
{
System.out.println("Wrong length!");
System.exit(-1);
}
for(int i=0;i<len;i++) {
this.dians[i] = new Dian(dians[i].x,dians[i].y);
}
for(int i=0;i<len;i++) {
this.bians[i] = new Xian(dians[i],dians[(i+1) % len]);
}
}
//保留三位小数的类函数
public static double xiaoshu_3(double a) {
String result = String.format("%.3f",a);
a = Double.parseDouble(result);
return a;
}
//两点是否相邻(是则返回true,否则返回false)
public boolean two_Points_adjacent(Dian a,Dian b) {
int i,j;
for(i=0;i<side;i++) {
if(a.equal(dians[i]))
break;
}
for(j=0;i<side;i++) {
if(b.equal(dians[j]))
break;
}
if( Math.abs(i-j) == 0 || Math.abs(i-j) == 1)
return true;
return false;
}
//求多边形的周长
public double getCir() {
double Cir=0;
for(int i=0;i<side;i++) {
Cir += bians[i].lineLength();
}
return duobianxing.xiaoshu_3(Cir);
}
//求多边形的面积
public double getArea() {
int n = side;
double area = 0;
for(int i = 0; i < n; i++) {
area += dians[i % n].x * dians[(i + 1) % n].y - dians[(i + 1) % n].x * dians[i % n].y;
}
return xiaoshu_3(0.5 * Math.abs(area));
}
public double getAArea() {
int n = side;
double area = 0;
for(int i = 0; i < n; i++) {
area += dians[i % n].x * dians[(i + 1) % n].y - dians[(i + 1) % n].x * dians[i % n].y;
}
return 0.5 * Math.abs(area);
}
//判断多边形是否有点重合的(有则返回true,没有则返回false)
public boolean coinCidence() {
for(int i=0;i<side-1;i++)
{
for(int j=i+1;j<side;j++)
{
if(dians[i].equal(dians[j]))
return true;
}
}
return false;
}
//删除多边形重复的点(重新返回一个多边形)
public duobianxing deleteCoincidence(duobianxing p) {
ArrayList<Dian> dianList = new ArrayList<>();
for(int i=0;i<side;i++) {
if(!duobianxing.cheakDian(dianList,dians[i]))
dianList.add(dians[i]);
}
Dian[] DDD = new Dian[dianList.size()];
dianList.toArray(DDD);
duobianxing duo = new duobianxing(DDD,DDD.length);
return duo;
}
//判断多边形是否有三点共线的情况(三点共线则返回true,否则返回false)
public boolean three_Points_collinear() {
Xian line = new Xian();
for(int i=0;i<side;i++) {
line.setDian(dians[i],dians[(i+2)%side]);
if(line.inXianduan(dians[(i+1)%side]))
return true;
}
return false;
}
//判断点是否在多边形的内部(在则返回true,不在返回false)
public boolean point_In_duobianxing(Dian a) {
Triangle t = new Triangle();
double S = 0.0;
for(int i=0;i<side;i++) {
t.setpoint(dians[i], dians[(i+1)%dians.length], a);
S += t.getArea();
}
if(Math.abs(S-this.getAArea())<0.0001)
return true;
else
return false;
}
//判断点是否在多边形的边上
public boolean point_In_Edge(Dian a) {
for(int i=0;i<side;i++)
if(bians[i].inXianduan(a))
return true;
return false;
}
//判断多边形的凹凸性(凹返回false,凸返回true)
public boolean Aotu() {
int len = side;
double res = 1;
for(int i=0;i<len;i++) {
double t = (dians[i%len].x-dians[(i+1)%len].x)*(dians[(i+2)%len].y-dians[(i+1)%len].y)-(dians[i%len].y-dians[(i+1)%len].y)*(dians[(i+2)%len].x-dians[(i+1)%len].x);
res = res*t;
}
if(res < 0.000001)
return true;
else
return false;
}
//直线是否与多边形的边重合(重合返回true,不重合返回false)
public boolean line_Coincidence_Edge(Xian line) {
for(int i=0;i<side;i++)
if(line.inLine(dians[i])&&line.inLine(dians[(i+1)%side]))
return true;
return false;
}
//直线交多边形交点的个数(自己输出交点的个数,交点个数为2的话,输出分割的面积小到大)
public void interSection_num(Xian line) {
//直线与边重合
if(this.line_Coincidence_Edge(line))
System.out.println("The line is coincide with one of the lines");
else //与边相交
{
Dian jDian = new Dian();
int interSection_num = 0;
ArrayList<Dian> listDian = new ArrayList<>();
boolean flag = false;
int len = side;
for(int i=0;i<len;i++)
{
if(bians[i].interSectionInline(line))
{
jDian = bians[i].jiaoDian(line);
if(jDian.equal(dians[i]))
len--;
if(jDian.equal(dians[(i+1)%side]))
i++;
if(flag == false)
{
listDian.add(jDian);
flag = true;
}
else
{
listDian.add(jDian);
flag = false;
}
interSection_num++;
}
if(flag)
listDian.add(dians[(i+1)%side]);
}
System.out.print(interSection_num+" ");
if(interSection_num == 2)
{
Dian[] DDD = new Dian[listDian.size()];
listDian.toArray(DDD);
duobianxing m = new duobianxing(DDD,DDD.length);
Double S1 = m.getArea();
Double S2 = this.getArea() - S1;
System.out.println(duobianxing.xiaoshu_3(Math.min(S1,S2))+" "+duobianxing.xiaoshu_3(Math.max(S1,S2)));
}
}
}
//根据多边形的边返回多边形的字符串
public static String exchange_Edge_toString(int Edge) {
String string = "";
switch (Edge) {
case 1: string = "1";break;
case 2: string = "2";break;
case 3: string = "triangle";break;
case 4: string = "quadrilateral";break;
case 5: string = "pentagon";break;
}
return string;
}
//两个多边形之间的关系
public void two_Duobianxing_Relationship(duobianxing polygon) {
//Front表示前一个多边形,Behind表示后一个多边形
duobianxing first = this.duobianxing_Adjustment();
duobianxing second = polygon.duobianxing_Adjustment();
int Front_Edge = first.side;
int Behind_Edge = second.side;
String Front = duobianxing.exchange_Edge_toString(Front_Edge);
String Behind = duobianxing.exchange_Edge_toString(Behind_Edge);
int i;
int count = 0;
int secondInfirst_count = 0;
for(i=0;i<second.side;i++)
if( first.point_In_duobianxing(second.dians[i]) )
count++;
for(i=0;i<first.side;i++)
if( second.point_In_duobianxing(first.dians[i]) )
secondInfirst_count++;
double publicArea = first.two_Duobianxing_publicArea(second);
if(publicArea == 0) {
//分离
if(count == 0 && secondInfirst_count == 0)
System.out.println("no overlapping area between the previous "+Front+" and the following "+Behind);
//连接
else if(count!=0 && secondInfirst_count!=0 && count != first.side && secondInfirst_count != second.side)
System.out.println("the previous "+Front+" is connected to the following "+Behind);
}
//有公共面积的情况
else {
//完全重合
if(first.side == second.side&&count == secondInfirst_count&&count == first.side)
System.out.println("the previous "+Front+" coincides with the following "+Behind);
//包含
if(first.getArea() > second.getArea() && second.getArea() == publicArea)
System.out.println("the previous "+Front+" contains the following "+Behind);
//被包含
if(first.getArea() < second.getArea() && first.getArea() == publicArea)
System.out.println("the previous "+Front+" is inside the following "+Behind);
//交错
if( first.getArea() > publicArea && second.getArea() > publicArea )
System.out.println("the previous "+Front+" is interlaced with the following "+Behind);
}
}
//将多边形变成正确的多边形(除去重复的点和三点一线上的点),返回新的多边形
public duobianxing duobianxing_Adjustment() {
ArrayList<Dian> listDian = new ArrayList<Dian>();
Xian line = new Xian();
duobianxing p = this.deleteCoincidence(this);
for(int i=0;i<p.side;i++)
{
line.setDian(p.dians[i],p.dians[(i+2)%p.side]);
listDian.add(p.dians[i]);
if(line.inXianduan(p.dians[(i+1)%p.side]))
{
if( listDian.size() > ((i+1)%p.side) )
listDian.remove(p.dians[(i+1)%p.side]);
if(line.inLine(p.dians[(i+3)%p.side]))
i++;
i++;
}
}
Dian p1 = new Dian();
Dian p2 = new Dian();
for(int i=0;i<listDian.size();i++)
{
p1 = listDian.get(i);
p2 = listDian.get((i+1)%listDian.size());
line.setDian(p1,p2);
for(int j=0;j<listDian.size();j++)
{
if(line.inXianduan(listDian.get(j)) && !listDian.get(j).equal(p1) && !listDian.get(j).equal(p2) )
listDian.remove(j);
}
}
Dian[] DDD = new Dian[listDian.size()];
listDian.toArray(DDD);
duobianxing duo = new duobianxing(DDD,DDD.length);
return duo;
}
//求两个多边形的交面积(如果值为0表示未相交或连接)
public double two_Duobianxing_publicArea(duobianxing polygon) {
double mianji = 0.0;
ArrayList<Dian> dianList = new ArrayList<Dian>();
Dian jDian = new Dian();
for(int i=0;i<polygon.side;i++)
if(this.point_In_duobianxing(polygon.dians[i])&&!duobianxing.cheakDian(dianList,polygon.dians[i]) )
dianList.add(polygon.dians[i]);
for(int i=0;i<this.side;i++)
if(polygon.point_In_duobianxing(this.dians[i])&&!duobianxing.cheakDian(dianList,this.dians[i]))
dianList.add(this.dians[i]);
for(int i=0;i<side;i++)
{
for(int j=0;j<polygon.side;j++)
{
if(bians[i].interSectionXianduan(polygon.bians[j]))
{
jDian = bians[i].jiaoDian(polygon.bians[j]);
if(!duobianxing.cheakDian(dianList, jDian))
dianList.add(jDian);
}
}
}
Dian[] DDD = new Dian[dianList.size()];
dianList.toArray(DDD);
//点排序
DDD = ClockwiseSortPoints(DDD, DDD.length);
duobianxing m = new duobianxing(DDD,DDD.length);
m = m.duobianxing_Adjustment();
mianji = m.getArea();
return mianji;
}
//arraylist中是否有点a(有true,无false)
public static boolean cheakDian(ArrayList<Dian> list,Dian a) {
for(int i=0;i<list.size();i++) {
if(list.get(i).equal(a))
return true;
}
return false;
}
public static boolean PointCmp(Dian a, Dian b, Dian 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;
}
//点的排序
public static Dian[] ClockwiseSortPoints(Dian[] vPoints, int n) {
//计算重心
double x = 0, y = 0;
for (int i = 0; i < n; i++) {
x += vPoints[i].x;
y += vPoints[i].y;
}
Dian center = new Dian(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)) {
Dian tmp = vPoints[j];
vPoints[j] = vPoints[j + 1];
vPoints[j + 1] = tmp;
}
return vPoints;
}
期中考试:
7-1 点与线(类设计)
类图:
耦合度:
7-2 点线面问题重构(继承与多态)
类图:
耦合度:
7-3 点线面问题再重构(容器类)
类图:
耦合度:
期中考试分析:
这里对期中考试的三道题目做综合分析,本次考试还是非常简单的,只是自己的错写导致浪费了一些时间。但是好在最后成功写了出来。本次就是对之前所学知识的一个阶段性测验,重构造一个类,到新增父类来继承再到多态的一个使用。对方法的重构,多态的用法等等进行了考究。总的来说还是比较简单的没什么特别好讲的。但是我自己的点的大小判断是放在了构造函数之中,其余的地方只要熟悉ArrayList中的方法应该也能很好的解决,这边给出最后一题7-3的代码。
期中考试最后一题的代码:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
GeometryObject geometryObject = new GeometryObject();
int choice = in.nextInt();
while(choice != 0) {
switch(choice) {
case 1://insert Point object into list
double x = in.nextDouble();
double y = in.nextDouble();
geometryObject.add(new Point(x, y));
break;
case 2://insert Line object into list
double x1 = in.nextDouble();
double y1 = in.nextDouble();
double x2 = in.nextDouble();
double y2 = in.nextDouble();
String color = in.next();
geometryObject.add(new Line(new Point(x1, y1),new Point(x2, y2), color));
break;
case 3://insert Plane object into list
String color1 = in.next();
geometryObject.add(new Plane(color1));
break;
case 4://delete index - 1 object from list
int index = in.nextInt();
geometryObject.remove(index);
break;
}
choice = in.nextInt();
}
for( Element element : geometryObject.getList() ) {
element.display();
}
}
public static String xiaoshu_2(double a) {
String result = String.format("%.2f",a);
return result;
}
}
class Point extends Element {
double x,y;
public Point() {
// TODO 自动生成的构造函数存根
}
public Point(double x,double y) {
if(x<0 || x>=200) {
System.out.println("Wrong Format");
System.exit(0);
}
if(y<0 || y>=200) {
System.out.println("Wrong Format");
System.exit(0);
}
this.x = x;
this.y = y;
}
double getX() {
return x;
}
void setX(double x) {
this.x = x;
}
double getY() {
return y;
}
void setY(double y) {
this.y = y;
}
@Override
public void display() {
System.out.println("(" + Main.xiaoshu_2(x) + "," + Main.xiaoshu_2(y) + ")");
}
}
class Line extends Element {
Point point1,point2;
String color;
public Line() {
// TODO 自动生成的构造函数存根
}
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 Math.sqrt((point2.x-point1.x)*(point2.x-point1.x)+(point2.y-point1.y)*(point2.y-point1.y));
}
@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:"+Main.xiaoshu_2(getDistance()) );
}
}
abstract class Element {
public abstract void display();
}
class Plane extends Element {
private String color;
public Plane() {
// TODO 自动生成的构造函数存根
}
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 GeometryObject {
ArrayList<Element> elements = new ArrayList<>();
public void add(Element e) {
elements.add(e);
}
public void remove(int index) {
if(index - 1 < 0 || index - 1 >= elements.size()) {
}
else
elements.remove(index - 1);
}
public ArrayList<Element> getList() {
return elements;
}
}
总结与感想:
对本次的PTA与期中考试来说,能明显感受到自己对于问题思考方式与构造方法的改变。在这次PTA5中还是有不少可以优化的地方的,可以加入try和catch去抓取自己定义的点线类的错误。对于这次的五边形的类来讲还是写的过于大了,很多方法其实可以放入一个新的类中再通过继承来实现方法的传递。有些许方法并不适合存放在五边形的类中,还是类的设计过程中的部分问题,之后能更好的解决这类问题应该还能大大减少不必要的时间消耗与提升检查bug的效率与正确性。
这次期中考试也算对自己进行了一次小小的检查,还有挺多不足的地方与不懂的地方还是需要多看MOOC学习呀。
在实验中设计农夫过河的问题中也能体会到自己对于类设计的些许进步吧,训练上课所学知识。
最后,希望大家可以一起进步,一起加油吧。
标签:Dian,return,int,五边形,duobianxing,PTA,四边形,dians,public From: https://www.cnblogs.com/-feishu/p/16830264.html