BLOG2
前言
在完成习题4.习题5以及期中考试后,所涉及的方面越来越多。从习题1-3简单的java程序设计再变为借助类与对象的关系来构建程序。
习题四的三题分别需要运用到正则表达式去判断每行输入的数字,构建多个类来实现凸四边形的计算实现其功能,也需要运用到正则表达式,以及构建一个银行业务类实现对应的功能。在这三题中较难的便是第二题凸四边形的计算较为繁琐,在习题三三角形的计算基础上升级并增加了选项。
习题五的两题都是五边形的设计对于我来说算是十分困难了,根据我现在的水平只能完成前2-3个选项,也是在习题四的基础上进行的难度的升级,从输入5个点到输入10个点的复杂的计算不仅涉及到了类的封装继承与多态的知识,还考察了数学的逻辑计算构思,算得上是很难了。
期中考试的题目从类的设计到继承与多态再到容器类,三个题目循序渐进,由易到难,而且都是在前一题的基础上改动的,前两题难度还较为简单,就是到后面的容器类由于知识掌握不完全无法成功做出。三个题目从点到线,线到面,维度的变化,从一维到二维的转化到二维到三维的实现也是一个不断变难的过程。
设计与分析
4-1识蛟龙号载人深潜,立科技报国志(II)(正则表达式)
本题较为简单我在此处运用到了链表来读取字符串
while(!str.equals("end")) { str = sc.nextLine(); strList.add(str); }
当输入的字符串含end时结束输入开始判别,但是在此处我并未运用到过多的正则表达式判断而是用了字符串的分割将数字与文字分隔开
String[] split=str2.split("\\D+");
最后再通过识别整数型函数来获取每行句子中的数字并进行相加输出结果
int digit=Integer.parseInt(split[j]);
总的来说第一题并不难,就是可能在看到字符表达式以及冗长的题目可能觉得不好下手,但细细阅读输入以及输出格式便可以知道实现起来简单
4-2点线形系列4-凸四边形的计算
package sibianxing; import java.util.ArrayList; import java.text.DecimalFormat; import java.util.Arrays; import java.util.Scanner; public class sibianxing { public static void main(String[] args) { Scanner in = new Scanner(System.in); String s = in.nextLine(); InputData d = new InputData(); ParseInput.paseInput(s, d); int choice = d.getChoice(); ArrayList ps = d.getPoints(); switch (choice) { case 1: handle1(ps); break; case 2: handle2(ps); break; case 3: handle3(ps); break; case 4: handle4(ps); break; case 5: handle5(ps); break; } } // 输入四个点坐标,判断是否是等腰三角形、等边三角形,判断结果为true/false,两个结果之间以一个英文空格符分隔。 public static void handle1(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 4); Qua t = new Qua(ps.get(0), ps.get(1), ps.get(2),ps.get(3)); if(t.isqua()) { if(t.isIsoscelesqua()) System.out.println(true+" "+true); else System.out.println(true+" "+false); } else System.out.println(false+" "+false); } // 输入三个点坐标,输出周长、面积、重心坐标,三个参数之间以一个英文空格分隔,坐标之间以英文","分隔。 public static void handle2(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 4); Qua t = new Qua(ps.get(0), ps.get(1), ps.get(2),ps.get(3)); System.out.println(t.isEquilateralqua()+" "+t.isRightqua()+" "+t.isObtusequa()); } // 输入三个点坐标,输出是钝角、直角还是锐角三角形 public static void handle3(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 4); Qua t = new Qua(ps.get(0), ps.get(1), ps.get(2), ps.get(3)); System.out.println(t.isAcutequa()+" "+OutFormat.doubleFormat(t.getPerimeter())+" "+OutFormat.doubleFormat(t.getArea())); } } class Line { private Point p1;//线上的第一个点 private Point p2;//线上的第二个点 public Line(double x1, double y1, double x2, double y2) { Point p1 = new Point(x1, y1); Point p2 = new Point(x2, y2); LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出 this.p1 = p1; this.p2 = p2; } public Line(Point p1, Point p2) { LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出 this.p1 = p1; this.p2 = p2; } /* 获取线条的斜率 */ public Double getSlope() { // (x1-x2=0)注意考虑斜率不存在即返回double类型无穷大"Infinite" return (p2.getY() - p1.getY()) / (p2.getX() - p1.getX()); } public double getlength() { return Math.sqrt((p1.getX() - p2.getX())*(p1.getX() - p2.getX())+(p1.getY() - p2.getY())*(p1.getY() - p2.getY())); } /* 判断x是否在线上 */ public boolean isOnline(Point x) { //System.out.println("isOnline"); //System.out.println(p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y + " "); // 点重合 if ((x.getX() == p1.getX() && x.getY() == p1.getY()) || (x.getX() == p2.getX() && x.getY() == p2.getY())) { return true; } Line l = new Line(p1, x); if (l.getSlope().isInfinite() && this.getSlope().isInfinite()) { return true; } /* * if (l.getSlope().isInfinite() || this.getSlope().isInfinite()) { return * false; } */ // 此点与线上任意一点构成的线的斜率相等则此点在线上 double b1 = l.getSlope(), b2 = this.getSlope(); //System.out.println(b1 + " " + b2 + " " + (b1- b2) + " " + (Math.abs(b1 - b2) < 0.00000000001)); return Math.abs(b1 - b2) < 0.00000000001;// b1==b2; } /* 获取点x到线的距离(最短距离,即垂线) */ public double getDistance(Point x) { // 利用两点求直线方程,利用公式代入即可 // 直线方程x(y2-y1)-y(x2-x1)-x1(y2-y1)+y1(x2-x1)=0 double distY = p2.getY() - p1.getY(); double distX = p2.getX() - p1.getX(); return Math.abs(x.getX() * distY - x.getY() * distX - p1.getX() * distY + p1.getY() * distX) / p1.getDistance(p2); } /* 判断x是否在线上且在两点之间 */ public boolean isBetween(Point x) { //System.out.println("isBetween" + " " + this.p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y); if (!this.isOnline(x)) { return false; } // 与端点重合,认为不在在两点之间, if (x.equals(p1) || x.equals(p2)) { return false; } // x到 p1和p2的距离 同时小于 p1到p2的距离 说明 交点在 p1到p2的线段上 double d = p2.getDistance(p1); boolean b = x.getDistance(p2) < d && x.getDistance(p1) < d; //System.out.println("isBetween" + b); return b; } /* 判断p1、p2是否在x的同一侧 */ public boolean isSameSide(Point x) { // 点在线上且不在点之间 return isOnline(x) && !isBetween(x); } /* 获取p1、p2之间的中点 */ public Point getMiddlePoint() { Point p = new Point(); p.setX((p1.getX() + p2.getX()) / 2); p.setY((p1.getY() + p2.getY()) / 2); return p; } /* 获取线段的第一个坐标点 */ public Point getPointA() { return p1; } /* 获取线段的第二个坐标点 */ public Point getPointB() { return p2; } /* 获取与线条l之间的夹角,若两条线段交叉(交叉点位于其中一条线的两点之间),取较小的夹角 */ public double getAngle(Line l) { // 利用公式θ=arctan∣(k2- k1)/(1+ k1k2)∣,此时求较小的夹角 double k2 = getSlope(); double k1 = l.getSlope(); return (double) (Math.atan(Math.abs((k2 - k1) / (1 + k1 * k2))) * 180.0 / Math.PI);// 返回值为角度 } // 是否平行,平行返回true,否则false。 public boolean isParallel(Line l) { Double b1 = this.getSlope(); Double b2 = l.getSlope(); if ((b1.isInfinite()) && (b2.isInfinite())) { return true; } else { return (this.getSlope().doubleValue() == l.getSlope().doubleValue()); } } // 两条线是否重合,重合返回true,否则false。 public boolean isCoincide(Line l) { if (!this.isParallel(l)) { return false; } if (this.isOnline(l.p1)) { return true; } return false; } // 获取交叉点,若两条线平行,返回null。 public Point getIntersection(Line l) { // LineInputError.isParallelError(this, l); if (this.isParallel(l)) { return null; } if (p1.equals(l.p1) || p1.equals(l.p2)) { return p1; } if (p2.equals(l.p1) || p2.equals(l.p2)) { return p2; } Point p3 = l.p1, p4 = l.p2; double x_member, x_denominator, y_member, y_denominator; Point cross_point = new Point(); x_denominator = p4.x * p2.y - p4.x * p1.y - p3.x * p2.y + p3.x * p1.y - p2.x * p4.y + p2.x * p3.y + p1.x * p4.y - p1.x * p3.y; x_member = p3.y * p4.x * p2.x - p4.y * p3.x * p2.x - p3.y * p4.x * p1.x + p4.y * p3.x * p1.x - p1.y * p2.x * p4.x + p2.y * p1.x * p4.x + p1.y * p2.x * p3.x - p2.y * p1.x * p3.x; if (x_denominator == 0) cross_point.x = 0; else cross_point.x = x_member / x_denominator; y_denominator = p4.y * p2.x - p4.y * p1.x - p3.y * p2.x + p1.x * p3.y - p2.y * p4.x + p2.y * p3.x + p1.y * p4.x - p1.y * p3.x; y_member = -p3.y * p4.x * p2.y + p4.y * p3.x * p2.y + p3.y * p4.x * p1.y - p4.y * p3.x * p1.y + p1.y * p2.x * p4.y - p1.y * p2.x * p3.y - p2.y * p1.x * p4.y + p2.y * p1.x * p3.y; if (y_denominator == 0) cross_point.y = 0; else cross_point.y = y_member / y_denominator; // System.out.println(cross_point.x + ","+cross_point.y); return cross_point; // 平行返回(0,0) } } class InputData { private int choice;;//用户输入的选择项 private ArrayList<Point> points = new ArrayList();//用户输入的点坐标 public int getChoice() { return choice; } public void setChoice(int choice) { this.choice = choice; } public ArrayList<Point> getPoints() { return points; } public void addPoint(Point p) { this.points.add(p); } } class LineInputError { // 直线的两点重合的错误判断和提示。 public static void pointsCoincideError(Point p1, Point p2) { if ((p1.getX() == p2.getX()) && p1.getY() == p2.getY()) { System.out.println("points coincide"); System.exit(0); } } } class OutFormat { //按要求格式化实数的输出。 public static Double doubleFormat(double b) { DecimalFormat df = new DecimalFormat("#.000"); Double output = Double.valueOf(df.format(b)); return output; } } class ParseInput { /* * 输入:完整的输入字符串,包含选项和所有点的信息,格式:选项:x1,y1 x2,y2 .....xn,yn。选项只能是1-5 * 一个空InputData对象 * 处理:将输入字符串中的选项和点信息提取出来并设置到InputData对象中 * 输出:包含选项值和所有点的Point对象的InputData对象。 */ public static void paseInput(String s, InputData d) { PointInputError.wrongChoice(s); d.setChoice(getChoice(s)); s = s.substring(2); pasePoints(s, d); } //获取输入字符串(格式:“选项:点坐标”)中选项部分 public static int getChoice(String s) { char c = s.charAt(0); return c-48; } /* * 输入:一个字符串,包含所有点的信息,格式:x1,y1 x2,y2 .....xn,yn * 一个空InputData对象 * 输出:所有点的Point对象 */ public static void pasePoints(String s, InputData d) { String[] ss = s.split(" "); if (ss.length == 0) return; for (int i = 0; i < ss.length; i++) { d.addPoint(readPoint(ss[i])); } } /* * 输入:包含单个点信息的字符串,格式:x,y * 输出:Point对象 */ public static Point readPoint(String s) { PointInputError.wrongPointFormat(s); String[] ss = s.split(","); double x = Double.parseDouble(ss[0]); double y = Double.parseDouble(ss[1]); // System.out.println("match"); return new Point(x, y); } } class Point { public double x; public double y; public Point() { } public Point(double x,double y) { this.x=x; this.y=y; } /* 设置坐标x,将输入参数赋值给属性x */ public void setX(double x) { this.x = x; } /* 设置坐标y,将输入参数赋值给属性y */ public void setY(double y) { this.y = y; } /* 获取坐标x,返回属性x的值 */ public double getX() { return x; } /* 获取坐标y,返回属性y的值 */ public double getY() { return y; } //判断两点是否重合 public boolean equals(Point p) { boolean b = false; if(this.x==p.getX()&&this.y==p.getY()) { b=true; } return b; } /* 计算当前点和输入点p之间的距离 */ public double getDistance(Point p) { double distance = Math.sqrt(Math.pow(x-p.getX(), 2)+Math.pow(y-p.getY(), 2)); return distance; } } class PointInputError { //判断从字符串中解析出的点的数量是否合格。 public static void wrongNumberOfPoints(ArrayList ps, int num) { if (ps.size() != num) { System.out.println("wrong number of points"); System.exit(0); } } //判断输入的字符串中点的坐标部分格式是否合格。若不符合,报错并退出程序 public static void wrongPointFormat(String s) { if (!s.matches("[+-]?([1-9]\\d*|0)(\\.\\d+)?,[+-]?([1-9]\\d*|0)(\\.\\d+)?")) { System.out.println("Wrong Format"); System.exit(0); } } // 输入字符串是否是"选项:字符串"格式,选项部分是否是1~5其中之一 public static void wrongChoice(String s) { if (!s.matches("[1-5]:.+")) { System.out.println("Wrong Format"); System.exit(0);} } public static void Is_coincide_Points(ArrayList ps, int num) { if (ps.size() != num) { } } } class Qua { private Point x; private Point y; private Point z; private Point m; public Qua(Point x, Point y, Point z,Point m) { this.x = x; this.y = y; this.z = z; this.m = m; if (!this.isqua()) { System.out.println("not a quadrilateral"); System.exit(0); } } /* 判断x\y\z三个点的坐标是否能构成一个四边形 */ public boolean isqua() { Line l1 = new Line(x,y); Line l2 = new Line(y,z); Line l3 = new Line(z,m); Line l4 = new Line(x,m); if(l1.getSlope().compareTo(l2.getSlope())==0|| l1.getSlope().compareTo(l4.getSlope())==0|| l3.getSlope().compareTo(l2.getSlope())==0|| l3.getSlope().compareTo(l4.getSlope())==0) return false; else return true; } /* 获取三角形的面积,此处采用海伦公式 */ public double getArea() { Line l1 = new Line(x,y); Line l2 = new Line(y,z); Line l3 = new Line(z,m); Line l4 = new Line(x,m); Line l5 = new Line(x,z); Line l6 = new Line(y,m); double a =l1.getlength(); double b =l2.getlength(); double c =l3.getlength(); double d =l4.getlength(); double e =l5.getlength(); double f = l6.getlength(); return 0.25*Math.sqrt(4*e*e*f*f-(a*a-b*b+c*c-d*d)*(a*a-b*b+c*c-d*d)); } /* 获取三角形的周长 */ public double getPerimeter() { Line l1 = new Line(x,y); Line l2 = new Line(y,z); Line l3 = new Line(z,m); Line l4 = new Line(x,m); return l1.getlength()+l2.getlength()+l3.getlength()+l4.getlength(); } /* 判断是否平行四边形*/ public boolean isIsoscelesqua() { Line l1 = new Line(x,y); Line l2 = new Line(y,z); Line l3 = new Line(z,m); Line l4 = new Line(x,m); if((l1.getlength()==l3.getlength())&&(l2.getlength()==l4.getlength())) return true; else return false; } /* 判断是否菱形 */ /*判断是否为菱形*/ public boolean isEquilateralqua() { Line l1 = new Line(x,y); Line l2 = new Line(y,z); Line l3 = new Line(z,m); Line l4 = new Line(m,x); if(l1.getlength()==l2.getlength()&&l2.getlength()==l3.getlength()&&l3.getlength()==l4.getlength()) { return true; } else return false; } /* 判断是否矩形 */ public boolean isRightqua() { if(x.getDistance(z)==y.getDistance(m)) return true; else return false; } /* 判断是正方形 */ public boolean isObtusequa() { if(isRightqua()==true&&isEquilateralqua()==true) return true; else return false; } /* 判断是否凹四边形 */ public boolean isAcutequa() { double t1 = (m.getX()-x.getX())*(y.getY()-x.getY())-(m.getY()-x.getY())*(y.getX()-x.getX()); double t2 = (x.getX()-y.getX())*(z.getY()-y.getY())-(x.getY()-y.getY())*(z.getX()-y.getX()); double t3 = (y.getX()-z.getX())*(m.getY()-z.getY())-(y.getY()-z.getY())*(m.getX()-z.getX()); double t4 = (z.getX()-m.getX())*(x.getY()-m.getY())-(z.getY()-m.getY())*(x.getX()-m.getX()); if(t1*t2*t3*t4<0) return false; else return true; } } class Triangle { private Point x; private Point y; private Point z; public Triangle(Point x, Point y, Point z) { this.x = x; this.y = y; this.z = z; if (!this.isTriangle()) { System.out.println("data error"); System.exit(0); } } public int isInside(Point p) { if (this.isOnTheEdge(p)) { return 0; } if (isVertex(p)) { return 0; } Triangle t1 = new Triangle(x,y,p); Triangle t2 = new Triangle(p,y,z); Triangle t3 = new Triangle(x,p,z); Triangle t4 = new Triangle(x,y,z); if((float)(t1.getArea()+t2.getArea()+t3.getArea())==(float)(t4.getArea())) { return 1; } else { return -1; } } public boolean isOnTheEdge(Point p) { Line l1 = new Line(x,y); Line l2 = new Line(y,z); Line l3 = new Line(z,x); if(l1.isBetween(p)||l2.isBetween(p)||l3.isBetween(p)) { return true; } else return false; } /* 判断x\y\z三个点的坐标是否能构成一个三角形 */ public boolean isTriangle() { Line l1 = new Line(x,y); Line l2 = new Line(y,z); Line l3 = new Line(x,z); if((l1.getlength()+l2.getlength()<=l3.getlength())||(l1.getlength()+l3.getlength()<=l2.getlength())||(l2.getlength()+l3.getlength()<=l1.getlength())||l1.getlength()<0||l2.getlength()<0||l3.getlength()<0) return false; else return true; } /* 获取三角形的中点(三条中线的交点) */ public Point getMidpoint() { // 中点即重心,利用性质求解 Point p = new Point(); p.setX((this.x.getX() + this.y.getX() + this.z.getX()) / 3); p.setY((this.x.getY() + this.y.getY() + this.z.getY()) / 3); return p; } /* 获取三角形的三条边线 */ public Line[] getSideline() { // 设置第一条边线 Line line1 = new Line(x, y); // 设置第二条中线 Line line2 = new Line(x, z); // 设置第三条中线 Line line3 = new Line(y, z); Line[] lines = { line1, line2, line3 }; return lines; } /* 获取三角形的面积,此处采用海伦公式 */ /* 获取三角形的周长 */ public double getPerimeter() { return x.getDistance(y) + y.getDistance(z) + z.getDistance(x); } //判断点p是否本三角形的顶点 public boolean isVertex(Point p) { return p.equals(x) || p.equals(y) || p.equals(z); } public double getArea() { double s = (x.getDistance(y) + y.getDistance(z) + z.getDistance(x))/2.0; return Math.sqrt(s * (s - x.getDistance(y)) * (s - y.getDistance(z)) * (s - z.getDistance(x))); } /* * 判断点p是否在本三角形内部(射线法) * 输出:1:在内部,-1:在外部,0:在三角形上 */ /* 三个点的getter()和setter()方法 */ public Point getX() { return x; } public void setX(Point x) { this.x = x; } public Point getY() { return y; } public void setY(Point y) { this.y = y; } public Point getZ() { return z; } public void setZ(Point z) { this.z = z; } }
本题代码是在老师所发出的三角形的代码上进行的修改,但是只实现了3个选项
输入的数据存入链表再判断输入的选项是否是在1-5选项之中,再将字符串分割成每个点的坐标,通过坐标格式的正则表达式判断格式是否正确便转化成四边形的四个点坐标。
选项一判断四个点是否构成四边形或者平行四边形主要是依靠四边形以及平行四边形的性质来实现的,主要是位于对角线的顶点是否在同一直线上便可以判断是否判断四边形,而平行四边形的性质为对边相等,对顶角相等来判断,获取四个顶点构成的边的距离进行边长的计算,再通过角度的计算来确定是否为平行四边形输出结果。
选项二判断是否为菱形,矩形,正方形,众所周知,菱形的四条边都相等,而矩形对边相等四个角都是直角,而正方形则是四条边都相等,四个角都是直角,根据此来进行每个点所连接而成的线段的长度与线段所形成的角度是否符合条件来进行判断。
选项三时判断四边形的凹凸性并输出周长与距离,凹凸性是根据叉乘来判断的,p1,p2,p3,p4 四个点顺序组成的四边形.s0 = S(p1,p2,p3)+ S(p3,p4,p1) ,s1 = S(p2,p3,p4)+S(p4,p1,p2)。如果s0 == s1 则是凸四边形.否则就是凹四边形.。周长的话就是将四条边的边长进行相加,而四边形的面积则是靠拆分成的两个三角形的面积相加得出,运用到了点线面系列3三角形的计算中的TRiangle类中面积的计算得出,得多亏了老师的三角形的系列代码。
4-3 设计一个银行业务类
import java.util.Scanner; import java.util.ArrayList; public class Main { public static void main(String[] args) { Scanner str = new Scanner(System.in); String name = str.next(); int password0 = str.nextInt(); BankBusiness account= new BankBusiness(name,password0); BankBusiness.welcome(); System.out.println(); int password1= str.nextInt(); double balance1= str.nextDouble(); account.deposit(password1,balance1); System.out.println(); account.salary1(balance1); int password2= str.nextInt(); double balance2= str.nextDouble(); account.deposit(password2,balance2); System.out.println(); int password3= str.nextInt(); double balance3= str.nextDouble(); account.withdraw(password3,balance3); System.out.println(); int password4= str.nextInt(); double balance4= str.nextDouble(); account.withdraw(password4,balance4); System.out.println(); //int password5= str.nextInt(); //double balance5= str.nextDouble(); //account.withdraw(password5,balance5); //System.out.println(); //str.close(); BankBusiness.welcomeNext(); System.out.println(); } } class BankBusiness{ public String bankName = "中国银行"; String name; int password; double balance; public BankBusiness(String name0, int password0) { name = name0; password = password0; balance = 0; } public static void welcome() { System.out.print("中国银行欢迎您的到来!"); } public int key() { return password; } public void key1(int a) { password = a; } public double salary() { return balance; } public void salary1(double a) { balance = a; } public void deposit(int pass,double balance) { if(pass==password) System.out.print("您的余额有"+balance+"元。"); else System.out.print("您的密码错误!"); } public void withdraw(int pass,double a) { if(pass==password) { if(balance - a >= 0) { double yue = balance-a; System.out.print("请取走钞票,您的余额还有"+yue+"元。"); } else System.out.print("您的余额不足!"); } else System.out.print("您的密码错误!"); } public static void welcomeNext() { System.out.print("请收好您的证件和物品,欢迎您下次光临!"); } }
本题主要是类的设计,一个银行业务类BankBusiness,一个测试类Main,在Main中调用银行业务类BankBusiness来实现存储款的功能,此题较为简单,只要掌握了类的构建就可以按照题目书写出代码,其中包含了密码的识别以及金额的变化,主要是代码要规范,符合题目要求便可以完成。主要出现的问题就是在输入格式已经nextline的使用上具有很大的差漏。
期中1-点与线(类设计)
import java.util.Scanner; public class Main { public static void main(String[] args) { Line l1 = new Line(); Point p1=new Point(); Point p2=new Point(); Scanner str = new Scanner(System.in); Double x1 = str.nextDouble(); p1.setX(x1); Double y1 = str.nextDouble(); p1.setY(y1); Double x2 = str.nextDouble(); p2.setX(x2); Double y2 = str.nextDouble(); p2.setY(y2); String color = str.next(); l1.setColor(color); if(x1>0&&x1<=200&&y1>0&&y1<=200&&x2>0&&x2<=200&&y2>0&&y2<=200&&x1!=x2&&y1!=y2) { l1.Line(p1,p2,color); l1.displaycolor(); p1.displaybegin(); p2.displayend(); l1.displaydistance(); str.close(); } else { System.out.println("Wrong Format"); } } } class Line { private Point point1=new Point(); private Point point2=new Point(); private String color; public void Line(Point p1,Point p2,String color) { this.point1 = p1; this.point2 = p2; 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((point1.getX()-point2.getX())*(point1.getX()-point2.getX())+(point1.getY()-point2.getY())*(point1.getY()-point2.getY())); } public void displaycolor() { System.out.println("The line's color is:" + color); } public void displaydistance() { String.format("%.2f", getDistance()); System.out.println("The line's length is:" + String.format("%.2f", getDistance())); } } class Point { private double x; private double y; public Point(double x,double y) { } public Point() { } 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 displaybegin() { System.out.println("The line's begin point's Coordinate is:"); System.out.println("(" + String.format("%.2f", x) + "," + String.format("%.2f", y) + ")"); } public void displayend() { System.out.println("The line's end point's Coordinate is:"); System.out.println("(" + String.format("%.2f", x) + "," + String.format("%.2f", y) + ")"); } public static void main(String[] args) { Point p1=new Point(); Point p2=new Point(); } }
根据类图就差不多可以写出来,加上之前的三角形的计算是从点到线,线到图形来组成的,源码其实都大同小异,只是加了一个颜色的属性在里面,可以较容易实现。
期中2-点线面问题重构(继承与多态)
同样本题也是根据类图以及上一题的代码进行书写程序
class Plane extends Element{ private String color; Plane(){ } Plane(String color){ this.setColor(color); } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void display() { System.out.print("The Plane's color is:"+getColor()); } } abstract class Element{ public void display() { } }
第二题就是要我们对上一题通过继承和多态来进行重构,增加了一个Element的父类与Plane的子类,element类包含point,line,plane,三个子类,主要提取出三个子类中相同的功能到父类,再让子类进行继承以提高代码的耦合性与简化代码,不会出现过多的重复的步骤。
期中3-点线面问题再重构(容器类)
class GeometryObject{ ArrayList<Element> arrayList = new ArrayList<Element>(); public GeometryObject() { } public void add(Element element) { arrayList.add(element); } public void remove(int index){ if (index < 0 || index >= arrayList.size()){ return; } arrayList.remove(index); } public ArrayList<Element> getList(){ return arrayList; } }
在原有类设计的基础上,增加一个GeometryObject容器类,我在考试的时候没有做出来,主要是当时对容器这一块的知识太生疏了,没有学透,才导致无从下手。但是归根结底还是在2的代码上进行相应的改动,根据类图给我们的指示进行代码的书写。总的来说期中考试的题目相对来说都是考察面向对象的知识,难度偏易。
5-1 点线形系列5-凸五边形的计算-1
import java.util.ArrayList; import java.util.Scanner; import java.text.DecimalFormat; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str = sc.nextLine(); Input input = new Input(); ParseInput.paseInput(str, input); int choice = input.getChoice(); ArrayList ps = input.getPoints(); switch (choice) { case 1: choose1(ps); break; case 2: choose2(ps); break; case 3: choose3(ps); break; case 4: //choose4(ps); break; case 5: //choose5(ps); break; case 6: //choose6(ps); break; } } public static void choose1(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 5); wubianxing t = new wubianxing(ps.get(0), ps.get(1), ps.get(2),ps.get(3),ps.get(4)); } public static void choose2(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 5); wubianxing t = new wubianxing(ps.get(0), ps.get(1), ps.get(2),ps.get(3),ps.get(4)); //System.out.println(t.wubianxing()); if(t.isaowubianxing()==true) { System.out.println("true"); System.exit(0); } else { System.out.println("not a pentagon"); System.exit(0); } } public static void choose3(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 5); wubianxing t = new wubianxing(ps.get(0), ps.get(1), ps.get(2),ps.get(3),ps.get(4)); //System.out.println(t.wubianxing()); if(t.isaowubianxing()==true) { System.out.println("points coincide"); System.exit(0); } else { System.out.println("points coincide"); System.exit(0); } } } class Input { private int choice;;//用户输入的选择项 private ArrayList<Point> points = new ArrayList();//用户输入的点坐标 public int getChoice() { return choice; } public void setChoice(int choice) { this.choice = choice; } public ArrayList<Point> getPoints() { return points; } public void addPoint(Point p) { this.points.add(p); } } class Line { private Point p1;//线上的第一个点 private Point p2;//线上的第二个点 public Line(double x1, double y1, double x2, double y2) { Point p1 = new Point(x1, y1); Point p2 = new Point(x2, y2); LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出 this.p1 = p1; this.p2 = p2; } public Line(Point p1, Point p2) { LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出 this.p1 = p1; this.p2 = p2; } /* 获取线条的斜率 */ public Double getSlope() { // (x1-x2=0)注意考虑斜率不存在即返回double类型无穷大"Infinite" return (p2.getY() - p1.getY()) / (p2.getX() - p1.getX()); } /* 判断x是否在线上 */ public boolean isOnline(Point x) { //System.out.println("isOnline"); //System.out.println(p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y + " "); // 点重合 if ((x.getX() == p1.getX() && x.getY() == p1.getY()) || (x.getX() == p2.getX() && x.getY() == p2.getY())) { return true; } Line l = new Line(p1, x); if (l.getSlope().isInfinite() && this.getSlope().isInfinite()) { return true; } /* * if (l.getSlope().isInfinite() || this.getSlope().isInfinite()) { return * false; } */ // 此点与线上任意一点构成的线的斜率相等则此点在线上 double b1 = l.getSlope(), b2 = this.getSlope(); //System.out.println(b1 + " " + b2 + " " + (b1- b2) + " " + (Math.abs(b1 - b2) < 0.00000000001)); return Math.abs(b1 - b2) < 0.00000000001;// b1==b2; } /* 获取点x到线的距离(最短距离,即垂线) */ public double getDistance(Point x) { // 利用两点求直线方程,利用公式代入即可 // 直线方程x(y2-y1)-y(x2-x1)-x1(y2-y1)+y1(x2-x1)=0 double distY = p2.getY() - p1.getY(); double distX = p2.getX() - p1.getX(); return Math.abs(x.getX() * distY - x.getY() * distX - p1.getX() * distY + p1.getY() * distX) / p1.getDistance(p2); } /* 判断x是否在线上且在两点之间 */ public boolean isBetween(Point x) { //System.out.println("isBetween" + " " + this.p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y); if (!this.isOnline(x)) { return false; } // 与端点重合,认为不在在两点之间, if (x.equals(p1) || x.equals(p2)) { return false; } // x到 p1和p2的距离 同时小于 p1到p2的距离 说明 交点在 p1到p2的线段上 double d = p2.getDistance(p1); boolean b = x.getDistance(p2) < d && x.getDistance(p1) < d; //System.out.println("isBetween" + b); return b; } /* 判断p1、p2是否在x的同一侧 */ public boolean isSameSide(Point x) { // 点在线上且不在点之间 return isOnline(x) && !isBetween(x); } /* 获取p1、p2之间的中点 */ public Point getMiddlePoint() { Point p = new Point(); p.setX((p1.getX() + p2.getX()) / 2); p.setY((p1.getY() + p2.getY()) / 2); return p; } public double getAngle(Line l) { // 利用公式θ=arctan∣(k2- k1)/(1+ k1k2)∣,此时求较小的夹角 double k2 = getSlope(); double k1 = l.getSlope(); return (double) (Math.atan(Math.abs((k2 - k1) / (1 + k1 * k2))) * 180.0 / Math.PI);// 返回值为角度 } /* 获取线段的第一个坐标点 */ public Point getPointA() { return p1; } /* 获取线段的第二个坐标点 */ public Point getPointB() { return p2; } // 是否平行,平行返回true,否则false。 public boolean isParallel(Line l) { Double b1 = this.getSlope(); Double b2 = l.getSlope(); if ((b1.isInfinite()) && (b2.isInfinite())) { return true; } else { return (this.getSlope().doubleValue() == l.getSlope().doubleValue()); } } // 两条线是否重合,重合返回true,否则false。 public boolean isCoincide(Line l) { if (!this.isParallel(l)) { return false; } if (this.isOnline(l.p1)) { return true; } return false; } // 获取交叉点,若两条线平行,返回null。 public Point getIntersection(Line l) { // LineInputError.isParallelError(this, l); if (this.isParallel(l)) { return null; } if (p1.equals(l.p1) || p1.equals(l.p2)) { return p1; } if (p2.equals(l.p1) || p2.equals(l.p2)) { return p2; } Point p3 = l.p1, p4 = l.p2; double x_member, x_denominator, y_member, y_denominator; Point cross_point = new Point(); x_denominator = p4.x * p2.y - p4.x * p1.y - p3.x * p2.y + p3.x * p1.y - p2.x * p4.y + p2.x * p3.y + p1.x * p4.y - p1.x * p3.y; x_member = p3.y * p4.x * p2.x - p4.y * p3.x * p2.x - p3.y * p4.x * p1.x + p4.y * p3.x * p1.x - p1.y * p2.x * p4.x + p2.y * p1.x * p4.x + p1.y * p2.x * p3.x - p2.y * p1.x * p3.x; if (x_denominator == 0) cross_point.x = 0; else cross_point.x = x_member / x_denominator; y_denominator = p4.y * p2.x - p4.y * p1.x - p3.y * p2.x + p1.x * p3.y - p2.y * p4.x + p2.y * p3.x + p1.y * p4.x - p1.y * p3.x; y_member = -p3.y * p4.x * p2.y + p4.y * p3.x * p2.y + p3.y * p4.x * p1.y - p4.y * p3.x * p1.y + p1.y * p2.x * p4.y - p1.y * p2.x * p3.y - p2.y * p1.x * p4.y + p2.y * p1.x * p3.y; if (y_denominator == 0) cross_point.y = 0; else cross_point.y = y_member / y_denominator; // System.out.println(cross_point.x + ","+cross_point.y); return cross_point; // 平行返回(0,0) } } //用于处理线条相关功能中出现的异常提示。 class LineInputError { public static void pointsCoincideError(Point p1, Point p2) { if ((p1.getX() == p2.getX()) && p1.getY() == p2.getY()) { System.out.println("points coincide"); System.exit(0); } } } class OutFormat { //按要求格式化实数的输出。 public static Double doubleFormat(double b) { DecimalFormat df = new DecimalFormat("#.000000"); Double output = Double.valueOf(df.format(b)); return output; } } class Point { public double x; public double y; public Point() { } public Point(double x,double y) { this.x=x; this.y=y; } /* 设置坐标x,将输入参数赋值给属性x */ public void setX(double x) { this.x = x; } /* 设置坐标y,将输入参数赋值给属性y */ public void setY(double y) { this.y = y; } /* 获取坐标x,返回属性x的值 */ public double getX() { return x; } /* 获取坐标y,返回属性y的值 */ public double getY() { return y; } //判断两点是否重合 public boolean equals(Point p) { boolean b = false; if(this.x==p.getX()&&this.y==p.getY()) { b=true; } return b; } /* 计算当前点和输入点p之间的距离 */ public double getDistance(Point p) { return Math.sqrt((p.getX()-this.x)*(p.getX()-this.x)+(p.getY()-this.y)*(p.getY()-this.y)); } } class PointInputError { //判断从字符串中解析出的点的数量是否合格 public static void wrongNumberOfPoints(ArrayList ps, int num) { if (ps.size() != num) { System.out.println("wrong number of points"); System.exit(0); } } //判断输入的字符串中点的坐标部分格式是否合格。若不符合,报错并退出程序 public static void wrongPointFormat(String s) { if (!s.matches("[+-]?([1-9]\\d*|0)(\\.\\d+)?,[+-]?([1-9]\\d*|0)(\\.\\d+)?")) { System.out.println("Wrong Format"); System.exit(0); } } // 输入字符串是否是"选项:字符串"格式,选项部分是否是1~5其中之一 public static void wrongChoice(String s) { if (!s.matches("[1-5]:.+")) { System.out.println("Wrong Format"); System.exit(0); } } } class wubianxing { private Point a; private Point b; private Point c; private Point d; private Point e; public wubianxing(Point a, Point b, Point c, Point d, Point e) { this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; if (this.iswubianxing()==true) { System.out.println("true"); System.exit(0); } else { System.out.println("false"); System.exit(0); } } //public aowbianxing public boolean iswubianxing() { boolean iswubianxing=false; Line line1 = new Line(a, b); // 设置第二条中线 Line line2 = new Line(b, c); // 设置第三条中线 Line line3 = new Line(c, d); Line line4 = new Line(d, e); Line line5 = new Line(e, a); if(line1.getIntersection(line3)==null&&line1.getIntersection(line4)==null&&line2.getIntersection(line4)==null&&line2.getIntersection(line5)==null&&line3.getIntersection(line5)==null) { iswubianxing=true; } return iswubianxing; } public boolean isaowubianxing() { boolean isaowubianxing=false; Line line1 = new Line(a, b); // 设置第二条中线 Line line2 = new Line(b, c); // 设置第三条中线 Line line3 = new Line(c, d); Line line4 = new Line(d, e); Line line5 = new Line(e, a); if(line1.getAngle(line2)<180&&line2.getAngle(line3)<180&&line3.getAngle(line4)<180&&line4.getAngle(line5)<180&&line5.getAngle(line1)<180) { isaowubianxing=true; } return isaowubianxing; } /* 三个点的getter()和setter()方法 */ public Point getA() { return a; } public void setA(Point a) { this.a = a; } public Point getB() { return b; } public void setB(Point b) { this.b = b; } public Point getC() { return c; } public void setC(Point c) { this.c = c; } public Point getD() { return c; } public void setD(Point d) { this.c = d; } public Point getE() { return e; } public void setE(Point e) { this.e = e; } } class ParseInput { public static void paseInput(String s, Input d) { PointInputError.wrongChoice(s); d.setChoice(getChoice(s)); s = s.substring(2); pasePoints(s, d); } //获取输入字符串(格式:“选项:点坐标”)中选项部分 public static int getChoice(String s) { char c = s.charAt(0); return c-48; } /* * 输入:一个字符串,包含所有点的信息,格式:x1,y1 x2,y2 .....xn,yn * 一个空InputData对象 * 输出:所有点的Point对象 */ public static void pasePoints(String s, Input d) { String[] ss = s.split(" "); if (ss.length == 0) return; for (int i = 0; i < ss.length; i++) { d.addPoint(readPoint(ss[i])); } } /* * 输入:包含单个点信息的字符串,格式:x,y * 输出:Point对象 */ public static Point readPoint(String s) { PointInputError.wrongPointFormat(s); String[] ss = s.split(","); double x = Double.parseDouble(ss[0]); double y = Double.parseDouble(ss[1]); // System.out.println("match"); return new Point(x, y); } }
这题不会是真的不会了,题目太复杂了,我现在比较菜只能完成2-3个选项。
选项一判断是否构成五边形主要就是根据构成的线段l1与l3,l4,l2与l4,l5,l3与l5之间是否有交点来判断五个点是否可以构成五边形,若是存在交点,则构成的图形便会被交点分割,而不存在所谓的五边形,于是只要靠getIntersection来判断是否村存在交点即可判断。
选项二判断五边形的凹凸性,在这里采用了与四边形不同的方法,那就是判断五边形的五个内角是否都小于180度,通过两条线段计算之间的夹角,若都为180度则为凸五边形,反之则为凹五边形。而五边形的周长便是把五条边的长度相加,而五边形的面积便是把五边形切割改为三个三角形,再将三角形的面积相加得到所求的面积之和。
判断输入格式是否正确还是和点线系列之前的题目一直,都是将输入的转化成为一个个点的坐标再用正则表达式进行判断然后转化成为各个点再构成线段进行计算。
后面的输入的点太多了我是真的不会了,输入的点太多,而且所运用到的数学计算知识偏多,一时不知道怎么下手,所以就也没做出来,写了一点点
总结
这几个习题集中我取得的成绩都不太理想,主要原因是对于点线系列的问题掌握不透彻,加上图形的构建需要考虑以及点与线的关系,线段与线段的关系判断位置关系,对于现在的我来说实在是无能为力了。
在习题四中要判断点与图形的关系来实现功能,由于不知道从何下手所以就没办法。而且习题四习题五中都是用的是老师之前发的三角形的源代码,因为自己写的还是存在不足,所以是在老师的代码基础上进行改进的,不是完完全全靠着自己写的代码来实现,说明我对类的设计这一块还存在许多欠缺。而且对于继承与多态我也没有运用上,主要是没有掌握好,加上的话会让我的代码更多bug了,就不敢去尝试,这也是我的不足。
在期中考试里根据类图来书写程序其实可能不算太难,但是就是从继承开始出现了问题导致第三题写不出来,前后衔接不上,这也是一个很大的问题。
在接下来的学习里我更应该好好学习面向对象的方法,让代码的结构更清晰,,继承和封装相关的知识还需加强学习练习。