PTA题目集4~6+期中总结

发布时间 2023-11-19 13:27:31作者: 我就是个鹌鹑

目录:

    1.前言

    2.设计与分析

    3.BUG与修正

    4.缺陷与改进

    5.总结

一、前言

  题目集4的主要难点是在菜单2和菜单3,大概只有一半的同学通过了全部测试点。主要的原因是这次的题目相比之前的题目,类与类之间的关系更加紧密了,也更加复杂了。也正是因为菜单2和菜单3的通过率低,导致后续的菜单迭代题通过率更低了。

  题目集5只有一道菜单4,但只有19人获得了满分,85人及格。这很大一部分原因是菜单3的分太低,导致菜单4更加无法得分,甚至直接放弃。而菜单3高分的人菜单4也依然是高分。而菜单4的难点就在对输入的判断上,各种各样的错误也是让人应接不暇。

  题目集6也只有一道菜单5,有29人获得满分,92人及格。相较于菜单4好了不少,这很大的原因是菜单5与菜单4没有关系,是由菜单3迭代而来。并且增加的内容也并不多,没有各种各样的的错误判断,难度不是很大。

 

二、设计与分析

  1.题目7-4 菜单计价程序-2

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

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

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

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


订单分:点菜记录和删除信息。每一类信息都可包含一条或多条记录,每条记录一行。
点菜记录包含:序号、菜名、份额、份数。
份额可选项包括:1、2、3,分别代表小、中、大份。

删除记录格式:序号 delete

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

不同份额菜价的计算方法:
小份菜的价格=菜品的基础价格。
中份菜的价格=菜品的基础价格1.5。
小份菜的价格=菜品的基础价格
2。

如果计算出现小数,按四舍五入的规则进行处理。

参考以下类的模板进行设计:
菜品类:对应菜谱上一道菜的信息。

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)//根据序号查找一条记录
}

输入格式:

菜品记录格式:

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

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

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

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


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

输出格式:

按顺序输出每条订单记录的处理信息,

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

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

最后输出订单上所有菜品的总价(整数数值),

本次题目不考虑其他错误情况,如:菜单订单顺序颠倒、不符合格式的输入、序号重复等。

 

  代码如下:

  1 import java.util.Scanner;
  2 import java.math.BigDecimal;
  3 
  4 public class Main
  5 {
  6     public static void main(String args[])
  7     {
  8         Scanner input = new Scanner(System.in);
  9         Menu menu = new Menu();
 10         Order order = new Order();
 11         
 12         String s0 = input.nextLine();
 13         String[] s = s0.split(" ");
 14 
 15         while(!s[0].equals("end"))
 16         {
 17             if(s.length==2)
 18             {
 19                 if(!s[1].equals("delete"))
 20                 {
 21                     menu.addDish(s[0],Integer.parseInt(s[1]));
 22                 }
 23                 else
 24                 {
 25                     int target = order.findRecordByNum(Integer.parseInt(s[0]));
 26                     if(target == -1) System.out.println("delete error;");
 27                     else order.delARecordByOrderNum(Integer.parseInt(s[0]));
 28                 }
 29             }
 30             if(s.length==4)
 31             {
 32                 Dish d = menu.searthDish(s[1]);
 33                 if(d.name.equals("")&&d.unit_price==0)
 34                     System.out.println(s[1]+" does not exist");
 35                 else
 36                 {
 37                     order.addARecord(Integer.parseInt(s[0]),d,Integer.parseInt(s[2]),Integer.parseInt(s[3]));
 38                     
 39                     int an1 = Integer.parseInt(s[0]);
 40                     String an2 = s[1];
 41                     int an3 = order.records[order.num-1].getPriceMust();
 42                     System.out.println(an1+" "+an2+" "+an3);
 43                 }
 44             }
 45             s0 = input.nextLine();
 46             s = s0.split(" ");
 47         }
 48 
 49         /*for(int i=0;i<order.num;i++)
 50         {
 51             int an1 = order.records[i].orderNum;
 52             String an2 = order.records[i].d.name;
 53             int an3 = order.records[i].getPriceMust();
 54             System.out.println(an1+" "+an2+" "+an3);
 55         }*/
 56 
 57         System.out.println(order.getTotalPrice());
 58     }
 59 }
 60 
 61 class Dish
 62 {
 63     String name;
 64     int unit_price;
 65 
 66     Dish(String name,int unit_price)
 67     {
 68         this.name = name;
 69         this.unit_price = unit_price;
 70     }
 71     
 72     int getPrice(int portion)
 73     {
 74         BigDecimal bg = new BigDecimal((double)unit_price*1.5);
 75         int res = 0;
 76         if(portion==1) res = unit_price;
 77         if(portion==2) res = (int)bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
 78         if(portion==3) res = unit_price*2;
 79 
 80         return res;
 81     }
 82 }
 83 
 84 class Menu
 85 {
 86     int dishNum;
 87     Dish[] dishs;
 88 
 89     Menu()
 90     {
 91         dishNum = 0;
 92         dishs = new Dish[100];
 93     }
 94     
 95     Dish searthDish(String dishName)
 96     {
 97         Dish d = new Dish("",0);
 98         for(int i=0;i<dishNum;i++)
 99         {
100             if(dishs[i]!=null)
101                 if(dishs[i].name.equals(dishName))
102                     d=dishs[i];
103         }
104         return d;
105     }
106 
107     void addDish(String dishName,int unit_price)
108     {
109         dishs[dishNum] = new Dish(dishName,unit_price);
110         dishNum++;
111     }
112 }
113 
114 class Record
115 {
116     boolean isExist;
117     int orderNum;
118     int num;
119     Dish d;
120     int portion;
121 
122     Record(int orderNum,Dish d,int portion,int num)
123     {
124         isExist = true;
125         this.orderNum = orderNum;
126         this.d = d;
127         this.portion = portion;
128         this.num = num;
129     }
130 
131     int getPriceMust()
132     {
133         return d.getPrice(portion)*num;
134     }
135     
136     int getPrice()
137     {
138         if(isExist)
139             return d.getPrice(portion)*num;
140         else return 0;
141     }
142 }
143 
144 class Order
145 {
146     int num;
147     Record[] records;
148 
149     Order()
150     {
151         num = 0;
152         records = new Record[100];
153     }
154     
155     int getTotalPrice()
156     {
157         int res = 0;
158         for(int i=0;i<num;i++)
159             res += records[i].getPrice();
160         return res;
161     }
162 
163     void addARecord(int orderNum,Dish d,int portion,int num)
164     {
165         records[this.num] = new Record(orderNum,d,portion,num);
166         this.num++;
167     }
168 
169     int findRecordByNum(int orderNum)
170     {
171         int res = -1;
172         for(int i=0;i<num;i++)
173             if(records[i].orderNum == orderNum&&records[i].isExist == true)
174                 res = i;
175 
176         return res;
177     }
178 
179     void delARecordByOrderNum(int orderNum)
180     {
181         int target = findRecordByNum(orderNum);
182         records[target].isExist = false;
183     }
184 }

    分析:

  此题的重点是在输入类型的判断和价格的计算上。

    类图:

              

  对于输入类型的判断,我并没有使用正则表达式,而是使用了一行输入的字符串数量来判断。我注意到,菜单输入为两个字符串,点菜输入为三个字符串,删除输入为两个字符串而且第二个字符串一定为“delete”。由于题目中强调不会有异常输入,所以这样的方法快捷由方便。这样就可以区分三种不同的输入。

  对于价格的计算,我分别在Dish中写了返回折扣后价格的函数,Record中写了返回计算了数量后的价格的函数,Order中写了返回所有未被删除的菜的价格的函数。这三个函数相辅相成,共同完成计算价格的功能。

 

  2.题目7-1 菜单计价程序-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)//根据序号查找一条记录

}

### 输入格式:

桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价

本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。

输入格式:

桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价

