第二次博客作业
第二次博客作业
一、 前言
经过一段时间的接触和多次的练习,我已经开始熟悉Java这门编程语言了,但有些问题还是不能解决,说明我还需要更深入的学习。PTA最近的几次作业对我来说难度都非常大,有两次PTA作业没有拿到满分。因为PTA三次作业是迭代的,所以第一次没解决的问题在下一次作业中还存在,并且更复杂了,这就让我做起来的感觉很难受。尽管如此,我还是尽自己的最大能力取得了一个勉强可以的成绩(80以上)。至于期中考试和超星的链表类练习题目,我都能轻松解决,毕竟是比较基础的练习。PTA三次题目集的情况如下:
- 题目集04
题量不大,但是难度集中在一个点上,第三题我没能满分。知识点主要有:多态的应用,DecimalFormat类的应用,边界值判断等。
- 题目集05
题量适中,难度对我来说适中。知识点主要有:正则表达式的应用,字符串的处理等。
- 题目集06
题量不大,难度集中在第二题,这题就是题目集04中第三题的升级版,我同样没满分。知识点主要有:正则表达式的应用,字符串的处理,多态的应用等。
二、 设计与分析
下面我将要对这三次的题目集和期中考试,超星的链表类练习进行详细分析,重点是对源码的分析,解释和完成题目后的心得。分析如下:(以下均是我个人的理解,可能与标准说法不同,请见谅)
- 题目集04
这次题目集第一题很简单,第二题偏难,但花点时间还是可以满分的,第三题很难,我试了很多次都不能满分。下面分析第三题:
7-3 点线形系列3-三角形的计算:
本题思路是输入选择,将五个功能做成五个方法,每个方法对应一个选择,可以添加一些辅助方法。主要代码如下:(辅助方法已略去)
Main类:
public class Main { //main方法: public static void main(String[] args) { Scanner in = new Scanner(System.in); String str=in.nextLine(); if(checkvalid(str)) { //辅助方法 char choice=str.charAt(0); //处理选项 switch(choice) { case '1':{ part1(str.substring(2,str.length()));//处理输入的坐标 }break; case '2':{ part2(str.substring(2,str.length())); }break; case '3':{ part3(str.substring(2,str.length())); }break; case '4':{ part4(str.substring(2,str.length())); }break; case '5':{ part5(str.substring(2,str.length())); } } } else System.out.println("Wrong Format"); }
功能1:
public static void part1(String str) { String[] s=str.split(" "); //分割出单个坐标 if(count(str)>=2) { Point p1=new Point(s[0]); //自定义的Point类 Point p2=new Point(s[1]); Point p3=new Point(s[2]); if(p1.valid()&&p2.valid()&&p3.valid()) { if(count(str)==2) { Triangle t=new Triangle(p1,p2,p3);//自定义的Triangle类 if(t.geta()+t.getb()<=t.getc()||t.geta()+t.getc()<=t.getb()||t.getb()+t.getc()<=t.geta()) System.out.println("data error"); else if(t.geta()==t.getb()&&t.getb()==t.getc()) System.out.println("true true"); else if(t.geta()==t.getb()||t.getb()==t.getc()||t.geta()==t.getc()) System.out.println("true false"); else System.out.println("false false"); } else over(str); //辅助方法,判断是否输出点数量的错误 } else System.out.println("Wrong Format"); } else over(str); }
功能2:
public static void part2(String str) { String[] s=str.split(" "); if(count(str)>=2) { Point p1=new Point(s[0]); Point p2=new Point(s[1]); Point p3=new Point(s[2]); if(p1.valid()&&p2.valid()&&p3.valid()) { if(count(str)==2) { Triangle t=new Triangle(p1,p2,p3); if(t.geta()+t.getb()<=t.getc()||t.geta()+t.getc()<=t.getb()||t.getb()+t.getc()<=t.geta()) System.out.println("data error"); else { double p=(t.geta()+t.getb()+t.getc())/2; double area=Math.abs( Math.sqrt( p*(p-t.geta())*(p-t.getb())*(p-t.getc()) ) ); //海伦公式计算面积 double x1,x2,y1,y2,x3,y3,x,y; x1=Double.parseDouble(p1.sub()[0]); y1=Double.parseDouble(p1.sub()[1]); x2=Double.parseDouble(p2.sub()[0]); y2=Double.parseDouble(p2.sub()[1]); x3=Double.parseDouble(p3.sub()[0]); y3=Double.parseDouble(p3.sub()[1]); x=(x1+x2+x3)/3; y=(y1+y2+y3)/3; DecimalFormat d=new DecimalFormat("0.0#####"); //规定小数点后的位数 System.out.println(d.format(2*p)+" "+d.format(area)+" "+d.format(x)+","+d.format(y)); } } else over(str); } else System.out.println("Wrong Format"); } else over(str); }
功能3:
public static void part3(String str) { String[] s=str.split(" "); if(count(str)>=2) { Point p1=new Point(s[0]); Point p2=new Point(s[1]); Point p3=new Point(s[2]); if(p1.valid()&&p2.valid()&&p3.valid()) { if(count(str)==2) { Triangle t=new Triangle(p1,p2,p3); if(t.geta()+t.getb()<=t.getc()||t.geta()+t.getc()<=t.getb()||t.getb()+t.getc()<=t.geta()) System.out.println("data error"); else { //cos()是辅助方法 double cos1=cos(t.geta(), t.getb(), t.getc()); double cos2=cos(t.getb(), t.getc(), t.geta()); double cos3=cos(t.geta(), t.getc(), t.getb()); if(cos1<-0.000005||cos2<-0.000005||cos3<-0.000005) System.out.println("true false false"); else if(Math.abs(cos1)<0.000005||Math.abs(cos2)<0.000005||Math.abs(cos3)<0.000005) System.out.println("false true false"); else if(cos1>0&&cos2>0&&cos3>0) System.out.println("false false true"); } } else over(str); } else System.out.println("Wrong Format"); } else over(str); }
功能4:
代码过长,而且没有全对,此处略去。
功能5:(没有全对,一个测试点没通过)
public static void part5(String str) { String[] s=str.split(" "); if(count(str)>=3) { Point p1=new Point(s[0]); Point p2=new Point(s[1]); Point p3=new Point(s[2]); Point p4=new Point(s[3]); if(p1.valid()&&p2.valid()&&p3.valid()&&p4.valid()) { if(count(str)==3) { double x1,x2,y1,y2,x3,y3,x4,y4; x1=Double.parseDouble(p1.sub()[0]); y1=Double.parseDouble(p1.sub()[1]); x2=Double.parseDouble(p2.sub()[0]); y2=Double.parseDouble(p2.sub()[1]); x3=Double.parseDouble(p3.sub()[0]); y3=Double.parseDouble(p3.sub()[1]); x4=Double.parseDouble(p4.sub()[0]); y4=Double.parseDouble(p4.sub()[1]); Triangle t=new Triangle(p2,p3,p4); Triangle t1=new Triangle(p1,p2,p3); Triangle t2=new Triangle(p1,p3,p4); Triangle t3=new Triangle(p1,p2,p4); if(t.geta()+t.getb()<=t.getc()||t.geta()+t.getc()<=t.getb()||t.getb()+t.getc()<=t.geta()) System.out.println("data error"); else { //边界判断 if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x1==x4&&y1==y4)) System.out.println("on the triangle"); else if((y1-y2)/(x1-x2)==(y2-y3)/(x2-x3)||(y1-y3)/(x1-x3)==(y3-y4)/(x3-x4)||(y1-y4)/(x1-x4)==(y2-y4)/(x2-x4)) System.out.println("on the triangle"); else { double area1=Math.abs(((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)))/2.0; double area2=Math.abs(((x3-x1)*(y4-y1)-(x4-x1)*(y3-y1)))/2.0; double area3=Math.abs(((x2-x1)*(y4-y1)-(x4-x1)*(y2-y1)))/2.0; double area=Math.abs(((x3-x2)*(y4-y2)-(x4-x2)*(y3-y2)))/2.0; if(area1+area2+area3>area) System.out.println("outof triangle"); else System.out.println("in the triangle"); } } } else over(str); } else System.out.println("Wrong Format"); } else over(str); } }
本题类图如下:
- 题目集05
这次题目集主要是学习和应用正则表达式,所以前四道题目都比较基础,第五题稍微难一点。下面分析第五题:
7-5 ATM机类结构设计(一):
本题的关键在于用户数据的储存,并且能够随时更新用户数据。大体思路是:创建User类初始化用户数据,Card类复制当前ATM机中的银行卡中的用户数据,ATM类对用户数据进行操作,使用字符串数组和实数数组存储用户名称和余额。
类图如下:
主要代码如下:
Main类:
public class Main { public static void main(String[] args) { ATM atm=new ATM(); atm.play(); } }
Card类:
class Card{ String cardnum; String name; String key; double balance; Card(){ } public String getNum() { return cardnum; } public String getName() { return name; } public String getKey() { return key; } public double getBalance() { return balance; } }
User类:
class User{ String name; static String key="88888888"; String[] cardnum=new String[100]; String atm; public User(String n,String[] c,String a){ this.name=n; this.cardnum=c; this.atm=a; } }
ATM类:
class ATM{ //储存用户数据 private Card card; String[] cardnum1= {"6217000010041315709","6217000010041315715","6217000010041315718"}; String[] cardnum2= {"6217000010051320007"}; String[] cardnum3= {"6222081502001312389","6222081502001312390","6222081502001312399","6222081502001312400"}; String[] cardnum4= {"6222081502051320785","6222081502051320786"}; double[] balance1= {10000.00,10000.00}; double[] balance2= {10000.00}; double[] balance3= {10000.00,10000.00,10000.00}; double[] balance4= {10000.00,10000.00}; //规定小数点后的位数 DecimalFormat d=new DecimalFormat("0.00"); //初始化用户数据 private User user1=new User("杨过",cardnum1,"0[1-4]"); private User user2=new User("郭靖",cardnum2,"0[1-4]"); private User user3=new User("张无忌",cardnum3,"0[5-6]"); private User user4=new User("韦小宝",cardnum4,"0[5-6]"); ATM(){ card = new Card(); } public void play() { Scanner in = new Scanner(System.in); String[] str = new String[100]; int c=0; //复制用户数据 for(int i=0;;i++) { str[i]=in.nextLine(); c++; if(str[i].contains("#")) break; } for(int i=0;i<c-1;i++) { String[] operate= new String[100]; if(str[i].contains(" ")) { operate = str[i].split("\\s+");//使用正则表达式,判断以一个或多个空格分割 card.cardnum=operate[0]; card.key= operate[1]; String atm = operate[2]; double amount = Double.parseDouble(operate[3]); //先判断卡号是否存在,再判断使用的是哪个银行账户,然后再进行接下来的操作 if(card.getNum().matches(user1.cardnum[0])||card.getNum().matches(user1.cardnum[1])||card.getNum().matches(user1.cardnum[2])) { if(card.getKey().matches(User.key)) { if(atm.matches(user1.atm)) { if(amount>=0) { //代码太长,此处省略,大体结构同上 ……… else if(card.getNum().matches(user4.cardnum[0])||card.getNum().matches(user4.cardnum[1])) { if(card.getNum().matches(user4.cardnum[0])) System.out.println("¥"+d.format(balance4[0])); else System.out.println("¥"+d.format(balance4[1])); } else System.out.println("Sorry,this card does not exist."); } } } }
- 题目集06
本次题目集重点在于第二题(图形类的设计),其他两题都很基础。关于第二题,我最后试了所有给出的用例,并且得出了正确的结果,但是还是没能拿到全部分数,因为我实在想不到还有哪种测试用例了。下面分析第二题:
7-2 点线形系列4-凸四边形的计算:
这题我尝试了很多次,甚至有一次代码超长了。难点在于不仅要考虑四边形的情况,还要考虑后四个点只能构成三角形的情况,于是代码长度一下子增加了不少,而且还有很多结构重复。大体思路和题目集04的第三题差不多,但是考虑的情况的复杂度很高:先考虑四边形的所有情况,然后考虑构成三角形的情况,如果都不符合则输出不构成四边形或三角形。
类图如下:
主要代码如下:
Main类(main方法):
public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String str=in.nextLine(); if(checkvalid(str)) { char choice=str.charAt(0);//判断选项 switch(choice) { case '1':{ part1(str.substring(2,str.length())); }break; case '2':{ part2(str.substring(2,str.length())); }break; case '3':{ part3(str.substring(2,str.length())); }break; case '4':{ part4(str.substring(2,str.length())); }break; case '5':{ part5(str.substring(2,str.length())); } } }else System.out.println("Wrong Format"); }
功能1:
public static void part1(String str) { String[] s=str.split(" "); if(count(str)>=3) { Point p1=new Point(s[0]); Point p2=new Point(s[1]); Point p3=new Point(s[2]); Point p4=new Point(s[3]); if(p1.valid()&&p2.valid()&&p3.valid()&&p4.valid()) { double x1,y1,x2,y2,x3,y3,x4,y4; x1=Double.parseDouble(p1.sub()[0]); y1=Double.parseDouble(p1.sub()[1]); x2=Double.parseDouble(p2.sub()[0]); y2=Double.parseDouble(p2.sub()[1]); x3=Double.parseDouble(p3.sub()[0]); y3=Double.parseDouble(p3.sub()[1]); x4=Double.parseDouble(p4.sub()[0]); y4=Double.parseDouble(p4.sub()[1]); Quadrilateral q= new Quadrilateral(p1, p2, p3, p4); if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x1==x4&&y1==y4)||(x2==x3&&y2==y3)||(x2==x4&&y2==y4)||(x3==x4&&y3==y4)) System.out.println("points coincide"); else { if(q.valid()){ if(q.distance(p1, p2)==q.distance(p3, p4)&&q.distance(p2, p3)==q.distance(p1, p4)) System.out.println("true true"); else System.out.println("true false"); }else System.out.println("false false"); } }else System.out.println("wrong number of points"); }else System.out.println("wrong number of points"); }
功能2:
public static void part2(String str) { String[] s=str.split(" "); if(count(str)>=3) { Point p1=new Point(s[0]); Point p2=new Point(s[1]); Point p3=new Point(s[2]); Point p4=new Point(s[3]); if(p1.valid()&&p2.valid()&&p3.valid()&&p4.valid()) { double x1,y1,x2,y2,x3,y3,x4,y4; x1=Double.parseDouble(p1.sub()[0]); y1=Double.parseDouble(p1.sub()[1]); x2=Double.parseDouble(p2.sub()[0]); y2=Double.parseDouble(p2.sub()[1]); x3=Double.parseDouble(p3.sub()[0]); y3=Double.parseDouble(p3.sub()[1]); x4=Double.parseDouble(p4.sub()[0]); y4=Double.parseDouble(p4.sub()[1]); Quadrilateral q= new Quadrilateral(p1, p2, p3, p4); if(q.valid()) { if(q.distance(p1, p2)==q.distance(p2, p3)&&q.distance(p2, p3)==q.distance(p3, p4)&&q.distance(p3, p4)==q.distance(p4, p1)) { if((x1==x2||x1==x4)||(((y1-y2)*(y1-y4))/((x1-x2)*(x1-x4))==-1)) System.out.println("true true true"); else System.out.println("true false false"); }else if(q.distance(p1, p2)==q.distance(p3, p4)&&q.distance(p2, p3)!=q.distance(p3, p4)&&q.distance(p2, p3)==q.distance(p4, p1)){ if((x1==x2||x1==x4)||(((y1-y2)*(y1-y4))/((x1-x2)*(x1-x4))==-1)) { System.out.println("false true false"); }else System.out.println("false false false"); }else System.out.println("false false false"); }else System.out.println("not a quadrilateral"); }else System.out.println("wrong number of points"); }else System.out.println("wrong number of points"); }
功能3:
public static void part3(String str) { String[] s=str.split(" "); DecimalFormat d=new DecimalFormat("0.0##"); if(count(str)>=3) { Point p1=new Point(s[0]); Point p2=new Point(s[1]); Point p3=new Point(s[2]); Point p4=new Point(s[3]); if(p1.valid()&&p2.valid()&&p3.valid()) { double x1,y1,x2,y2,x3,y3,x4,y4; x1=Double.parseDouble(p1.sub()[0]); y1=Double.parseDouble(p1.sub()[1]); x2=Double.parseDouble(p2.sub()[0]); y2=Double.parseDouble(p2.sub()[1]); x3=Double.parseDouble(p3.sub()[0]); y3=Double.parseDouble(p3.sub()[1]); x4=Double.parseDouble(p4.sub()[0]); y4=Double.parseDouble(p4.sub()[1]); Quadrilateral q= new Quadrilateral(p1, p2, p3, p4); if(q.valid()) { //判断点在直线的哪一侧 double d1=(y4-y2)*x1+(x2-x4)*y1+x4*y2-x2*y4; double d2=(y3-y1)*x2+(x1-x3)*y2+x3*y1-x1*y3; double d3=(y4-y2)*x3+(x2-x4)*y3+x4*y2-x2*y4; double d4=(y3-y1)*x4+(x1-x3)*y4+x3*y1-x1*y3; if((d1>0&&d3<0&&d2<0&&d4>0)||(d1<0&&d3>0&&d2>0&&d4<0)) { System.out.print("true "); }else System.out.print("false "); System.out.println(d.format(q.distance(p1, p2)+q.distance(p2, p3)+q.distance(p3, p4)+q.distance(p1, p4))+" "+d.format(q.getArea())); }else System.out.println("not a quadrilateral"); }else System.out.println("wrong number of points"); }else System.out.println("wrong number of points"); }
功能4:
代码过长,而且没有全对,此处略去。
功能5:(没有全对)
public static void part5(String str) { String[] s=str.split(" "); if(count(str)>=4) { Point p1=new Point(s[0]); Point p2=new Point(s[1]); Point p3=new Point(s[2]); Point p4=new Point(s[3]); Point p5=new Point(s[4]); if(p1.valid()&&p2.valid()&&p3.valid()&&p4.valid()&&p5.valid()) { double x1,y1,x2,y2,x3,y3,x4,y4,x5,y5; x1=Double.parseDouble(p1.sub()[0]); y1=Double.parseDouble(p1.sub()[1]); x2=Double.parseDouble(p2.sub()[0]); y2=Double.parseDouble(p2.sub()[1]); x3=Double.parseDouble(p3.sub()[0]); y3=Double.parseDouble(p3.sub()[1]); x4=Double.parseDouble(p4.sub()[0]); y4=Double.parseDouble(p4.sub()[1]); x5=Double.parseDouble(p5.sub()[0]); y5=Double.parseDouble(p5.sub()[1]); Quadrilateral q = new Quadrilateral( p2, p3, p4, p5); //四边形的情况 if(q.valid()) { double d1=(y3-y2)*x1+(x2-x3)*y1+x3*y2-x2*y3; double d2=(y4-y3)*x1+(x3-x4)*y1+x4*y3-x3*y4; double d3=(y5-y4)*x1+(x4-x5)*y1+x5*y4-x4*y5; double d4=(y2-y5)*x1+(x5-x2)*y1+x2*y5-x5*y2; if((d1>0&&d2>0&&d3>0&&d4>0)||(d1<0&&d2<0&&d3<0&&d4<0)) System.out.println("in the quadrilateral"); else if(d1==0||d2==0||d3==0||d4==0) System.out.println("on the quadrilateral"); else System.out.println("outof the quadrilateral"); } //三角形的情况 else if(x2==x3&&y2==y3) in(p1,p3,p4,p5); else if(x3==x4&&y3==y4) in(p1,p2,p4,p5); else if(x4==x5&&y4==y5) in(p1,p2,p3,p5); else if(x5==x2&&y5==y2) in(p1,p3,p4,p2); else if((y4-y2)*x3+(x2-x4)*y3+x4*y2-x2*y4==0) in(p1,p2,p4,p5); else if((y5-y3)*x4+(x3-x5)*y4+x5*y3-x3*y5==0) in(p1,p2,p3,p5); else if((y2-y4)*x5+(x4-x2)*y5+x2*y4-x4*y2==0) in(p1,p3,p4,p2); else System.out.println("not a quadrilateral or triangle"); }else System.out.println("wrong number of points"); }else System.out.println("wrong number of points"); } }
- 期中考试
期中考试的题目都比较基础,而且三道题目是迭代的,我没有花费很长的时间就完成了。下面简单分析一下:
7-1 点与线(类设计):
设计两个类:Point,Line。然后跟着题目给出的步骤就可以完成了。使用String.format("(%.2f,%.2f)", x,y)来控制输出数据的小数点位数。
7-2 点线面问题重构(继承与多态)
在第一题的基础上,添加Plane类和三个类的共同父类Element(抽象类),将display()方法在父类方法中进行声明(抽象方法)。然后创建父类的对象,再进行子类的操作。
7-3 点线面问题再重构(容器类)
在第二题的基础上,添加容器和泛型,将main方法重构,添加容器类GeometryObject,从而进行增、删、遍历操作。
- 超星的链表类练习
单向链表:
在java中,将节点的结构体做成节点类,创建链表及增删查改操作放入链表类,然后在Main类中测试即可。定义接口后,则链表类需要实现接口中的方法(implements)。
双向链表:
与单向链表结构相似,只不过是多了一个前驱指针,将代码稍微改一下就可以了。
三、 采坑心得
在完成这3次题目集的过程中,我遇到了许多的问题,下面将对我遇到一些的问题分享一下我的心得:
首先,我感觉在完成题目的过程中有很多数学知识点的应用,其中一些是我之前从未接触过的,感觉学习了解析几何的一些知识点。其次,就是情况的判断太多,比如题目集06的第二题,有十几种情况的判断,有时候会让我感觉很头疼,总是会漏掉一些情况。然后就是,因为不知道哪些情况漏了,后面改进十分困难,不知道哪种测试用例不能通过。
四、 改进建议
在编写代码之前,最好理清思路和逻辑,再着手尝试。(希望如此)
先考虑创建的类需要实现哪些功能,再根据逻辑编写代码。尤其需要注意边界值的测试和每一种情况的单独考虑,逐步将情况细化。
五、 总结
在完成这三次题目集的过程中,我遇到了很多困难,也收获了很多知识点。尽管我总是被难题虐到心累,我还是愿意继续不断的尝试,直到正确。之后,我需要学习和改进的地方还有很多,但是我会尽量使自己变得更优秀。靠自己的努力得到的满分,才是满满的成就感!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?