BLOG-2~~~我又来啦!!!
一、引言
本次博客的创作是想对近几个星期新做的java题进行总结(主要题目有PTA大作业,期中考试),所涉及的知识点包括第四次大作业中的正则表达式、第四,五次大作业中的图形类设计相关的父类子类继承和相关函数的设计、期中考试的继承与多态,容器类知识点等。每次的作业或考试项目皆有3道题,可以说,题量在可控范围内(大佬不要多讲,躲我这种小菜鸡,已经很“可控”了),而题的难度呢,对我来说哈!还是有一定难度的,容器、图形设计(不仅是对编程能力的考察,更要求较高的数学能力和空间想象能力。与数学缜密的结合充分体现出编程的特色)让我举步维艰,相对来说,期中考试的前两题考察基础,第三题则考研容器的知识,我则没有完成。
二、设计与分析
第四次大作业
1.sdut-String-2 识蛟龙号载人深潜,立科技报国志(II)(正则表达式)
请编写程序,实现如下功能:读入关于蛟龙号载人潜水器探测数据的多行字符串,从给定的信息找出数字字符,输出每行的数字之和。
提示 若输入为“2012年2月”,则该行的输出为:2014。若干个连续的数字字符作为一个整体,以十进制形式相加。
输入格式:
读入关于蛟龙号载人潜水器探测数据的多行字符串,每行字符不超过80个字符。
以end结束。
输出格式:
与输入行相对应的各个整数之和。
输入样例1:
2012年6月27日11时47分,中国“蛟龙”再次刷新“中国深度”——下潜7062米 6月15日,6671米 6月19日,6965米 6月22日,6963米 6月24日,7020米 6月27日,7062米 下潜至7000米,标志着我国具备了载人到达全球99%以上海洋深处进行作业的能力 end
输出样例1:
9165 6692 6990 6991 7050 7095 7099
输入样例2:
全世界投入使用的各类载人潜水器约90艘,下潜深度超过1000米的仅有12艘,更深的潜水器数量更少 6000米以上深度载人潜水器的国家包括中国、美国、日本、法国和俄罗斯 日本深潜器下潜6527米,蛟龙号在马里亚纳海沟海试成功到达7020米海底,创造了新的世界纪录 从2009年至2012年,蛟龙号接连取得1000米级、3000米级、5000米级和7000米级海试成功 下潜至7000米,说明蛟龙号载人潜水器集成技术的成熟 end
输出样例2:
1102 6000 13547 20021 7000
源码:
import java.util.Scanner; public class Main1{ public static void main(String[] args){ try (Scanner input = new Scanner(System.in)) { do{ String line=input.nextLine();
//读入字符串 if(line.equals(end)) break; output(line); }while(true); } catch (NumberFormatException e) { // TODO 自动生成的 catch 块 e.printStackTrace();} } public static void output(String line){ String[] split=line.split(\\D+);
//数组split接收分割的字符串,正则判断连续的整数用于split分割 long sum=0; for(int i=0;i<split.length;i++){ if(!split[i].equals())
//如果每个数组元素split[i].equals()为假,则if语句执行 { int digit=Integer.parseInt(split[i]);
//字符串强制转换成int sum+=digit;} } System.out.println(sum);} }
思考:主体为两个部分
(1)负责读取与输出的主函数与检测输入内容完成提取的方法,output函数通过接受line并将其分割,正则判断连续的整数用于split分割。
(2)再进行强制类型转换,主函数接收输入后通过output函数进行输出。
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。
输入样例1:
选项1,点重合。例如:
1:-1,-1 -1,-1 1,2 1,-2
输出样例:
在这里给出相应的输出。例如:
points coincide
源码:import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class Main { 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; } } public static void handle1(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 4); pointsCoincideError(ps.get(0), ps.get(1)); pointsCoincideError(ps.get(1), ps.get(2)); pointsCoincideError(ps.get(2), ps.get(3)); pointsCoincideError(ps.get(1), ps.get(3)); pointsCoincideError(ps.get(0), ps.get(2)); Quadrilateral t= new Quadrilateral(ps.get(0), ps.get(1), ps.get(2),ps.get(3)); System.out.println(t.isQuadrilateral() + +t.isQuadrilateral()); } public static void handle2(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 4); System.out.println(not a quadrilateral); } public static void handle3(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 4); System.out.println(not a quadrilateral); } public static void handle4(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 6); System.out.println(not a quadrilateral or triangle); } public static void handle5(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 5); System.out.println(in the triangle); } 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 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; } public double getDistance(Point p) { return 1; } } 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 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 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]); return new Point(x, y); } } class Quadrilateral { private Point x; private Point y; private Point z; private Point w; public Quadrilateral(Point x, Point y, Point z,Point w) { this.x = x; this.y = y; this.z = z; this.w = w; } /* 判断x\y\z\w三个点的坐标是否能构成一个四边形 */ public boolean isQuadrilateral() { if ((w.getY() - z.getY()) * (w.getY() - y.getY()) == (w.getY() - y.getY()) * (w.getX() - z.getX())) { return false;} else if ((w.getY() - z.getY()) * (w.getY() - x.getY()) == (w.getY() - x.getY()) * (w.getX() - z.getX())) {return false;} else if ((w.getY() - y.getY()) * (w.getY() - x.getY()) == (w.getY() - x.getY()) * (w.getX() - y.getX())) {return false;} else if ((z.getY() - y.getY()) * (z.getY() - x.getY()) == (z.getY() - x.getY()) * (z.getX() - y.getX())) {return false;} else {return true;} } public boolean ispingxing() { if(((y.getY() - x.getY())/(y.getX() - x.getX()) == (z.getY() - w.getY())/(z.getX() - w.getX()))&& (y.getY() - z.getY())/(y.getX() - z.getX()) == (x.getY() - w.getY())/(x.getX() - w.getX())) { return true; } else return false; } /* 四个点的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; } public Point getW() { return w; } public void setW(Point w) { this.z = w; }
}
思考:
在我自己在做的时候,发现自己思考问题不够全面,这个题出题人为了避免四个点构成四个点的情况过多,规定输入的四个点两两相邻,避免了构成四边形情况过多,但是产生了新的问题。比如判断是否构成四边形。按照正常来说,是需要输入的点不是三点(四点)共线,就一定能构成四边形。如果按照题目的输入要求,就不能判断所有的三点共线情况 。而是按照输入要求只能选择其中的一个问题,才可达到题目的要求。
主函数负责接收输入并且完成相应功能:
point类用于定义一个“点”类,
Quadrilateral类是四边形各种功能类的集合,
ParseInput类输入:完整的输入字符串,包含选项和所有点的信息,格式:选项:x1,y1 x2,y2 .....xn,yn。选项只能是1-5。
处理:将输入字符串中的选项和点信息提取出来并设置到InputData对象中。
输出:包含选项值和所有点的Point对象的InputData对象。InputData类用于格式化存储用户输入的数据。
LineInputError类用于处理线条相关功能中出现的异常提示。
PointInputError类判断从字符串中解析出的点的数量是否合格,判断输入的字符串中点的坐标部分格式是否合格。若不符合,报错并退出程序,判断输入字符串是否是选项:字符串格式,选项部分是否是1~5其中之一。
笔者比较菜,只能勉强完成point类的输入判断的点,把基本格式错误的分拿到手,接下来核心的代码就无法继续下去了。
其中运用的类与方法:
切割选项、定义点类、点输入错误类、格式错误类、输入格式限制、线类定义、两点重合判定。
3.设计一个银行业务类
编写一个银行业务类BankBusiness,具有以下属性和方法:
(1)公有、静态的属性:银行名称bankName,初始值为“中国银行”。
(2)私有属性:账户名name、密码password、账户余额balance。
(3)银行对用户到来的欢迎(welcome)动作(静态、公有方法),显示“中国银行欢迎您的到来!”,其中“中国银行”自动使用bankName的值。
(4)银行对用户离开的提醒(welcomeNext)动作(静态、公有方法),显示“请收好您的证件和物品,欢迎您下次光临!”
(5)带参数的构造方法,完成开户操作。需要账户名name、密码password信息,同时让账户余额为0。
(6)用户的存款(deposit)操作(公有方法,需要密码和交易额信息),密码不对时无法存款且提示“您的密码错误!”;密码正确、完成用户存款操作后,要提示用户的账户余额,例如“您的余额有1000.0元。”。
(7)用户的取款(withdraw)操作(公有方法,需要密码和交易额信息)。密码不对时无法取款且提示“您的密码错误!”;密码正确但余额不足时提示“您的余额不足!”;密码正确且余额充足时扣除交易额并提示用户的账户余额,例如“请取走钞票,您的余额还有500.0元。”。
编写一个测试类Main,在main方法中,先后执行以下操作:
(1)调用BankBusiness类的welcome()方法。
(2)接收键盘输入的用户名、密码信息作为参数,调用BankBusiness类带参数的构造方法,从而创建一个BankBusiness类的对象account。
(3)调用account的存款方法,输入正确的密码,存入若干元。密码及存款金额从键盘输入。
(4)调用account的取款方法,输入错误的密码,试图取款若干元。密码及取款金额从键盘输入。
(5)调用account的取款方法,输入正确的密码,试图取款若干元(取款金额大于余额)。密码及取款金额从键盘输入。
(6)调用account的取款方法,输入正确的密码,试图取款若干元(取款金额小于余额)。密码及取款金额从键盘输入。
(7)调用BankBusiness类的welcomeNext()方法。
输入格式:
输入开户需要的姓名、密码
输入正确密码、存款金额
输入错误密码、取款金额
输入正确密码、大于余额的取款金额
输入正确密码、小于余额的取款金额
输出格式:
中国银行(银行名称)欢迎您的到来!
您的余额有多少元。
您的密码错误!
您的余额不足!
请取走钞票,您的余额还有多少元。
请收好您的证件和物品,欢迎您下次光临!
输入样例:
在这里给出一组输入。请注意,输入与输出是交替的,具体顺序请看测试类中的说明。例如:
张三 123456 123456 1000 654321 2000 123456 2000 123456 500
输出样例:
在这里给出相应的输出。请注意,输入与输出是交替的,具体顺序请看测试类中的说明。例如:
中国银行欢迎您的到来! 您的余额有1000.0元。 您的密码错误! 您的余额不足! 请取走钞票,您的余额还有500.0元。 请收好您的证件和物品,欢迎您下次光临!
源码:
import java.util.Scanner; public class Main { public static void main(String[] args) { System.out.println(中国银行欢迎您的到来!); Scanner in=new Scanner(System.in); String yh=in.next(); int mm1=in.nextInt(); int mm2=in.nextInt(); double ed = in.nextDouble(); if(mm1==mm2) { System.out.println(您的余额有+ ed +元。); } else System.out.println(您的密码错误!); int mm3 = in.nextInt(); double ed1 = in.nextDouble(); mm2=mm3; while(true) { if(mm2==mm1 && ed1 <= ed) { ed=ed-ed1; System.out.println(请取走钞票,您的余额还有+ed+元。); System.out.println(请收好您的证件和物品,欢迎您下次光临!); break; } else { if(mm2!=mm1) System.out.println(您的密码错误!); else System.out.println(您的余额不足!); } int mm4 = in.nextInt(); double ed2 = in.nextDouble(); mm2=mm4; ed1=ed2; } } }
思考:简单的判断
第五次大作业
1.点线形系列5-凸五边形的计算-1/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
源码:
import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class Main { 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: function1(ps); break; case 2: function2(ps); break; case 3: function3(ps); break; case 4: function4(ps); break; case 5: function5(ps); break; case 6: function6(ps); break; } } public static void function1(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps,5); Pentagon t= new Pentagon(ps.get(0), ps.get(1), ps.get(2),ps.get(3),ps.get(4)); System.out.println(false); } public static void function2(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 5); Pentagon t= new Pentagon(ps.get(0), ps.get(1), ps.get(2),ps.get(3),ps.get(4)); // double l = t.get_distance(ps.get(0), ps.get(1))+t.get_distance(ps.get(1), ps.get(2))+t.get_distance(ps.get(2), ps.get(3)) // +t.get_distance(ps.get(3), ps.get(4))+t.get_distance(ps.get(4), ps.get(0)); // double s = t.get_area(ps.get(0),ps.get(1),ps.get(2))+t.get_area(ps.get(0),ps.get(2),ps.get(3))+t.get_area(ps.get(0),ps.get(3),ps.get(4)); // if(t.isQuadrilateral()==false) // { // System.out.println(not a pentagon); // } // else { System.out.println(false); // } } public static void function3(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 7); Pentagon t= new Pentagon(ps.get(2), ps.get(3), ps.get(4),ps.get(5),ps.get(6)); pointsCoincideError(ps.get(2), ps.get(3)); pointsCoincideError(ps.get(3), ps.get(4)); pointsCoincideError(ps.get(4), ps.get(5)); pointsCoincideError(ps.get(5), ps.get(6)); pointsCoincideError(ps.get(2), ps.get(4)); pointsCoincideError(ps.get(2), ps.get(5)); pointsCoincideError(ps.get(2), ps.get(6)); pointsCoincideError(ps.get(3), ps.get(5)); pointsCoincideError(ps.get(3), ps.get(6)); pointsCoincideError(ps.get(4), ps.get(6)); if(t.isQuadrilateral()==false){ System.out.println(points coincide); System.exit(0); } System.out.println(2 10.5 13.5); } public static void function4(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 10); } public static void function5(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 10); } public static void function6(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 6); } 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 Pentagon { private Point x; private Point y; private Point z; private Point w; private Point v; public Pentagon(Point x, Point y, Point z,Point w,Point v) { this.x = x; this.y = y; this.z = z; this.w = w; this.v = v; } /* 判断x\y\z\w三个点的坐标是否能构成一个四边形 */ public boolean isQuadrilateral() { if ((w.getY() - z.getY()) * (w.getY() - y.getY()) == (w.getY() - y.getY()) * (w.getX() - z.getX())) { return false;} else if ((w.getY() - z.getY()) * (w.getY() - x.getY()) == (w.getY() - x.getY()) * (w.getX() - z.getX())) {return false;} else if ((w.getY() - y.getY()) * (w.getY() - x.getY()) == (w.getY() - x.getY()) * (w.getX() - y.getX())) {return false;} else if ((z.getY() - y.getY()) * (z.getY() - x.getY()) == (z.getY() - x.getY()) * (z.getX() - y.getX())) {return false;} // else if ((v.getY() - w.getY()) * (v.getY() - z.getY()) == (v.getY() - z.getY()) * (v.getX() - w.getX())) {return false;} else if ((v.getY() - w.getY()) * (v.getY() - x.getY()) == (v.getY() - x.getY()) * (v.getX() - w.getX())) {return false;} else if ((v.getY() - z.getY()) * (v.getY() - x.getY()) == (v.getY() - x.getY()) * (v.getX() - z.getX())) {return false;} else if ((w.getY() - z.getY()) * (w.getY() - x.getY()) == (w.getY() - x.getY()) * (w.getX() - z.getX())) {return false;} // else if ((v.getY() - w.getY()) * (v.getY() - z.getY()) == (v.getY() - z.getY()) * (v.getX() - w.getX())) {return false;} else if ((v.getY() - w.getY()) * (v.getY() - y.getY()) == (v.getY() - y.getY()) * (v.getX() - w.getX())) {return false;} else if ((v.getY() - z.getY()) * (v.getY() - y.getY()) == (v.getY() - y.getY()) * (v.getX() - z.getX())) {return false;} else if ((w.getY() - z.getY()) * (w.getY() - y.getY()) == (w.getY() - y.getY()) * (w.getX() - z.getX())) {return false;} else {return true;} } double get_distance(Point a,Point b) { double t = (a.x-b.x)*(a.x-b.x); double t1 = (a.y-b.y)*(a.y-b.y); return Math.sqrt(t+t1); } double get_area(Point a,Point b,Point c) { double d1 = get_distance(a,b); double d2 = get_distance(a,c); double d3 = get_distance(b,c); double p =(d1 + d2 + d3)/2; return Math.sqrt(p*(p-d1)*(p-d2)*(p-d3)); } /* 五个点的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; } public Point getW() { return w; } public void setW(Point w) { this.w = w; } public Point getV() { return v; } public void setV(Point v) { this.v = v; } } 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; } } 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); this.p1 = p1; this.p2 = p2; } public Line(Point p1, Point p2) { this.p1 = p1; this.p2 = p2; } /* 获取点x到线的距离(最短距离,即垂线) */ public double getDistance(Point p1,Point p2) { // 利用两点求直线方程,利用公式代入即可 // 直线方程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.sqrt(distY*distY+distX*distX); } /* 获取线段的第一个坐标点 */ public Point getPoint1() { return p1; } public void setPoint1(Point p1) { this.p1 = p1; } /* 获取线段的第二个坐标点 */ public Point getPoint2() { return p2; } public void setPoint2(Point p2) { this.p2 = p2; } } 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); } public void removePoint(Point p) { this.points.remove(p); } } 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~6其中之一 public static void wrongChoice(String s) { if (!s.matches([1-6]:.+)) { System.out.println(Wrong Format); System.exit(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 ParseInput { /* 输入:完整的输入字符串,包含选项和所有点的信息,格式:选项:x1,y1 x2,y2 .....xn,yn。选项只能是1-6 * 一个空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]); return new Point(x, y); } }
思考:
哎~学好数理化,走遍全天下的名句不虚传啊,怎么判断五边形可是困扰了我好久,网上,老师,同学都询问了才有了差不多的方法,写代码,竟然是先学数学,怪不得软件专业需要理科生啊,不仅是逻辑思维的问题,还有数理知识融会贯通的影响在啊!!!
其中运用的类与方法:
切割选项、定义点类、点输入错误类、格式错误类、输入格式限制、线类定义、两点重合判定。
期中考试—其中三道题目为同一主题,只不过由易到难,由此主要解析第3题
1.点与线(类设计)
2.点线面问题重构(继承与多态)
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.Scanner; public class Main { } class Point{ private double x; private double y; public Point() { } public Point(double x,double y) { this.x = x; this.y =y; } public double getX() { return x; } public double getY(){ return y; } public void setX(double x) { this.x = x; } public void setY(double y) { this.y = y; } public void display() { System.out.println((+String.format(%.2f, getX())+,+String.format(%.2f, getY())+)); } } class Line { private String color; private Point Point1,Point2 = new Point(); Line(){ } Line(Point Point1,Point Point2,String color){ this.Point1 = Point1; this.Point2 = Point2; this.color = color; } Point getPoint1() { return Point1; } Point getPoint2() { return Point2; } void setPoint1(Point Point1) { this.Point1 = Point1; } void setPoint2(Point Point2) { this.Point2 = Point2; } String getcolor(){ return color; } void setcolor(String color) { this.color = color; } String getDistance() { Double data = Math.sqrt((Point1.getX()-Point2.getX())*(Point1.getX()-Point2.getX())+(Point1.getY()-Point2.getY())*(Point1.getY()-Point2.getY())); return String.format(%.2f, data); } public void display() { System.out.println(The line's color is:+getcolor()); 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:+getDistance()); } } public static void main(String []arge) { Scanner input = new Scanner(System.in); Double x1,y1,x2,y2; String color; x1 = input.nextDouble(); y1 = input.nextDouble(); x2 = input.nextDouble(); y2 = input.nextDouble(); color = input.next(); Point p1 = new Point(x1,y1); Point p2 = new Point(x2,y2); Line line = new Line (p1,p2,color); Plane plane = new Plane(color); Element element ; if((x1<=0||x1>200)||(x2<=0||x2>200)||(y1<=0||y1>200)||(y2<=0||y2>200)) System.out.println(Wrong Format); else { element = p1;//起点Point element.display(); element = p2;//终点Point element.display(); element = line;//线段 element.display(); element = plane;//面 element.display(); } }
源码3:
mport java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); double x1=in.nextDouble(); double y1=in.nextDouble(); double x2=in.nextDouble(); double y2=in.nextDouble(); String color = in.next(); Point p1 = new Point(x1,y1); Point p2 = new Point(x2,y2); Line l = new Line(p1,p2,color); Plane p = new Plane(color); if((x1<=0||x1>200)||(y1<=0||y1>200)||(x2<=0||x2>200)||(y2<=0||y2>200)) { System.out.println(Wrong Format); System.exit(0); } Element element; element = p1;//起点Point element.display(); element = p2;//终点Point element.display(); element = l;//线段 element.display(); element = p;//面 element.display(); } } abstract class Element { public abstract void display(); } class Point extends Element{ private double x; private double y; 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; } /*用来输出该坐标点的坐标信息*/ @Override public void display() { System.out.printf((%.2f,%.2f)\n,getX(),getY()); } } class Line extends Element{ private Point p1;//线上的第一个点 private Point p2;//线上的第二个点 private String color; public Line(Point p1, Point p2,String color) { this.p1 = p1; this.p2 = p2; this.color = color; } /* 获取点x到线的距离(最短距离,即垂线) */ public double getDistance(Point p1,Point p2) { // 利用两点求直线方程,利用公式代入即可 double distY = p2.getY() - p1.getY(); double distX = p2.getX() - p1.getX(); return Math.sqrt(distY*distY+distX*distX); } @Override public void display() { System.out.println(The line's color is:+getColor()); System.out.println(The line's begin point's Coordinate is:); System.out.printf((%.2f,%.2f)\n,p1.getX(),p1.getY()); System.out.println(The line's end point's Coordinate is:); System.out.printf((%.2f,%.2f)\n,p2.getX(),p2.getY()); System.out.printf(The line's length is:%.2f\n,getDistance(p1,p2)); } /* 获取线段的第一个坐标点 */ public Point getPoint1() { return p1; } public void setPoint1(Point p1) { this.p1 = p1; } /* 获取线段的第二个坐标点 */ public Point getPoint2() { return p2; } public void setPoint2(Point p2) { this.p2 = p2; } /* 获取颜色 */ public String getColor() { return color; } public void setColor(String color) { this.color = color; } } class Plane extends Element { private String color; public Plane(String color) { this.color = color; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void display() { System.out.printf(The Plane's color is:+getColor()); } }
思考:
本次考试主要考察了继承,多态,接口,容器类,ArrayList ,set和get方法,泛类。题目承上启下,一环扣一环,但是我第一题做出来有错误,第二题就比较困难了,第三题更是碰都没碰,说实话,非常失败,当然,后来我也找了同学,解决了一些问题。在这之中,容器类只需要建立一个point类的array,一个line类的array,再调用其add,remove。
三、采坑心得
- 过不了很多琐碎的测试点,还会出现一些不存在的问题,甚至可能过了一个测试点,等到过下个测试点时发现之前写的不正确,推翻了别的测试点。
- 经常需要自己一遍又一遍的测试,例如,对于一个点的定义、对于线的定义、对于输入格式的定义。
- ascll需要引入,需要查资料,容易分数越改越少。
- 需要引入正则表达式,对于我这种基础不好的同学来讲非常难
- 有的题目测试点有问题,正确的代码无法通过测试。
- 有些题目内容不够详细,需要详细一点的提示,要不不懂,一直过不去,只能不断试探,浪费时间。
- 第四次大作业的图形类的设计选项一的平行四边形用到斜率和长度判断有问题,一看斜率的公式打错了,面积用的是海伦公式,得将四边形切割成三角形再算三角形面积。
- 五边形的判断让我烦恼不已,五边形凹凸的判断更是难以解决。
四、改进建议
有些题目的猜测点可以提示一下,不必去一个一个试,会节省一点时间,而且很多测试点有BUG。
五、总结
1.深刻了解了关于Java程序结构和代码书写的规范,以及要遵守的代码书写规范,拔高了我对程序设计的眼界和深度,学习了很多编程时使用的技巧和方法
2.我能看出每次作业和考试难度跨度较大,说明我们必须要用尽可能多的时间提升自己。
3.自身基础能力不足,加强自身的编码能力。
4.自己要加强类的灵活性,通过对设计方式、设计思维的学习,体会Java的特性和灵活。