本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。

  

  代码如下:

  1 import java.util.Scanner;
  2 import java.math.BigDecimal;
  3 
  4 public class Main
  5 {
  6     public static void main(String args[])
  7     {
  8         Scanner input = new Scanner(System.in);
  9         Menu menu = new Menu();
 10         Order[] order = new Order[100];
 11         int orderNum = 0;
 12         
 13         String s0 = input.nextLine();
 14         String[] s = s0.split(" ");
 15 
 16         while(!s[0].equals("end"))
 17         {
 18             if(s.length==2)
 19             {
 20                 if(!s[1].equals("delete"))
 21                 {
 22                     menu.addDish(s[0],Integer.parseInt(s[1]));
 23                 }
 24                 else
 25                 {
 26                     int target = order[orderNum-1].findRecordByNum(Integer.parseInt(s[0]));
 27                     if(target == -1) System.out.println("delete error;");
 28                     else order[orderNum-1].delARecordByOrderNum(Integer.parseInt(s[0]));
 29                 }
 30             }
 31             if(s.length==4)
 32             {
 33                 if(!isDate(s[2]))
 34                 {
 35                     Dish d = menu.searthDish(s[1]);
 36                     if(d.name.equals("")&&d.unit_price==0)
 37                         System.out.println(s[1]+" does not exist");
 38                     else
 39                     {
 40                         order[orderNum-1].addARecord(Integer.parseInt(s[0]),d,Integer.parseInt(s[2]),Integer.parseInt(s[3]));
 41                         
 42                         
 43                         int an1 = Integer.parseInt(s[0]);
 44                         String an2 = s[1];
 45                         int an3 = order[orderNum-1].records[order[orderNum-1].num-1].getPriceMust();
 46                         
 47                         System.out.println(an1+" "+an2+" "+an3);
 48                     }
 49                 }
 50                 else
 51                 {
 52                     int t = isTime(s[2],s[3]);
 53                     order[orderNum] = new Order(Integer.parseInt(s[1]),t);
 54                     orderNum++;
 55                     System.out.println("table "+s[1]+": ");
 56                 }
 57             }
 58             if(s.length==5)
 59             {
 60                 Dish d = menu.searthDish(s[2]);
 61                 if(d.name.equals("")&&d.unit_price==0)
 62                     System.out.println(s[2]+" does not exist");
 63                 else
 64                 {
 65                     order[orderNum-1].addARecord(Integer.parseInt(s[1]),d,Integer.parseInt(s[3]),Integer.parseInt(s[4]));
 66                     
 67                     int an1 = Integer.parseInt(s[1]);
 68                     int an2 = orderNum;
 69                     int an3 = Integer.parseInt(s[0]);
 70                     int an4 = order[orderNum-1].records[order[orderNum-1].num-1].getPriceMust();
 71                     
 72                     
 73                     System.out.println(an1+" table "+an2+" pay for table "+an3+" "+an4);
 74                 }
 75             }
 76             
 77             s0 = input.nextLine();
 78             s = s0.split(" ");
 79         }
 80 
 81         for(int i=0;i<orderNum;i++)
 82         {
 83             if(order[i].time == 0)
 84                 System.out.println("table "+order[i].tableNumber+" out of opening hours");
 85             else
 86                 System.out.println("table "+order[i].tableNumber+": "+order[i].getTotalPrice());
 87         }
 88     }
 89 
 90     static boolean isDate(String s)
 91     {
 92         return s.matches("[0-9]{4}/[0-9]{1,2}/[0-9]{1,2}");
 93     }
 94 
 95     static int isTime(String s1,String s2)        //0:超时   -1:周末     1:中午6     2:晚上8
 96     {
 97         int res=0;
 98         String s[] = s1.split("/");
 99         int y = Integer.parseInt(s[0]);
100         int m = Integer.parseInt(s[1]);
101         int d = Integer.parseInt(s[2]);
102         
103         s = s2.split("/");
104         int h = Integer.parseInt(s[0]);
105         int f = Integer.parseInt(s[1]);
106         int ss = Integer.parseInt(s[2]);
107         int w = dayInWeek(y,m,d);
108 
109         if(w==6||w==7)
110             if(h>=10&&h<=20||h==9&&f>=30||h==21&&f<30||h==21&&f==30&&ss==0)
111                 res = -1;
112         if(w>=1&&w<=5)
113         {
114             if(h>=11&&h<=13||h==10&&f>=30||h==14&&f<30||h==14&&f==30&&ss==0)
115                 res = 1;
116             if(h>=17&&h<=19||h==20&&f<30||h==20&&f==30&&ss==0)
117                 res = 2;
118         }
119         
120         return res;
121     }
122 
123     static int dayInWeek(int y, int m, int d)
124     {
125         if(m<3)
126         {
127             y--;
128             m+=12;
129         }
130         int c = y/100;
131         y = y%100;
132         int w = (c/4)-2*c+(y+y/4)+(13*(m+1)/5)+d-1;
133         w=(w%7+7)%7;
134         if(w==0) w=7;
135         return w;
136     }
137 }
138 
139 class Dish
140 {
141     String name;
142     int unit_price;
143 
144     Dish(String name,int unit_price)
145     {
146         this.name = name;
147         this.unit_price = unit_price;
148     }
149     
150     int getPrice(int portion)
151     {
152         BigDecimal bg = new BigDecimal((double)unit_price*1.5);
153         int res = 0;
154         if(portion==1) res = unit_price;
155         if(portion==2) res = (int)bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
156         if(portion==3) res = unit_price*2;
157 
158         return res;
159     }
160 }
161 
162 class Menu
163 {
164     int dishNum;
165     Dish[] dishs;
166 
167     Menu()
168     {
169         dishNum = 0;
170         dishs = new Dish[100];
171     }
172     
173     Dish searthDish(String dishName)
174     {
175         Dish d = new Dish("",0);
176         for(int i=0;i<dishNum;i++)
177         {
178             if(dishs[i]!=null)
179                 if(dishs[i].name.equals(dishName))
180                     d=dishs[i];
181         }
182         return d;
183     }
184 
185     void addDish(String dishName,int unit_price)
186     {
187         dishs[dishNum] = new Dish(dishName,unit_price);
188         dishNum++;
189     }
190 }
191 
192 class Record
193 {
194     boolean isExist;
195     int orderNum;
196     int num;
197     Dish d;
198     int portion;
199 
200     Record(int orderNum,Dish d,int portion,int num)
201     {
202         isExist = true;
203         this.orderNum = orderNum;
204         this.d = d;
205         this.portion = portion;
206         this.num = num;
207     }
208 
209     int getPriceMust()
210     {
211         return d.getPrice(portion)*num;
212     }
213     
214     int getPrice()
215     {
216         if(isExist)
217             return d.getPrice(portion)*num;
218         else return 0;
219     }
220 }
221 
222 class Order
223 {
224     int tableNumber;
225     int time;
226     int num;
227     Record[] records;
228 
229     Order(int tableNumber,int t)
230     {
231         this.time = t;
232         this.tableNumber = tableNumber;
233         num = 0;
234         records = new Record[100];
235     }
236     
237     int getTotalPrice()
238     {
239         int res = 0;
240         for(int i=0;i<num;i++)
241             res += records[i].getPrice();
242         
243         BigDecimal bg = null;
244         if(time == 1) //中午
245         {
246             bg = new BigDecimal((double)res*0.6);
247             res = (int)bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
248         }
249         if(time == 2) //晚上
250         {
251             bg = new BigDecimal((double)res*0.8);
252             res = (int)bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
253         }
254         
255         return res;
256     }
257 
258     void addARecord(int orderNum,Dish d,int portion,int num)
259     {
260         records[this.num] = new Record(orderNum,d,portion,num);
261         this.num++;
262     }
263 
264     int findRecordByNum(int orderNum)
265     {
266         int res = -1;
267         for(int i=0;i<num;i++)
268             if(records[i].orderNum == orderNum&&records[i].isExist == true)
269                 res = i;
270 
271         return res;
272     }
273 
274     void delARecordByOrderNum(int orderNum)
275     {
276         int target = findRecordByNum(orderNum);
277         records[target].isExist = false;
278     }
279 }

    分析:

  本题相较于菜单2难点在于时间的判断和各种不同的折扣的计算,如果不仔细就会有四舍五入的错误。

    类图:

        

  相较于菜单2,这一题我并没有修改类的结构,而只是在主函数中添加了Order的数组来表示不同的桌,然后在Order中添加桌号的属性来表示不同的桌。对于时间的判断,我在主类中添加了一个判断时间段的函数,返回0表示不在服务时间内,返回-1表示周末,返回1表示中午,返回2表示晚上。在这个函数中我移植了之前题目中的判断周的函数。对于价格的计算,由于折扣只影响最后每一个订单总价的输出,所以我只修改了Order中计算总价的函数,添加了通过Order中time的属性来计算折扣的功能。

 

  3.题目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+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价

 

  代码如下:

 

  1 import java.util.Scanner;
  2 import java.math.BigDecimal;
  3 
  4 public class Main
  5 {
  6     public static void main(String args[])
  7     {
  8         Scanner input = new Scanner(System.in);
  9         Menu menu = new Menu();
 10         Order[] order = new Order[100];
 11         int orderNum = 0;
 12         int nowOrderNum = 0;
 13         boolean ignore = false;
 14         
 15         String s0 = input.nextLine();
 16         String[] s = s0.split(" ");
 17 
 18         while(!s[0].equals("end"))
 19         {
 20             int datasort = DATAsort(s0);
 21 
 22             if(ignore)
 23             {
 24                 if(datasort == 3)
 25                     ignore = false;
 26                 else 
 27                 {
 28                     s0 = input.nextLine();
 29                     s = s0.split(" ");
 30                     continue;
 31                 }
 32             }
 33             
 34             if(datasort == 0)                                    //格式错误
 35             {
 36                 if(s[0].equals("table"))
 37                     ignore = true;
 38                 System.out.println("wrong format");
 39             }
 40             if(datasort == 1)                                    //普通菜
 41             {
 42                 int price = Integer.parseInt(s[1]);
 43                 
 44                 if(nowOrderNum != 0)
 45                     System.out.println("invalid dish");
 46                 else if(price>=300)
 47                     System.out.println(s[0]+" price out of range "+s[1]);
 48                 else
 49                     menu.addDish(s[0],Integer.parseInt(s[1]),false);
 50                 
 51             }
 52             if(datasort == 2)                                    //特殊菜
 53             {
 54                 if(nowOrderNum == 0)
 55                     menu.addDish(s[0],Integer.parseInt(s[1]),true);
 56                 else
 57                     System.out.println("invalid dish");
 58             }
 59             if(datasort == 3)                                    //桌信息
 60             {
 61                 if(!isRule(s[2]))
 62                 {
 63                     System.out.println(s[1]+" date error");
 64                     s0 = input.nextLine();
 65                     s = s0.split(" ");
 66                     ignore = true;
 67                     continue;
 68                 }
 69                 
 70                 int tablenum = Integer.parseInt(s[1]);
 71                 
 72                 if(tablenum>55)
 73                 {
 74                     System.out.println(s[1]+" table num out of range");
 75                     s0 = input.nextLine();
 76                     s = s0.split(" ");
 77                     ignore = true;
 78                     continue;
 79                 }
 80                 
 81                 if(!dateRule(s[2]))
 82                 {
 83                     System.out.println("not a valid time period");
 84                     s0 = input.nextLine();
 85                     s = s0.split(" ");
 86                     ignore = true;
 87                     continue;
 88                 }
 89                 
 90                 int t = isTime(s[2],s[3]);
 91                 
 92                 if(t==0)
 93                 {
 94                     System.out.println("table "+s[1]+" out of opening hours");
 95                     s0 = input.nextLine();
 96                     s = s0.split(" ");
 97                     ignore = true;
 98                     continue;
 99                 }
100                 
101                 nowOrderNum = Integer.parseInt(s[1]);
102                 order[orderNum] = new Order(Integer.parseInt(s[1]),t,s[2],s[3]);
103                 orderNum++;
104                 System.out.println("table "+s[1]+": ");
105             }
106             if(datasort == 4)                                    //点菜
107             {
108                 if(nowOrderNum == 0)
109                 {
110                     s0 = input.nextLine();
111                     s = s0.split(" ");
112                     continue;
113                 }
114                 
115                 int portion = Integer.parseInt(s[2]);
116                 int num = Integer.parseInt(s[3]);
117                 int serial = Integer.parseInt(s[0]);
118                 Dish d = menu.searthDish(s[1]);
119                 if(serial<=order[orderNum-1].nowOrder)
120                     System.out.println("record serial number sequence error");
121                 else if(d.name.equals("")&&d.unit_price==0)
122                     System.out.println(s[1]+" does not exist");
123                 else if(portion!=1&&portion!=2&&portion!=3)
124                     System.out.println(s[0]+" portion out of range "+portion);
125                 else if(num>15)
126                     System.out.println(s[0]+" num out of range "+num);
127                 else
128                 {
129                     order[orderNum-1].addARecord(Integer.parseInt(s[0]),d,Integer.parseInt(s[2]),Integer.parseInt(s[3]),false);
130                     
131                     int an1 = Integer.parseInt(s[0]);
132                     String an2 = s[1];
133                     int an3 = order[orderNum-1].records[order[orderNum-1].num-1].getPriceMust();
134                     
135                     System.out.println(an1+" "+an2+" "+an3);
136                 }
137             }
138             if(datasort == 5)                                //删除
139             {
140                 int target = order[orderNum-1].findRecordByNum(Integer.parseInt(s[0]));
141                 if(target == -1) System.out.println("delete error");
142                 else if(target == -2) System.out.println("deduplication "+s[0]);
143                 else order[orderNum-1].delARecordByOrderNum(Integer.parseInt(s[0]));
144             }
145             if(datasort == 6)                                //代点菜
146             {
147                 int portion = Integer.parseInt(s[3]);
148                 int num = Integer.parseInt(s[4]);
149                 Dish d = menu.searthDish(s[2]);
150                 if(!tableExist(s[0],order,orderNum)||Integer.parseInt(s[0])==order[orderNum-1].tableNumber)
151                     System.out.println("Table number :"+s[0]+" does not exist");
152                 else if(d.name.equals("")&&d.unit_price==0)
153                     System.out.println(s[2]+" does not exist");
154                 else if(portion!=1&&portion!=2&&portion!=3)
155                     System.out.println(s[1]+" portion out of range "+portion);
156                 else if(num>15)
157                     System.out.println(s[1]+" num out of range "+num);
158                 else
159                 {
160                     order[orderNum-1].addARecord(Integer.parseInt(s[1]),d,Integer.parseInt(s[3]),Integer.parseInt(s[4]),true);
161                     
162                     int an1 = Integer.parseInt(s[1]);
163                     int an2 = order[orderNum-1].tableNumber;
164                     int an3 = Integer.parseInt(s[0]);
165                     int an4 = order[orderNum-1].records[order[orderNum-1].num-1].getPriceMust();
166                     
167                     System.out.println(an1+" table "+an2+" pay for table "+an3+" "+an4);
168                 }
169             }
170             
171             
172             s0 = input.nextLine();
173             s = s0.split(" ");
174         }
175         
176         for(int i=0;i<orderNum;i++)
177             for(int j=i+1;j<orderNum;j++)
178             {
179                 if(isSameTime(order[i],order[j]))
180                     order[i].mergeOrder(order[j]);
181                 
182             }
183         
184         for(int i=0;i<orderNum;i++)
185             order[i].mergeRecords();
186         
187         
188         for(int i=0;i<orderNum;i++)
189         {
190             if(order[i].time == 0)
191                 System.out.println("table "+order[i].tableNumber+" out of opening hours");
192             else if(order[i].isExist)
193                 System.out.println("table "+order[i].tableNumber+": "+order[i].getOriginalPrice()+" "+order[i].getTotalPrice());
194         }
195     }
196     
197     static boolean dateRule(String s0)
198     {
199         boolean f = true;
200         String s[] = s0.split("/");
201         int y = Integer.parseInt(s[0]);
202         
203         if(y<2022||y>2023)
204             return false;
205         
206         return f;
207     }
208     
209     static boolean tableExist(String s,Order[] order,int n)
210     {
211         boolean f =false;
212         int tablenum = Integer.parseInt(s);
213         for(int i=0;i<n;i++)
214             if(order[i].tableNumber == tablenum)
215                 f = true;
216         return f;
217     }
218     
219     static boolean isSameTime(Order o1,Order o2)
220     {
221         boolean f = false;
222         
223         String s[] = o1.date.split("/");
224         int y1 = Integer.parseInt(s[0]);
225         int m1 = Integer.parseInt(s[1]);
226         int d1 = Integer.parseInt(s[2]);
227         
228         s = o2.date.split("/");
229         int y2 = Integer.parseInt(s[0]);
230         int m2 = Integer.parseInt(s[1]);
231         int d2 = Integer.parseInt(s[2]);
232         
233         if(o1.time==1&&o1.time==o2.time)
234         {
235             if(y1==y2&&m1==m2&&d1==d2)
236                 return true;
237         }
238         if(o1.time==2&&o1.time==o2.time)
239         {
240             if(y1==y2&&m1==m2&&d1==d2)
241                 return true;
242         }
243         if(o1.time==-1&&o1.time==o2.time)
244         {
245             if(y1==y2&&m1==m2&&d1==d2)
246             if(subTime(o1.t, o2.t))
247                 return true;
248         }
249         return f;
250     }
251     
252     static boolean subTime(String t1, String t2)
253     {
254         boolean f =false;
255         String s[] = t1.split("/");
256         int h1 = Integer.parseInt(s[0]);
257         int m1 = Integer.parseInt(s[1]);
258         int s1 = Integer.parseInt(s[2]);
259         
260         s = t1.split("/");
261         int h2 = Integer.parseInt(s[0]);
262         int m2 = Integer.parseInt(s[1]);
263         int s2 = Integer.parseInt(s[2]);
264         
265         int tt1 = h1*60*60+m1*60+s1;
266         int tt2 = h2*60*60+m2*60+s2;
267         
268         if(tt1-tt2>=0&&tt1-tt2<3600)
269             return true;
270         if(tt2-tt1>=0&&tt2-tt1<3600)
271             return true;
272         return f;
273     }
274     
275     static int DATAsort(String s)
276     {
277         int datasort = 0;
278         if(s.matches("[\\u4e00-\\u9fa5]+ [1-9][0-9]?[0-9]?[0-9]?"))
279             datasort = 1;//普通菜
280         if(s.matches("[\\u4e00-\\u9fa5]+ [1-9][0-9]?[0-9]?[0-9]? T"))
281             datasort = 2;//特殊菜
282         if(s.matches("table [1-9]+[0-9]?[0-9]? [0-9]{4}/[0-9]{1,2}/[0-9]{1,2} [0-9]{1,2}/[0-9]{1,2}/[0-9]{1,2}"))
283             datasort = 3;//桌信息
284         if(s.matches("[1-9][0-9]? [\\u4e00-\\u9fa5]+ [0-9] [1-9][0-9]?[0-9]?"))
285             datasort = 4;//点菜
286         if(s.matches("[1-9][0-9]{0,2} delete"))
287             datasort = 5;//删除
288         if(s.matches("[0-9][0-9]{0,10} [1-9][0-9]{0,2} [\\u4e00-\\u9fa5]+ [0-9] [1-9][0-9]{0,2}"))
289             datasort = 6;//代点
290         
291         return datasort;
292     }
293     
294     
295     static boolean isDate(String s)
296     {
297         return s.matches("[0-9]{4}/[0-9]{1,2}/[0-9]{1,2}");
298     }
299 
300     static int isTime(String s1,String s2)        //0:超时   -1:周末     1:中午6     2:晚上8
301     {
302         int res=0;
303         String s[] = s1.split("/");
304         int y = Integer.parseInt(s[0]);
305         int m = Integer.parseInt(s[1]);
306         int d = Integer.parseInt(s[2]);
307         
308         s = s2.split("/");
309         int h = Integer.parseInt(s[0]);
310         int f = Integer.parseInt(s[1]);
311         int ss = Integer.parseInt(s[2]);
312         int w = dayInWeek(y,m,d);
313 
314         if(w==6||w==7)
315             if(h>=10&&h<=20||h==9&&f>=30||h==21&&f<30||h==21&&f==30&&ss==0)
316                 res = -1;
317         if(w>=1&&w<=5)
318         {
319             if(h>=11&&h<=13||h==10&&f>=30||h==14&&f<30||h==14&&f==30&&ss==0)
320                 res = 1;
321             if(h>=17&&h<=19||h==20&&f<30||h==20&&f==30&&ss==0)
322                 res = 2;
323         }
324         
325         return res;
326     }
327 
328     static int dayInWeek(int y, int m, int d)
329     {
330         if(m<3)
331         {
332             y--;
333             m+=12;
334         }
335         int c = y/100;
336         y = y%100;
337         int w = (c/4)-2*c+(y+y/4)+(13*(m+1)/5)+d-1;
338         w=(w%7+7)%7;
339         if(w==0) w=7;
340         return w;
341     }
342     
343     public static boolean isRule(String s0)
344     {
345         int y,m,d;
346         String s[] = s0.split("/");
347         y = Integer.parseInt(s[0]);
348         m = Integer.parseInt(s[1]);
349         d = Integer.parseInt(s[2]);
350         
351         boolean f = true;
352         if(m<=0||m>12) f=false;
353         if(m<=7)
354         {
355             if(m%2==1)
356                 if(d<=0||d>31) f=false;
357             if(m%2==0)
358             {
359                 if(m==2)
360                 {
361                     if(isLeap(y))
362                         if(d<=0||d>29) f=false;
363                     if(!isLeap(y))
364                         if(d<=0||d>28) f=false;
365                 }
366                 else
367                     if(d<=0||d>30) f=false;
368             }
369         }
370         if(m>=8)
371         {
372             if(m%2==0)
373                 if(d<=0||d>31) f=false;
374             if(m%2==1)
375                 if(d<=0||d>30) f=false;
376         }
377         return f;
378     }
379 
380     public static boolean isLeap(int y)
381     {
382         boolean f = false;
383         if(y%4==0&&y%100!=0||y%400==0)
384             f=true;
385         return f;
386     }
387 }
388 
389 class Dish
390 {
391     String name;
392     int unit_price;
393     boolean isSpecial;
394 
395     Dish(String name,int unit_price,boolean isSpecial)
396     {
397         this.name = name;
398         this.unit_price = unit_price;
399         this.isSpecial = isSpecial;
400     }
401     
402     int getPrice(int portion)
403     {
404         BigDecimal bg = new BigDecimal((double)unit_price*1.5);
405         int res = 0;
406         if(portion==1) res = unit_price;
407         if(portion==2) res = (int)bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
408         if(portion==3) res = unit_price*2;
409 
410         return res;
411     }
412 }
413 
414 class Menu
415 {
416     int dishNum;
417     Dish[] dishs;
418 
419     Menu()
420     {
421         dishNum = 0;
422         dishs = new Dish[100];
423     }
424     
425     Dish searthDish(String dishName)
426     {
427         Dish d = new Dish("",0,false);
428         for(int i=0;i<dishNum;i++)
429         {
430             if(dishs[i]!=null)
431                 if(dishs[i].name.equals(dishName))
432                     d=dishs[i];
433         }
434         return d;
435     }
436 
437     void addDish(String dishName,int unit_price,boolean isSpecial)
438     {
439         dishs[dishNum] = new Dish(dishName,unit_price,isSpecial);
440         dishNum++;
441     }
442 }
443 
444 class Record
445 {
446     boolean isExist;
447     int orderNum;
448     int num;
449     Dish d;
450     int portion;
451 
452     Record(int orderNum,Dish d,int portion,int num)
453     {
454         isExist = true;
455         this.orderNum = orderNum;
456         this.d = d;
457         this.portion = portion;
458         this.num = num;
459     }
460 
461     int getPriceMust()
462     {
463         return d.getPrice(portion)*num;
464     }
465     
466     int getPrice()
467     {
468         if(isExist)
469             return d.getPrice(portion)*num;
470         else return 0;
471     }
472 }
473 
474 class Order
475 {
476     int tableNumber;
477     boolean isExist;
478     String date;
479     String t;
480     int time;
481     int num;
482     int nowOrder;
483     Record[] records;
484 
485     Order(int tableNumber,int t,String date,String time)
486     {
487         nowOrder = 0;
488         isExist = true;
489         this.time = t;
490         this.tableNumber = tableNumber;
491         this.date = date;
492         this.t = time;
493         num = 0;
494         records = new Record[100];
495     }
496     
497     void mergeRecords()
498     {
499         for(int i=0;i<num;i++)
500         {
501             for(int j=i+1;j<num;j++)
502             {
503                 if(records[i].isExist&&records[j].isExist)
504                 if(records[i].d.name.equals(records[j].d.name))
505                 if(records[i].portion==records[j].portion)
506                 {
507                     records[i].num+=records[j].num;
508                     records[j].isExist = false;
509                 }
510             }
511         }
512     }
513     
514     void mergeOrder(Order o)
515     {
516         
517         if(!this.isExist||!o.isExist)
518             return;
519         
520         for(int i=0;i<o.num;i++)
521         {
522             
523             this.addARecord(o.records[i].orderNum,o.records[i].d,o.records[i].portion,o.records[i].num,false);
524         }
525         o.isExist = false;
526     }
527     
528     int getOriginalPrice()
529     {
530         int res = 0;
531         for(int i=0;i<num;i++)
532         {
533             int recordPrice =records[i].getPrice();
534             res += recordPrice;
535         }
536         
537         return res;
538     }
539     
540     int getTotalPrice()
541     {
542         BigDecimal bg = null;
543         int res = 0;
544         for(int i=0;i<num;i++)
545         {
546             int recordPrice =records[i].getPrice();
547             if(records[i].d.isSpecial)
548             {
549                 if(time != -1)//周一~周五
550                     bg = new BigDecimal((double)recordPrice*0.7);
551                 else
552                     bg = new BigDecimal((double)recordPrice*1);
553             }
554             else
555             {
556                 if(time == 1)//中午
557                     bg = new BigDecimal((double)recordPrice*0.6);
558                 if(time == 2)//晚上
559                     bg = new BigDecimal((double)recordPrice*0.8);
560                 if(time == -1)//周末
561                     bg = new BigDecimal((double)recordPrice*1);
562             }
563             recordPrice = (int)bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
564             res += recordPrice;
565         }
566         
567         return res;
568     }
569 
570     void addARecord(int orderNum,Dish d,int portion,int num,boolean isReplace)
571     {
572         if(!isReplace)
573             nowOrder = orderNum;
574         records[this.num] = new Record(orderNum,d,portion,num);
575         this.num++;
576     }
577 
578     int findRecordByNum(int orderNum)
579     {
580         int res = -1;
581         for(int i=0;i<num;i++)
582             if(records[i].orderNum == orderNum)
583             {
584                 if(records[i].isExist == true)
585                     res = i;
586                 else
587                     res = -2;
588             }
589 
590         return res;
591     }
592 
593     void delARecordByOrderNum(int orderNum)
594     {
595         int target = findRecordByNum(orderNum);
596         records[target].isExist = false;
597     }
598 }

 

    分析:

  本题的代码量非常大,由于错误输入的存在,在编写代码时可以说是步步惊心,每添加一处代码我都在思考会不会有什么我每思考到地方会在此处产生错误,非常有趣!

    类图:

      

  这题中我依然没有改变类图的结构,也没有使用异常处理类,这也导致每一次输入的处理前都会有非常多的if-else。我也是尽量的将if中的语句变得简洁来使代码更加的长度不会太长,当然代码也是依然快到了600行。类中的修改都集中在了Order中,这是因为题目要求在输出总价时要合并同一时间段相同桌号的订单。所以我在Order中添加了合并桌和合并相同菜的代码。

  主类中的修改占大头。最大的修改就是我放弃了此前的通过一行中字符串的数量来判断输入类型的方法,而是使用了正则表达式。这是因为错误输入导致一行中字符串的数量不可控,还有各种新加入的输入类型使得这样的方法更加的鸡肋。在使用正则表达式之前我一直都担心我对它理解不深导致我会频繁试错消耗我的时间,但在使用之后才发现正则表达式非常的方便,用法也是十分简单。

  其次的修改就是我添加了许多规则的判断函数,为的就是减少主函数的复杂度。

 

  4.题目7-1 菜单计价程序-5

