目录:
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作为子类,类图如下所示:
试编程完成如上类图设计,主方法源码如下(可直接拷贝使用):
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的能力,谢谢各位的耐心观看!
标签:题目,记录,int,PTA,空格,桌号,期中,英文,菜品 From: https://www.cnblogs.com/AnchunDD/p/17841745.html