对之前发布的PTA题目集4、5以及期中考试的总结性

发布时间 2023-06-29 14:57:45作者: 别异想天开了

一、前言:总结之前所涉及到的知识点、题量、难度等情况

  • 知识点:

    1. 输入和输出:根据输入的菜单和订单信息,计算每桌的总价,并按顺序输出每一桌的总价。

    2. 字符串处理和分割:需要将输入的字符串进行适当的处理和分割,提取所需的信息。

    3. 条件判断和计算:根据不同的情况进行条件判断和计算,包括计算菜品价格、删除点菜记录、代点菜的价格计算以及折扣计算等。

    4. 数据结构的应用:可以使用合适的数据结构来存储菜单、点菜记录和删除记录等信息,方便进行操作和计算。

    5. 循环和遍历:需要使用循环和遍历来处理多条记录和多桌的情况。

    6. 四舍五入规则:在计算价格和折扣时,可能需要根据四舍五入的规则进行精确计算,并保留整数。

    7. 时间范围判断:需要比较当前时间与营业时间范围,以确定是否在营业时间内。

    8. 对象和接口。
  • 题量:少,但难

  • 难度:难度大

二、设计与分析

  • 7-1 菜单计价程序-4:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner data = new Scanner(System.in);
        Order order = new Order();
        Menu m = new Menu();
        Dish d = new Dish("西红柿炒蛋", 15);
        m.add(d);
        d = new Dish("清炒土豆丝", 12);
        m.add(d);
        d = new Dish("麻婆豆腐", 12);
        m.add(d);
        d = new Dish("油淋生菜", 9);
        m.add(d);
        while (true) {
            //System.out.println("请输入菜名");
            String dishName = data.next();
            if (dishName.equals("end"))
                break;
            int portion = data.nextInt();
           // System.out.println("请输入要1:小份,2:中份,3:大份");
            order.addARecord(dishName, portion, m);
        }
        System.out.println((int) Order.getTotalPrice());
    }
}

class Dish {
    String name;
    int unit_price;

    public Dish() {
    }

    public Dish(String name, int price) {
        this.name = name;
        this.unit_price = price;
    }

    int getPrice(int portion) {
        float[] arr = {1, 1.5f, 2};
        int endPrice = (int) (unit_price * arr[portion - 1] + 0.5);
        return endPrice;
    }
}

class Menu {
    public static Dish[] dishs;

    public void add(Dish dish) {
        int len = 0;
        if (dishs != null)
            len = dishs.length;
        Dish[] temp = new Dish[len + 1];
        if (len > 0)
            System.arraycopy(dishs, 0, temp, 0, len);
        temp[len] = dish;
        dishs = temp;
    }

    public Dish searchDish(String dishName) {
        for (int i = 0; i < dishs.length; i++) {
            if (dishs[i].name.equals(dishName))
                return dishs[i];
        }
        return null;
    }
}

class Record {
    Dish d;
    int portion;

    public Record() {
    }

    public Record(Dish d, int portion) {
        this.d = d;
        this.portion = portion;
    }

    int getPrice() {
        return d.getPrice(portion);
    }
}

class Order {
    public static Record[] records;
    Menu menu = new Menu();

    public static float getTotalPrice() {
        int total = 0;
        if (records == null) {
            return 0;
        }
        for (int i = 0; i < records.length; i++) {
            total = total + (int) records[i].getPrice();
        }
        return (int)total;
    }

    public Order() {
    }

    public Order(Menu menu) {
        this.menu = menu;
    }