本题在菜单计价程序-3的基础上增加了部分内容,增加的内容用加粗字体标识。

注意不是菜单计价程序-4,本题和菜单计价程序-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)//根据序号查找一条记录

}

### 输入格式:

桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价

以上为菜单计价系列-3的题目要求,加粗的部分是有调整的内容。本次课题相比菜单计价系列-3新增要求如下:

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金额都要累加。

输出用户支付金额格式:

用户姓名+英文空格+手机号+英文空格+支付金额

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

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

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

输入格式:

桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的计算折扣后总价+英文空格+辣度平均值+英文空格+酸度平均值+英文空格+甜度平均值+英文空格

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

 

  代码如下:

 

  1 import java.util.Arrays;
  2 import java.util.Comparator;
  3 import java.util.Scanner;
  4 import java.math.BigDecimal;
  5 import java.text.Collator;
  6 
  7 public class Main
  8 {
  9     public static void main(String args[])
 10     {
 11         Scanner input = new Scanner(System.in);
 12         Menu menu = new Menu();
 13         Order[] order = new Order[100];
 14         int orderNum = 0;
 15         boolean ignore = false;
 16         Customer[] customer = new Customer[100];
 17         int customerNum = 0;
 18         
 19         String s0 = input.nextLine();
 20         String[] s = s0.split(" ");
 21 
 22         while(!s[0].equals("end"))
 23         {
 24 
 25             int datasort = DATAsort(s0);
 26             
 27             if(ignore)
 28             {
 29                 if(datasort == 3)
 30                     ignore = false;
 31                 else 
 32                 {
 33                     s0 = input.nextLine();
 34                     s = s0.split(" ");
 35                     continue;
 36                 }
 37             }
 38             
 39             if(datasort == 0)                                    //格式错误
 40             {
 41                 if(s[0].equals("table"))
 42                     ignore = true;
 43                 System.out.println("wrong format");
 44             }
 45             if(datasort == 1)                                    //普通菜
 46             {
 47                 menu.addDish(s[0],Integer.parseInt(s[1]));
 48             }
 49             if(datasort == 2)                                    //特殊菜
 50             {
 51                 menu.addDish(s[0],Integer.parseInt(s[2]),s[1]);
 52             }
 53             if(datasort == 3)                                    //桌信息
 54             {
 55                 int t = isTime(s[5],s[6]);
 56                 
 57                 if(t==0)
 58                 {
 59                     System.out.println("table "+s[1]+" out of opening hours");
 60                     s0 = input.nextLine();
 61                     s = s0.split(" ");
 62                     ignore = true;
 63                     continue;
 64                 }
 65                 
 66                 order[orderNum] = new Order(Integer.parseInt(s[1]),t,s[3]);
 67                 orderNum++;
 68 
 69                 boolean isfind = false;
 70                 for(int i=0;i<customerNum;i++)
 71                     if(customer[i].name.equals(s[3]))
 72                         isfind = true;
 73                 if(!isfind)
 74                 {
 75                     customer[customerNum] = new Customer(s[3],s[4]);
 76                     customerNum++;
 77                 }
 78                 
 79                 System.out.println("table "+s[1]+": ");
 80             }
 81             if(datasort == 4)                                    //点普通菜
 82             {
 83                 Dish d = menu.searthDish(s[1]);
 84                 if(d.name.equals("")&&d.unit_price==0)
 85                     System.out.println(s[1]+" does not exist");
 86                 else
 87                 {
 88                     order[orderNum-1].addARecord(Integer.parseInt(s[0]),d,Integer.parseInt(s[2]),Integer.parseInt(s[3]));
 89                     
 90                     int an1 = Integer.parseInt(s[0]);
 91                     String an2 = s[1];
 92                     int an3 = order[orderNum-1].records[order[orderNum-1].num-1].getPriceMust();
 93                     
 94                     System.out.println(an1+" "+an2+" "+an3);
 95                 }
 96             }
 97             if(datasort == 5)                                //删除
 98             {
 99                 int target = order[orderNum-1].findRecordByNum(Integer.parseInt(s[0]));
100                 if(target == -1) System.out.println("delete error;");
101                 else order[orderNum-1].delARecordByOrderNum(Integer.parseInt(s[0]));
102             }
103             if(datasort == 6)                                //代点菜
104             {
105                 Dish d = menu.searthDish(s[2]);
106                 if(d.name.equals("")&&d.unit_price==0)
107                     System.out.println(s[2]+" does not exist");
108                 else
109                 {
110                     order[orderNum-1].addARecord(Integer.parseInt(s[1]),d,Integer.parseInt(s[3]),Integer.parseInt(s[4]));
111                     
112                     int an1 = Integer.parseInt(s[1]);
113                     int an2 = order[orderNum-1].tableNumber;
114                     int an3 = Integer.parseInt(s[0]);
115                     int an4 = order[orderNum-1].records[order[orderNum-1].num-1].getPriceMust();
116                     
117                     System.out.println(an1+" table "+an2+" pay for table "+an3+" "+an4);
118                 }
119             }
120             if(datasort == 7)                                //点特殊菜
121             {
122                 Dish d = menu.searthDish(s[1]);
123                 if(d.name.equals("")&&d.unit_price==0)
124                     System.out.println(s[1]+" does not exist");
125                 else if(Integer.parseInt(s[2])>d.maxFlavor)
126                 {
127                     if(d.maxFlavor==5) System.out.print("spicy");
128                     if(d.maxFlavor==4) System.out.print("acidity");
129                     if(d.maxFlavor==3) System.out.print("sweetness");
130                     System.out.println(" num out of range :"+s[2]);
131                 }
132                 else
133                 {
134                     order[orderNum-1].addARecord(Integer.parseInt(s[0]),d,Integer.parseInt(s[3]),Integer.parseInt(s[4]),Integer.parseInt(s[2]));
135                     
136                     int an1 = Integer.parseInt(s[0]);
137                     String an2 = s[1];
138                     int an3 = order[orderNum-1].records[order[orderNum-1].num-1].getPriceMust();
139                     
140                     System.out.println(an1+" "+an2+" "+an3);
141                 }
142             }
143             if(datasort == 8)                                //代点特殊菜
144             {
145                 Dish d = menu.searthDish(s[2]);
146                 if(d.name.equals("")&&d.unit_price==0)
147                     System.out.println(s[2]+" does not exist");
148                 else if(Integer.parseInt(s[3])>d.maxFlavor)
149                 {
150                     if(d.maxFlavor==5) System.out.println("spicy");
151                     if(d.maxFlavor==4) System.out.println("acidity");
152                     if(d.maxFlavor==3) System.out.println("sweetness");
153                     System.out.println(" num out of range : "+s[3]);
154                 }
155                 else
156                 {
157                     order[orderNum-1].addARecord(Integer.parseInt(s[1]),d,Integer.parseInt(s[4]),Integer.parseInt(s[5]),Integer.parseInt(s[3]),-1);
158                     
159                     int an1 = Integer.parseInt(s[1]);
160                     int an2 = order[orderNum-1].tableNumber;
161                     int an3 = Integer.parseInt(s[0]);
162                     int an4 = order[orderNum-1].records[order[orderNum-1].num-1].getPriceMust();
163                     
164                     System.out.println(an1+" table "+an2+" pay for table "+an3+" "+an4);
165                     
166                     int findOrder = 0;
167                     for(int i=0;i<orderNum;i++)
168                     {
169                         if(order[i].tableNumber==an3)
170                             findOrder = i;
171                     }
172                     order[findOrder].addARecord(Integer.parseInt(s[1]),d,Integer.parseInt(s[4]),Integer.parseInt(s[5]),Integer.parseInt(s[3]),1);
173                 }
174             }
175             
176             s0 = input.nextLine();
177             s = s0.split(" ");
178         }
179         
180         String Spi[]= {"不辣","微辣","稍辣","辣","很辣","爆辣"};
181         String Aci[]= {"不酸","微酸","稍酸","酸","很酸"};
182         String Sweet[]= {"不甜","微甜","稍甜","甜"};
183         for(int i=0;i<orderNum;i++)
184         {
185             if(order[i].time == 0)
186                 System.out.println("table "+order[i].tableNumber+" out of opening hours");
187             else
188             {
189                 System.out.print("table "+order[i].tableNumber+": "+order[i].getOriginalPrice()+" "+order[i].getTotalPrice()+" ");
190                 int spicy = order[i].getAllflavor(5);
191                 int    acidity = order[i].getAllflavor(4);
192                 int sweet = order[i].getAllflavor(3);
193                 int spiN = order[i].getAllflavornum(5);
194                 int    aciN = order[i].getAllflavornum(4);
195                 int sweetN = order[i].getAllflavornum(3);
196                 
197                 if(spiN!=0)
198                     System.out.print("川菜 "+spiN+" "+Spi[spicy]);
199                 if(spiN!=0&&aciN!=0)
200                     System.out.print(" ");
201                 if(aciN!=0)
202                     System.out.print("晋菜 "+aciN+" "+Aci[acidity]);
203                 if(aciN!=0&&sweetN!=0)
204                     System.out.print(" ");
205                 if(spiN!=0&&sweetN!=0&&aciN==0)
206                     System.out.print(" ");
207                 if(sweetN!=0)
208                     System.out.print("浙菜 "+sweetN+" "+Sweet[sweet]);
209                 
210                 System.out.println("");
211             }
212         }
213         
214         Arrays.sort(customer,0,customerNum,new Comparator<Customer>() {
215             public int compare(Customer a, Customer b) {
216                 return a.compareTo(b);
217             }
218          });
219         for(int i=0;i<customerNum;i++)
220             System.out.println(customer[i].name+" "+customer[i].phoneNumber+" "+customer[i].getAllPrice(order, orderNum));
221     }
222     
223     static int DATAsort(String s)
224     {
225         int datasort = 0;
226         if(s.matches("[\\u4e00-\\u9fa5]+ [1-9][0-9]?[0-9]?[0-9]?"))
227             datasort = 1;//普通菜
228         if(s.matches("[\\u4e00-\\u9fa5]+ [\\u4e00-\\u9fa5]+ [1-9][0-9]{0,2} T"))
229             datasort = 2;//特殊菜
230         if(s.matches("table [1-9]+[0-9]{0,2} : [a-zA-Z]{1,10} 1(8(0|1|9)|3(3|5|6))[0-9]{8} [0-9]{4}/[0-9]{1,2}/[0-9]{1,2} [0-9]{1,2}/[0-9]{1,2}/[0-9]{1,2}"))
231             datasort = 3;//桌信息
232         if(s.matches("[1-9][0-9]? [\\u4e00-\\u9fa5]+ [0-9] [1-9][0-9]{0,2}"))
233             datasort = 4;//点普通菜
234         if(s.matches("[1-9][0-9]? [\\u4e00-\\u9fa5]+ [0-9]{0,2} [0-9] [1-9][0-9]{0,2}"))
235             datasort = 7;//点特殊菜
236         if(s.matches("[1-9][0-9]{0,2} delete"))
237             datasort = 5;//删除
238         if(s.matches("[0-9][0-9]{0,10} [1-9][0-9]{0,2} [\\u4e00-\\u9fa5]+ [1-9][0-9]{0,2} [1-9][0-9]{0,2}"))
239             datasort = 6;//代点
240         if(s.matches("[1-9][0-9]{0,10} [1-9][0-9]{0,2} [\\u4e00-\\u9fa5]+ [0-9]{0,2} [1-9] [1-9][0-9]{0,2}"))
241             datasort = 8;//代点特殊菜
242         
243         return datasort;
244     }
245     
246     static boolean isDate(String s)
247     {
248         return s.matches("[0-9]{4}/[0-9]{1,2}/[0-9]{1,2}");
249     }
250 
251     static int isTime(String s1,String s2)        //0:超时   -1:周末     1:中午6     2:晚上8
252     {
253         int res=0;
254         String s[] = s1.split("/");
255         int y = Integer.parseInt(s[0]);
256         int m = Integer.parseInt(s[1]);
257         int d = Integer.parseInt(s[2]);
258         
259         s = s2.split("/");
260         int h = Integer.parseInt(s[0]);
261         int f = Integer.parseInt(s[1]);
262         int ss = Integer.parseInt(s[2]);
263         int w = dayInWeek(y,m,d);
264 
265         if(w==6||w==7)
266             if(h>=10&&h<=20||h==9&&f>=30||h==21&&f<30||h==21&&f==30&&ss==0)
267                 res = -1;
268         if(w>=1&&w<=5)
269         {
270             if(h>=11&&h<=13||h==10&&f>=30||h==14&&f<30||h==14&&f==30&&ss==0)
271                 res = 1;
272             if(h>=17&&h<=19||h==20&&f<30||h==20&&f==30&&ss==0)
273                 res = 2;
274         }
275         
276         return res;
277     }
278 
279     static int dayInWeek(int y, int m, int d)
280     {
281         if(m<3)
282         {
283             y--;
284             m+=12;
285         }
286         int c = y/100;
287         y = y%100;
288         int w = (c/4)-2*c+(y+y/4)+(13*(m+1)/5)+d-1;
289         w=(w%7+7)%7;
290         if(w==0) w=7;
291         return w;
292     }
293 }
294 
295 class Dish
296 {
297     String name;
298     int unit_price;
299     boolean isSpecial;
300     int maxFlavor;
301 
302     Dish(String name,int unit_price)
303     {
304         this.name = name;
305         this.unit_price = unit_price;
306         this.isSpecial = false;
307     }
308     Dish(String name,int unit_price,String flavor)
309     {
310         this.name = name;
311         this.unit_price = unit_price;
312         this.isSpecial = true;
313         if(flavor.equals("川菜")) maxFlavor = 5;
314         if(flavor.equals("晋菜")) maxFlavor = 4;
315         if(flavor.equals("浙菜")) maxFlavor = 3;
316     }
317     
318     int getPrice(int portion)
319     {
320         BigDecimal bg = new BigDecimal((double)unit_price*1.5);
321         int res = 0;
322         if(portion==1) res = unit_price;
323         if(portion==2) res = (int)bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
324         if(portion==3) res = unit_price*2;
325 
326         return res;
327     }
328 }
329 
330 class Menu
331 {
332     int dishNum;
333     Dish[] dishs;
334 
335     Menu()
336     {
337         dishNum = 0;
338         dishs = new Dish[100];
339     }
340     
341     Dish searthDish(String dishName)
342     {
343         Dish d = new Dish("",0);
344         for(int i=0;i<dishNum;i++)
345         {
346             if(dishs[i]!=null)
347                 if(dishs[i].name.equals(dishName))
348                     d=dishs[i];
349         }
350         return d;
351     }
352 
353     void addDish(String dishName,int unit_price)
354     {
355         dishs[dishNum] = new Dish(dishName,unit_price);
356         dishNum++;
357     }
358     void addDish(String dishName,int unit_price,String flavor)
359     {
360         dishs[dishNum] = new Dish(dishName,unit_price,flavor);
361         dishNum++;
362     }
363 }
364 
365 class Record
366 {
367     boolean isExist;
368     int Replace = 0;
369     int orderNum;
370     int num;
371     Dish d;
372     int portion;
373     int flavor = 0;
374 
375     Record(int orderNum,Dish d,int portion,int num)
376     {
377         isExist = true;
378         this.orderNum = orderNum;
379         this.d = d;
380         this.portion = portion;
381         this.num = num;
382     }
383     Record(int orderNum,Dish d,int portion,int num,int flavor)
384     {
385         isExist = true;
386         this.orderNum = orderNum;
387         this.d = d;
388         this.portion = portion;
389         this.num = num;
390         this.flavor = flavor;
391     }
392     Record(int orderNum,Dish d,int portion,int num,int flavor,int Replace)
393     {
394         isExist = true;
395         this.orderNum = orderNum;
396         this.d = d;
397         this.portion = portion;
398         this.num = num;
399         this.flavor = flavor;
400         this.Replace = Replace;
401     }
402 
403     int getPriceMust()
404     {
405         return d.getPrice(portion)*num;
406     }
407     
408     int getPrice()
409     {
410         if(isExist)
411             return d.getPrice(portion)*num;
412         else return 0;
413     }
414     
415     int getflavor()
416     {
417         return flavor*num;
418     }
419 }
420 
421 class Order
422 {
423     String name;
424     int tableNumber;
425     int time;
426     int num;
427     Record[] records;
428 
429     Order(int tableNumber,int t,String name)
430     {
431         this.time = t;
432         this.tableNumber = tableNumber;
433         this.name = name;
434         num = 0;
435         records = new Record[100];
436     }
437     
438     int getAllflavornum(int maxf)
439     {
440         int n = 0;
441         
442         for(int i=0;i<num;i++)
443         {
444             if(records[i].d.maxFlavor == maxf)
445             if(records[i].isExist)
446             if(records[i].Replace != -1)
447                 n += records[i].num;
448         }
449         return n;
450     }
451     
452     int getAllflavor(int maxf)
453     {
454         BigDecimal bg = null;
455         int res = 0;
456         int n = 0;
457         
458         for(int i=0;i<num;i++)
459         {
460             if(records[i].d.maxFlavor == maxf)
461             if(records[i].isExist)
462             if(records[i].Replace != -1)
463             {
464                 int recordflavor = records[i].getflavor();
465                 res += recordflavor;
466                 n += records[i].num;
467             }
468         }
469         if(n!=0)
470         {
471             bg = new BigDecimal((double)res/(double)n);
472             res = (int)bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
473         }
474         return res;
475     }
476     
477     int getOriginalPrice()
478     {
479         int res = 0;
480         for(int i=0;i<num;i++)
481         {
482             if(records[i].Replace != 1)
483             {
484                 int recordPrice =records[i].getPrice();
485                 res += recordPrice;
486             }
487         }
488         
489         return res;
490     }
491     
492     int getTotalPrice()
493     {
494         BigDecimal bg = null;
495         int res = 0;
496         for(int i=0;i<num;i++)
497         {
498             if(records[i].Replace != 1)
499             {
500                 int recordPrice =records[i].getPrice();
501                 if(records[i].d.isSpecial)
502                 {
503                     if(time != -1)//周一~周五
504                         bg = new BigDecimal((double)recordPrice*0.7);
505                     else
506                         bg = new BigDecimal((double)recordPrice*1);
507                 }
508                 else
509                 {
510                     if(time == 1)//中午
511                         bg = new BigDecimal((double)recordPrice*0.6);
512                     if(time == 2)//晚上
513                         bg = new BigDecimal((double)recordPrice*0.8);
514                     if(time == -1)//周末
515                         bg = new BigDecimal((double)recordPrice*1);
516                 }
517                 recordPrice = (int)bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
518                 res += recordPrice;
519             }
520         }
521         
522         return res;
523     }
524 
525     void addARecord(int orderNum,Dish d,int portion,int num)
526     {
527         records[this.num] = new Record(orderNum,d,portion,num);
528         this.num++;
529     }
530     void addARecord(int orderNum,Dish d,int portion,int num,int flavor)
531     {
532         records[this.num] = new Record(orderNum,d,portion,num,flavor);
533         this.num++;
534     }
535     void addARecord(int orderNum,Dish d,int portion,int num,int flavor,int Replace)
536     {
537         records[this.num] = new Record(orderNum,d,portion,num,flavor,Replace);
538         this.num++;
539     }
540 
541     int findRecordByNum(int orderNum)
542     {
543         int res = -1;
544         for(int i=0;i<num;i++)
545             if(records[i].orderNum == orderNum&&records[i].isExist == true)
546                 res = i;
547 
548         return res;
549     }
550 
551     void delARecordByOrderNum(int orderNum)
552     {
553         int target = findRecordByNum(orderNum);
554         records[target].isExist = false;
555     }
556 }
557 
558 class Customer
559 {
560     String name;
561     String phoneNumber;
562     
563     Customer(String name,String phoneNumber)
564     {
565         this.name = name;
566         this.phoneNumber = phoneNumber;
567     }
568     
569     int getAllPrice(Order[] order,int n)
570     {
571         int res = 0;
572         for(int i=0;i<n;i++)
573         {
574             if(order[i].name.equals(name))
575                 res += order[i].getTotalPrice();
576         }
577         return res;
578     }
579     
580     public int compareTo(Customer cust)
581     {
582         //return this.name.compareTo(cou.name);
583         Comparator<Object> compare = Collator.getInstance(java.util.Locale.CHINA);
584         return compare.compare(this.name, cust.name);
585     }
586 }

 

    分析:

  本题的代码量也是非常之大。难点是在口味度的计算和最后排序输出上。

    类图:

  由于题目中顾客的存在,类图也是终于有了改变——添加了一个Customer类。Customer主要的方法就是计算该顾客名下的所有订单。为了实现输出时按照名称顺序排序,重构了Customer中的compareTo方法。

  由于口味度的存在,订单输入的格式并不统一,于是我就专门在Order中异构了添加订单的方法,来面对不同的输入。由于口味度的输出只在最后输出总价的时候,所以我只在Order中添加了计算口味度的方法。

 

  5.题目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,不考虑无效输入)
