一.前言
菜单四
菜单四是在菜单三的基础上迭代的,难度较大,因为要求有很多,这次大作业只要这一道题,但是也是要花费很长时间的
一些知识点:
-
类和对象:在代码中定义了几个类,如
MenuItem
(菜单项)、OrderItem
(订单项)、TableOrder
(桌子订单)和Table
(桌子),它们用于组织和存储相关的数据和行为。 -
集合类的使用:使用
ArrayList
来存储菜单项、订单项和桌子订单等列表数据。通过添加、删除和遍历集合元素来管理订单信息。 -
条件语句和循环:使用
if-else
语句和for-each
循环来处理不同的条件和迭代订单项。 -
方法的定义和调用:定义了一些方法来实现订单处理的逻辑,如添加订单项、删除订单项、计算菜品价格等。这些方法可以在需要的时候被调用。
-
字符串处理:使用
String
类的方法来比较字符串、转换大小写等。 -
数学运算:使用
Math.round()
函数对总价格进行四舍五入
菜单五
菜单计价程序-5也是在菜单三的基础上迭代的,还是很有难度的,但是经历了菜单四的折磨后,菜单五没有那么要命,但还是花了很多时间
一些知识点:
-
异常处理:通过
try-catch
语句块捕获并处理ParseException
异常。 -
集合和数据结构:使用了
ArrayList
和HashMap
集合来存储菜单信息、订单信息以及其他数据。 -
字符串处理:使用了字符串的分割、拼接等操作,以及字符串的比较和匹配。
-
枚举类型(Enum):定义了一个
DishType
枚举类型来表示菜品类型。 -
自定义类和对象:定义了
Dish
、Menu
、Record
、Table
等类,并创建了相应的对象进行数据存储和操作。 -
时间和日期处理:使用了
SimpleDateFormat
类来解析和格式化日期和时间。 -
条件判断和逻辑运算:使用
if-else
语句对输入进行条件判断和处理。 -
数组操作:使用数组来存储字符串和数字等数据。
-
排序和比较:使用了
Comparator
接口和sort
方法对字符串进行排序。 -
面向对象编程:代码中使用了面向对象的封装、继承、多态等概念,通过类和对象的组织和交互来实现功能。
期中考试
期中考试有四道题,层层递进的,不断迭代,题目难度还可以,比较容易吧
- 使用ArrayList存储Shape对象。
- 使用while循环根据用户选择创建不同类型的形状对象并添加到ArrayList中。
- 使用Comparator接口的naturalOrder()方法对列表进行排序。
- 实现Comparable接口来定义Shape对象之间的比较规则。
- 创建Point类来表示坐标点。
- 创建抽象类Shape,并在子类Circle和Rectangle中实现抽象方法
设计与分析:重点对题目的提交源码进行分析,可参考SourceMonitor的生成报表内容以及PowerDesigner的相应类图,要有相应的解释和心得(做到有图有真相),本次Blog主要分析PTA中的菜单计价系列的题目以及期中考试的三道题目
二.设计与分析
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.*; 2 public class Main { 3 public static void main(String[] args) { 4 try (Scanner in = new Scanner(System.in)) { 5 String[] a=new String[50]; 6 int[]b=new int[50]; 7 Menu c=new Menu(); 8 table[] t=new table[50]; 9 Dish g=new Dish(); 10 int i=0;//桌号 11 int j=0;//菜数 12 int p=0;//当前处理桌号 13 int lastdish=0; 14 int dc1=0,dc2=0,dc3=0,dd1=0,dd2=0,dd3=0,dd4=0; 15 int inputnum=0,h; 16 a[0]=in.nextLine(); 17 b[0]=0; 18 for (int i1 = 0; !a[inputnum].equals("end"); i1++){ 19 inputnum++; 20 a[inputnum]=in.nextLine(); 21 b[inputnum]=0; 22 switch (a[inputnum]) { 23 case "": 24 System.out.println("wrong format"); 25 inputnum--; 26 break; 27 default: 28 // 其他情况的处理 29 break; 30 } 31 32 } 33 Worn w=new Worn(); 34 w.worninput(a,inputnum,b); 35 for(h=0;h<inputnum;h++) 36 { 37 boolean flagerror=false; 38 //分割字符 39 String[] arr = a[h].split(" "); 40 if(arr.length==4||arr[0].charAt(0)=='t') 41 { 42 43 if(arr[0].equals("table"))//加桌 44 { 45 flagerror=true; 46 lastdish=0; 47 table x=new table(); 48 x.input(a[h],b[h]); 49 switch (i) { 50 case 0: 51 break; 52 default: 53 p = t[i - 1].searchtime(t, x, i); 54 break; 55 } 56 if(p==i)//加新桌 57 { 58 t[i]=new table(); 59 t[p]=x; 60 i++; 61 lastdish=0;//初始化 62 while(t[p].flag) { 63 System.out.println("table "+t[p].tablenum+": "); 64 break; 65 } 66 } 67 else 68 { 69 while(t[p].flag) { 70 System.out.println("table "+t[p].tablenum+": "); 71 break; 72 } 73 lastdish=0; 74 } 75 76 } 77 else if(arr[0].matches("^[1-9][0-9]{0,1}$"))//自己点菜 78 { 79 if(b[h]==1) 80 { 81 flagerror=true; 82 while(i!=0&&t[p].flag) 83 { 84 System.out.println("wrong format"); 85 break; 86 } 87 continue; 88 } 89 dc1=Integer.parseInt(arr[0]); 90 dc2=Integer.parseInt(arr[2]); 91 dc3=Integer.parseInt(arr[3]); 92 while(i!=0&&t[p].flag) 93 { 94 while(i!=0) 95 { 96 if(dc1<=lastdish) 97 { 98 System.out.println("record serial number sequence error"); 99 } 100 else 101 { 102 t[p].selforder.addARecord(0,dc1,arr[1],dc2,dc3,true); 103 g=c.searthDish(arr[1]); 104 105 while(g!=null&&t[p].flag) 106 { 107 108 if(dc2>3&&dc2<10||dc2<=0&&dc2>-10)//情况9 109 { 110 System.out.println(dc1+" portion out of range "+dc2); 111 } 112 else if(dc3>15) 113 { 114 System.out.println(dc1+" num out of range "+dc3); 115 } 116 else 117 { 118 t[p].selforder.records[t[p].k].d=g; 119 int x=t[p].selforder.records[t[p].k].getPrice(); 120 lastdish=dc1; 121 System.out.println(dc1+" "+arr[1]+" "+x); 122 } 123 break; 124 } 125 t[p].k++; 126 127 } 128 break; 129 } 130 break; 131 } 132 } 133 else 134 { 135 System.out.println("wrong format"); 136 flagerror=true; 137 } 138 139 } 140 141 else if(arr.length==5)//代点 142 { 143 // 1 4 麻婆豆腐 1 1 144 if(b[h]==1) 145 { 146 flagerror=true; 147 while(i!=0&&t[p].flag) 148 { 149 System.out.println("wrong format"); 150 break; 151 } 152 continue; 153 } 154 dd1=Integer.parseInt(arr[0]); 155 dd2=Integer.parseInt(arr[1]); 156 dd3=Integer.parseInt(arr[3]); 157 dd4=Integer.parseInt(arr[4]); 158 while(t[p].searthtable(t,dd1,p)==true) 159 { 160 t[p].selforder.addARecord(dd2, dd1, arr[2], dd3,dd4,false); 161 g=c.searthDish(arr[2]); 162 while(g!=null) 163 { 164 t[p].selforder.records[t[p].k].d=g; 165 int x=t[p].selforder.records[t[p].k].getPrice(); 166 System.out.println(dd2+" table "+t[p].tablenum+" pay for table "+dd1+" "+x); 167 break; 168 } 169 //k++; 170 t[p].k++; 171 break; 172 } 173 } 174 else if(arr.length==2) 175 { 176 if(arr[1].equals("delete"))//删菜 177 { 178 179 if(i!=0) 180 { 181 if(b[h]==1) 182 { 183 flagerror=true; 184 while(i!=0) 185 { 186 System.out.println("wrong format"); 187 break; 188 } 189 continue; 190 } 191 while(t[p].flag) { 192 t[p].selforder.delARecordByOrderNum(Integer.parseInt(arr[0]),t[p]); 193 break; 194 } 195 } 196 } 197 else//加菜 198 { 199 if(b[h]==1) 200 { 201 flagerror=true; 202 System.out.println("wrong format"); 203 continue; 204 } 205 if(i!=0&&t[p].flag)//情况1 206 { 207 System.out.println("invalid dish"); 208 } 209 else 210 { 211 if(Integer.parseInt(arr[1])>0&&Integer.parseInt(arr[1])<300) 212 { 213 c.addDish(arr[0], Integer.parseInt(arr[1]),false); 214 j++; 215 } 216 else 217 { 218 System.out.println(arr[0]+" price out of range "+arr[1]); 219 } 220 } 221 } 222 } 223 else if(arr.length==3)//特色菜 224 { 225 if(b[h]==1) 226 { 227 flagerror=true; 228 System.out.println("wrong format"); 229 continue; 230 } 231 if(i!=0&&t[p].flag) 232 { 233 System.out.println("invalid dish"); 234 } 235 else 236 { 237 while(arr[2].equals("T")) 238 { 239 if(Integer.parseInt(arr[1])>0&&Integer.parseInt(arr[1])<300) 240 { 241 c.addDish(arr[0], Integer.parseInt(arr[1]),true); 242 j++; 243 } 244 else 245 { 246 System.out.println(arr[0]+" price out of range "+arr[1]); 247 } 248 break; 249 } 250 } 251 } 252 } 253 int l = 0; 254 while (l < i) { 255 t[l].getTotalPrice(); 256 l++; 257 } 258 } catch (NumberFormatException e) { 259 // TODO Auto-generated catch block 260 e.printStackTrace(); 261 } 262 } 263 264 } 265 class Dish 266 { 267 String name="";//菜品名称 268 int unit_price; 269 boolean special=false;//特色菜,true为是 270 //单价 271 int getPrice(int portion) { 272 int 菜价 = 0; 273 // 单菜价格 274 if (portion == 1) { 275 菜价 = unit_price; 276 } else if (portion == 2) { 277 菜价 = (int) Math.ceil(1.0 * unit_price * 3 / 2); 278 } else if (portion == 3) { 279 菜价 = unit_price * 2; 280 } 281 return 菜价; 282 } 283 284 } 285 class Menu 286 { 287 Dish[] dishs =new Dish[20]; 288 int i=0;//用于记录菜品总数 289 void addDish(String dishName,int unit_price,Boolean ts) 290 { 291 292 // Dish dish1=new Dish(); 293 dishs[i]=new Dish(); 294 dishs[i].name=dishName; 295 dishs[i].unit_price=unit_price; 296 dishs[i].special=ts; 297 i++; 298 //return dish1; 299 } 300 //菜品数组,保存所有菜品信息 301 Dish searthDish(String dishName) //根据菜名在菜谱中查找菜品信息,返回Dish对象。 302 { 303 int j=0; 304 int flag=0; 305 j = i - 1; 306 while (j >= 0) { 307 if (dishName.compareTo(dishs[j].name) == 0) { 308 flag = 1; 309 break; 310 } 311 j--; 312 } 313 switch (flag) { 314 case 1: 315 return dishs[j]; 316 default: 317 // 麻辣鸡丝 does not exist 318 System.out.println(dishName + " does not exist"); 319 return null; 320 } 321 322 } 323 } 324 class Record 325 { 326 Dish d=new Dish();//菜品 327 int orderNum=0;//序号\ 328 int portion=0; 329 int num=0;//份数 330 int tablenum=0;//桌号//没什么用 331 boolean self=true; 332 //份额(1/2/3代表小/中/大份) 333 int getPrice() 334 { 335 int n=0; 336 n=num*d.getPrice(portion); 337 //2 油淋生菜 27 338 // System.out.println(n); 339 return n; 340 }//计价,计算本条记录的价格 341 } 342 343 class Order 344 { 345 Record[] records=new Record[20]; 346 int j=0; 347 int[] deletenum=new int[50]; 348 //添加一条菜品信息到订单中。 349 void addARecord(int tablenum,int orderNum,String dishName,int portion,int num,boolean self)//添加一条菜品信息到订单中。 350 { 351 //1 麻婆豆腐 2 2 352 records[j]=new Record(); 353 records[j].tablenum=tablenum; 354 records[j].orderNum=orderNum; 355 records[j].d.name=dishName; 356 records[j].portion=portion; 357 records[j].num=num; 358 records[j].self=self; 359 //System.out.println(num); 360 j++; 361 } 362 363 boolean srarchdelete(int orderNum)//找到返回true 364 { 365 int i = 0; 366 while (i < 50) { 367 if (deletenum[i] != 0) { 368 while (orderNum == deletenum[i]) { 369 return true; 370 } 371 } else { 372 break; 373 } 374 i++; 375 } 376 377 deletenum[i]=orderNum; 378 while(i==0) 379 { 380 return false; 381 } 382 return false; 383 } 384 void delARecordByOrderNum(int orderNum,table t)//根据序号删除一条记录 385 //试试直接总价减去删除菜 386 { 387 if(srarchdelete(orderNum)==false) 388 { 389 int i = 0; 390 while (i < j) { 391 while (t.selforder.records[i].orderNum == orderNum) { 392 t.selforder.records[i].num = 0; 393 break; 394 } 395 // records[orderNum-1].getPrice(); 396 i++; 397 } 398 399 } 400 else//情况4 401 { 402 403 System.out.println("deduplication "+orderNum); 404 405 } 406 } 407 void srarchrecord(Record g,int k) 408 { 409 int i = 0; 410 while (i < k) { 411 if (g.d.name.equals(records[i].d.name) && g.portion == records[i].portion && records[i].self == true) { 412 records[i].num += g.num; 413 g.num = 0; 414 break; 415 } 416 i++; 417 } 418 419 420 } 421 } 422 class table 423 { 424 int tablenum;//桌号 425 String time;//点菜时间//2023/3/22 12/2/3 426 int year=0,month=0,day=0,ww=0,hh=0,mm=0,ss=0; 427 boolean flag=false;//判断时间是否正确 428 double count=0;//普通菜折扣 429 double specialcount=1; 430 Order selforder=new Order();//本桌订单 431 int sum=0;//计算总价 432 int truesum=0;//未打折价 433 int k=0;//点菜次数 434 int sumdish=0;//菜总数 435 void input(String time,int b)//预处理 436 { 437 String[] arr1=time.split(" "); 438 int blank=0; 439 for(int bk=0;bk<time.length();bk++) 440 { 441 while(time.charAt(bk)==' ') 442 { 443 blank++; 444 break; 445 } 446 } 447 //桌号 448 if(blank!=3||!arr1[1].matches("^[1-9][0-9]{0,}$")||arr1.length!=4) 449 { 450 System.out.println("wrong format"); 451 } 452 453 //System.out.println(); 454 else 455 { 456 this.time=arr1[2]+" "+arr1[3]; 457 // System.out.println(); 458 tablenum=Integer.parseInt(arr1[1]); 459 if(tablenum<=55&&tablenum>=1) 460 { 461 if(this.time.matches("^([0-9]{4}/[0-9]{1,2}/[0-9]{1,2}) ([0-9]{1,2}/[0-9]{1,2}/[0-9]{1,2})$")) 462 { 463 if(arr1[2].matches("^(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})/((([0]{0,1}[13578]|1[02])/([0]{0,1}[1-9]|[12][0-9]|3[01]))|(([0]{0,1}[469]|11)/([0]{0,1}[1-9]|[12][0-9]|30))|([0]{0,1}2/([1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})([48]|[0]{0,1}[2468][048]|[0]{0,1}[13579][26])|(([48]|[2468][048]|[3579][26])00))/[0]{0,1}2/29)$")&&arr1[3].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$")) 464 { 465 466 boolean flag1=judgetime1(); 467 if(flag1==true)//时间有效 468 { 469 timechange(); 470 jscount(); 471 pdflag(); 472 while(b==1) { 473 System.out.println("wrong format"); 474 break; 475 } 476 } 477 else 478 { 479 System.out.println("not a valid time period"); 480 } 481 } 482 else 483 System.out.println(tablenum+" date error"); 484 } 485 else 486 System.out.println("wrong format"); 487 488 } 489 490 491 else 492 { 493 System.out.println(arr1[1] +" table num out of range"); 494 } 495 } 496 } 497 498 boolean judgetime1()//是否有效//使用正则表达式 499 { 500 String[] arr=time.split(" "); 501 boolean flag=arr[0].matches("^(2022|2023)/(([13578]|0[13578]|10|12)/(([1-9]|0[1-9])|([12][0-9])|3[01])|([469]|0[469]|11)/(([1-9]|0[1-9])|([12][0-9])|30)|(2|02)/(([1-9]|0[1-9])|(1[0-9])|(2[0-8])))$"); 502 boolean flag1=arr[1].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$"); 503 return (flag&&flag1); 504 505 } 506 void getTotalPrice()//计算桌总价 507 { 508 if(flag) 509 { 510 511 int j=selforder.j; 512 int i = j-1; 513 while(i>=0) 514 { 515 selforder.srarchrecord(selforder.records[i],i); 516 i--; 517 } 518 int i1 = 0; 519 while(i1<j) 520 { 521 int x=0; 522 x=selforder.records[i1].getPrice(); 523 truesum+=x; 524 if(selforder.records[i1].d.special==true)//特色菜 525 { 526 sum+=(int)(x*specialcount+0.5); 527 } 528 else 529 sum+=(int)(x*count+0.5); 530 i1++; 531 } 532 533 System.out.println("table "+tablenum+": "+truesum+" "+sum); 534 //table 1: 63 535 } 536 537 } 538 void jscount()//运用时间计算折扣 539 { 540 if(ww>=1&&ww<=5) 541 { 542 specialcount=0.7; 543 switch (hh) { 544 case 17: 545 case 18: 546 case 19: 547 count = 0.8; 548 break; 549 case 20: 550 if (mm < 30 || (mm == 30 && ss == 0)) { 551 count = 0.8; 552 } 553 break; 554 case 11: 555 case 12: 556 case 13: 557 count = 0.6; 558 break; 559 case 10: 560 if (mm >= 30) { 561 count = 0.6; 562 } 563 break; 564 case 14: 565 if (mm < 30 || (mm == 30 && ss == 0)) { 566 count = 0.6; 567 } 568 break; 569 } 570 571 } 572 else 573 { 574 specialcount=1; 575 switch (hh) { 576 case 10: 577 case 11: 578 case 12: 579 case 13: 580 case 14: 581 case 15: 582 case 16: 583 case 17: 584 case 18: 585 case 19: 586 case 20: 587 count = 1.0; 588 break; 589 case 9: 590 if (mm >= 30) { 591 count = 1.0; 592 } 593 break; 594 case 21: 595 if (mm < 30 || (mm == 30 && ss == 0)) { 596 count = 1.0; 597 } 598 break; 599 } 600 601 } 602 } 603 void pdflag()//判断时间是否正确 604 { 605 if(count==0) 606 { 607 System.out.println("table "+tablenum+" out of opening hours"); 608 flag=false; 609 } 610 else 611 flag=true; 612 613 } 614 void timechange()//时间转换 615 { 616 //2023/3/22 12/2/3 617 String[] arr=time.split(" "); 618 String[] arr1=arr[0].split("/"); 619 String[] arr2=arr[1].split("/"); 620 year=Integer.parseInt(arr1[0]);//时间 621 month=Integer.parseInt(arr1[1]); 622 day=Integer.parseInt(arr1[2]); 623 Calendar c = Calendar.getInstance(); 624 c.set(year,month-1,day);//设置时间 625 ww=c.get(Calendar.DAY_OF_WEEK); 626 hh=Integer.parseInt(arr2[0]);//时间 627 mm=Integer.parseInt(arr2[1]); 628 ss=Integer.parseInt(arr2[2]); 629 switch (ww) { 630 case 1: 631 ww = 7; 632 break; 633 default: 634 ww--; 635 break; 636 } 637 638 } 639 boolean searthtable(table[]t,int num,int p) 640 { 641 int i=0; 642 while(i<50) 643 { 644 if(t[i]!=null&&i!=p) 645 { 646 while(t[i].tablenum==num&&t[i].flag) { 647 return true; 648 } 649 } 650 else 651 break; 652 i++; 653 } 654 //"Table number :"+被点菜桌号+" does not exist" 655 System.out.println("Table number :"+num+" does not exist"); 656 return false; 657 } 658 int searchtime(table[]t,table a,int sumtable)//若找到返回对应桌,找不到返回下一个空桌 659 { 660 int i=0; 661 //(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒) 662 while(i<sumtable) 663 { 664 while(a.tablenum==t[i].tablenum) { 665 while(a.year==t[i].year) 666 { 667 while(a.day==t[i].day) 668 { 669 if(a.ww>=1&&a.ww<=5)//周1~5 670 { 671 while(a.hh<=14&&t[i].hh<=14||a.hh>14&&t[i].hh>14)//在同一时段 672 { 673 674 return i; 675 676 } 677 } 678 else//周末 679 { 680 while(Math.abs((a.hh-t[i].hh)*60*60+(a.mm-t[i].mm)*60)+(a.ss-t[i].ss)<60*60)//在同一时段 681 { 682 683 return i; 684 } 685 686 } 687 break; 688 } 689 break; 690 } 691 break; 692 } 693 i++; 694 } 695 //System.out.println(sumtable); 696 return sumtable; 697 } 698 699 } 700 class Worn//错误判断,错误b[i]==1 701 { 702 void worninput(String[]a,int num,int[]b) 703 { 704 //boolean flag1=true; 705 int i=0; 706 while(i<num) 707 { 708 String[] arr=a[i].split(" "); 709 boolean flag=false; 710 //麻婆豆腐 12 711 while(arr.length>5) 712 { 713 b[i]=1; 714 break; 715 } 716 if(a[i].matches("^[\u4e00-\u9fa5]{1,} ([1-9][0-9]{0,2})$")==true)//普通菜存入 717 { 718 flag=true; 719 } 720 //油淋生菜 9 T 721 else if(a[i].matches("^[\u4e00-\u9fa5]{1,4} ([1-9][0-9]{0,2}) [T]$")==true)//特色菜存入 722 { 723 flag=true; 724 } 725 //table 31 2023/2/1 14/20/00 726 else if(arr[0].equals("table")==true)//桌 727 { 728 int blank=0; 729 int bk=0; 730 while(bk<a[i].length()) 731 { 732 while(a[i].charAt(bk)==' ') 733 { 734 blank++; 735 break; 736 } 737 bk++; 738 } 739 while(arr[1].matches("^([1-9][0-9]{0,})$")&&blank==3) { 740 flag=true; 741 break; 742 } 743 //int blank=0; 744 745 } 746 //1 麻婆豆腐 1 16 747 else if(a[i].matches("^[1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//自己点菜 748 { 749 flag=true; 750 } 751 //1 1 麻婆豆腐 1 16 752 else if(a[i].matches("^([1-9][0-9]{0,1}) [1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//待点菜 753 { 754 flag=true; 755 } 756 //2 delete 757 else if(a[i].matches("^([1-9][0-9]{0,1}) delete$")==true)//删菜 758 { 759 flag=true; 760 } 761 else if(a[i].matches("^end$")==true)//结尾 762 { 763 flag=true; 764 } 765 while(flag==false) 766 { 767 b[i]=1; 768 break; 769 } 770 i++; 771 } 772 } 773 }
类图如下:
代码难易程度如下图所示:
分析:
-
Dish
类:表示菜品,包含菜名、单价、是否为特色菜等信息。getPrice
方法用于计算菜品的价格。 -
Menu
类:表示菜单,包含菜品数组和添加菜品的方法。searthDish
方法用于根据菜名查找菜品。 -
Record
类:表示订单中的一条记录,包含菜品、序号、份额、份数等信息。getPrice
方法用于计算记录的价格。 -
Order
类:表示订单,包含记录数组和添加记录的方法。srarchdelete
方法用于在订单中查找是否存在相同的记录,delARecordByOrderNum
方法用于根据序号删除记录。 -
table
类:表示桌子订单,包含桌号、时间、订单等信息。getTotalPrice
方法用于计算桌子订单的总价,jscount
方法用于根据时间计算折扣。 -
Worn
类:用于检查输入是否符合预期格式,主要通过正则表达式进行判断。 -
Main
类:包含main
方法,用于程序的入口。通过命令行输入,处理用户输入的各种操作,包括添加桌子、点菜、代点菜、加菜、删菜等。
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.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 import java.time.LocalDate; 5 import java.util.ArrayList; 6 import java.time.format.DateTimeFormatter; 7 import java.util.Arrays; 8 import java.util.regex.Pattern; 9 import java.util.regex.Matcher; 10 import java.time.*; 11 import java.time.DayOfWeek; 12 public class Main { 13 public static void main(String[] args) throws IOException { 14 BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 15 Dish[] dishes = new Dish[20]; 16 SpecialDish[] specialDishes = new SpecialDish[20]; 17 Table table = new Table(); 18 Record[] records = new Record[20]; 19 PersonPay[] personPays = new PersonPay[10]; 20 Order order = new Order(); 21 Menu menu = new Menu(); 22 caicage cage = new caicage() ; 23 lastPrint print = new lastPrint(); 24 inputmat mat = new inputmat() ; 25 ArrayList<Table> tables = new ArrayList<>(); 26 int x = 0 , y = 0 , z = 0 , z1 = 0 , p = 0 ; 27 String menuName , name , tableName , telephoneNum , taste; 28 int tableNum , dishNum , portion , num , unit_price , deleteNum , tasteNum; 29 boolean isHaveTable = false , forOther = false; 30 boolean falg = true; 31 while(falg){ 32 String input = in.readLine(); 33 if(input.equals("end")){ 34 if(x!=0){ 35 table.order = order; 36 tables.add(x-1 , table); 37 } 38 39 break; 40 } 41 String[] getInput = input.split(" "); 42 int flag = mat.inpumat(input); 43 switch(flag) { 44 case 1: { 45 if (x != 0) { 46 table.order = order; 47 tables.add(x - 1, table); 48 table = new Table(); 49 y = 0; 50 } 51 isHaveTable = true; 52 tableNum = Integer.parseInt(getInput[1]); 53 tableName = getInput[3]; 54 telephoneNum = getInput[4]; 55 String dayTime = getInput[5]; 56 String hourTime = getInput[6]; 57 58 table.tableNum = tableNum; 59 table.tableName = tableName; 60 table.telephoneNum = telephoneNum; 61 table.mainTime = dayTime; 62 table.remainTime = hourTime; 63 64 if (!table.timeJudgement1()) { 65 isHaveTable = false; 66 System.out.println("table " + table.tableNum + " out of opening hours"); 67 continue; 68 } 69 70 order = new Order(); 71 records = new Record[10]; 72 73 if (x == 0) { 74 personPays[p] = new PersonPay(); //人名 75 personPays[p].name = tableName; 76 personPays[p].telephoneNum = telephoneNum; //电话号码 77 p++; 78 print.p = p; //应该输出多少次 79 } else { 80 boolean isNewPerson = true; 81 for (int i = 0; i < p; i++) { 82 if (personPays[i].name.equals(tableName) && personPays[i].telephoneNum.equals(telephoneNum)) { 83 isNewPerson = false; 84 break; 85 } 86 } 87 if (isNewPerson) { 88 personPays[p] = new PersonPay(); 89 personPays[p].name = tableName; 90 personPays[p].telephoneNum = telephoneNum; 91 p++; 92 print.p = p; 93 } 94 } 95 96 System.out.println("table " + tableNum + ": "); 97 x++; 98 break; 99 } 100 101 case 2: {//普通菜单 102 menuName = getInput[0]; 103 unit_price = Integer.parseInt(getInput[1]); 104 105 boolean dishFound = false; 106 for (int i = 0; i < z; i++) { 107 if (menuName.equalsIgnoreCase(dishes[i].name)) { 108 dishes[i].unit_price = unit_price; 109 dishFound = true; 110 break; 111 } 112 } 113 114 if (!dishFound) { 115 dishes[z] = menu.addDish(menuName, unit_price); 116 z++; 117 } 118 119 menu.dishes = dishes; 120 menu.dishNum = z; 121 break; 122 } 123 124 case 3: { //特色菜 125 menuName = getInput[0]; 126 unit_price = Integer.parseInt(getInput[2]); 127 String tasteToAdd = getInput[1]; // 修改变量名为tasteToAdd 128 129 boolean specialDishFound = false; 130 int i; 131 for (i = 0; i < z1; i++) { 132 if (menuName.equalsIgnoreCase(specialDishes[i].name)) { 133 specialDishes[i].unit_price = unit_price; 134 specialDishFound = true; 135 break; 136 } 137 } 138 139 if (!specialDishFound) { 140 specialDishes[z1] = menu.addSpecialDish(menuName, unit_price, tasteToAdd); 141 z1++; 142 } 143 144 menu.specialDishes = specialDishes; 145 menu.dishNum1 = z1; 146 break; 147 } 148 149 case 4: { 150 if (!isHaveTable) 151 continue; 152 name = getInput[1]; 153 if (menu.searthDish(name) != null) { 154 dishNum = Integer.parseInt(getInput[0]); 155 portion = Integer.parseInt(getInput[2]); 156 num = Integer.parseInt(getInput[3]); 157 records[y] = new Record(); 158 records[y] = order.addARecord(dishNum, name, portion, num, menu); 159 records[y].isSpecialDish = false; 160 System.out.println(records[y].orderNum + " " + records[y].d.name + " " + records[y].getPrice()); 161 y++; 162 order.records = records; 163 order.dishNum = y; 164 } else { 165 System.out.println(name + " does not exist"); 166 } 167 break; 168 } 169 170 case 5: { 171 if (!isHaveTable) 172 continue; 173 name = getInput[1]; 174 SpecialDish specialDish = menu.searthSpecialDish(name); 175 if (specialDish != null) { 176 tasteNum = Integer.parseInt(getInput[2]); 177 num = Integer.parseInt(getInput[4]); 178 int flag1 = mat.findcage(specialDish.taste); 179 if ((flag1 == 1 && tasteNum >= 0 && tasteNum <= 5) 180 || (flag1 == 2 && tasteNum >= 0 && tasteNum <= 4) 181 || (flag1 == 3 && tasteNum >= 0 && tasteNum <= 3)) { 182 records[y] = order.addASpecialRecord(Integer.parseInt(getInput[0]), name, Integer.parseInt(getInput[3]), num, menu, tasteNum, forOther); 183 records[y].isSpecialDish = true; 184 System.out.println(records[y].orderNum + " " + records[y].d.name + " " + records[y].getPrice()); 185 y++; 186 order.records = records; 187 order.dishNum = y; 188 } else { 189 mat.error(tasteNum, flag1); 190 break; 191 } 192 } else { 193 System.out.println(name + " does not exist"); 194 continue; 195 } 196 break; 197 } 198 199 case 6: { 200 if (!isHaveTable) 201 continue; 202 deleteNum = Integer.parseInt(getInput[0]); 203 if (order.findRecordByNum(deleteNum) == 1) { 204 order.delARecordByOrderNum(deleteNum); 205 } else 206 System.out.println("delete error;"); 207 break; 208 } 209 case 7: { 210 int t = Integer.parseInt(getInput[0]); 211 name = getInput[2]; 212 for (int i = 0; i < x - 1; i++) { 213 if (tables.get(i).tableNum == t && menu.searthDish(name) != null) { 214 records[y] = order.addARecord(Integer.parseInt(getInput[1]), name, Integer.parseInt(getInput[3]), Integer.parseInt(getInput[4]), menu); 215 records[y].isSpecialDish = false; 216 System.out.println(getInput[1] + " table " + table.tableNum + " pay for table " + t + " " + records[y].getPrice()); 217 y++; 218 order.records = records; 219 order.dishNum = y; 220 break; 221 } 222 } 223 break; 224 } 225 226 case 8: { 227 int t = Integer.parseInt(getInput[0]); 228 name = getInput[2]; 229 tasteNum = Integer.parseInt(getInput[3]); 230 int flag1 = mat.findcage(menu.searthSpecialDish(name).taste); 231 for (int i = 0; i < x - 1; i++) { 232 if (tables.get(i).tableNum == t && menu.searthSpecialDish(name) != null) { 233 if (((flag1 == 1 && tasteNum >= 1 && tasteNum <= 5) || 234 (flag1 == 2 && tasteNum <= 4) || 235 (flag1 == 3 && tasteNum <= 3))) { 236 records[y] = new Record(); 237 dishNum = Integer.parseInt(getInput[1]); 238 portion = Integer.parseInt(getInput[4]); 239 num = Integer.parseInt(getInput[5]); 240 records[y] = order.addASpecialRecord(dishNum, name, portion, num, menu, tasteNum, !forOther); 241 records[y].isSpecialDish = true; 242 System.out.println(dishNum + " table " + table.tableNum + " pay for table " + t + " " + records[y].getPrice()); 243 tables.get(i).giveTaste(name, num, tasteNum, menu); 244 y++; 245 order.records = records; 246 order.dishNum = y; 247 } 248 break; 249 } 250 } 251 break; 252 } 253 254 default :{ 255 System.out.println("wrong format"); 256 break; 257 } 258 } 259 } 260 print.tables = tables; 261 print.personPays = personPays; 262 for (Table table1 : tables) { 263 table1.order.getTotalPrice(); 264 table1.getTaste(); 265 if(table1.spicyNum==0&&table1.acidityNum==0&&table1.sweetnessNum==0) 266 System.out.println("table " + table1.tableNum + ": " + (table1.order.allCommonPrice + table1.order.allSpecialPrice) + " " + table1.tablePrice()+" "); 267 if(table1.spicyNum!=0&&table1.acidityNum==0&&table1.sweetnessNum==0) 268 System.out.println("table " + table1.tableNum + ": " + (table1.order.allCommonPrice + table1.order.allSpecialPrice) + " " + table1.tablePrice() + " 川菜 " +(int)table1.spicyNum+" "+mat.spicyLevel(table1.averageSpicy )); 269 if(table1.spicyNum==0&&table1.acidityNum!=0&&table1.sweetnessNum==0) 270 System.out.println("table " + table1.tableNum + ": " + (table1.order.allCommonPrice + table1.order.allSpecialPrice) + " " + table1.tablePrice() + " 晋菜 " +(int)table1.acidityNum+" "+mat.acidityLevel(table1.averageAcidity )); 271 if(table1.spicyNum==0&&table1.acidityNum==0&&table1.sweetnessNum!=0) 272 System.out.println("table " + table1.tableNum + ": " + (table1.order.allCommonPrice + table1.order.allSpecialPrice) + " " + table1.tablePrice() + " 浙菜 " +(int)table1.sweetnessNum+" "+ mat.sweetnessLevel(table1.averageSweetness )); 273 if(table1.spicyNum!=0&&table1.acidityNum!=0&&table1.sweetnessNum==0) 274 System.out.println("table " + table1.tableNum + ": " + (table1.order.allCommonPrice + table1.order.allSpecialPrice) + " " + table1.tablePrice() + " 川菜 " +(int)table1.spicyNum+" "+mat.spicyLevel(table1.averageSpicy )+" 晋菜 "+(int)table1.acidityNum+" "+mat.acidityLevel(table1.averageAcidity ) ); 275 if(table1.spicyNum!=0&&table1.acidityNum==0&&table1.sweetnessNum!=0) 276 System.out.println("table " + table1.tableNum + ": " + (table1.order.allCommonPrice + table1.order.allSpecialPrice) + " " + table1.tablePrice() + " 川菜 " +(int)table1.spicyNum+" "+mat.spicyLevel(table1.averageSpicy )+" 浙菜 "+(int)table1.sweetnessNum+" "+mat.sweetnessLevel(table1.averageSweetness ) ); 277 if(table1.spicyNum==0&&table1.acidityNum!=0&&table1.sweetnessNum!=0) 278 System.out.println("table " + table1.tableNum + ": " + (table1.order.allCommonPrice + table1.order.allSpecialPrice) + " " + table1.tablePrice() + " 晋菜 " +(int)table1.acidityNum+" "+mat.acidityLevel(table1.averageAcidity ) +" 浙菜 "+(int)table1.sweetnessNum+" "+mat.sweetnessLevel(table1.averageSweetness )); 279 if(table1.spicyNum!=0&&table1.acidityNum!=0&&table1.sweetnessNum!=0) 280 System.out.println("table " + table1.tableNum + ": " + (table1.order.allCommonPrice + table1.order.allSpecialPrice) + " " + table1.tablePrice() + " 川菜 " +(int)table1.spicyNum+" "+mat.spicyLevel(table1.averageSpicy )+" 晋菜 "+(int)table1.acidityNum+" "+mat.acidityLevel(table1.averageAcidity ) +" 浙菜 "+(int)table1.sweetnessNum+" "+mat.sweetnessLevel(table1.averageSweetness )); 281 } 282 print.payPrint(); 283 } 284 } 285 class Dish{ 286 String name; 287 String taste; 288 int unit_price; 289 public int getPrice(int portion){ 290 int Price=0; 291 if(portion==1) 292 Price=unit_price; 293 else if(portion==3) 294 Price=unit_price*2; 295 else if(portion==2) 296 Price=(int)Math.round((float)unit_price*1.5); 297 return Price; 298 } 299 } 300 class SpecialDish extends Dish{ 301 } 302 class Menu{ 303 Dish[] dishes; 304 SpecialDish[] specialDishes; 305 int dishNum; 306 int dishNum1; 307 308 public Dish searthDish(String dishName){ 309 for(int k=0;k<dishNum;k++) { 310 if(dishName.equals(dishes[k].name)){ 311 return dishes[k]; 312 } 313 } 314 return null; 315 } 316 public SpecialDish searthSpecialDish(String dishName){ 317 for(int k=0;k<dishNum1;k++) { 318 if(dishName.equals(specialDishes[k].name)){ 319 return specialDishes[k]; 320 } 321 } 322 return null; 323 } 324 public Dish addDish(String dishName,int unit_price){ 325 Dish addDish=new Dish(); 326 addDish.name=dishName; 327 addDish.unit_price=unit_price; 328 return addDish; 329 } 330 public SpecialDish addSpecialDish(String dishName,int unit_price,String taste){ 331 SpecialDish addDish=new SpecialDish(); 332 addDish.name=dishName; 333 addDish.unit_price=unit_price; 334 addDish.taste=taste; 335 return addDish; 336 } 337 } 338 class usedClass { 339 340 } 341 342 class Record{ 343 int orderNum; 344 Dish d; 345 int portion; 346 int num; 347 int spicy; 348 int acidity; 349 int sweetness; 350 boolean isSpecialDish; 351 public int getPrice() { 352 return d.getPrice(portion)*num; 353 } 354 } 355 class Order { 356 int dishNum; 357 int allCommonPrice; 358 int allSpecialPrice; 359 Record[] records = new Record[30]; 360 361 public void getTotalPrice(){ 362 for(int k=0;k<dishNum;k++) { 363 if(!records[k].isSpecialDish) 364 allCommonPrice+=records[k].getPrice(); 365 else 366 allSpecialPrice+=records[k].getPrice(); 367 } 368 } 369 370 public int getTotalPrice(double commonDiscount,double specialDiscount){ 371 int totalPrice = 0; 372 for(int k=0;k<dishNum;k++) { 373 totalPrice += records[k].isSpecialDish ? Math.round(records[k].getPrice()*specialDiscount) : Math.round(records[k].getPrice()*commonDiscount); 374 } 375 return totalPrice; 376 } 377 378 public Record addARecord(int orderNum,String dishName,int portion,int num , Menu menu){ 379 Record order=new Record(); 380 order.d=menu.searthDish(dishName); 381 order.orderNum=orderNum; 382 order.portion=portion; 383 order.num=num; 384 return order; 385 } 386 387 public Record addASpecialRecord(int orderNum, String dishName, int portion, int num, Menu menu, int tasteNum, boolean forOther) { 388 Record order = new Record(); 389 order.d = menu.searthSpecialDish(dishName); 390 order.orderNum = orderNum; 391 order.portion = portion; 392 order.num = num; 393 394 if (!forOther) { 395 inputmat mt = new inputmat(); 396 int flag = mt.findcage(menu.searthSpecialDish(dishName).taste); 397 if (flag == 1) { 398 order.spicy = tasteNum; 399 order.acidity = -1; 400 order.sweetness = -1; 401 } else if (flag == 3) { 402 order.spicy = -1; 403 order.acidity = -1; 404 order.sweetness = tasteNum; 405 } else if (flag == 2) { 406 order.spicy = -1; 407 order.acidity = tasteNum; 408 order.sweetness = -1; 409 } 410 } else { 411 order.spicy = -1; 412 order.acidity = -1; 413 order.sweetness = -1; 414 } 415 416 return order; 417 } 418 419 public void delARecordByOrderNum(int orderNum){ 420 for(int k=0;k<dishNum;k++) { 421 if(orderNum==records[k].orderNum) { 422 records[k].num=0; 423 } 424 } 425 } 426 427 public int findRecordByNum(int orderNum){ 428 for(int k = 0; k<dishNum;k++) { 429 if(records[k].orderNum==orderNum) { 430 return 1; 431 } 432 } 433 return 0; 434 } 435 } 436 437 class Table { 438 int tableNum; 439 String tableName; 440 String telephoneNum; 441 String mainTime; 442 String remainTime; 443 Order order; 444 double commonDiscount; 445 double specialDiscount; 446 int averageSpicy; 447 int averageAcidity; 448 int averageSweetness; 449 double spicyNum; 450 double acidityNum; 451 double sweetnessNum; 452 int week; 453 454 public boolean timeJudgement1() { 455 String[] timeArray = remainTime.split("/"); 456 String[] dateArray = mainTime.split("/"); 457 int time = Integer.parseInt(timeArray[0]) * 10000 + Integer.parseInt(timeArray[1]) * 100 + Integer.parseInt(timeArray[2]); 458 week = new inputmat().datetime(mainTime); 459 460 if ((week == 6 || week == 7) && (time >= 93000 && time <= 213000)) { 461 specialDiscount = commonDiscount = 1; 462 return true; 463 } else if (week >= 1 && week <= 5) { 464 if (time >= 103000 && time <= 143000) { 465 setDiscounts(0.6, 0.7); 466 return true; 467 } else if (time >= 170000 && time <= 203000) { 468 setDiscounts(0.8, 0.7); 469 return true; 470 } 471 } 472 return false; 473 } 474 475 private void setDiscounts(double common, double special) { 476 commonDiscount = common; 477 specialDiscount = special; 478 } 479 480 public int tablePrice() { 481 return order.getTotalPrice(commonDiscount, specialDiscount); 482 } 483 484 public void getTaste() { 485 for (int k = 0; k < order.dishNum; k++) { 486 if (order.records[k].isSpecialDish) { 487 Record record = order.records[k]; 488 updateTasteAverages(record.acidity, record.spicy, record.sweetness, record.num); 489 } 490 } 491 calculateAverageTaste(); 492 } 493 494 private void updateTasteAverages(int acidity, int spicy, int sweetness, int num) { 495 if (acidity != -1) { 496 averageAcidity += acidity * num; 497 acidityNum += num; 498 } 499 if (spicy != -1) { 500 averageSpicy += spicy * num; 501 spicyNum += num; 502 } 503 if (sweetness != -1) { 504 averageSweetness += sweetness * num; 505 sweetnessNum += num; 506 } 507 } 508 509 private void calculateAverageTaste() { 510 averageSpicy = (spicyNum != 0) ? (int) Math.round(averageSpicy / spicyNum) : averageSpicy; 511 averageSweetness = (sweetnessNum != 0) ? (int) Math.round(averageSweetness / sweetnessNum) : averageSweetness; 512 averageAcidity = (acidityNum != 0) ? (int) Math.round(averageAcidity / acidityNum) : averageAcidity; 513 } 514 515 public void giveTaste(String name, int num, int tasteLevel, Menu menu) { 516 int flag = new inputmat().findcage(menu.searthSpecialDish(name).taste); 517 switch (flag) { 518 case 1: 519 updateTasteAverages(tasteLevel, 0, 0, num); 520 break; 521 case 2: 522 updateTasteAverages(0, tasteLevel, 0, num); 523 break; 524 case 3: 525 updateTasteAverages(0, 0, tasteLevel, num); 526 break; 527 } 528 calculateAverageTaste(); 529 } 530 } 531 532 class lastPrint{ 533 ArrayList<Table> tables = new ArrayList<>(); 534 PersonPay[] personPays; 535 int p; 536 inputmat mat = new inputmat() ; 537 public void payPrint(){ 538 for(int k=0;k<p;k++){ 539 for(Table table:tables){ 540 if(table.tableName.equals(personPays[k].name)){ 541 personPays[k].payPrice+=table.tablePrice(); 542 } 543 } 544 } 545 for(int k=0;k<p-1;k++){ 546 for(int l=k+1;l<p;l++){ 547 if(personPays[k].name.toLowerCase().compareTo(personPays[l].name.toLowerCase())>0) { 548 PersonPay x; 549 x=personPays[l]; 550 personPays[l]=personPays[k]; 551 personPays[k]=x; 552 } 553 } 554 } 555 for(int k=0;k<p;k++){ 556 System.out.println(personPays[k].name+" "+personPays[k].telephoneNum+" "+personPays[k].payPrice); 557 } 558 } 559 } 560 class PersonPay{ 561 String name; 562 String telephoneNum; 563 int payPrice; 564 } 565 class caicage{ 566 567 } 568 class inputmat{ 569 String name1 = "川菜"; 570 String name2 = "晋菜"; 571 String name3 = "浙菜"; 572 int flag ; 573 int datetime(String time){ 574 DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy/M/d"); 575 LocalDate date1= LocalDate.parse(time , formatter1); // 将字符串解析为LocalDate对象 576 DayOfWeek dayOfWeek = date1.getDayOfWeek(); 577 int week =0; 578 if(dayOfWeek ==DayOfWeek.WEDNESDAY ) { 579 week = 3; 580 return week; 581 } 582 else if(dayOfWeek ==DayOfWeek.MONDAY) { 583 week = 1; 584 return week; 585 } 586 else if(dayOfWeek ==DayOfWeek.TUESDAY){ 587 week = 2; 588 return week; 589 } 590 else if(dayOfWeek ==DayOfWeek.THURSDAY){ 591 week = 4; 592 return week;} 593 else if(dayOfWeek ==DayOfWeek.FRIDAY) { 594 week = 5; 595 return week; 596 } 597 else if(dayOfWeek ==DayOfWeek.SATURDAY) { 598 week = 6; 599 return week; 600 } 601 else if(dayOfWeek ==DayOfWeek.SUNDAY) { 602 week = 7; 603 return week; 604 } 605 return 0; 606 } 607 int findcage(String s) { 608 flag = 0; 609 if (s.matches(name1)) { 610 flag = 1; 611 return flag; 612 } 613 else if(s.matches(name2) ){ 614 flag = 2; 615 return flag; 616 } 617 else if(s.matches(name3) ){ 618 flag = 3; 619 return flag; 620 } 621 return flag; 622 } 623 public String spicyLevel(int averageSpicy){ 624 switch (averageSpicy) { 625 case 0: 626 return "不辣"; 627 case 1: 628 return "微辣"; 629 case 2: 630 return "稍辣"; 631 case 3: 632 return "辣"; 633 case 4: 634 return "很辣"; 635 case 5: 636 return "爆辣"; 637 default: 638 return null; 639 } 640 } 641 642 public String acidityLevel(int averageAcidity){ 643 switch (averageAcidity) { 644 case 0: 645 return "不酸"; 646 case 1: 647 return "微酸"; 648 case 2: 649 return "稍酸"; 650 case 3: 651 return "酸"; 652 case 4: 653 return "很酸"; 654 default: 655 return null; 656 } 657 } 658 659 public String sweetnessLevel(int averageSweetness) { 660 switch (averageSweetness) { 661 case 0: 662 return "不甜"; 663 case 1: 664 return "微甜"; 665 case 2: 666 return "稍甜"; 667 case 3: 668 return "甜"; 669 default: 670 return null; 671 } 672 } 673 String p1 = "([1-9][0-9]*)"; 674 String p2 = "(\\S+)"; 675 String p3 = "(delete)"; 676 String p4 = "([0-9]*)"; 677 String p5 = "T"; 678 String table = "^(table)( )([1-9][0-9]*)( )(:)( )(\\S+)( )((136|133|135|180|181|189)[0-9]{8})( )([0-9]{4})(/)([0-9]|[0-9]{2})(/)([0-9]|[0-9]{2})( )([0-9]|[0-9]{2})(/)([0-9]|[0-9]{2})(/)([0-9]|[0-9]{2})$"; 679 String menu1 = p2+"( )([1-9][0-9]*)$"; 680 String menu2 = "^(\\S+)( )(\\S+)( )([1-9][0-9]*)( )"+p5; 681 String oeder1 = "^([1-9][0-9]*)( )(\\S+)( )([1-9][0-9]*)( )([1-9][0-9]*)$"; 682 String oder2 = "^([1-9][0-9]*)( )(\\S+)( )([0-9]+)( )([1-9][0-9]*)( )([1-9][0-9]*)$"; 683 String oder3 = p1+" "+p3 ;//"([1-9][0-9]*)( )(delete)"; 684 String oder4 = "^([1-9][0-9]*)( )([1-9][0-9]*)( )(\\S+)( )([1-9][0-9]*)( )([1-9][0-9]*)$"; 685 String oder5 = "^([1-9][0-9]*)( )([1-9][0-9]*)( )(\\S+)( )"+p4+"( )([1-9][0-9]*)( )([1-9][0-9]*)$"; 686 int inpumat(String s){ 687 if(s.matches(table) ) 688 return 1; 689 else if(s.matches(menu1) ) 690 return 2; 691 else if(s.matches(menu2) ) 692 return 3; 693 else if(s.matches(oeder1) ) 694 return 4; 695 else if(s.matches(oder2) ) 696 return 5; 697 else if(s.matches(oder3) ) 698 return 6; 699 else if(s.matches(oder4) ) 700 return 7; 701 else if(s.matches(oder5) ) 702 return 8; 703 return 0; 704 } 705 void error(int a, int flag) { 706 switch (flag) { 707 case 1: 708 if (a < 0 || a > 5) { 709 System.out.println("spicy num out of range :" + a); 710 } 711 break; 712 case 2: 713 if (a < 0 || a > 4) 714 System.out.println("acidity num out of range :" + a); 715 break; 716 case 3: 717 if (a < 0 || a > 3) 718 System.out.println("sweetness num out of range :" + a); 719 break; 720 } 721 } 722 }
类图如下:
代码难度如下:
分析:
-
主类 (
Main
):- 程序从
Main
类的main
方法开始执行。 - 使用
BufferedReader
从控制台读取输入。 - 声明了各种数组和对象,用于存储有关桌子、菜品、订单等的信息。
- 程序从
-
桌子类 (
Table
):- 代表餐厅中的一张桌子,具有属性如
tableNum
、tableName
、telephoneNum
等。 - 包含用于计算桌子总价、处理基于时间的折扣和更新口味平均值的方法。
- 代表餐厅中的一张桌子,具有属性如
-
菜品和特色菜品类:
Dish
和SpecialDish
是分别代表常规和特色菜品的类。- 它们具有属性如
name
、taste
和unit_price
。
-
菜单类 (
Menu
):- 管理餐厅的菜单,包括常规和特色菜品。
- 提供搜索菜品和添加新菜品的方法。
-
订单类 (
Order
):- 代表一个订单,包含
Record
对象数组。 - 计算和管理订单的总价。
- 代表一个订单,包含
-
记录类 (
Record
):- 代表订单中一道菜的记录。
- 包含菜品、份数、数量以及是否为特色菜的信息。
-
最终打印类 (
lastPrint
):- 管理最终付款详情的打印输出。
- 计算并打印每个人需要支付的总金额。
-
个人支付类 (
PersonPay
):- 代表个人的支付信息,包括姓名、电话号码和支付金额。
-
caicage 类和 inputmat 类:
caicage
类为空,似乎未被使用。inputmat
类包含处理各种输入模式的方法,包括创建桌子、更新菜单和录入订单。
-
日期时间格式化:
- 使用
DateTimeFormatter
和LocalDate
解析和格式化日期和时间。
- 循环和用户输入:
- 程序在循环中运行,不断读取用户输入,直到输入 "end" 命令为止。
- 错误处理:
- 实现了一些基本的错误处理,例如在添加到订单之前检查菜品是否存在。
- 打印结果:
- 最终结果包括每张桌子的总价,考虑到折扣和口味平均值。
期中考试
7-1 测验1-圆类设计
创建一个圆形类(Circle),私有属性为圆的半径,从控制台输入圆的半径,输出圆的面积
输入格式:
输入圆的半径,取值范围为(0,+∞)
,输入数据非法,则程序输出Wrong Format
,注意:只考虑从控制台输入数值的情况
输出格式:
输出圆的面积(保留两位小数,可以使用String.format(“%.2f”,输出数值)控制精度)
输入样例:
在这里给出一组输入。例如:
2.35
输出样例:
在这里给出相应的输出。例如:
17.35
我的代码如下:
1 import java.util.Scanner; 2 public class Main{ 3 public static void main(String[] args) { 4 Scanner scanner = new Scanner(System.in); 5 double radius = scanner.nextDouble(); 6 Circle circle = new Circle(); 7 circle.setRadius(radius); 8 double area = circle.getArea(); 9 if (radius > 0) { 10 String formattedArea = String.format("%.2f", area); 11 System.out.println(formattedArea); 12 }else { 13 System.out.println("Wrong Format"); 14 } 15 } 16 } 17 class Circle{ 18 private double radius; 19 public void setRadius(double radius) { 20 this.radius = radius; 21 } 22 23 public double getArea() { 24 return Math.PI * radius * radius; 25 } 26 }
此题较为简单,不进行追加分析
7-2 测验2-类结构设计
设计一个矩形类,其属性由矩形左上角坐标点(x1,y1)及右下角坐标点(x2,y2)组成,其中,坐标点属性包括该坐标点的X轴及Y轴的坐标值(实型数),求得该矩形的面积。类设计如下图:
输入格式:
分别输入两个坐标点的坐标值x1,y1,x2,y2。
输出格式:
输出该矩形的面积值(保留两位小数)。
输入样例:
在这里给出一组输入。例如:
6 5.8 -7 8.9
输出样例:
在这里给出相应的输出。例如:
40.30
我的代码如下:
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 6 Scanner input = new Scanner(System.in); 7 8 double x1 = input.nextDouble(); 9 double y1 = input.nextDouble(); 10 double x2 = input.nextDouble(); 11 double y2 = input.nextDouble(); 12 13 Point leftTopPoint = new Point(x1, y1); 14 Point lowerRightPoint = new Point(x2, y2); 15 16 Rectangle rectangle = new Rectangle(leftTopPoint, lowerRightPoint); 17 System.out.printf("%.2f", rectangle.area()); 18 19 20 } 21 22 } 23 abstract class Shape { 24 public abstract double area(); 25 } 26 class Rectangle extends Shape { 27 private Point leftTopPoint; 28 private Point lowerRightPoint; 29 30 public Rectangle(Point leftTopPoint, Point lowerRightPoint) { 31 this.leftTopPoint = leftTopPoint; 32 this.lowerRightPoint = lowerRightPoint; 33 } 34 35 public Point getLeftTopPoint() { 36 return leftTopPoint; 37 } 38 39 public void setLeftTopPoint(Point leftTopPoint) { 40 this.leftTopPoint = leftTopPoint; 41 } 42 43 public Point getLowerRightPoint() { 44 return lowerRightPoint; 45 } 46 47 public void setLowerRightPoint(Point lowerRightPoint) { 48 this.lowerRightPoint = lowerRightPoint; 49 } 50 51 @Override 52 public double area() { 53 double length = Math.abs(lowerRightPoint.getX() - leftTopPoint.getX()); 54 double width = Math.abs(lowerRightPoint.getY() - leftTopPoint.getY()); 55 return length * width; 56 } 57 } 58 class Point { 59 private double x; 60 private double y; 61 62 public Point(double x, double y) { 63 this.x = x; 64 this.y = y; 65 } 66 67 public double getX() { 68 return x; 69 } 70 71 public double getY() { 72 return y; 73 } 74 }
此题并不困难,不进行分析
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:
1
5.6
输出样例1:
在这里给出相应的输出。例如:
98.52
输入样例2:
2
5.6
-32.5
9.4
-5.6
输出样例2:
在这里给出相应的输出。例如:
102.22
我的代码如下:
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner input = new Scanner(System.in); 6 7 int choice = input.nextInt(); 8 9 switch (choice) { 10 case 1:// Circle 11 double radius = input.nextDouble(); 12 if (radius <= 0) { 13 System.out.println("Wrong Format"); 14 }else{ 15 Shape circle = new Circle(radius); 16 printArea(circle);} 17 break; 18 case 2:// Rectangle 19 double x1 = input.nextDouble(); 20 double y1 = input.nextDouble(); 21 double x2 = input.nextDouble(); 22 double y2 = input.nextDouble(); 23 24 Point leftTopPoint = new Point(x1, y1); 25 Point lowerRightPoint = new Point(x2, y2); 26 27 Rectangle rectangle = new Rectangle(leftTopPoint, lowerRightPoint); 28 29 printArea(rectangle); 30 break; 31 } 32 33 input.close(); 34 } 35 36 public static void printArea(Shape shape) { 37 System.out.printf("%.2f", shape.area()); 38 } 39 } 40 abstract class Shape { 41 public abstract double area(); 42 } 43 class Circle extends Shape { 44 private double radius; 45 46 public Circle(double radius) { 47 48 this.radius = radius; 49 50 } 51 52 public double getRadius() { 53 return radius; 54 } 55 56 public void setRadius(double radius) { 57 58 this.radius = radius; 59 60 } 61 62 @Override 63 public double area() { 64 return Math.PI * radius * radius; 65 } 66 } 67 class Rectangle extends Shape { 68 private Point leftTopPoint; 69 private Point lowerRightPoint; 70 71 public Rectangle(Point leftTopPoint, Point lowerRightPoint) { 72 this.leftTopPoint = leftTopPoint; 73 this.lowerRightPoint = lowerRightPoint; 74 } 75 76 public Point getLeftTopPoint() { 77 return leftTopPoint; 78 } 79 80 public void setLeftTopPoint(Point leftTopPoint) { 81 this.leftTopPoint = leftTopPoint; 82 } 83 84 public Point getLowerRightPoint() { 85 return lowerRightPoint; 86 } 87 88 public void setLowerRightPoint(Point lowerRightPoint) { 89 this.lowerRightPoint = lowerRightPoint; 90 } 91 92 @Override 93 public double area() { 94 double length = Math.abs(lowerRightPoint.getX() - leftTopPoint.getX()); 95 double width = Math.abs(lowerRightPoint.getY() - leftTopPoint.getY()); 96 return length * width; 97 } 98 } 99 class Point { 100 private double x; 101 private double y; 102 103 public Point(double x, double y) { 104 this.x = x; 105 this.y = y; 106 } 107 108 public double getX() { 109 return x; 110 } 111 112 public double getY() { 113 return y; 114 } 115 }
类图如下:
代码难度如下:
分析:
-
Main
类:main
方法中使用Scanner
从控制台获取用户的选择。- 根据用户的选择(1 或 2),创建相应的图形对象(
Circle
或Rectangle
)。 - 调用
printArea
方法打印图形的面积。
-
printArea
方法:- 接收一个
Shape
类型的参数,调用其area
方法,并使用printf
打印面积值。
- 接收一个
-
Shape
抽象类:- 声明了一个抽象方法
area
,要求子类实现该方法。 - 用于表示各种形状的基类。
- 声明了一个抽象方法
-
Circle
类:- 继承自
Shape
类。 - 包含一个私有的半径属性。
- 提供构造方法、获取半径的方法、设置半径的方法以及实现
area
方法计算圆的面积。
- 继承自
-
Rectangle
类:- 继承自
Shape
类。 - 包含两个私有的
Point
对象,分别表示矩形的左上角和右下角坐标。 - 提供构造方法、获取左上角和右下角坐标的方法、设置坐标的方法以及实现
area
方法计算矩形的面积。
- 继承自
-
Point
类:- 表示一个点,包含 x 和 y 坐标。
- 提供构造方法和获取坐标的方法。
-
用户输入和条件检查:
- 使用
Scanner
获取用户输入。 - 对用户输入的半径、矩形的两个点坐标进行检查,如果不符合条件(例如半径小于等于0),输出错误提示。
- 使用
-
输出结果:
- 使用
printf
打印计算得到的面积,保留两位小数。
- 使用
我通过类的继承和抽象类的使用实现了简单的图形面积计算功能。运行代码后可以选择计算圆的面积或矩形的面积,然后输入相应的参数,程序将计算并输出结果。
7-4 测验4-抽象类与接口
在测验3的题目基础上,重构类设计,实现列表内图形的排序功能(按照图形的面积进行排序)。
提示:题目中Shape类要实现Comparable接口。
其中,Main类源码如下(可直接拷贝使用):
public class Main {
public static void main(String\[\] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
ArrayList<Shape> list = new ArrayList<>();
int choice = input.nextInt();
while(choice != 0) {
switch(choice) {
case 1://Circle
double radiums = input.nextDouble();
Shape circle = new Circle(radiums);
list.add(circle);
break;
case 2://Rectangle
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double x2 = input.nextDouble();
double y2 = input.nextDouble();
Point leftTopPoint = new Point(x1,y1);
Point lowerRightPoint = new Point(x2,y2);
Rectangle rectangle = new Rectangle(leftTopPoint,lowerRightPoint);
list.add(rectangle);
break;
}
choice = input.nextInt();
}
list.sort(Comparator.naturalOrder());//正向排序
for(int i = 0; i < list.size(); i++) {
System.out.print(String.format("%.2f", list.get(i).getArea()) + " ");
}
}
}
输入格式:
输入图形类型(1:圆形;2:矩形;0:结束输入)
输入图形所需参数
输出格式:
按升序排序输出列表中各图形的面积(保留两位小数),各图形面积之间用空格分隔。
输入样例:
在这里给出一组输入。例如:
1
2.3
2
3.2
3
6
5
1
2.3
0
输出样例:
在这里给出相应的输出。例如:
5.60 16.62 16.62
我的代码如下:
1 import java.util.ArrayList; 2 import java.util.Comparator; 3 import java.util.Scanner; 4 5 public class Main { 6 public static void main(String[] args) { 7 Scanner input = new Scanner(System.in); 8 ArrayList<Shape> list = new ArrayList<>(); 9 10 int choice = input.nextInt(); 11 12 while (choice != 0) { 13 switch (choice) { 14 case 1: // Circle 15 double radius = input.nextDouble(); 16 Shape circle = new Circle(radius); 17 list.add(circle); 18 break; 19 case 2: // Rectangle 20 double x1 = input.nextDouble(); 21 double y1 = input.nextDouble(); 22 double x2 = input.nextDouble(); 23 double y2 = input.nextDouble(); 24 Point leftTopPoint = new Point(x1, y1); 25 Point lowerRightPoint = new Point(x2, y2); 26 Rectangle rectangle = new Rectangle(leftTopPoint, lowerRightPoint); 27 list.add(rectangle); 28 break; 29 } 30 choice = input.nextInt(); 31 } 32 33 list.sort(Comparator.naturalOrder()); 34 35 for (Shape shape : list) { 36 System.out.print(String.format("%.2f", shape.getArea()) + " "); 37 } 38 } 39 } 40 41 abstract class Shape implements Comparable<Shape> { 42 public abstract double area(); 43 44 public double getArea() { 45 return area(); 46 } 47 48 @Override 49 public int compareTo(Shape other) { 50 return Double.compare(this.area(), other.area()); 51 } 52 } 53 54 class Circle extends Shape { 55 private double radius; 56 57 public Circle(double radius) { 58 this.radius = radius; 59 } 60 61 @Override 62 public double area() { 63 return Math.PI * radius * radius; 64 } 65 } 66 67 class Rectangle extends Shape { 68 private Point leftTopPoint; 69 private Point lowerRightPoint; 70 71 public Rectangle(Point leftTopPoint, Point lowerRightPoint) { 72 this.leftTopPoint = leftTopPoint; 73 this.lowerRightPoint = lowerRightPoint; 74 } 75 76 @Override 77 public double area() { 78 double length = Math.abs(lowerRightPoint.getX() - leftTopPoint.getX()); 79 double width = Math.abs(lowerRightPoint.getY() - leftTopPoint.getY()); 80 return length * width; 81 } 82 } 83 84 class Point { 85 private double x; 86 private double y; 87 88 public Point(double x, double y) { 89 this.x = x; 90 this.y = y; 91 } 92 93 public double getX() { 94 return x; 95 } 96 97 public double getY() { 98 return y; 99 } 100 }
类图如下:
代码难度如下:
分析:
-
Main
类:- 创建了一个
ArrayList
类型的列表list
用于存储图形对象。 - 使用
while
循环,允许用户输入多个图形,直到用户输入0
为止。 - 根据用户的选择(1 或 2),创建相应的图形对象(
Circle
或Rectangle
),并将其添加到列表中。 - 用户输入结束后,对列表中的图形对象进行排序(按面积升序)。
- 遍历列表并输出各个图形的面积。
- 创建了一个
-
Shape
抽象类:- 实现了
Comparable
接口,使得图形对象可以进行比较。 - 增加了
getArea
方法,用于获取图形的面积。 - 实现了
compareTo
方法,用于排序时比较图形的面积。
- 实现了
-
Circle
类 和Rectangle
类:- 没有大的变化,仍然继承自
Shape
类,实现了各自的area
方法。
- 没有大的变化,仍然继承自
-
Point
类:- 没有变化,用于表示一个点。
-
用户输入:
- 用户可以输入多个图形,每次输入一个图形的相关信息,直到输入
0
结束。 - 对输入的坐标和半径进行检查,例如,确保半径大于 0,以避免不合理的图形。
- 用户可以输入多个图形,每次输入一个图形的相关信息,直到输入
-
列表排序:
- 使用
list.sort(Comparator.naturalOrder())
对图形列表进行排序。这里利用了Comparable
接口中的比较方法。
- 使用
-
输出结果:
- 遍历排序后的列表,使用
String.format
打印各个图形的面积,保留两位小数。
- 遍历排序后的列表,使用
7-4在7-3的基础上增加了列表和排序功能,能够输入多个图形,然后按照面积升序输出这些图形的面积。
三.踩坑心得
1、注意检查价格算法,特别是特色菜的定价算法和打折时间。确保算法正确并准确反映实际情况
2、ArrayList 使用:- 潜在问题: 操作
ArrayList
时可能会出现索引越界、空指针等问题。 - 踩坑心得: 注意数组和列表的索引从 0 开始。在使用列表之前,确保它不为
null
,并在添加、删除元素时小心边界条件
3、异常处理:
- 潜在问题: Java 中的输入操作(例如
nextInt
、nextDouble
)可能引发异常,尤其是在用户输入无效数据时。 - 踩坑心得: 使用
try-catch
块捕获异常,确保程序在出现异常时能够 gracefully 处理。
四.主要困难及改进建议
-
输入验证:
- 在接收用户输入时,添加验证以确保输入的半径和坐标等参数是合法的。可以在输入前使用循环来不断提示用户输入,直到得到有效的输入。
-
面向对象设计:
- 尽量遵循单一职责原则,确保每个类都有清晰的职责。我的代码在
Shape
类中,getArea
方法似乎有些多余,因为area
方法本身已经提供了相同的功能。
- 尽量遵循单一职责原则,确保每个类都有清晰的职责。我的代码在
-
代码重复:
- 期中考试部分可以将用户输入半径和坐标的部分提取成方法,以减少重复代码。
五、总结
通过编写这个菜单系统,我深入学习了如何使用Java编程语言构建基本的命令行应用程序。在这个过程中,我掌握了面向对象编程的基本概念和原则,并成功地将它们应用到项目中。
在学习中,我了解了类的定义和使用,学会了如何创建和操作对象,并学习了如何设计和组织代码结构。异常处理成为我编程技能中的一部分,我学到了如何在程序中有效地处理错误和异常情况,提高了代码的健壮性。
通过这个项目,我还学会了使用集合类,如ArrayList和HashMap,来存储和管理数据,将它们应用于系统的各项功能。通过自主思考和查阅相关资料,我成功地解决了一些编程中遇到的问题。
这个过程也提高了我对Java编程的理解能力。逐步完善自己的设计是一项具有挑战性但令人愉悦的任务。我学到了编程思维,并对开闭原则、继承和多态有了更深入的了解。
在编写PTA时,我认识到自己的代码可读性较差,条理性不够清晰。这让我意识到注重代码书写习惯的重要性。因此,学习Java不仅对今后学习其他编程语言有帮助,还培养了我作为一个编程人员应具备的良好心理素质。
标签:空格,记录,int,BLOG,英文,菜品,new From: https://www.cnblogs.com/zzz3898/p/17837182.html