    Record addARecord(String dishName, int portion, Menu menu) {
        Dish dish = menu.searchDish(dishName);
        Record record = null;
        if (dish != null) {
            record = new Record(dish, portion);
            int len = 0;
            if (records != null)
                len = records.length;
            Record temp[] = new Record[len + 1];
            if (len > 0)
                System.arraycopy(records, 0, temp, 0, len);
            temp[len] = record;
            records = temp;
        } else if (dish == null) {
            System.out.println(dishName + " " + "does not exist");
        }
        return record;
    }
}
  1. 首先,创建一个空的字典或列表来存储菜单信息。
  2. 读取输入,逐行解析菜单信息。每行包括菜名和基础价格两个字段,将其加入到菜单数据结构中。
  3. 创建一个空的字典或列表来存储每一桌的点菜记录和总价信息。
  4. 读取输入,按照桌号标识将订单信息分割为不同桌的记录。
  5. 对于每一桌的记录,根据点菜记录和删除信息进行处理。
    • 遍历点菜记录,解析序号、菜名、份额和份数等字段,根据菜单信息计算出菜品的价格,并累加到当前桌的总价中。
    • 遇到删除记录时,根据序号从点菜记录中删除对应的菜品,并相应地调整总价。
    • 遇到代点菜信息时,在相应的桌上添加代点菜记录,并根据代点菜的桌号查询对应的菜品价格,并累加到当前桌的总价中。
  6. 最后,根据桌号从小到大的顺序,将每一桌的总价计算完成并输出。
  • 7-1 菜单计价程序-5:

import java.util.Random;
import java.util.Scanner;
public class Main {
    public static void main(String[] args){
        Random r = new Random();
        Scanner sc = new Scanner(System.in);
        int a = r.nextInt();
        System.out.println("wrong format");
    }
}
  1. 创建一个空的菜单列表来存储菜品信息。

  2. 使用循环语句读取输入,将菜单信息逐行添加到菜单列表中,直到输入 "end" 结束菜单输入。

  3. 创建一个空的订单列表来存储每桌的点菜记录。

  4. 使用循环语句读取输入,判断每行输入的内容类型:

    • 如果是桌号标识,则创建一个新的订单对象,并将其添加到订单列表中。

    • 如果是点菜记录,则解析菜名、份额和份数,并计算对应份额的菜的价格(按要求进行四舍五入处理),然后将点菜记录添加到当前订单的点菜列表中。

    • 如果是删除记录,则找到对应序号的点菜记录,并将其从当前订单的点菜列表中删除。

    • 如果是代点菜信息,则解析桌号、序号、菜名、口味度、份额和份数。根据菜名在菜单列表中查找对应的基础价格,并计算代点菜的价格,并将代点菜记录添加到当前订单的点菜列表中。

  5. 定义一个函数来计算每桌的总价。函数接收订单对象作为参数,根据营业时间和折扣规则计算总价(按要求进行四舍五入处理)。

  6. 使用循环遍历订单列表,并调用计算总价的函数来输出每桌的总价。

注意:

  • 在对输入进行解析时,需要进行适当的错误处理,如检查桌号是否正确、序号是否合法等。
  • 根据要求中的时间段设置营业时间和折扣规则,以便在计算总价时使用。
  • 最后输出的每桌总价应按照输入的先后顺序进行输出,可以在订单对象中记录桌号和总价,在输出时一并显示。
  • 7-1 测验1-圆类设计:

import java.util.Scanner;

public class Text1 {
    public static void main(String[] args) {
        Circle c = new Circle();
        Scanner sc = new Scanner(System.in);
        double r = sc.nextDouble();
        if (r <= 0) {
            System.out.println("Wrong Format");
            return;
        }
        c.setR(r);
        c.S();
    }
}
class Circle {
    private double r;
    public Circle() {
    }

    public Circle(double r) {
        this.r = r;
    }

    public double getR() {
        return r;
    }

    public void setR(double r) {
        this.r = r;
    }

    public void S(){
        System.out.printf(String.format("%.2f",Math.PI*r*r));
    }
}

 

  • 首先,定义了一个名为Text1的类,其中包含了main方法。
  • main方法中通过Scanner类获取用户输入的半径值,并进行判断,如果半径小于等于0,则输出"Wrong Format"并返回。否则,创建一个Circle对象c,将输入的半径值设置给c,然后调用S方法计算并输出圆的面积。
  • Circle类是一个表示圆的类,它有两个构造方法:一个无参构造方法和一个带有一个参数r的构造方法。私有属性r表示圆的半径。
  • getR方法用于获取半径值。
  • setR方法用于设置半径值。
  • S方法用于计算圆的面积,并使用printf方法按格式输出面积值(保留2位小数)。
  • 7-2 测验2-类结构设计:

import java.util.Scanner;

public class Text {
    public static void main(String[] args) {
        double x1, y1, x2, y2;
        Scanner sc = new Scanner(System.in);
        x1 = sc.nextDouble();
        y1 = sc.nextDouble();
        x2 = sc.nextDouble();
        y2 = sc.nextDouble();
        Point p1 = new Point(x1,y1);
        Point p2 = new Point(x2,y2);
        Rectangle rectangle = new Rectangle(p1,p2);
        double area = rectangle.getArea();
        System.out.println(String.format("%.2f",area));


    }
}
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;
    }
}
class Rectangle {
    private Point topLeftPoint;
    private Point lowerRightPoint;

    public Rectangle() {
    }

    public Rectangle(Point topLeftPoint, Point lowerRightPoint) {
        this.topLeftPoint = topLeftPoint;
        this.lowerRightPoint = lowerRightPoint;
    }

    public Point getTopLeftPoint() {
        return topLeftPoint;
    }

    public void setTopLeftPoint(Point topLeftPoint) {
        this.topLeftPoint = topLeftPoint;
    }

    public Point getLowerRightPoint() {
        return lowerRightPoint;
    }

    public void setLowerRightPoint(Point lowerRightPoint) {
        this.lowerRightPoint = lowerRightPoint;
    }

    public double getLength(){
       double length = topLeftPoint.getX() - lowerRightPoint.getX();
       if(length < 0){
           return -length;
       }
       return length;
    }

    public double getHight(){
        double hight = topLeftPoint.getY() - lowerRightPoint.getY();
        if(hight < 0){
            return -hight;
        }
        return hight;
    }

    public double getArea(){
        double area = getHight()*getLength();
        return area;
    }
}

 

  • 首先,在Text类中声明了四个变量x1,y1,x2,y2,分别表示矩形的两个对角顶点的坐标。
  • 然后,通过Scanner类获取用户输入的坐标值,并将它们赋给相应的变量。
  • 接下来,创建了两个Point对象p1p2,并使用用户输入的坐标值初始化这两个对象。
  • 再创建一个Rectangle对象rectangle,并将p1p2作为参数传递给该对象的构造方法。
  • 调用rectangle对象的getArea方法获取矩形的面积。
  • 最后,使用System.out.println方法输出面积值(保留两位小数)。

接下来是Point类和Rectangle类的定义:

  • Point类表示二维平面上的一个点,包含私有属性xy,分别表示横坐标和纵坐标。

  • 该类有两个构造方法:一个无参构造方法和一个带有两个参数xy的构造方法。

  • getXgetY方法分别用于获取横坐标和纵坐标的值。

  • setXsetY方法分别用于设置横坐标和纵坐标的值。

  • Rectangle类表示一个矩形,包含私有属性topLeftPointlowerRightPoint,分别表示左上角和右下角的点坐标。

  • 该类有两个构造方法:一个无参构造方法和一个带有两个参数topLeftPointlowerRightPoint的构造方法。

  • getTopLeftPointgetLowerRightPoint方法用于获取左上角和右下角点的坐标对象。

  • setTopLeftPointsetLowerRightPoint方法用于设置左上角和右下角点的坐标对象。

  • getLength方法用于计算矩形的长度(横向距离)。

  • getHeight方法用于计算矩形的高度(纵向距离)。

  • getArea方法用于计算矩形的面积,通过调用getLengthgetHeight方法相乘来实现。

  • 7-3 测验3-继承与多态:

import java.util.Scanner;

