Blog2——题目集4,5及期中考试

发布时间 2023-06-30 10:35:20作者: 摩根!我的超人!

一、前言

本篇博客包含了以下Java的主要知识点:

  • 面向对象基础: 包括类和对象的基本概念、构造方法、访问权限和成员变量。
  • 面向对象设计原则: 重点讨论了继承和组合这两个重要的设计原则。要求学生深入理解它们的区别,并能根据实际需求选择恰当的设计原则。
  • 异常处理: 涉及到许多异常情况,要求学生能够正确处理这些异常情况。
  • 字符串处理: 涉及输入和输出的字符串处理,包括字符串的拆分、组合和转换等操作。
  • 基本控制流和数据结构: 例如循环、条件语句、数组和列表。

本次题目主要为PTA6-8次题目集,主要为菜单计价系统4和5,以及部分Java进阶知识的应用,难度有亿点点高,数量还行,涵盖了多个细节和要求,包括异常处理和特殊情况的处理。

总的来说,这几道题目,能够全面测试学生的Java编程能力,包括面向对象设计原则、异常处理、字符串处理和基本的控制流和数据结构。完成这些题目后,我对Java编程有了更深入的理解。

二、题目

(1)第四次题目集

7-1 菜单计价程序-4

本体大部分内容与菜单计价程序-3相同,增加的部分用加粗文字进行了标注。

设计点菜计价程序,根据输入的信息,计算并输出总价格。

输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。

菜单由一条或多条菜品记录组成,每条记录一行

每条菜品记录包含:菜名、基础价格 两个信息。

订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。

桌号标识独占一行,包含两个信息:桌号、时间。

桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。

点菜记录包含:序号、菜名、份额、份数。份额可选项包括:1、2、3,分别代表小、中、大份。

不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。

删除记录格式:序号 delete

标识删除对应序号的那条点菜记录。

如果序号不对,输出"delete error"

代点菜信息包含:桌号 序号 菜品名称 份额 分数

代点菜是当前桌为另外一桌点菜,信息中的桌号是另一桌的桌号,带点菜的价格计算在当前这一桌。

程序最后按输入的桌号从小到大的顺序依次输出每一桌的总价(注意:由于有代点菜的功能,总价不一定等于当前桌上的菜的价格之和)。

每桌的总价等于那一桌所有菜的价格之和乘以折扣。如存在小数,按四舍五入规则计算,保留整数。

折扣的计算方法(注:以下时间段均按闭区间计算):

周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。

周末全价,营业时间:9:30-21:30

如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"

参考以下类的模板进行设计(本内容与计价程序之前相同,其他类根据需要自行定义):

菜品类:对应菜谱上一道菜的信息。

Dish {

String name;//菜品名称

int unit_price; //单价

int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }

菜谱类:对应菜谱,包含饭店提供的所有菜的信息。

Menu {

Dish[] dishs ;//菜品数组,保存所有菜品信息

Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。

Dish addDish(String dishName,int unit_price)//添加一道菜品信息

}

点菜记录类:保存订单上的一道菜品记录

Record {

int orderNum;//序号

Dish d;//菜品\

int portion;//份额(1/2/3代表小/中/大份)

int getPrice()//计价,计算本条记录的价格

}

订单类:保存用户点的所有菜的信息。

Order {

Record[] records;//保存订单上每一道的记录

int getTotalPrice()//计算订单的总价

Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。

delARecordByOrderNum(int orderNum)//根据序号删除一条记录

findRecordByNum(int orderNum)//根据序号查找一条记录

}

本次课题比菜单计价系列-3增加的异常情况:

1、菜谱信息与订单信息混合,应忽略夹在订单信息中的菜谱信息。输出:"invalid dish"

2、桌号所带时间格式合法(格式见输入格式部分说明,其中年必须是4位数字,月、日、时、分、秒可以是1位或2位数),数据非法,比如:2023/15/16 ,输出桌号+" date error"

3、同一桌菜名、份额相同的点菜记录要合并成一条进行计算,否则可能会出现四舍五入的误差。

4、重复删除,重复的删除记录输出"deduplication :"+序号。

5、代点菜时,桌号不存在,输出"Table number :"+被点菜桌号+" does not exist";本次作业不考虑两桌记录时间不匹配的情况。

6、菜谱信息中出现重复的菜品名,以最后一条记录为准。

7、如果有重复的桌号信息,如果两条信息的时间不在同一时间段,(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒)以内算统一时段),此时输出结果按不同的记录分别计价。

8、重复的桌号信息如果两条信息的时间在同一时间段,此时输出结果时合并点菜记录统一计价。前提:两个的桌号信息的时间都在有效时间段以内。计算每一桌总价要先合并符合本条件的饭桌的点菜记录,统一计价输出。

9、份额超出范围(1、2、3)输出:序号+" portion out of range "+份额,份额不能超过1位,否则为非法格式,参照第13条输出。

10、份数超出范围,每桌不超过15份,超出范围输出:序号+" num out of range "+份数。份数必须为数值,最高位不能为0,否则按非法格式参照第16条输出。

11、桌号超出范围[1,55]。输出:桌号 +" table num out of range",桌号必须为1位或多位数值,最高位不能为0,否则按非法格式参照第16条输出。

12、菜谱信息中菜价超出范围(区间(0,300)),输出:菜品名+" price out of range "+价格,菜价必须为数值,最高位不能为0,否则按非法格式参照第16条输出。

13、时间输入有效但超出范围[2022.1.1-2023.12.31],输出:"not a valid time period"

14、一条点菜记录中若格式正确,但数据出现问题,如:菜名不存在、份额超出范围、份数超出范围,按记录中从左到右的次序优先级由高到低,输出时只提示优先级最高的那个错误。

15、每桌的点菜记录的序号必须按从小到大的顺序排列(可以不连续,也可以不从1开始),未按序排列序号的输出:"record serial number sequence error"。当前记录忽略。(代点菜信息的序号除外)

16、所有记录其它非法格式输入,统一输出"wrong format"

17、如果记录以“table”开头,对应记录的格式或者数据不符合桌号的要求,那一桌下面定义的所有信息无论正确或错误均忽略,不做处理。如果记录不是以“table”开头,比如“tab le 55 2023/3/2 12/00/00”,该条记录认为是错误记录,后面所有的信息并入上一桌一起计算。

