Java第二次bolg作业

一:前言

1.知识点:

题目集04:共有3道题目,难度较大,考察点线型系列的运算。

题目集06:共有5道题目,难度较小。主要考察字符串的解析及正则表达式的运用和学习。

题目集07:共有3道题,有些难度,主要考察类设计和几何图形相关的运算,及正则表达式的练习。

期中考试:共3道题,考察了类设计,继承与多态及容器类的使用。

链表练习:考察了对链表的理解及设计。

2.题量和难度:

总的来说题量和难度适中,题目也契合阶段性的java学习,考察内容精确,循序渐进,有很好的java学习引导和锻炼作用。

 

二:设计与分析

1.PTA 题目集07 7-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"。

 

以下为类设计:

 

 

 

 

解释与心得:

设计了三个类:点类 Point   线类 Line  四边形类  Quadrilateral 

Line 类传入两个Point 构成线 在类内完成两点距离,斜率,点线距离的计算 和判断点在线上,两线平行及是否重合的方法。

在 Quadrilateral 类内传入 4个Point 在类内完成判断是否构成四边形及平行四边形的方法。

 

采坑心得:

在输出数值的时候容易忽略小数位数的规定

如下:

注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0

if((((p1.getDistance(p2)+p2.getDistance(p3)+p3.getDistance(p4)+p4.getDistance(p1))*1e3)%10 != 0))
                    System.out.printf("%.3f ",p1.getDistance(p2)+p2.getDistance(p3)+p3.getDistance(p4)+p4.getDistance(p1));
                else
                    System.out.print(p1.getDistance(p2)+p2.getDistance(p3)+p3.getDistance(p4)+p4.getDistance(p1)+" ");

采用该方法进行判断后输出

 

以下为Point类的代码:

class Point {
    public Double x;
    public Double y;

    public Point(){
    }

    public 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 boolean equals(Point p){
        if(this.x.equals(p.getX()) && Objects.equals(this.y, p.getY())){
            return true;
        }
        else
            return false;
    }

    public double getDistance(Point p){
        return Math.sqrt((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y));
    }


}

 

Line 类

class Line{
    private Point a;
    private Point b;

    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 Line(Double x1,Double y1, Double x2 ,Double y2){
        this.a.setX(x1);
        this.a.setY(y1);
        this.b.setX(x2);
        this.b.setY(y2);
    }

    public Line(Point a, Point b) {
        this.a = a;
        this.b = b;
    }

    public Double getSlope(){
        return (b.getY()-a.getY())/(b.getX()-a.getX());
    }

    public boolean isOnline(Point X){//在延长线上
        double slope1 = (X.y-a.y)/(X.x-a.x);
        if(slope1 == getSlope() && !Between(X)){
            return true;
        }
        else
            return false;

    }

    public Double getDistance(Point p){

        double l1 = a.getDistance(p);
        double l2 = b.getDistance(p);
        double l3 = a.getDistance(b);
        double l = (l1 + l2 + l3) / 2;
        double s = Math.sqrt(l * (l - l1) * (l - l2) * (l - l3));// 海伦公式
        return  2 * s / l3;// 返回点到线的距离 用三角形面积求高
    }

    public boolean Between(Point p){//在线内
        return a.getDistance(p) + b.getDistance(p) == a.getDistance(b);
    }

    public boolean isParallel(Line l){
        return Math.abs(getSlope()) == Math.abs(l.getSlope());
    }

    public boolean isCoincide(Line l){//两线重合
        return (a.equals(l.a) && b.equals(l.b)) || (a.equals(l.b) && b.equals(l.a));
    }


    //public Point getIntersection(Line l){}//求两线交点

}

 

四边形类:

class Quadrilateral{
    public Point p1;
    public Point p2;
    public Point p3;
    public Point p4;

    public Quadrilateral(Point p1, Point p2, Point p3, Point p4) {
        this.p1 = p1;
        this.p2 = p2;
        this.p3 = p3;
        this.p4 = p4;
    }

    public boolean isQuadrilateral(){//任意三个顶点成直线,非四边形

            if ((p4.y - p3.y) * (p4.x - p2.x) == (p4.y - p2.y) * (p4.x - p3.x)||(p4.y - p3.y) * (p4.x - p1.x) == (p4.y - p1.y) * (p4.x - p3.x)||(p4.y - p2.y) * (p4.x - p1.x) == (p4.y - p1.y) * (p4.x - p2.x)||(p3.y - p2.y) * (p3.x - p1.x) == (p3.y - p1.y) * (p3.x - p2.x)) {
                return false;
            }
            else
                return true;
    }