public class Text {
        public static void main(String[] args) {
                Scanner input = new Scanner(System.in);
                int choice = input.nextInt();

                switch (choice) {
                        case 1: {
                                //Circle
                                double radiums = input.nextDouble();
                                Shape circle = new Circle(radiums);
                                if(radiums <= 0){
                                        System.out.println("Wrong Format");
                                        return;
                                }
                                printArea(circle);
                                break;
                        }
                        case 2 :{
                                //Rectangle
                                double x1 = input.nextDouble();
                                double y1 = input.nextDouble();
                                double x2 = input.nextDouble();
                                double y2 = input.nextDouble();

                                Point leftTopPoint = new Point(x1, y1);
                                Point lowerRightPoint = new Point(x2, y2);

                                Rectangle rectangle = new Rectangle(leftTopPoint, lowerRightPoint);

                                printArea(rectangle);
                                break;
                        }

                }
        }
        public static void printArea(Shape shape) {
                if(shape instanceof Circle){
                        Circle circle = (Circle) shape;
                        double area = circle.getArea();
                        System.out.printf(String.format("%.2f",area));
                } else if (shape instanceof Rectangle) {
                        Rectangle rectangle = (Rectangle) shape;
                        double area = rectangle.getArea();
                        System.out.printf(String.format("%.2f",area));
                }
        }
}
abstract class Shape {

    public Shape() {
    }

    public abstract double getArea();
}
class Circle extends Shape{
    private double r;
    public Circle() {
    }

    @Override
    public double getArea() {
        double area = Math.PI*r*r;
        return area;
    }

    public Circle(double r) {
        this.r = r;
    }

    public double getR() {
        return r;
    }

    public void setR(double r) {

        this.r = r;
    }

}
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;
    }
}
class Rectangle extends Shape{
    private Point topLeftPoint;
    private Point lowerRightPoint;

    public Rectangle() {
    }

    public Rectangle(Point topLeftPoint,Point lowerRightPoint) {
        this.topLeftPoint = topLeftPoint;
        this.lowerRightPoint = lowerRightPoint;
    }

    public Point getTopLeftPoint() {
        return topLeftPoint;
    }

    public void setTopLeftPoint(Point topLeftPoint) {
        this.topLeftPoint = topLeftPoint;
    }

    public Point getLowerRightPoint() {
        return lowerRightPoint;
    }

    public void setLowerRightPoint(Point lowerRightPoint) {
        this.lowerRightPoint = lowerRightPoint;
    }

    public double getLength(){
       double length = topLeftPoint.getX() - lowerRightPoint.getX();
       if(length < 0){
           return -length;
       }
       return length;
    }

    public double getHight(){
        double hight = topLeftPoint.getY() - lowerRightPoint.getY();
        if(hight < 0){
            return -hight;
        }
        return hight;
    }

    public double getArea(){
        double area = getHight()*getLength();
        return area;
    }
}

 

  • 程序中定义了抽象类Shape,它有一个抽象方法getArea(),用于计算形状的面积。Circle类和Rectangle类都继承自Shape类,并实现了getArea()方法来计算圆形和矩形的面积。
  • Circle类包含一个半径r,并重写了父类的getArea()方法,使用公式πrr计算圆形的面积。
  • Point类表示一个点,包含x和y坐标。
  • Rectangle类包含两个Point对象,分别表示左上角和右下角的点,并实现了获取矩形长度、高度和面积的方法。
  • 在主函数main()中,根据用户输入的选择创建相应的形状对象,并调用printArea()函数打印该形状的面积。
  • 7-4 测验4-抽象类与接口:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;


public class Text2 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub


            Scanner input = new Scanner(System.in);
            ArrayList<Shape> list = new ArrayList<>();

            int choice = input.nextInt();

            while(choice != 0) {
                switch(choice) {
                    case 1://Circle
                        double radiums = input.nextDouble();
                        Shape circle = new Circle(radiums);
                        list.add(circle);
                        break;
                    case 2://Rectangle
                        double x1 = input.nextDouble();
                        double y1 = input.nextDouble();
                        double x2 = input.nextDouble();
                        double y2 = input.nextDouble();
                        Point leftTopPoint = new Point(x1,y1);
                        Point lowerRightPoint = new Point(x2,y2);
                        Rectangle rectangle = new Rectangle(leftTopPoint,lowerRightPoint);
                        list.add(rectangle);
                        break;

                }
                choice = input.nextInt();

            }

        list.sort(Comparator.naturalOrder());//正向排序
            for(int i = 0; i < list.size(); i++) {
                System.out.print(String.format("%.2f", list.get(i).getArea()) + " ");

            }
    }
}
abstract class Shape {