本次作业比菜单计价系列-3增加的功能:

菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+基础价格+"T"

例如:麻婆豆腐 9 T

菜价的计算方法:

周一至周五 7折, 周末全价。

注意: 不同的四舍五入顺序可能会造成误差,请按以下步骤累计一桌菜的菜价:

计算每条记录的菜价:将每份菜的单价按份额进行四舍五入运算后,乘以份数计算多份的价格,然后乘以折扣,再进行四舍五入,得到本条记录的最终支付价格。

最后将所有记录的菜价累加得到整桌菜的价格。

输入格式:
桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)

菜品记录格式:

菜名+英文空格+基础价格

如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。

点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。

删除记录格式:序号 +英文空格+delete

代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数

最后一条记录以“end”结束。

输出格式:
按输入顺序输出每一桌的订单记录处理信息,包括:

1、桌号,格式:table+英文空格+桌号+”:”

2、按顺序输出当前这一桌每条订单记录的处理信息,

每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“** does not exist”,**是不能识别的菜名

如果删除记录的序号不存在,则输出“delete error”

最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class Main {
    public static void main(String[] args) throws ParseException {
        Scanner input = new Scanner(System.in);
        int i, t = 0, year, month, day, shi, fen, miao, f = 0, y = -1;
        String a = null;
        Menu menu = new Menu();
        Table[] tables = new Table[10];
        for (i = 0; ; i++) {
            if(f==1)
                break;
            if (y == -1)
                a = input.nextLine();
            if (a.equals("end"))
                break;
            String[] s = a.split(" ");
            int x = s.length;
            if (x <= 3 && t == 0) {//菜品
                int l = 0;
                int n = 0;
                if (!s[1].matches("[1-9]||[1-9][0-9]||[1-2][0-9][0-9]")) {
                    System.out.println("wrong format");
                    menu.dishs[menu.t] = new Dish();
                } else {
                    n = Integer.parseInt(s[1]);
                    boolean special = false;
                    if (x == 3) {
                        if(s[2].matches("T"))
                        special = true;
                       else{
                           System.out.println("wrong format");
                    System.exit(0);
                       }
                    }
                    menu.addDish(s[0], n, special);
                    if (n <= 0 || n >= 300) {//菜价超出范围
                        System.out.println(s[0] + " price out of range " + n);
                    }
                }
            } else {

                t = 1;
                if(x>4){
                    System.out.println("wrong format");
                    System.exit(0);
                }
                while (true) {
                    if(f==1)
                        break;
                    y++;
                    if (x == 4 && !(s[0].matches("table")) && y == 0) {//第一个
                        System.out.println("wrong format");
                        System.exit(0);
                    }
                    while ((x == 4 && s[0].matches("table")) || y > 0) {
                        if(f==1)
                            break;
                        if (s.length == 4) {////后面的桌子直接进入点菜,后面所有的信息并入上一桌一起计算
                            tables[y] = new Table();
                            tables[y].order = new Order();
                            String[] s1 = s[2].split("/");//年月日的分割
                            String[] s2 = s[3].split("/");//时分秒的分割
                            SimpleDateFormat d = new SimpleDateFormat("yyyy-MM-dd");
                            SimpleDateFormat d2 = new SimpleDateFormat("u");
                            Date date = d.parse(s1[0] + "-" + s1[1] + "-" + s1[2]);//日期格式化
                            int week = Integer.parseInt(d2.format(date));//提取星期几
                            tables[y].week = week;
                            if (!s[1].matches("\\d*")) {//检查"table"部分
                                System.out.println("wrong format");
                                if (y == 0)//第一个桌子桌号错误直接退出
                                    System.exit(0);
                                else//后面所有的信息并入上一桌一起计算
                                    y--;
                            } else {
                                tables[y].num = Integer.parseInt(s[1]);
                                tables[y].year = Integer.parseInt(s1[0]);
                                tables[y].month = Integer.parseInt(s1[1]);
                                tables[y].day = Integer.parseInt(s1[2]);
                                tables[y].shi = Integer.parseInt(s2[0]);
                                tables[y].fen = Integer.parseInt(s2[1]);
                                tables[y].miao = Integer.parseInt(s2[2]);
                                if(s[1].matches("[0].+")){
                                    System.out.println("wrong format");
                                    System.exit(0);
                                }

                                if (!(tables[y].num <= 55 && tables[y].num >= 1)) {
                                    System.out.println("table num out of range");
                                    System.exit(0);
                                }
                                else if(!tables[y].check()){
                                    System.out.println(tables[y].num+" date error");
                                    System.exit(0);
                                }
                                else if(tables[y].year>2023||tables[y].year<2022){
                                    System.out.println("not a valid time period");
                                    System.exit(0);
                                }
                                else
                                    System.out.println("table " + Integer.parseInt(s[1]) + ": ");
                            }
                        } else {
                            System.out.println("wrong format");
                            f = 0;
                            y--;//数据并入上一卓
                        }
                        for (; ; i++) {//点菜
                            if (f == 1 || f == 2)
                                break;
                            String aa = input.nextLine();
                            String[] ss = aa.split(" ");
                            //System.out.println(y + "---------" + aa);
                            if (ss.length == 4 && ss[0].charAt(0) == 't') {//新桌子
                                s = ss;
                                y++;
                                break;
                            }
                            if (ss.length == 4) {//点菜
                                //System.out.println(y+"%"+ss[0]);
                                //tables[y].order.addARecord(Integer.parseInt(ss[0]), ss[1], Integer.parseInt(ss[2]), Integer.parseInt(ss[3]), menu, tables[y].week);
                                if (!tables[y].checkorder(Integer.parseInt(ss[0])))//检查订单序号顺序
                                    System.out.println("record serial number sequence error");
                                else if (menu.searthDish(ss[1])==null)//订单的菜不存在
                                    System.out.println(ss[1] + " does not exist");
                                else if (Integer.parseInt(ss[2]) > 3) {//份额超过3
                                    System.out.println(ss[0] + " " + "portion out of range" + " " + ss[2]);
                                } else if (Integer.parseInt(ss[3]) > 15) {//订单大于15
                                    System.out.println(ss[0] + " " + "num out of range" + " " + ss[3]);
                                } else {
                                    tables[y].order.addARecord(Integer.parseInt(ss[0]), ss[1], Integer.parseInt(ss[2]), Integer.parseInt(ss[3]), menu, tables[y].week);
                                    System.out.println(ss[0] + " " + ss[1] + " " + tables[y].order.records[tables[y].order.s - 1].ygetPrice());
                                    tables[y].order.records[tables[y].order.s - 1].shi=tables[y].shi;
                                    tables[y].order.records[tables[y].order.s - 1].fen=tables[y].fen;
                                    
                                }
                            }
                            if (ss.length == 2 && ss[1].matches("delete")) {//删除
                                if(tables[y].order.findRecordByNum(Integer.parseInt(ss[0]))==-1) {
                                    System.out.println("delete error");
                                }
                                else {

                                    tables[y].order.delARecordByOrderNum(Integer.parseInt(ss[0]));
                                    if (tables[y].order.records[tables[y].order.findRecordByNum(Integer.parseInt(ss[0]))].life == 2) //重复删除的情况
                                        System.out.println("deduplication " + ss[0]);
                                }
                            }
                            if ((ss.length == 2 || ss.length == 3) && !ss[1].matches("delete")) {
                                System.out.println("invalid dish");
                            }
                            if (ss.length > 4) {
                                a = aa;
                                s = a.split(" ");

                                f = 2;

                            }
                           // System.out.println("////");
                        /*if(ss.length==5){//代点菜
                            for(int t=0;t<=y;t++){
                                if(ss[0].equals(tables[i].num))
                            }
                        }*/
                            if (aa.equals("end")) {
                                f = 1;
                                break;
                            }

                        }
                        if (f == 1 || f == 2)
                            break;
                    }
                    if (f == 1)
                        break;
                }
            }
            }
            for (i = 0; i <= y; i++) {
                System.out.println("table " + tables[i].num + ": " + tables[i].order.ygetTotalPrice() + " " + tables[i].order.getTotalPrice());
            }
    }
}

    class Dish {

        String name;//菜品名称

        int unit_price; //单价
        int life=0;//
        boolean special = false;
        public Dish(){

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

        int getPrice(int portion){
            int s = 0;
            if(portion==1)
                s = unit_price*1;
            if (portion==2)
                s = (int) Math.round(unit_price*1.5);
            if(portion==3)
                s = unit_price*2;
            return s;
        }//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
    }
    class Menu {

        Dish[] dishs = new Dish[10];//菜品数组,保存所有菜品信息
        int t=0;
        public Menu(){

        }
        Dish searthDish(String dishName) {
            for (int i = 0;i < t; i++) {
                if (dishName.equals(dishs[i].name)) {
                    return dishs[i];
                }
            }
            return null;
        }
        //根据菜名在菜谱中查找菜品信息,返回Dish对象。

        Dish addDish(String dishName,int unit_price,boolean special){
            if(t>0){
                int k=t-1;
                for (;k>=0;k--){
                    if (dishName.matches(dishs[k].name)){
                        dishs[k].unit_price = unit_price;
                        return null;
                    }
                }
            }
            dishs[t] = new Dish(dishName,unit_price,special);
            t++;
            return dishs[t-1];
        }//添加一道菜品信息

    }
    class Record {

        int orderNum;//序号

        Dish d;//菜品\\
        int portion;//份额(1/2/3代表小/中/大份)
        int num;//数量
        int week;//星期几
        int shi;
        int fen;
        int miao;

        int life = 0;//初始为0,删除为1,重复删除为2,无视为3
        public Record(){

        }
        int getPrice(){
            int s=1;
            if(d.special==true) {//特价菜订单价格
                if (week <= 5 && week >= 1)
                    s = (int)Math.round(d.getPrice(portion) * num * 0.7);
                else
                    s = (int) Math.round(d.getPrice(portion) * num);
            }
            else{//普通菜订单价格
                if(week <= 5 && week >= 1) {
                    if ((shi >= 17 && shi < 20) || (shi == 20 && fen <= 30))
                        s = (int) Math.round(d.getPrice(portion) * num * 0.8);
                    else
                        s = (int) Math.round(d.getPrice(portion) * num * 0.6);
                }
                else
                    s = (int) Math.round(d.getPrice(portion) * num);
            }
            return s;
        }//计价,计算本条记录的价格
        int ygetPrice(){
            int s=1;
            s = (int) Math.round(d.getPrice(portion) * num);
            return s;
        }

}
    class Order {

        Record[] records = new Record[100];//保存订单上每一道的记录
        int i=0,s=0;//s为点菜数
        int year;
        int month;
        int day;


        public Order(){

        }


        int getTotalPrice(){
            int num = 0;
            for(i=0;i<s;i++){
                if(records[i].life==0)
                     num = num + records[i].getPrice();
            }
            return num;
        }//计算订单的总价
        int ygetTotalPrice(){
            int num = 0;
            for(i=0;i<s;i++){
                if(records[i].life==0)
                    num = num + records[i].ygetPrice();
            }
            return num;
        }//计算订单的原总价

        public Record addARecord(int orderNum,String dishName,int portion,int num,Menu menu,int week){

            for (i=0;i<s;i++){
                if(dishName==records[i].d.name&&portion==records[i].portion) {
                    records[i].num = records[i].num + num;
                    s++;
                    return records[i];
                }
            }
            if(i==s) {

                records[i] = new Record();
                if(menu.searthDish(dishName)!=null) {
                    records[i].d = menu.searthDish(dishName);
                    records[i].orderNum = orderNum;
                    records[i].d.name = dishName;
                    records[i].portion = portion;
                    records[i].num = num;
                    records[i].week = week;

                    s++;
                }
                else {
                    records[i].d = new Dish();
                    records[i].d.name=dishName;
                    records[i].life=6;//订单的菜不存在
                    s++;
                }
                return records[i];
            }
            return null;
        }//添加一条菜品信息到订单中。

        public void delARecordByOrderNum(int orderNum){
            for (i=0;i<s;i++){
                if(records[i].orderNum==orderNum){
                    if(records[i].life==1)
                        records[i].life = 2;
                    else
                        records[i].life = 1;
                }

            }

        }//根据序号删除一条记录

        public int findRecordByNum(int orderNum){
            for (i=0;i<s;i++){
                if (records[i].orderNum==orderNum)
                    return i;
            }
            return -1;
        }//根据序号查找一条记录

    }
    class Table {
        Order order;
        int num;
        int year;
        int month;
        int day;
        int shi;
        int fen;
        int miao;
        int week;
        public Table(){

        }
        public boolean check(){
            int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
            if (month >= 1 && month <= 12) {
                //判断是否为闰年
                if ((year % 100 == 0 && year % 400 == 0) || year % 4 == 0) {
                    //判断当前月份是否为2月,因为闰年的2月份为29天
                    if (month == 2 && day <= 29) return true;
                    else {
                        if (day <= days[month - 1]) return true;
                    }
                } else {
                    if (day <= days[month - 1])
                        return true;
                }
            }
            return false;
        }
        boolean checkorder(int x){//检查点菜序号
            for(int j=0;j<=order.s-1;j++){
                if(x<=order.records[j].orderNum)
                    return false;
            }
            return true;
        }

    }

分析:

菜单计价系统-4是在菜单计价系统-3的基础上添加了特色菜部分,大体思路与菜单3一致。.这里的时间错误尤为的复杂,一是对工作日的判断,齐次是对优惠日的判断,最后是对开店时间的判断。在进行判断的同时还必须对不存在的日期进行对应的信息处理(如:2月30号和25:00分的错误情况)这里大概率是得要用try和catch来对错误的信息输入进行正确的错误判断。

类图:

 (2)第五次题目集

比菜单计价程序-4多的部分

输入格式

代点菜信息包含:桌号 序号 菜品名称 口味度 份额 份数

信息处理

1、菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+口味类型+英文空格+基础价格+"T"

例如:麻婆豆腐 川菜 9 T

菜价的计算方法:

周一至周五 7折, 周末全价。

特色菜的口味类型:川菜、晋菜、浙菜

川菜增加辣度值:辣度0-5级;对应辣度水平为:不辣、微辣、稍辣、辣、很辣、爆辣;

晋菜增加酸度值,酸度0-4级;对应酸度水平为:不酸、微酸、稍酸、酸、很酸;

浙菜增加甜度值,甜度0-3级;对应酸度水平为:不甜、微甜、稍甜、甜;    

例如:麻婆豆腐 川菜 9 T

输入订单记录时如果是特色菜,添加口味度(辣/酸/甜度)值,格式为:序号+英文空格+菜名+英文空格+口味度值+英文空格+份额+英文空格+份数

例如:1 麻婆豆腐 4 1 9

单条信息在处理时,如果口味度超过正常范围,输出"spicy/acidity/sweetness num out of range : "+口味度值,spicy/acidity/sweetness(辣度/酸度/甜度)根据菜品类型择一输出,例如:

acidity num out of range : 5

输出一桌的信息时,按辣、酸、甜度的顺序依次输出本桌菜各种口味的口味度水平,如果没有某个类型的菜,对应的口味(辣/酸/甜)度不输出,只输出已点的菜的口味度。口味度水平由口味度平均值确定,口味度平均值只综合对应口味菜系的菜计算,不做所有菜的平均。比如,某桌菜点了3份川菜,辣度分别是1、3、5;还有4份晋菜,酸度分别是,1、1、2、2,辣度平均值为3、酸度平均值四舍五入为2,甜度没有,不输出。

一桌信息的输出格式:table+英文空格+桌号+:+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格+"川菜"+数量+辣度+英文空格+"晋菜"+数量+酸度+英文空格+"浙菜"+数量+甜度。

如果整桌菜没有特色菜,则只输出table的基本信息,格式如下,注意最后加一个英文空格:

table+英文空格+桌号+:+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格

例如:table 1: 60 36 川菜 2 爆辣 浙菜 1 微甜

计算口味度时要累计本桌各类菜系所有记录的口味度总和(每条记录的口味度乘以菜的份数),再除以对应菜系菜的总份数,最后四舍五入。

注:本题要考虑代点菜的情况,当前桌点的菜要加上被其他桌代点的菜综合计算口味度平均值。

2、考虑客户订多桌菜的情况,输入时桌号时,增加用户的信息:

格式:table+英文空格+桌号+英文空格+":"+英文空格+客户姓名+英文空格+手机号+日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)