    public boolean isParallelogram(){
        Line line1 = new Line(p1,p2);
        Line line2 = new Line(p2,p3);
        Line line3 = new Line(p3,p4);
        Line line4 = new Line(p4,p1);

        if(line1.isParallel(line3)&&p1.getDistance(p2)==p3.getDistance(p4)){//对边平行相等
            return true;
        }
        else if(line2.isParallel(line4)&&p2.getDistance(p3)==p4.getDistance(p1)){
            return true;
        }
        else{
            return false;
        }

    }
    public boolean pointCoincide(){
        if(p1.equals(p2)|| p3.equals(p4)|| p1.equals(p3)|| p1.equals(p4)||p2.equals(p3)||p2.equals(p4)){
            return true;
        }
        else
            return false;
    }
}

 

2.双向链表练习

要求:

 实现双向链表的设计,要求实现如下功能

判断链表是否为空

获取当前链表节点数量

获取链表中第index个位置的节点的data值

删除链表最后一个节点

删除链表中第index位置的节点

在链表的第index个位置之前插入一个节点,值为theElement,index∈[1,size]

在链表尾插入节点,插入节点data值为element

获取第一个节点的data值

获取链表最后一个节点的data值

 

类图如下:

 

 

 

解释与分析:

话不多说 上代码:

删除某个节点 删除最后的节点只要删除尾节点

 

public void remove(int index) {
        if(index < 1||index>this.size) {
             return ;
         }
         curr = head;
         if(index == 1) {
             curr = head.getNext();
             head.setNext(curr.getNext());
             curr.getNext().setPrevious(head);
         }
         else if(index == this.size) {//设置tail
             tail.getPrevious().setNext(null);
             tail = tail.getPrevious();
         }
         else {
             for(int i=1;i<index;i++) {//找到被删除节点的前一个节点
                 curr = curr.getNext();
             }
             
             curr.setNext(curr.getNext().getNext());
             curr.getNext().getNext().setPrevious(curr);
             
         }
         this.size--;
    }

 

在指定位置添加一个节点的数据

public void add(int index, E theElement) {
//创建新增节点
         Node<E> curr = new Node<>();
         curr.setData(theElement);
         curr.setNext(null);
         
         if(index == 0) {//插入第一个位置
             head.setNext(curr);
             curr.setPrevious(head);
         }
         else if(index == this.size ) {//插入最后一个位置
             curr.setPrevious(tail);
             this.tail.setNext(curr);
             this.tail = curr;
         }
         else {//插入中间位置
             Node<E> tempNoed =head;
             for(int i=0;i<index;i++) {
                 tempNoed = tempNoed.getNext();
             }
             
             curr.setNext(tempNoed.getNext());
             tempNoed.getNext().setPrevious(curr);
             tempNoed.setNext(curr);
             curr.setPrevious(tempNoed);
             
         }
         this.size++;
         
         if(this.size == 1) {
             tail = curr;
         }
    }
    

 

输出链表:

public void printList() {
        curr = head.getNext();
        for(int i = 0;i<size;i++) {
            System.out.print(curr.getData()+" ");
            curr = curr.getNext();
        }
        System.out.println();
    }

 

采坑心得:

注意在添加或删除后要注意将前后节点的  前驱引用(指针) 后继引用(指针)连接到相应位置。

 

3.期中考试题集

7-1:

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

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

  ```
      The line's color is:颜色值
      The line's begin point's Coordinate is:
      (x1,y1)
      The line's end point's Coordinate is:
      (x2,y2)
      The line's length is:长度值
  ```

 

 并给出了类图:
 

 

 

解释与心得:

line 类传入两点构成线并设置了颜色属性 及和Point 类都设计了display 输出内容

 

代码如下:

class Line {
    private Point a;
    private Point b;

    public Line() {
    }

    public Line(Point a, Point b, String color) {
        this.a = a;
        this.b = b;
        this.color = color;
    }

    private String color;

    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 String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public double getDistance(){
        return Math.sqrt((b.getX()-a.getX())*(b.getX()-a.getX())+(b.getY()-a.getY())*(b.getY()-a.getY()));
    }

    public void display(){
        System.out.println("The line's color is:"+color);
        System.out.println("The line's begin point's Coordinate is:");
        a.display();
        System.out.println("The line's end point's Coordinate is:");
        b.display();
        System.out.println("The line's length is:"+String.format("%.2f",getDistance()));
    }


}
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 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.printf("("+"%.2f"+","+"%.2f"+")",x,y);
        System.out.println();
    }

}

 

7-2  : 点线面问题重构(继承与多态)

要求:

在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。

  • 对题目中的点Point类和线Line类进行进一步抽象,定义一个两个类的共同父类Element(抽象类),将display()方法在该方法中进行声明(抽象方法),将Point类和Line类作为该类的子类。
  • 再定义一个Element类的子类面Plane,该类只有一个私有属性颜色color,除了构造方法和属性的getter、setter方法外,display()方法用于输出面的颜色,输出格式如下:The Plane's color is:颜色
  • 在主方法内,定义两个Point(线段的起点和终点)对象、一个Line对象和一个Plane对象,依次从键盘输入两个Point对象的起点、终点坐标和颜色值(Line对象和Plane对象颜色相同),然后定义一个Element类的引用,分别使用该引用调用以上四个对象的display()方法,从而实现多态特性。示例代码如下:
          element = p1;//起点Point
          element.display();
          
          element = p2;//终点Point
          element.display();
          
          element = line;//线段
          element.display();
          
          element = plane;//面
          element.display();
 
