第二次blog

(1)PTA题目集、超星作业以及期中考试的总结性前言

知识点总结:

1.对象的继承关系.
2.对于抽象类的认识与使用.
3.对于四边形的各种形状判断和面积分割的方法求解.
4.正则表达式的使用.
5.ArrayList类中的增、删、减、查的各个作用.

 

 题目量:题目集四共三道,期中考试共三道,农夫过河一道.

 

题目难度:题目集四中的三、四尤其是三较难,期中考试三道题难度是过渡的,一、二、三三道题难度依次增大,其中第三道是有关容器类保存点 、线、面难度较大,农夫过河给了大部分源代码,只需要加上一些父类添加适合的属性和方法即可,因此算是比较简单的一个.

 

(2)设计与分析:

题目集四7-1 sdut-String-2 识蛟龙号载人深潜,立科技报国志(II)(正则表达式): 

import java.util.Scanner; import java.util.Arrays; public class Main{     public static void main(String[] args){         Scanner in=new Scanner(System.in);         while(true){             String s=in.nextLine();             if(s.equals(end)){                 break;             }else{             String[] a=s.split(\\D+);             int sum=0;             for(int i=0 ; i<a.length; i++){                 if(!a[i].equals()){                     int number = Integer.parseInt(a[i]);                     sum+=number;                 }             }             System.out.println(sum);         }         }     }          }

 本题体现了正则表达式的使用,实现如下功能:读入关于蛟龙号载人潜水器探测数据的多行字符串,从给定的信息找出数字字符,输出每行的数字之和。                                                                                                                                                                                                                                                                                                                                                

1、如果用“.”作为分隔的话,必须是如下写法:String.split(\\.),这样才能正确的分隔开,不能用String.split(.);
2、如果用“|”作为分隔的话,必须是如下写法:String.split(\\|),这样才能正确的分隔开,不能用String.split(|);
“.”和“|”都是转义字符,必须得加\;
3、如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如:“acount=? and uu =? or n=?”,把三个都分隔出来,可以用String.split(and|or);
使用String.split方法分隔字符串时,分隔符如果用到一些特殊字符,可能会得不到我们预期的结果。
我们看jdk doc中说明
public String[] split(String regex)
Splits this string around matches of the given regular expression.
参数regex是一个 regular-expression的匹配模式而不是一个简单的String,他对一些特殊的字符可能会出现你预想不到的结果。

 

代码质量检查:

  

 

 

   题目集四7-2 点线形系列4-凸四边形的计算(部分代码):

题目要求:用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。

public static void fn(String s) {                     int flag1 = 0;                 int flag2 = 0;                 int flag3 = 0;                 boolean sibian = true;                 boolean pxsibian = false;                 for(int i = 0; i < s.length()-1; i++)                 {                      char a = s.charAt(i);                      char b = s.charAt(i+1);                      if(a==':'){                          flag1++;                      }                      else if(a==',') {                          flag2++;                      }                      else if(a==' ') {                          flag3++;                      }                      if((a=='+'&&b=='+')||(a=='-'&&b=='-'))                      {                            System.out.print(Wrong Format);                            return;                      }                 }                 if(flag1!=1||flag2!=4||flag3!=3)                 {                     System.out.print(Wrong Format);                 }                 else {                     String s1 = s.replaceAll(:,,);                     String s2 = s1.replaceAll( ,,);                     String[] num = s2.split(,);                     double[] a = new double[8];                     for(int i=0;i<8;i++) {                         a[i] = Double.parseDouble(num[i+1]);                     }                     double k1 = (a[3]-a[1])/(a[2]-a[0]);                     double k2 = (a[5]-a[3])/(a[4]-a[2]);                     double k3 = (a[7]-a[5])/(a[6]-a[4]);                     double k4 = (a[1]-a[7])/(a[0]-a[6]);                     if((Math.abs(a[0]-a[2])<0.1&&Math.abs(a[1]-a[3])<0.1)||(Math.abs(a[2]-a[4])<0.1&&Math.abs(a[3]-a[5])<0.1)||(Math.abs(a[4]-a[6])<0.1&&Math.abs(a[5]-a[7])<0.1)||(Math.abs(a[6]-a[0])<0.1&&Math.abs(a[7]-a[1])<0.1)) {                         System.out.println(points coincide);                         return;                     }                     if((Math.abs(k1-k2)<0.1)||(Math.abs(k1-k4)<0.1)||(Math.abs(k2-k3)<0.1)||(Math.abs(k3-k4)<0.1)) {                         sibian=false;                     }                     else if((Math.abs(k1-k3)<0.1&&Math.abs(k2-k4)<0.1)){                         pxsibian = true;                     }                     System.out.println(sibian+ +pxsibian);                 }         } }