例如:table 1 : tom 13670008181 2023/5/1 21/30/00

约束条件:客户姓名不超过10个字符,手机号11位,前三位必须是180、181、189、133、135、136其中之一。

输出结果时,先按要求输出每一桌的信息,最后按字母顺序依次输出每位客户需要支付的金额。不考虑各桌时间段的问题,同一个客户的所有table金额都要累加。

输出用户支付金额格式:

输入格式

菜名+口味类型+英文空格+基础价格

点菜记录格式:序号+英文空格+菜名+英文空格+辣/酸/甜度值+英文空格+份额+英文空格+份数 注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。辣/酸/甜度取值范围见题目中说明。

输出格式

格式:table+英文空格+桌号+“:”+英文空格+当前桌的计算折扣后总价+英文空格+辣度平均值+英文空格+酸度平均值+英文空格+甜度平均值+英文空格

最后按拼音顺序输出每位客户(不考虑客户同名或拼音相同的情况)的支付金额,格式: 用户姓名+英文空格+手机号+英文空格+支付总金额,按输入顺序排列。

import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
import java.util.Calendar;
import java.util.Date;
public class Main {
    public static void main(String[] args) {
        Work work = new Work();
        work.play();
    }
}
class Work {
    boolean Stop = false;  //用来确定订单和菜单混杂在一起的情况
    Menu menu;  //单位菜单
    Record record;  //单位记录
    Table table; //单位座位
    ArrayList<Table> tables = new ArrayList<>();  //座位数组