对应图形的参数(圆或矩形)

输出格式:

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

 

  代码如下:

 

 1 import java.util.Scanner;
 2 
 3 public class Main
 4 {
 5         public static void main(String[] args) {
 6         // TODO Auto-generated method stub
 7         Scanner input = new Scanner(System.in);
 8         double s;
 9         int choice = input.nextInt();
10             
11         //System.out.println("xx");
12         switch(choice) {
13         case 1://Circle
14             double radiums = input.nextDouble();
15                 if(radiums<=0) System.out.println("Wrong Format");
16                 else{
17             Shape circle = new Circle(radiums);
18             
19             //printArea(circle);
20             s=circle.getS();
21             System.out.println(String.format("%.2f",s));
22                 }
23             break;
24         case 2://Rectangle
25             double x1 = input.nextDouble();
26             double y1 = input.nextDouble();
27             double x2 = input.nextDouble();
28             double y2 = input.nextDouble();
29             
30             
31             Rectangle rectangle = new Rectangle(x1,x2,y1,y2);
32 
33             s=rectangle.getS();
34             System.out.println(String.format("%.2f",s));
35             //printArea(rectangle);
36             break;
37         }
38         
39     }
40 
41 }
42 
43 
44 class Shape
45 {
46     double getS()
47     {
48         return 1;
49     }
50 }
51 
52 class Circle extends Shape
53 {
54     private double r;
55 
56     Circle(Double r)
57     {
58         this.r=r;
59     }
60     
61     double getS()
62     {
63         double S;
64         S=Math.PI*r*r;
65         return S;
66     }
67 }
68 
69 class Rectangle extends Shape
70 {
71     private double x1,y1,x2,y2;
72 
73     Rectangle(double x1,double x2,double y1,double y2)
74     {
75         this.x1=x1;
76         this.x2=x2;
77         this.y1=y1;
78         this.y2=y2;
79     }
80     
81     double getS()
82     {
83         double S;
84         S=(x1-x2)*(y1-y2);
85         if(S<0) S=-S;
86         return S;
87     }
88 }

 

    分析:

  我设计了三个类,Shape类,Circle类,Rectangle类,其中Circle类和Rectangle类继承至shape。Circle类和Rectangle类中都重构了父类中的getS()方法。题目中说要使Shape类为抽象类,我因为考试时紧张,没设计为抽象类。

 

  5.题目测验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:结束输入)

