Blog—two
作者:互联网
-
前言
1.PTA大作业四前言
本次习题集,共分为三道题,第一题考察了对于正则表达式的运用,相对于前几次运用正则表达式判断输入格式是否合法,本题对于正则表达式的考察更复杂一些,需要提取一段文字中的所有数字,"\\D+" 可以匹配多个除数字外的字符,运用split函数提取出一段文字的数字。
第二题是一个熟悉的点线面问题,难度颇大,要实现五个对于图形的处理的函数,考察了对于四边形图形之间的运用,期中要实现的 “ 输入六个点坐标,前两个点构成一条直线,后四个点构成一个四边形或三角形,输出直线与四边形(也可能是三角形)相交的交点数量。” 和 “ 输入五个点坐标,输出第一个是否在后四个点所构成的四边形 。” 的难度都相对较大,考察了逻辑思维能力和数学能力,以及将数学思维转换为代码的编程能力。 同时对于输入格式的判定也考察到了正则表达式。
第三题难度相对较小一些,要求设计一个银行业务类,考察了一些基本语法与类的设计,只要按照题目要求进行设计,没什么太大的问题。
2.期中考试前言
期中考试一共三道题,层层递进,每一题都对前一题进行改进,进行更深层面的运用面对对象语言去编程,同时引导我们一步步的去认识去熟悉面对对象编程的魅力,考察到了类的设计、类的继承、多态的使用、抽象类的设计、抽象方法的定义等等。第一题较为基础的设计了一个对于点、线之间的操作的编程实现,要求类成员都为私有类型。
第二题在第一题的基础上,要求利用继承去解决点、线问题,并要求加入一个面的类型,在使用继承类的时候要进行多态操作,使用到向上造型,设计好点类、线类、面类之后只要按照题目要求去设计一些解决基本数学问题的函数就可以,题目整体和第一题相差不大。
第三题就要求加入了容器类 ArrayList ,并且将继承和多态的操作融入其中,需要对 ArrayList 操作熟悉,例如ArrayList的定义,往里添加元素和删除元素,以及对ArrayList得到遍历等等,对继承和多态都要有一定的理解,也要求使用抽象类,抽象类不可用于声明对象,熟悉抽象类的运用问题也不大,同时第三题难度最大的部分就是容器类和继承类的结合使用问题,需要按照输入的序号来指定的定义点、线、面类,并执行其操作,且要删除ArrayList种指定位置的元素。
3.实验二前言
实验二分为一、二两部分,第一部分主要是考察了类与对象的基本概念、 类的声明、创建与使用方法、类的构造方法的定义与使用方法 、类的成员变量、成员方法的定义与使用方法 ,以及是否理解类变量、类方法与实例变量、实例方法的区别;第一题要设计一个农夫过河问题,狼会在人不在的时候吃羊,羊会在人不在的时候吃草,当理解如何才能赢得游戏之后,只需要简单进行类的设计,并设计好成功的路线,就剩下了一些基本语法。
实验二第二部分要求增加了船类,这就需要考虑到对于船停靠的岸边有哪些是可以上船的。还考察了是否理解引用变量与对象实例之间的关系与区别、方法调用时引用类型参数的传递过程、private、protected、public等关键的使用场合与使用方法、对象组合的方式与方法、java中方法重载的实现方式。还需要去对农夫、狼、羊、菜进行数据封装,在使用到继承类的时候,如何运用super也是一个关键点。
三次练习的难度不一,从普通编程再到面对对象入门,考察的知识面广,还有对于类的设计,使我更加深入的了解到类的使用方法,理解面对对象的含义。
- 设计与分析
① PTA大作业四第一题:
源码如下:
import java.util.Scanner;
import java.util.Arrays;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(true){
String line=sc.nextLine();
if(line.equals("end"))
break;
String[] s=line.split("\\D+");
int i;
long sum=0;
for(i=0;i<s.length;i++){
if(!s[i].equals(""))
{
int digit=Integer.parseInt(s[i]);
sum+=digit;
}
}
System.out.println(sum);
}
}
}
分析:
这里比较巧妙的避免了直接使用正则表达式语句,而是使用 String[] s=line.split("\\D+"); 分隔开文段当中的数据,提取出其中的全部数字,再全部加起来,最后算出答案。
② PTA大作业四第二题:
作为点线面系列,此题也是不出意料的先判断一个输入格式问题,对于这个问题,我们已经处理过很多遍了,把输入的字符串,分割成一个点的坐标 ( x , y ) 之后再去判断格式。
if(!(h[i].matches("[+-]?(([0-9]+[.]{1}[1-9]+)|([1-9]+[0-9]*)|(0){1}),[+-]?(([0-9]+[.]{1}[1-9]+)|([1-9]+[0-9]*)|(0){1})")))
利用这个正则表达式,就可以解决输入格式非法问题。
第一个函数:输入四个点坐标,判断是否是四边形、平行四边形 。对于判断是否是四边形,只需要判断是否对于这四个点,任意的三个点都不共线,是则说明这四个点可以构成一个四边形,代码如下:
double k1 = (y1-y2)/(x1-x2); double k2 = (y2-y3)/(x2-x3); double k3 = (y3-y4)/(x3-x4); double k4 = (y4-y1)/(x4-x1); if(k1!=k2&&k2!=k3&&k3!=k4&&k4!=k1){ System.out.print("true "); } else{ System.out.print("false "); }
对于平行四边形的判断,运用初中的数学知识,平行四边形的对边平行且相等,用一个count去记录,当count==2时,就说明这四个点可以构成一个平行四边形,代码如下:
int count=0; if((y1-y2)*(x3-x4)==(y3-y4)*(x1-x2)) count++; if((y1-y3)*(x2-x4)==(y2-y4)*(x1-x3)) count++; if((y1-y4)*(x2-x3)==(y2-y3)*(x1-x4)) count++; if(count==2){ System.out.print("true"); } else{ System.out.print("false"); } break;
第二个函数:输入四个点坐标,判断是否是菱形、矩形、正方形。同样考察了一些基本数学问题,其关键点在于如何把数学问题的解决方法用代码去实现, 菱形就是简单的计算四条边,判断四条边是否相等,而对于矩形,一个知识点就是对于两条垂直的直线,其斜率的关系为 k1 * k2 = -1 ,但是需要特别考虑的是斜率不存在的情况,而正方形就是四边相等的矩形,代码如下:
count=0;
if((y1-y2)*(x3-x4)==(y3-y4)*(x1-x2)) count++; if((y1-y3)*(x2-x4)==(y2-y4)*(x1-x3)) count++; if((y1-y4)*(x2-x3)==(y2-y3)*(x1-x4)) count++; double A = Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); double B = Math.sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)); if(count==2 && A==B){ System.out.print("true "); } else{ System.out.print("false "); } if(count==2 && (k4*k1==-1 || y4==y3&&y3==0&&x1==x4 || y1==y4&&y4==0&&x3==x4 ) ){ System.out.print("true "); } else{ System.out.print("false "); } if(count==2 && (k4*k1==-1 || y4==y3&&y3==0&&x1==x4 || y1==y4&&y4==0&&x3==x4 ) && A==B){ System.out.print("true"); } else{ System.out.print("false"); }
从第三个函数开始,后面三个函数的难度都很大,要把其中的数学解决方法转换为代码实现,都有一定的难度,第三个函数提出了一个凹四边形与凸四边形,并去计算四边形的周长与面积,这个函数相对于后面两个函数还相对简单一点。
第四个函数开始难度就相当大了,题面:( 输入六个点坐标,前两个点构成一条直线,后四个点构成一个四边形或三角形,输出直线与四边形(也可能是三角形)相交的交点数量。如果交点有两个,再按面积从小到大输出四边形(或三角形)被直线分割成两部分的面积(不换行)。若直线与四边形或三角形的一条边线重合,输出"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 )
解决难度很大,并没有什么好的方法。
第五个函数 题面为:( 输入五个点坐标,输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形(判定方法见选项4)的内部(若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。如果点在多边形的某条边上,输出"on the triangle或者on the quadrilateral"。若后四个点不符合四边形或三角形,输出"not a quadrilateral or triangle"。 )
难度也不小,暂时没有什么好的解决办法。
3.PTA大作业四第三题
第三题难度较小,只需要按部就班的依照题面的要求去设计程序就好,代码如下:
import java.util.Scanner; public class Main{ static Scanner in = new Scanner(System.in); public static void main(String [] args) { BankBusiness.welcome(); //System.out.println("请输入您的用户名:"); String name = in.next(); // System.out.println("请输入您的密码:"); String password = in.next(); BankBusiness account = new BankBusiness(name,password); // System.out.println("请输入您的密码:"); String p1 = in.next(); double n1 = in.nextDouble(); // double balance1 = in.nextDouble(); account.deposit(p1,n1); String p2 = in.next(); double n2 = in.nextDouble(); account.withdraw(p2,n2); String p3 = in.next(); double n3 = in.nextDouble(); account.withdraw(p3,n3); String p4 = in.next(); double n4 = in.nextDouble(); account.withdraw(p4,n4); account.bye(); } static class BankBusiness { Scanner in = new Scanner(System.in); public static String bankName = "中国银行"; private String name = ""; private String password = ""; private double balance = 0; BankBusiness(String name,String password){ this.name = name; this.password = password; this.balance = 0; } public static void welcome() { System.out.println(bankName+"欢迎您的到来!"); } public void bye() { System.out.println("请收好您的证件和物品,欢迎您下次光临!"); } public void deposit(String p,double now) { if(p.equals(password)) { //System.out.println("密码正确,请输入要存入的金额:"); //double now = in.nextDouble(); balance += now; System.out.print("您的余额有"); System.out.printf("%.1f元。\n",balance); } else { System.out.println("您的密码错误!"); } } public void withdraw(String p,double now) { if(p.equals(password)) { //System.out.println("密码正确,请输入要取出的金额:"); //double now = in.nextDouble(); if(balance < now) { System.out.println("您的余额不足!"); } else { balance -= now; System.out.print("请取走钞票,您的余额还有"); System.out.printf("%.1f元。\n",balance); } } else { System.out.println("您的密码错误!"); } } } }
4.期中考试第一题
- 第一题简单的要求设计一个线段类,一个点类,按要求计算线段的长度,然后设计一个display 方法按要求输出所有的信息。类图如下
- 期中考试的第二题在第一题的基础上加一个抽象类,并且增加了一个面类,要求实现多态的特性,题目要求相差不大,主要在于继承与抽象类的运用,抽象类的设计如下:
static abstract class Element{ public abstract void display(); }
注意定义抽象方法的时候,只需要声明抽象方法,不需要方法体,不用加上大括号 “ { ” 与 “ } ” 。
类的继承:
static class Point extends Element static class Line extends Element static class Plane extends Element
多态的使用: 向上造型,父类的管理者可以去管理一个子类的对象 。
Element element = p1; element.display(); element = p2; element.display(); element = l; element.display(); element = p; element.display();
向高手学习一个封装的保留对应位小数的方法:
double zh(double a){
String x=a+"";
String z[]=x.split("\\.");
if(z[1].length()>3) {
x = String.format("%.3f",a);
a = Double.parseDouble(x);
}
return a;
}
- 期中考试的最后一题,要求使用一个泛型容器类去储存 Element 类
类图如下:
在主方法中,用户循环输入要进行的操作(choice∈[0,4]),其含义如下:
1:向容器中增加Point对象
2:向容器中增加Line对象
3:向容器中增加Plane对象
4:删除容器中第index - 1个数据,若index数据非法,则无视此操作
0:输入结束
由上一个 blog 我们已经知道用一个switch来解决这个问题可以有效节省圈层复杂度,对于使用remove删除ArrayList里的元素的时候,需要注意的是,如果该位置已经没有元素了,则不需要去进行删除操作,所以需要一个 if 语句判断去处理这个特殊情况。这部分代码如下:
while(a!=0){ switch(a) { case 1: double x = in.nextDouble(); double y = in.nextDouble(); Point p1 = new Point(x,y); g.add(p1); break; case 2: double x1 = in.nextDouble(); double x2 = in.nextDouble(); double x3 = in.nextDouble(); double x4 = in.nextDouble(); String s = in.next(); p1 = new Point(x1,x2); Point p2 = new Point(x3,x4); Line l = new Line(p1,p2,s); g.add(l); break; case 3: s = in.next(); Plane p = new Plane(s); g.add(p); break; case 4: int index = in.nextInt(); if(index<=g.geo.size()){ g.remove(index); } break; case 0: return ; }
这道题目的关键就在于 容器类的设计 以及 ArrayList 的泛型运用,容器类需要定义一个私有属性的 ArraList ,对于容器类自己设计的 remove 方法,需要注意的是,删除传进来的下标 index 的前一个元素。类设计代码如下:
static class GeometryObject{ private ArrayList<Element> geo = new ArrayList<>(); GeometryObject(){ } GeometryObject(ArrayList<Element> g){ this.geo = g; } void add(Element element) { geo.add(element); } void remove(int index) { geo.remove(index-1); } ArrayList<Element> getList(){ return geo; } }
5.实验二——农夫过河游戏设计
对于农夫过河游戏,需要设计一个农夫类、狼类、羊类、船类、菜类,我们可以发现,对于这几个类,其中都有很多相同之处,如果每个类都去详细的设计,会发现有很多的代码重复,代码重复是一个程序质量不高的体现,我们要避免这个现象,可想而知需要运用到类的继承,我们可以先设计一个通用类 —— NPC类 ,NPC 类里面包含他们的通用属性,例如名字等,在子类中去完善其独特的内容,例如在狼类中需要一个 EatSheep() 方法,羊类中需要一个 EatCabbage() 方法,而船需要运输农夫或者带上其他物品,则需要完善一个 Transport() 方法。
- 踩坑心得
- 开始并不了解正则表达式,完全按照题目要求一个一个去写判断输入合法的条件,一提交就发现各种问题,包括重复零输入和小数点后无数字等等,反复修改代码,在磕磕绊绊中写完第一题之后才开始了解到正则表达式,只需要一行代码就可以解决全部的输入合法问题,一行抵十几行。
- 声明对象数组之后,每次使用该对象数组元素时都需要重新new一下,不然其为空。
- 对于浮点型数据,判断三条边是否构成直角三角形时,使用勾股定理不能简单的写成:
if(a*a+b*b==c*c || b*b+c*c==a*a || c*c+a*a==b*b)
要考虑浮点型数据的误差,可写成:
if(((a==b)&&Math.abs(a*a+b*b-c*c)<1e-6)||((c==a)&&Math.abs(c*c+a*a-b*b)<1e-6)||((c==b)&&Math.abs(c*c+b*b-a*a)<1e-6))
对于抽象方法的定义,不需要定义方法体:
public abstract void display();
- 改进建议
1. 在定义方法时,需要适当的采取简便方法降低算法的复杂度,完全暴力不光复杂度高,而且代码冗长,可读性差。
2. 添加注释,并不是每次都有充足的时间一次性完成这个程序,若不添加注释,隔了一段时间后再来看自己写的代码,发现都不知道自己在写什么,加上一些注释,方便之后的查阅和修改。
3. 对代码实现模块化,自顶而下,逐步细化,根据所需要求固定一个大方向,比如设计一个类,再去考虑定义方法一个一个去解决题目的要求。
4. 尽可能减少代码复用,提高代码质量。
- 总结
①通过三次大作业,更加理解了java这门语言,熟练了使用java语言来编写程序解决问题,尤其是大作业三,让我对面对对象程序设计初窥门径。
②通过大作业三,学到了正则表达式,合理的运用正则表达式能够节省很多不必要的分支判断,提高效率,使代码更加简洁。
③也因为三次大作业了解到了许多关于字符串操作方面的方法,如split、substring、charAT等等,对字符串操作更加娴熟。
④关于类的设计与类的应用,也有了一个新的层面的认知和经验,这是面对对象的魅力所在。
⑤这三次作业,让我的编程能力更进一步,了解到更多不曾知晓或者不够熟悉的知识点,初步形成了面对对象编程的思想。
标签:String,double,two,System,Blog,&&,四边形,out 来源: https://www.cnblogs.com/330zrm/p/16250804.html