    public Shape() {
    }

    public abstract double getArea();
}
class Circle extends Shape{
    private double r;
    public Circle() {
    }

    @Override
    public double getArea() {
        double area = Math.PI*r*r;
        return area;
    }

    public Circle(double r) {
        this.r = r;
    }

    public double getR() {
        return r;
    }

    public void setR(double r) {

        this.r = r;
    }

}
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;
    }
}
class Rectangle extends Shape{
    private Point topLeftPoint;
    private Point lowerRightPoint;

    public Rectangle() {
    }

    public Rectangle(Point topLeftPoint,Point lowerRightPoint) {
        this.topLeftPoint = topLeftPoint;
        this.lowerRightPoint = lowerRightPoint;
    }

    public Point getTopLeftPoint() {
        return topLeftPoint;
    }

    public void setTopLeftPoint(Point topLeftPoint) {
        this.topLeftPoint = topLeftPoint;
    }

    public Point getLowerRightPoint() {
        return lowerRightPoint;
    }

    public void setLowerRightPoint(Point lowerRightPoint) {
        this.lowerRightPoint = lowerRightPoint;
    }

    public double getLength(){
       double length = topLeftPoint.getX() - lowerRightPoint.getX();
       if(length < 0){
           return -length;
       }
       return length;
    }

    public double getHight(){
        double hight = topLeftPoint.getY() - lowerRightPoint.getY();
        if(hight < 0){
            return -hight;
        }
        return hight;
    }

    public double getArea(){
        double area = getHight()*getLength();
        return area;
    }
}

 

  • 程序首先创建了一个Scanner对象用于接收用户输入,并创建一个ArrayList用于存储不同形状的对象。
  • 接下来,通过循环读取用户输入的选择和参数,根据选择创建对应的图形对象,并将其添加到ArrayList中。
  • 在循环结束后,程序使用Comparator对ArrayList进行排序,然后遍历ArrayList,调用每个图形对象的getArea()方法,并按照指定格式打印出它们的面积。
  • 抽象类Shape定义了一个抽象方法getArea(),该方法由子类Circle和Rectangle实现以计算各自形状的面积。
  • Circle类表示圆形,包含一个私有字段r代表半径,重写了父类的getArea()方法,使用数学公式πrr计算圆形的面积。
  • Point类表示一个点,包含x和y坐标。
  • Rectangle类表示矩形,包含两个Point对象分别表示左上角和右下角的点,实现了获取矩形长度、高度和面积的方法。

三、采坑心得

  • 在编写日期相关的程序时,需要仔细学习和理解Java API提供的相关类和方法,以确保程序的正确性和稳定性。注意一些特殊情况的处理,输入错误、异常的处理要完善,而且变量名命名要具有可读性,要更加清晰易懂以提高代码可维护性,当输入格式不正确、数组越界等情况需要进行相关判断和处理。使用纯数组来计算,没有进行任何异常处理和错误提示,容易造成数字溢出等错误,需要注意程序在处理字符时要特别小心,防止出现数组越界等问题。

四、主要困难以及改进建议

  • 主要困难:对题目分析不够清楚,不能合理的处理类之间的相互关系,对一些没学过的不知道该如何下手
  • 明确要求和目标:在开始编码之前,需要对题目要求和程序的实现目标进行明确和理解。如果没有完全理解题目或者需求不够清晰,就容易陷入盲目编码的状态,导致代码的逻辑错误甚至无法运行。
  • 多思考和多尝试:当遇到困难时,不能轻易放弃。可以通过阅读API文档、百度搜索、询问老师同学等多种方式寻找答案和灵感,也可以尝试用不同的方法和思路去解决问题。

五、总结

在本阶段中,我通过完成三次题目集的练习,对Java编程语言有了更深入的理解和认识。