输入图形所需参数

输出格式:

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

 

  代码如下:

 

  1 import java.util.Arrays;
  2 import java.util.Scanner;
  3 
  4 public class Main
  5 {
  6         public static void main(String[] args) {
  7         // TODO Auto-generated method stub
  8         Scanner input = new Scanner(System.in);
  9         double s;
 10         int choice = input.nextInt();
 11         double res[] = new double [100];
 12         
 13         Shape shape[] = new Shape[100];  
 14         int num=0;
 15         
 16          while(choice !=0)
 17          {
 18         switch(choice) {
 19         case 1://Circle
 20             double radiums = input.nextDouble();
 21             if(radiums<=0) System.out.println("Wrong Format");
 22             else{
 23                 Shape circle = new Circle(radiums);
 24                 s=circle.getS();
 25                 //System.out.println(String.format("%.2f",s));
 26                 res[num] = s;
 27                 num++;
 28             }
 29             break;
 30         case 2://Rectangle
 31             double x1 = input.nextDouble();
 32             double y1 = input.nextDouble();
 33             double x2 = input.nextDouble();
 34             double y2 = input.nextDouble();
 35                 
 36             Rectangle rectangle = new Rectangle(x1,x2,y1,y2);
 37             s=rectangle.getS();
 38             //System.out.println(String.format("%.2f",s));
 39             res[num]=s;
 40             num++;
 41             break;
 42         }
 43         choice = input.nextInt();
 44          }
 45          
 46          Arrays.sort(res,0,num);
 47          
 48          for(int i=0;i<num;i++)
 49          {
 50              
 51              System.out.print(String.format("%.2f",res[i]));
 52              System.out.print(" ");
 53          }
 54         
 55     }
 56 
 57 }
 58 
 59 class Shape
 60 {
 61     double S;
 62     
 63     double getS()
 64     {
 65         return 1;
 66     }
 67 
 68     
 69 }
 70 
 71 class Circle extends Shape
 72 {
 73     private double r;
 74 
 75     Circle(Double r)
 76     {
 77         this.r=r;
 78     }
 79     
 80     double getS()
 81     {
 82         double S;
 83         S=Math.PI*r*r;
 84         return S;
 85     }
 86 }
 87 
 88 class Rectangle extends Shape
 89 {
 90     private double x1,y1,x2,y2;
 91 
 92     Rectangle(double x1,double x2,double y1,double y2)
 93     {
 94         this.x1=x1;
 95         this.x2=x2;
 96         this.y1=y1;
 97         this.y2=y2;
 98     }
 99     
100     double getS()
101     {
102         double S;
103         S=(x1-x2)*(y1-y2);
104         if(S<0) S=-S;
105         return S;
106     }
107 }

 

    分析:

  现在回想起来,当时确实是没仔细看题,我的代码完全没按照题目中的写。正确的写法应该是在写一个排序的接口,然后让Shape类实现这个接口。这也给了我一个教训,做事一定不要焦躁,要静下心来。

 