    Work() {    //初始化,用来创建基本的类数组
        //只能用一个菜单,别单位化
        //对所有的table都开放
        menu = new Menu();
        //单位化,订单?   Record应该是必须得单位化
        record = new Record();
        //定义一个存储Table的一个ArrayList —— tables的动态数组
        tables = new ArrayList<>();
    }

    public void play() {  //play 菜单程序主要运行的程序
        Scanner in = new Scanner(System.in);
        while (true) {
            String Line = in.nextLine();
            if (Line.equals("end")) {
                break;
            }
            String[] LineArray = Line.split(" ");
            if (LineArray.length == 2) { //一个空格
                if (LineArray[1].equals("delete")) {  //删除订单
                    int num = Integer.parseInt(LineArray[0]);
                    if (table.deletes.contains(num)) {
                        System.out.println("deduplication " + num);
                        continue;
                    }
                    else {
                        Record pp =table.order.find(num);
                        table.order.delARecordByOrderNum(num);
                        table.deletes.add(num);
                    }
                } else {   //菜单添加
                    if (!Stop) { //菜单还没有输出完
                        try {
                            int x = Integer.parseInt(LineArray[1]);
                        }
                        catch (Exception e1) {
                            System.out.println("wrong format");
                            continue;
                        }
                        Dish dish = new Dish(LineArray[0],Integer.parseInt(LineArray[1]));
                        menu.addDish(dish);
                    }
                    else {
                        System.out.println("invalid dish");
                    }
                }
                //continue;
            }
            else if (LineArray.length == 3) {
                if (LineArray[2].equals("T")) { //特色菜
                    Dish dish = new Dish(LineArray[0],Integer.parseInt(LineArray[1]),LineArray[2]);
                    menu.addDish(dish);
                }
            }
            else if (LineArray.length == 4) {   //三个空格,四个数据
                if (LineArray[0].equals("table")) { //座号
                    try {
                        table = new Table(LineArray[1], LineArray[2], LineArray[3],menu);
                        if (table.time_error) {
                            int yy = Integer.parseInt(LineArray[2]);  //用来故意报错
                        }
                        table.Discount(); //设定该table的折扣
                        System.out.println("table " + table.num + ": ");
                        tables.add(table);
                        Stop = true;
                    }
                    catch (Exception e2) {
                        System.out.println("wrong format");
                        break;
                    }
                } else { //添加订单
                    int number = Integer.parseInt(LineArray[0]);
                    int portion = Integer.parseInt(LineArray[2]);
                    int num = Integer.parseInt(LineArray[3]);
                    if ((3<portion && portion<10)|| portion<1) {
                        System.out.println(number + " portion out of range " + portion);
                        if (num>15) {
                            System.out.println(number + " num out of range " + num);
                        }
                        continue;
                    }
                    if (portion>=10) {
                        System.out.println("not a valid time period");
                        if (num>15) {
                            System.out.println(number + " num out of range " + num);
                        }
                        continue;
                    }
                    if (num>15) {
                        System.out.println(number + " num out of range " + num);
                        continue;
                    }
                    record = new Record(number, LineArray[1], portion, num);  //初始化单位record的序号,菜名,份额,数量
                    if (menu.searchDish(LineArray[1]) != null) {   //有该菜
                        Record oop = table.order.find_ByName(LineArray[1]); //查看Order中是否有该菜名的Record
                        if (oop!=null && oop.portion == portion) { //如果有该菜名的Record并且portion相等
                            oop.num += num;
                            continue;
                        }
                        record.d = menu.searchDish(LineArray[1]);  //获得该菜名的Dish类
                        table.order.addARecord(record);   //答案在if的前面???
                        int under_number = table.order.records.size()-1;   //存储最后一个的table的下标
                        //往record中添加菜品,提供单价
                        //在record里面添加菜品的单价和名字
                        table.order.records.get(under_number).d = menu.searchDish(LineArray[1]);
                        //获取record的单个总价
                        int price = table.order.records.get(under_number).getPrice();
                        //输出单个record的表出
                        System.out.println(table.order.records.get(under_number).orderNum + " " +
                                LineArray[1] + " " +price);
                    }
                }
                //continue;
            }
            else if (LineArray.length == 5) { //代点菜
                try {
                    int number = Integer.parseInt(LineArray[1]);
                    int portion = Integer.parseInt(LineArray[3]);
                    int num = Integer.parseInt(LineArray[4]);
                    record = new Record(number, LineArray[2], portion, num);
                    if (menu.searchDish(LineArray[2])!=null) {   //菜单内有该菜品
                        //添加record
                        table.order.addARecord(record);
                        int under_number = table.order.records.size()-1;
                        //设定record的菜品单价
                        table.order.records.get(under_number).d = menu.searchDish(LineArray[2]);
                        int price = table.order.records.get(under_number).getPrice();
                        System.out.println(number + " table " + table.num + " pay for table " + LineArray[0] + price);
                    }
                }
                catch (Exception e2){
                    System.out.println("wrong format");
                    break;
                }
            }
        }
        for (int i = 0 ; i < tables.size() ; i++) {
            tables.get(i).GetToTalPrice();
        }
    }
}
//    菜品类:对应菜谱上一道菜的信息。
class Dish { //封装
    Dish() { } //空构造器
    Dish(String dishName) {
        this.name = dishName;
    }
    Dish(String dishName , int unit_price) {
        this.name = dishName;
        this.unit_price = unit_price;
    } //普通菜的构造器
    Dish(String dishName , int unit_price , String pp) {
        this.name = dishName;
        this.unit_price = unit_price;
        if (pp.equals("T")) {
            TT = true;
        }
    } //特色菜的构造器
    private String name;//菜品名称
    private int unit_price; //单价
    private boolean TT = false; //特色菜标志
    public int getPrice(int portion) {
        double[] size = {1,1.5,2};
        double Price = 0;
        switch (portion) {
            case 1:
                Price = this.unit_price * size[0];
                break;
            case 2:
                Price = this.unit_price * size[1];
                break;
            case 3:
                Price = this.unit_price * size[2];
                break;
            default:;
        }
        return ((int)Math.round(Price));
    }//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }
    //封装的读取器
    public String getName() {
        return name;
    }//读取Name
    public int getUnit_price() {
        return unit_price;
    }//读取单价
    public boolean getTT() {
        return TT;
    }// 读取特色菜的标志
    public void setUnit_price(int unit_price) {
        this.unit_price = unit_price;
    }  //重新定义单价
}
//菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
class Menu {
    Menu() {
    }
    ArrayList<Dish> dishes = new ArrayList<>(); //菜品数组,保存所有菜品信息
    public Dish searchDish(String dishName) {
        boolean find = false;
        for (Dish dish : dishes){
            if (dish.getName().equals(dishName)) {
                find = true;
                return dish;
            } //如果找到就返回dish的类信息
        }
        System.out.println(dishName + " does not exist");
        return null;  //没有就返回null,用于判断是否找到
    }//根据菜名在菜谱中查找菜品信息,返回Dish对象。
    public void addDish(Dish dish) { //开始为返回Dish类???为什么???
        if (search(dish.getName())) {
            Dish pp = searchDish(dish.getName());
            pp.setUnit_price(dish.getUnit_price());
        }//如果发现有该菜品则重新定义该单价
        else {
            dishes.add(dish);
        }//没有发现则直接加入dishes列表里面去
    }   //添加一道菜品信息
    public boolean search(String dishName) {
        boolean find = false;
        for (Dish dish : dishes){
            if (dish.getName().equals(dishName)) {
                find = true;
                break;
            } //如果找到就返回boolean
        }
        return find;
    }//根据菜名在菜谱中查找菜品信息,返回Dish对象。
}
//希望能够实现存储每一个table的基本信息
//包括该table的订单和记录
class Table {
    ArrayList<Integer> deletes = new ArrayList<>();
    Menu menu = new Menu();
    int num;//座序号
//    int sum = 0;//总价钱
    Calendar data = Calendar.getInstance();//时间
    Order order;//订单
    Record record;//记录
    double discount = -1;
    int year,month,day,hours,minute,second;   //时间存储Date的参数
    int week; //用来存储星期数目的
    boolean time_error = false;   //保存time的格式对错
    Table(String num , String Day , String Time,Menu menu) {
        this.num = Integer.parseInt(num);  //保存序号

        String[] dataString = Day.split("/"); //保存日期
        this.year = Integer.parseInt(dataString[0]);
        this.month = Integer.parseInt(dataString[1]);
        this.day = Integer.parseInt(dataString[2]);

        String[] timeString = Time.split("/"); //保存时间
        this.hours = Integer.parseInt(timeString[0]);
        this.minute = Integer.parseInt(timeString[1]);
        this.second = Integer.parseInt(timeString[2]);

        try {
            for (int i = 0 ; i < 3 ; i++) {
                if (timeString[i].length()>2) {
                    time_error = true;
                    break;
                }
            }
            if (year%1000==0) {
                System.out.println(num + " date error");
            }
            else {
                Calendar data_start = Calendar.getInstance();
                data_start.set(2022,1,1);
                Calendar data_end = Calendar.getInstance();
                data_end.set(2023,12,31);
                data.set(year,month,day,hours,minute,second);
                if (data.after(data_end) || data.before(data_start)) {
                    System.out.println("not a valid time period");
                }
                else {
                    boolean isFirstSunday = (data.getFirstDayOfWeek() == Calendar.SUNDAY);
                    week = data.get(Calendar.DAY_OF_WEEK);
                    //若一周第一天为星期天,则-1
                    if(isFirstSunday){
                        week = week - 1;
                        if(week == 0){
                            week = 7;
                        }
                    }
                    order = new Order(); //同时构造Order类和Record类
                    record = new Record();
                    this.menu = menu;
                }
            }
        }
        catch (Exception e1) {
            System.out.println(num + " date error");
        }
    }
    public void GetToTalPrice() {
        if (discount<0) { //没有折扣,说明不在营业时间之内
            System.out.println("table " + num + " out of opening hours");
        }
        else { //有折扣,说明在营业时间之内
            int primer_uuu = 0;
            int uuu = 0;
            for (int i = 0 ; i < order.records.size() ; i++) {
                if (!deletes.contains(order.records.get(i).orderNum)) {   //把没有删除的进行相加
                    primer_uuu = primer_uuu + order.records.get(i).getPrice();
                    if (order.records.get(i).d.getTT()) {   //是特色菜,特别处理折扣
                        uuu = uuu + (int)Math.round(primer_uuu * 0.7);
                    }
                    else {     //不是特色菜
                        uuu = uuu + (int)Math.round(primer_uuu * discount);
                    }
                }
            }
//            int sum_primer = (int)sum;
//            sum = (int)Math.round(sum*discount);
            System.out.println("table " + num + ": " + primer_uuu + " " + uuu);
        }
    }
    public void Discount() {
        if (week>=1 && week<=5) {   //在工作日的时间内
            if (hours>=17 && hours<20) {
                discount = 0.8;
            }
            else if (hours==20 && minute<30){
                discount = 0.8;
            }
            else if (hours==20 && minute==30 && second==0){
                discount = 0.8;
            }
            else if ((hours>=11 && hours <=13) || (hours==10 && minute>=30)){
                discount = 0.6;
            }
            else if (hours==14 && minute<30) {
                discount = 0.6;
            }
            else if (hours==14 && minute==30 && second==0) {
                discount = 0.6;
            }
        }
        else {   //周末
            if (hours>=10 && hours<=20) {
                discount = 1.0;
            }
            else if (hours==9 && minute>=30){
                discount = 1.0;
            }
            else if ((hours==21 && minute<30) || (hours==21 && minute==30 && second==0)){
                discount = 1.0;
            }
        }
    } //判断是否在营业的时间内
}
//订单类:保存用户点的所有菜的信息。
class Order {
    Order() {} //构造器
    ArrayList<Record> records = new ArrayList<>();//保存订单上每一道的记录
    public int getTotalPrice() {
        int sum = 0;
        for (Record pp : records){
            sum=sum+pp.getPrice();
        }
        return sum;
        //打算放到Table里面进行相对应的Date判断,以便进行相对应的日期优惠!!!
        //还是使用它,先计算总价位,再来对日期进行相对应的打折
    }//计算订单的总价