用正则表达式的匹配规则来判断输入的坐标是否正确

 

代码质量检查:

 本题大多涉及数学方面的计算以及判断

矢量叉积
计算矢量叉积是与直线和线段相关算法的核心部分。设矢量P = ( x1, y1 ),Q = ( x2, y2 ),则矢量叉积定义为由(0,0)、p1、p2和p1+p2所组成的平行四边形的带符号的面积,即:P × Q = x1y2 - x2y1,其结果是一个标量。显然有性质 P × Q = - ( Q × P ) 和 P × ( - Q ) = - ( P × Q )。一般在不加说明的情况下,本文下述算法中所有的点都看作矢量,两点的加减法就是矢量相加减,而点的乘法则看作矢量叉积。

 

    期中考试PTA1:7-1 点与线(类设计) :题目要求,

  • 设计一个类表示平面直角坐标系上的点Point,私有属性分别为横坐标x与纵坐标y,数据类型均为实型数,除构造方法以及属性的getter与setter方法外,定义一个用于显示信息的方法display(),用来输出该坐标点的坐标信息,格式如下:(x,y),数值保留两位小数。为简化题目,其中,坐标点的取值范围设定为(0,200]。若输入有误,系统则直接输出Wrong Format

  • 设计一个类表示平面直角坐标系上的线Line,私有属性除了标识线段两端的点point1、point2外,还有一个字符串类型的color,用于表示该线段的颜色,同样,除构造方法以及属性的getter与setter方法外,定义一个用于计算该线段长度的方法getDistance(),还有一个用于显示信息的方法display(),用来输出线段的相关信息

设计类图如下图所示:

部分代码:

class Point{     private double x;     private double y;          public void Point(double x,double y){         this.x=x;         this.y=y;     }     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 display() {                  System.out.println(The line's begin point's Coordinate is:());         System.out.println(The line's begin point's Coordinate is:());         System.out.println(The line's length is:);     } }

代码质量检查:

该题目的解决的关键就是认识到类的哪些属性或者方法是私有的还是公有

 

期中考试7-2 点线面问题重构(继承与多态):题目要求,

  • 对题目中的点Point类和线Line类进行进一步抽象,定义一个两个类的共同父类Element(抽象类),将display()方法在该方法中进行声明(抽象方法),将Point类和Line类作为该类的子类。
  • 再定义一个Element类的子类面Plane,该类只有一个私有属性颜色color,除了构造方法和属性的getter、setter方法外,display()方法用于输出面的颜色,输出格式如下:The Plane's color is:颜色

类结构如下图所示:

 

 

解决问题的关键在于是否理解抽象方法的定义和是否可以正确的使用。

 

期中考试7-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:输入结束

类图如下所示

 

ArrayList类中的增、删、减、查的各个作用.

 

农夫过河问题(实验):题目要求,

(1)为之前的类添加合适的父类。

(2)为父类添加适合的属性和方法。并以此为基础修改原有的类,使之与添加的类构成继承关系。

(3)使用多态改进整个代码,提高代码的复用性。

(类图)

狼、羊、菜、农夫类:

class Wolf {     boolean crossRiver = true;     boolean hasCross = false;     boolean isAlive = true;     void eatSheep(Sheep sheep,Farmer farmer)     {         if((hasCross&&sheep.hasCross&&!farmer.hasCross)||(crossRiver&&sheep.crossRiver&&!farmer.crossRiver)) {             sheep.isAlive = false;         }     }     void showStatus() {         System.out.println(Wolf is alive:+isAlive +\t+ Wolf has Cross:+hasCross);     }  } class Sheep {     boolean crossRiver = true;     boolean hasCross = false;     boolean isAlive = true;     void eatCabbage(Cabbage cabbage,Farmer farmer)     {         if((hasCross&&cabbage.hasCross&&!farmer.hasCross)||(crossRiver&&cabbage.crossRiver&&!farmer.crossRiver)) {             cabbage.isAlive = false;         }     }     void showStatus() {         System.out.println(Sheep is alive:+isAlive +\t+ Sheep has Cross:+hasCross);         } }  class Cabbage {     boolean crossRiver = true;     boolean hasCross = false;     boolean isAlive = true;     void showStatus() {         System.out.println(Cabbage is alive:+isAlive +\t+ Cabbage has Cross:+hasCross);         } }  class Farmer {     boolean crossRiver = true;     boolean hasCross = false;     void showStatus() {         System.out.println(Farmer has cross:+hasCross);     } }    

代码质量检测:

农夫、白菜、狼、羊之间的关系的理解

可以将农夫的CrossRiver来作为静态变量,然后将农夫的CrossRiver作为父类的属性来供给子类的引用
这样做:

    • 将农夫(Farmer)中的CrossRiver进行标号(public static boolean crossRiver);
    • 然后Sheep和cabbage和Wolf用extends Farmer来使用Farmer 的crossRiver;
  • 在做农夫过河的问题是农夫过不了河
    解决方法
    将所有的生物的属性改为静态属性
    而且在代码撰写的过程中,我们需要注意的时对象中的属性的可变、不变性,并根据题目来进行对应的处理
    在对于题目的理解中,切不可偏僻,要理解全面否则就会出现代码异常的问题;
    所以从理论上来说,通过Java的这种继承关系可以规范化编程。

(3)踩坑心得:

 1.处理父类和子类关系时,要了解继承的关系和逻辑。

2.在对字符串进行处理时,最好先遍历一遍整个字符串。

3.仔细阅读这些作业中所出现的知识点,将其中所有的约束条件进行代码的单元测试。

 

(4)改进建议:

1.应当养成良好的编程习惯,使自己的代码看起来容易理解,自己能看懂,加上一些必要的注释使别人也能看懂代码的作用。

2.对于变量的命名做到和变量有关系,让人看见变量名就能知道这个变量是什么。

3.以后的代码编写,应尽量少使用if语句,减少自己的圈复杂度,提高自己代码的效率。

4.知识都是主动摄取的,不是被动灌输的,要提前学习Java,这样才能跟上老师的步伐。

5.加快敲代码的速度,这需要日积月累不断地坚持。

6.对于新知识,如正则表达式应当主动去学习并应用,不要拖到需要用时才开始学。

7.只有边学习边敲代码才能得到进步,光看视频或是听老师讲课是远远不够的。

 

(5)总结:
1.Java需要循序渐进而且系统的学习方案,不要想着天上掉馅饼的速成方式,给自己制定一个学习计划,制定好每天学习的新知识,然后用什么案例和练习巩固你每天学习的新东西。系统的学习教程,自学Java肯定是主视频,副书籍,因为书大多数人是看不下去的,所以视频要新颖,要系统,不要杂乱不精。

2.学习中需要注意一些问题:开始养成良好代码习惯;先自己多思考,然后再去问老师,培养自己解决问题能力。大量时间用来写代码,而不是看视频。书籍用来回顾知识点,而不要用来一页一页翻书提高学习效率,一个问题不要在意太久,规划好每天做的事情,完成就行,贪多嚼不烂。

3.学好Java的入门,必须知道类和对象的概念,了解类是什么,对象是什么。