三、踩坑与修正

  1.在题目7-1 菜单计价程序-4中有两个测试点是“代点菜信息,桌号不存在”,第一个代点桌号不存在的测试输入为:

麻婆豆腐 12

油淋生菜 9 T

table 55 2023/3/31 12/00/00

1 麻婆豆腐 1 1

2 油淋生菜 2 1

table 5 2023/3/31 17/00/00

1 麻婆豆腐 1 1

7 2 油淋生菜 2 1

 

end

  这个测试点十分顺利就通过了,但第二给测试点却迟迟无法通过。我测试了非常多的输入用例,始终没找到是什么原因导致。就这样这最后一个测试点耗费了我一个下午的时间。最后还是在课后询问老师才知道测试点是给自己代点菜算作未找到桌号。虽然是一个简单的错误,我也明白了遇到不懂的问题一定要向别人请教,千万不能就自己钻牛角尖,费时又费力。

 

五、总结

  题目集4~6是非常有挑战性的一次作业,在挑战的过程中我也是收益颇深。

  我在这几周的学习中学到了非常多的java技巧,比如抽象类,接口,继承,重构,工厂,java代码编写的原则等等。

  这几次的题目对我来说是十分有意思的,每一次的题目都是前几次的迭代,难度也是在不断提升。这样一步一个脚印的写代码是我原先从来没有过的经历,我希望我能在将来的学习中真正的掌握各种面对对象的代码编写技巧!

  我在写题时,总是对新学到的技巧有些抗拒,总是想着下次再用。这也就导致我对新知识学习较慢,我应该要改变这样的心态,勇于接受新事物,才能不被新社会淘汰。

  对于课堂的建议,我希望将来能有更多的代码实例讲解,如果只是对着类图讲解总觉得有些不好理解。

  希望能与大家一起提升Java的能力,谢谢各位的耐心观看!