    public void addARecord(Record pp) { //原来为Record返回类型
        records.add(pp);
    }//添加一条菜品信息到订单中。

    public void delARecordByOrderNum(int orderNum) {  //例子为int类???
        if (findRecordByNum(orderNum)) {
            records.remove(find(orderNum));
        }//找到删除
        else {
            System.out.println("delete error");
        }//未找到则输出对应的信息
    }//根据序号删除一条记录

    public boolean findRecordByNum(int orderNum) {  //原来为void类型
        for (Record pp : records) {
            if (pp.orderNum == orderNum) {
                return true;
            }
        }
        return false;
    }//根据序号查找一条记录
    public Record find (int orderNum) {  //可以通过订单进行记录的查找
        for (Record pp : records) {
            if (pp.orderNum == orderNum) {
                return pp;
            }
        }
        return null;
    }//返回对应的Record类
    public Record find_ByName(String name) {   //通过名字查找Order中的Record
        for (Record pp : records) {
            if (pp.d.getName().equals(name)){
                return pp;
            }
        }
        return null;
    }
}
//点菜记录类:保存订单上的一道菜品记录
class Record {
    Record(){
    } //空构造器
    Record(int orderNum,String dishName,int portion,int num) { //构造器
        this.orderNum = orderNum;
        this.portion = portion;
        this.d = new Dish(dishName);
        this.num = num;
        setDish(dishName);
    }  //非空构造器
    int orderNum;//序号
    Dish d;//菜品
    public void setDish(String dishName) {
        d = new Dish(dishName);
    }
    int portion;//份额(1/2/3代表小/中/大份)
    int num; //份数,用来存储份数
    public int getPrice() {
        int Price = 0;
        Price = d.getPrice(portion)*num;
        return Price;
    }//计价,计算本条记录的价格,返回int单个菜品的总价
    //注意这里是未打折的总价
}