同样给出了类图:

 

 

解释与分析:

设计了Point 和 Line 类共同的父类 Element 设置了一个抽象方法display以实现最后的多态。

 

代码如下:

 

public class Main {
    public static void main(String[] ages){
        Scanner in = new Scanner(System.in);
        double x1 = in.nextDouble();
        double y1 = in.nextDouble();
        double x2 = in.nextDouble();
        double y2 = in.nextDouble();
        String str = in.next();
        
        if(x1>0&&x1<=200&&x2>0&&x2<=200&&y1>0&&y1<=200&&y2>0&&y2<=200){
            Element p1 = new Point(x1,y1);
            p1.display();
            Element p2 = new Point(x2,y2);
            p2.display();
            
            Element line = new Line(new Point(x1,y1),new Point(x2,y2),str);
            line.display();
            Element color = new Plane(str);
            color.display();
            
        }
        else{
            System.out.println("Wrong Format");
        }
    }
}

class Line extends Element{
    private Point a;
    private Point b;

    public Line() {
    }

    public Line(Point a, Point b, String color) {
        this.a = a;
        this.b = b;
        this.color = color;
    }

    private String color;

    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 String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public double getDistance(){
        return Math.sqrt((b.getX()-a.getX())*(b.getX()-a.getX())+(b.getY()-a.getY())*(b.getY()-a.getY()));
    }

    public void display(){
        System.out.println("The line's color is:"+color);
        System.out.println("The line's begin point's Coordinate is:");
        a.display();
        System.out.println("The line's end point's Coordinate is:");
        b.display();
        System.out.println("The line's length is:"+String.format("%.2f",getDistance()));
    }


}
class Point extends Element{
    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 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.printf("("+"%.2f"+","+"%.2f"+")",x,y);
        System.out.println();
    }

}

abstract class Element{
    
    public abstract void display();
}

class Plane extends Element{
    private String color;
    
    
    
    public Plane() {
        
    }


    public Plane(String str) {
        this.color = str;
    }


    public String getColor() {
        return color;
    }


    public void setColor(String color) {
        this.color = color;
    }


    public void display() {
        System.out.println("The Plane's color is:"+color);
    }
}

 

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:输入结束
    示例代码如下:
       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();
        }

同样有类图:

 

 

 

解释与心得:

代码如下:

容器类:

class GeometryObject{
    private ArrayList<Element> list = new ArrayList<>();

    public ArrayList<Element> getList() {
        return list;
    }

    public void add(Element element){
        list.add(element);
    }

    public void remove(int index){
        list.remove(index);
    }
}

 

主函数:

public class Main {
    public static void main(String[] ages){
        Scanner in = new Scanner(System.in);
        int choice = in.nextInt();
        GeometryObject g = new GeometryObject();
        while(choice!=0){
            switch(choice) {
                case 1://insert Point object into list
                    double x1 = in.nextDouble();
                    double y1 = in.nextDouble();
                    if(x1<=0||y1<=0||x1>200||y1>200){
                        System.out.println("Wrong Format");
                        System.exit(0);
                    }
                    Element p1 = new Point(x1,y1);
                    g.add(p1);
                    break;
                case 2://insert Line object into list
                    double x = in.nextDouble();
                    double y = in.nextDouble();
                    double x2 = in.nextDouble();
                    double y2 = in.nextDouble();
                    String str = in.next();
                    if(x<=0||y<=0||x>200||y>200||x2<=0||y2<=0||x2>200||y2>200){
                        System.out.println("Wrong Format");
                        System.exit(0);
                    }
                    Element line = new Line(new Point(x,y),new Point(x2,y2),str);
                    g.add(line);
                    break;
                case 3://insert Plane object into list
                    Element Plane = new Plane(in.next());
                    g.add(Plane);
                    break;
                case 4://delete index - 1 object from list
                    int i = in.nextInt();
                    if(i-1>= g.getList().size()||i-1<0){
                        choice = in.nextInt();
                        continue;
                    }
                    else{
                        g.remove(i-1);
                    }
                    break;
                    
                    
                default:
                    System.out.println("Wrong Format");
            }
            choice = in.nextInt();
        }
        for(Element e: g.getList()){
            e.display();
        }
    }
}

 

采坑❤得:

注意输出两位数和点的范围。注意删除容器中第index - 1个数据,若index数据非法,则无视此操作。

 

 

三:改进建议

在类设计上要符合单一职责原则,降低类与类间的耦合性,改进代码结构,让代码更加高效。

 

四:总结

在这阶段的学习中,学习了正则表达式的使用,加强了类设计,容器,继承与多态的练习。

 

 

 

posted @ 2022-05-01 19:58  内卷达人  阅读(157)  评论(0)    收藏  举报