类图:

 分析:

这里相比上面的菜单4多了特色菜,多了名字和身份证,多了table的错误判断的因素。需要对对应的输出进行对应的数据处理。相较于上次多了菜品和菜品的甜度,酸度,辣度,也加大的代码对信息的读入和处理量。输入需要在两种相似的输入格式进行细致的区分。

(3)期中考试

7-1 测验1-圆类设计

创建一个圆形类(Circle),私有属性为圆的半径,从控制台输入圆的半径,输出圆的面积

输入格式:
输入圆的半径,取值范围为(0,+∞),输入数据非法,则程序输出Wrong Format,注意:只考虑从控制台输入数值的情况

输出格式:
输出圆的面积(保留两位小数,可以使用String.format(“%.2f”,输出数值)控制精度)
import java.util.Scanner;

public class Main{
    private double radius;

    public static void main(String[] args) {
        Main circle = new Main();
        circle.readRadius();
        circle.calculateArea();
    }

    public void readRadius() {
        Scanner scanner = new Scanner(System.in);
        double inputRadius = scanner.nextDouble();
        if (inputRadius <= 0) {
            System.out.println("Wrong Format");
            System.exit(0);
        }
        radius = inputRadius;
    }

    public void calculateArea() {
        double area = Math.PI * radius * radius;
        System.out.println(String.format("%.2f", area));
    }
}

分析:没啥可分析的,写一个Circle类即可

7-2 测验2-类结构设计

设计一个矩形类,其属性由矩形左上角坐标点(x1,y1)及右下角坐标点(x2,y2)组成,其中,坐标点属性包括该坐标点的X轴及Y轴的坐标值(实型数),求得该矩形的面积。类设计如下图:


image.png

输入格式:

分别输入两个坐标点的坐标值x1,y1,x2,y2。

输出格式:

输出该矩形的面积值(保留两位小数)。

代码:

import java.util.*;
public class Main {
    private double x1;
    private double y1;
    private double x2;
    private double y2;

    public Main(double x1, double y1, double x2, double y2) {
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
    }

    public double getArea() {
        double width = Math.abs(x2 - x1);
        double height = Math.abs(y2 - y1);
        return width * height;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        double x1 = scanner.nextDouble();
        double y1 = scanner.nextDouble();
        double x2 = scanner.nextDouble();
        double y2 = scanner.nextDouble();

        Main rectangle = new Main(x1, y1, x2, y2);
        double area = rectangle.getArea();
        System.out.format("%.2f%n", area);
    }
}

分析:本题类图已给出,主要考察根据已知类完成代码的能力,只需要按照类图书写即可。同时略微涉及到构造函数的知识! 设计一个矩形类,以及点类,矩形由两个点组成(左上,右下),只需要输出面积,唯一麻烦的是所有的属性都 是prevate类型的都要所有对应的set和get方法进行操作,以及要写新的构造方法(在构造时将属性全部设置好)。

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

将测验1与测验2的类设计进行合并设计,抽象出Shape父类(抽象类),Circle及Rectangle作为子类,类图如下所示:


image.png

试编程完成如上类图设计,主方法源码如下(可直接拷贝使用):

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner input = new Scanner(System.in);
        
        int choice = input.nextInt();
        
        switch(choice) {
        case 1://Circle
            double radiums = input.nextDouble();
            Shape circle = new Circle(radiums);
            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;
        }
        
    }
 

其中,printArea(Shape shape)方法为定义在Main类中的静态方法,体现程序设计的多态性。

输入格式:

输入类型选择(1或2,不考虑无效输入)
对应图形的参数(圆或矩形)

输出格式:

图形的面积(保留两位小数)

import java.util.Scanner;

abstract class Shape {
    protected double area;
    
    public abstract void calculateArea();
    
    public double getArea() {
        return area;
    }
}

class Circle extends Shape {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public void calculateArea() {
        area = Math.PI * radius * radius;
    }
}

class Rectangle extends Shape {
    private Point leftTop;
    private Point lowerRight;
    
    public Rectangle(Point leftTop, Point lowerRight) {
        this.leftTop = leftTop;
        this.lowerRight = lowerRight;
    }
    
    @Override
    public void calculateArea() {
        double width = Math.abs(lowerRight.getX() - leftTop.getX());
        double height = Math.abs(lowerRight.getY() - leftTop.getY());
        area = width * height;
    }
}

class Point {
    private double x;
    private double y;
    
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
    
    public double getX() {
        return x;
    }
    
    public double getY() {
        return y;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        
        int choice = input.nextInt();
        
        switch(choice) {
            case 1: // Circle
                double radius = input.nextDouble();
                Shape circle = new Circle(radius);
                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);
                
                Shape rectangle = new Rectangle(leftTopPoint, lowerRightPoint);
                printArea(rectangle);
                break;
        }
    }
    
    public static void printArea(Shape shape) {
        shape.calculateArea();
        System.out.printf("%.2f\n", shape.getArea());
    }
}

分析:一般

7-4 测验4-抽象类与接口

在测验3的题目基础上,重构类设计,实现列表内图形的排序功能(按照图形的面积进行排序)。
提示:题目中Shape类要实现Comparable接口。

其中,Main类源码如下(可直接拷贝使用):

public class Main {
    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()) + " ");
        }    
    }    
}

 

输入格式:

输入图形类型(1:圆形;2:矩形;0:结束输入)

输入图形所需参数

输出格式:

按升序排序输出列表中各图形的面积(保留两位小数),各图形面积之间用空格分隔。

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

interface Shape extends Comparable<Shape>{
double getArea();
}

class Circle implements Shape {
private double radius;

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

@Override
public double getArea() {
    return Math.PI * radius * radius;
}

@Override
public int compareTo(Shape other) {
    double diff = this.getArea() - other.getArea();
    if (diff < 0) {
        return -1;
    } else if (diff > 0) {
        return 1;
    } else {
        return 0;
    }
}
}

class Rectangle implements Shape {
private Point leftTop;
private Point lowerRight;

public Rectangle(Point leftTop, Point lowerRight) {
    this.leftTop = leftTop;
    this.lowerRight = lowerRight;
}

@Override
public double getArea() {
    return Math.abs(lowerRight.getX() - leftTop.getX()) * Math.abs(lowerRight.getY() - leftTop.getY());
}

@Override
public int compareTo(Shape other) {
    double diff = this.getArea() - other.getArea();
    if (diff < 0) {
        return -1;
    } else if (diff > 0) {
        return 1;
    } else {
        return 0;
    }
}
}

class Point {
private double x;
private double y;

public Point(double x, double y) {
    this.x = x;
    this.y = y;
}

public double getX() {
    return x;
}

public double getY() {
    return y;
}
}

public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
ArrayList<Shape> list = new ArrayList<>();

    int choice = input.nextInt();

    while (choice != 0) {
        switch (choice) {
            case 1: // Circle
                double radius = input.nextDouble();
                Shape circle = new Circle(radius);
                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()) + " ");
    }    
}    
}

三、踩坑心得

1. 编译错误:PTA上的题目往往需要使用Java的类库,如果没有正确导入这些类库,就会出现编译错误。在做题之前,要先阅读题目中所提到的类库,并将其导入到代码中。

2. 输入输出问题:PTA平台会提供多组测试数据,所以要注意输入输出格式。在处理输入时,应该使用Scanner等工具类;在输出时,应该注意格式控制。(格式错误真的很烦)

3. 数组越界错误:数组越界错误是一个常见的运行时错误。要避免这个错误,可以使用for循环或者List等Java集合代替原生数组。

4. 逻辑错误:有些PTA题目需要考虑边界和特殊情况。在编写代码之前,要认真阅读题目并理解需求,在代码实现过程中考虑各种可能性,并对每个分支进行测试。

5. 在使用Scanner类获取用户输入时,要注意避免空格、回车等非数字字符的干扰。可以在获取完数字后使用nextLine()方法将其余字符清空。

四、改进建议

  1. 优化算法和数据结构:确保你所使用的算法和数据结构是高效的,并且能够满足程序的需求。在适当的情况下,可以考虑使用更高效的数据结构或算法,以提高程序的性能。

  2. 减少内存使用:Java程序在内存管理方面拥有一定的优势,但仍然需要注意内存使用情况。确保及时释放不再使用的对象,避免内存泄漏问题。可以使用一些内存分析工具来监测和解决内存问题。

  3. 多线程和并发处理:对于需要处理大量并发请求或需要执行长时间任务的程序,可以考虑使用多线程或并发处理来提高程序的性能和响应能力。使用Java提供的线程池和并发工具可以简化并发编程的复杂性。

  4. 异常处理:合理处理异常对于程序的稳定性和可靠性很重要。使用try-catch语句来捕获和处理异常,并根据具体情况选择适当的异常处理策略,如重试、回滚或记录错误信息。

  5. 代码重构:对于复杂或冗长的代码,可以考虑进行重构,以提高代码的可读性、易维护性和性能。使用设计模式和优化技巧来改善代码结构和性能。

  6. 性能测试和优化:定期进行性能测试,并使用性能分析工具来找出程序的瓶颈。根据测试结果进行适当的优化,以提高程序的响应时间和吞吐量。

  7. 代码规范和可维护性:遵循统一的代码规范和最佳实践,使代码易于阅读、理解和维护。使用注释和文档来解释代码的逻辑和功能。

  8. 引入第三方库和框架:合理使用一些优秀的第三方库和框架,可以提高开发效率和程序的功能性。但要注意选择稳定、活跃维护且符合项目需求的库和框架。

五、总结

作为一个学习Java的学生,我想总结一下我的学习经验和收获。

首先,学习Java需要打好基础。我首先学习了Java的基本语法,包括变量、数据类型、运算符、控制流等。这些基础知识是编写Java程序的基石,掌握了这些知识之后才能进一步深入学习。

其次,我学习了面向对象编程(OOP)的概念和Java中的实现。Java是一门面向对象的编程语言,理解面向对象的思想和原则对于编写高质量的Java程序至关重要。我学习了类、对象、继承、封装、多态等概念,并通过实践项目来巩固所学知识。

接着,我学习了Java的核心 API。Java提供了丰富的类库和API,掌握常用的API对于开发各类应用程序非常重要。我学习了字符串处理、集合框架、IO操作、多线程编程等常用的API,并通过实例来加深理解和熟悉使用。

此外,我也了解并学习了一些常用的开发工具和框架。例如,我使用过Eclipse和IntelliJ IDEA等集成开发环境来编写和调试Java程序,学习了使用Maven进行项目构建和依赖管理,熟悉了Spring框架的基本用法等。这些工具和框架能够提高开发效率和代码质量。

在学习Java的过程中,我也遇到了一些挑战。有时候遇到难以理解的概念或者错误的代码逻辑,但我通过查阅文档、阅读相关书籍、参考网上的教程和提问论坛等途径,最终都能够解决问题和理清思路。

总的来说,学习Java是一个不断探索和成长的过程。通过不断练习和实践,我越来越熟悉Java的语法和特性,并且能够编写出功能完善、可维护的Java程序。Java是一门广泛应用于企业级开发的编程语言,掌握它对于我的职业发展来说是非常有价值的。