一、前言
(1)第4-5次PTA题目集都是菜单计价程序,难度逐步提升。期中考试考察全面,难度比较简单。
(2)相关知识点:这三次题目集基本覆盖了大部分java基础语法及其用法,以及java中的Comparable接口。此外,还涉及了java的继承、多态。
二、设计与分析
第四次题目集(即菜单计价程序-4)在原有基础上增加了特色菜的输入:菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+基础价格+"T", 例如:麻婆豆腐 9 T
以下给出相关分析:
设计点菜计价程序的主要思路如下:
- 创建一个HashMap用于存储菜单信息,键为菜名,值为基础价格。
- 读取输入内容,并将菜单信息存储到HashMap中,直到遇到"end"结束。
- 按照桌号标识进行订单处理,每个桌号对应一个订单。
- 对于每个订单,创建一个HashMap用于存储点菜记录,键为序号,值为点菜信息对象。
- 解析每条订单记录,根据记录类型进行相应的处理:
- 如果是点菜记录,解析菜名、份额和份数,计算菜品价格并加入到点菜记录HashMap中。
- 如果是删除记录,检查序号是否存在,存在则从点菜记录HashMap中删除对应的记录,否则输出"delete error"。
- 如果是代点菜记录,解析桌号、序号、菜品名称、份额和分数,通过桌号找到对应的点菜记录HashMap,在其中添加代点菜信息。
- 遍历所有桌号,按照从小到大顺序依次计算每桌的总价,并输出结果。
- 根据桌号获取对应的点菜记录HashMap,遍历其中的所有点菜信息,累加计算每道菜的价格。
- 根据当前时间判断是否在营业范围内,并根据折扣规则计算折后价格。
- 对价格进行四舍五入,保留整数部分作为最终的总价。
- 如果当前时间不在营业范围内,输出对应的提示信息。
以上是设计点菜计价程序的基本思路和步骤,当分析完设计思路后,我们可以考虑更详细的实现细节以及可能遇到的问题:
-
菜单信息存储:使用HashMap可以高效地存储菜单信息。键为菜名,值为基础价格。需要注意的是,菜名应该作为唯一标识,不同菜品名称不能重复,否则会引起数据覆盖或混淆。
-
订单处理:对于每个桌号创建一个订单记录HashMap。这样可以根据桌号快速找到对应的点菜记录。如果存在多个桌号需要处理,可以将所有订单记录存储在一个HashMap或ArrayList中,键为桌号,值为订单记录HashMap。
-
点菜记录:解析点菜记录时,需要检查输入的菜名是否存在于菜单信息中。如果菜名不存在,可以输出"菜品不存在"的提示。另外,还需要注意对份额和份数的合法性判断,例如限制份额范围和份数为正整数。
-
删除记录:删除操作前需要判断序号是否存在。如果存在,则从点菜记录HashMap中删除对应的记录;如果不存在,则输出"delete error"提示。在删除操作时,也可以考虑给出删除成功的提示。
-
代点菜记录:代点菜记录需要指定桌号、序号、菜品名称、份额和份数。在处理代点菜记录时,需要根据桌号找到对应的点菜记录HashMap,并在其中添加代点菜信息。同时,也要进行合法性判断,确保相关数据的正确性。
-
计算总价与折扣:对于每个订单,可以遍历其中的所有点菜信息,累加计算每道菜的价格。根据当前时间判断是否在营业范围内,并根据折扣规则计算折后价格。折扣规则可以在代码中定义或者通过配置文件进行设置。最终,将价格进行四舍五入,保留整数部分作为最终的总价。
-
错误处理:需要考虑输入格式错误、菜品不存在、删除序号不存在等异常情况的处理。对于这些情况,可以输出相应的提示信息,帮助用户排查并解决问题。
以上是进一步分析点菜计价程序的细节和可能的问题。在实际编写代码时,还需要考虑边界条件、异常处理、数据存储方式、用户交互等方面的具体实现。
以下给出菜单计价程序-4的类图:
菜单计价程序-5与菜单计价程序-4设计类似,在细节上要求有所不同,这里不多赘述。
以下给出菜单计价程序-4及菜单计价程序-5的相关代码:
import java.text.ParseException; import java.time.DateTimeException; import java.time.Duration; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String[] args) { Menu menu = new Menu(); ArrayList<Table> tables = new ArrayList<Table>(); Scanner input = new Scanner(System.in); String data ; int i; int portion, copies; while (true) {// 输入菜单 Dish dish = new Dish(); data = input.nextLine(); if (data.matches("[\\S]* [1-9][\\d]*")||data.matches("[\\S]* [\\d]* T")) { String[] letters = data.split(" "); dish.name = letters[0]; dish.unit_price = Integer.parseInt(letters[1]); if (dish.unit_price > 300) { System.out.println(dish.name + " price out of range " + dish.unit_price); continue; } if(letters.length==2) { dish.isSpecial = false; menu.dishes.add(dish); } else if (letters.length==3) { dish.isSpecial = true; menu.dishes.add(dish); } } else if (data.equals("end")) { break; } else if (data.matches("tab.*")) { break; } else { System.out.println("wrong format"); continue; } } while (!data.equals("end")) { Table table = new Table(); if (data.matches("table.*")) { if (data.matches("table [1-9][\\d]* [\\d]*/[\\d][\\d]?/[\\d][\\d]? [\\d][\\d]?/[\\d][\\d]?/[\\d][\\d]?")) { String[] letters = data.split(" "); String[] Date = letters[2].split("/");//年月日 String[] Time = letters[3].split("/");//时分秒 int[] date = new int[3]; int[] times = new int[3]; for (i = 0; i < 3; i++) { date[i] = Integer.parseInt(Date[i]); times[i] = Integer.parseInt(Time[i]); } table.num = Integer.parseInt(letters[1]); if (table.num > 55) { System.out.println(table.num + " table num out of range"); data = input.nextLine(); continue; } try { table.time = LocalDateTime.of(date[0], date[1], date[2], times[0], times[1], times[2]); table.setWeekDay(); table.setPhase(table.time); } catch (DateTimeException e) { System.out.println(table.num + " date error"); data= input.nextLine(); continue; } if (table.inRange()) { System.out.println("not a valid time period"); data = input.nextLine(); continue; } // 判断桌号是否重复 if (table.isOpen()) { table=table.isSamePhase(table); } } else { System.out.println("wrong format"); data = input.nextLine(); continue; } /**本桌开始点菜*/ while (true) { data = input.nextLine(); if (data.matches("[1-9][\\d]* [\\S]* [\\d] [1-9][\\d]*")) { String[] token = data.split(" "); portion = Integer.parseInt(token[2]);//份额 copies = Integer.parseInt(token[3]);//份数 if (table.order.records.size() > 0) { if (Integer.parseInt(token[0]) <= table.order.records.get(table.order.records.size() - 1).orderNum) { System.out.println("record serial number sequence error"); continue; } } if (menu.searchDish(token[1]) == null) { System.out.println(token[1] + " does not exist"); continue; } if (portion > 3 || portion < 1) { System.out.println(Integer.parseInt(token[0]) + " portion out of range " + portion); continue; } if (copies > 15) { System.out.println(Integer.parseInt(token[0]) + " num out of range " + copies); continue; } table.addRecords(menu, token[0], token[1], portion, copies); } // 判断是否为删除订单 else if (data.matches("[1-9][\\d]* delete")) { String[] token = data.split(" "); table.order.delARecordByOrderNum(Integer.parseInt(token[0])); } // 判断是否为夹杂菜单 else if (data.matches("[\\S]* [\\d]*")) { System.out.println("invalid dish"); continue; } else if (data.matches("[\\S]* [\\d]* T")) { System.out.println("invalid dish"); continue; } // 判断是否为代点 else if (data.matches("[\\d]* [\\d]* [\\S]* [\\d] [1-9][\\d]*")) { String[] letters = data.split(" "); // 判断代点桌号是否存在 boolean exist = table.isExist(Integer.parseInt(letters[0])); if (exist) { System.out.print(Integer.parseInt(letters[1]) + " table " + table.num + " pay for table " + Integer.parseInt(letters[0]) + " "); Record insteadOrder = new Record(); insteadOrder.dish = menu.searchDish(letters[2]); portion = Integer.parseInt(letters[3]); copies = Integer.parseInt(letters[4]); insteadOrder.portion = portion; insteadOrder.copies =copies; System.out.print(insteadOrder.getPrice() + "\n"); table.discountSum += insteadOrder.getPrice(); } // 若不存在则输出内容 else { System.out.println("Table number :" + Integer.parseInt(letters[0]) + " does not exist"); } } else if (data.equals("end")) { break; } else if(data.matches("ta.*")){ break; } else { System.out.println("wrong format"); continue; } } // 本桌点菜结束,进入下一桌 table.getSum(); tables.add(table); } else if (data.matches("t.*")) { System.out.println("wrong format"); if(tables.size()!=0) { table = tables.get(tables.size()-1); } while (true) { data = input.nextLine(); if (data.matches("[1-9][\\d]* [\\S]* [\\d] [1-9][\\d]*")) { String[] letters = data.split(" "); portion = Integer.parseInt(letters[2]); copies = Integer.parseInt(letters[3]); // 判断订单号是否由小到大排列 if (table.order.records.size() > 0) { if (Integer.parseInt( letters[0]) <= table.order.records.get(table.order.records.size() - 1).orderNum) { System.out.println("record serial number sequence error"); continue; } } if (menu.searchDish(letters[1]) == null) { System.out.println(letters[1] + " does not exist"); continue; } if (portion > 3 || portion < 1) { System.out.println(Integer.parseInt(letters[0]) + " portion out of range " + portion); continue; } if (copies > 15) { System.out.println(Integer.parseInt(letters[0]) + " num out of range " +copies); continue; } table.addRecords(menu, letters[0], letters[1], portion, copies); } // 判断是否为删除订单 else if (data.matches("[1-9][\\d]* delete")) { String[] token = data.split(" "); table.order.delARecordByOrderNum(Integer.parseInt(token[0])); } // 判断是否为夹杂菜单 else if (data.matches("[\\S]* [\\d]*")) { System.out.println("invalid dish"); continue; } else if (data.matches("[\\S]* [\\d]* T")) { System.out.println("invalid dish"); continue; } // 判断是否为代点 else if (data.matches("[\\d]* [\\d]* [\\S]* [\\d] [1-9][\\d]*")) { String[] token = data.split(" "); // 判断代点桌号是否存在 boolean exist = false; for (int j = 0; j < tables.size(); j++) { if (tables.get(j).num == Integer.parseInt(token[0])) { exist = true; break; } } if (exist) { System.out.print(Integer.parseInt(token[1]) + " table " + table.num + " pay for table " + Integer.parseInt(token[0]) + " "); Record insteadOrder = new Record(); insteadOrder.dish = menu.searchDish(token[2]); portion = Integer.parseInt(token[3]); copies = Integer.parseInt(token[4]); insteadOrder.portion = portion; insteadOrder.copies = copies; System.out.print(insteadOrder.getPrice() + "\n"); table.discountSum += insteadOrder.getPrice(); } // 若不存在则输出内容 else { System.out.println("Table number :" + Integer.parseInt(token[0]) + " does not exist"); } } else if (data.equals("end")) { break; } else { System.out.println("wrong format"); continue; } } if (tables.size() != 0) { tables.remove(tables.size() - 1); table.discountSum = 0; table.sum = 0; table.getSum(); tables.add(table); } } else { data = input.nextLine(); continue; } } // 最终输出桌号订单信息 for (i = 0; i < tables.size(); i++) { if (tables.get(i).isOpen()) { System.out .println("table " + tables.get(i).num + ": " + tables.get(i).sum + " " + tables.get(i).discountSum); } else System.out.println("table " + tables.get(i).num + " out of opening hours"); } } static class Dish { String name; int unit_price; boolean isSpecial = false; } static class Record { int orderNum; Dish dish; int portion; int copies; boolean isDeleted = false; int getPrice() { if (portion == 2) return (int) Math.round(1.5 * dish.unit_price) * copies; else if (portion == 3) return 2 * dish.unit_price * copies; else return dish.unit_price * copies; } } static class Menu { ArrayList<Dish> dishes = new ArrayList<Dish>(); Dish searchDish(String dishName) { for (int i = 0; i < dishes.size(); i++) { if (dishName.equals(dishes.get(i).name)) { return dishes.get(i); } } return null; } } static class Order { ArrayList<Record> records = new ArrayList<Record>(); Record record; Record addARecord(int orderNum, String dishName, int portion, int copies, Menu menu) { record = new Record(); record.orderNum = orderNum; record.dish = menu.searchDish(dishName); record.portion = portion; record.copies = copies; System.out.println(record.orderNum + " " + record.dish.name + " " + record.getPrice()); return record; } boolean delARecordByOrderNum(int orderNum) { int i = 0, flag = 0; for (i = 0; i < records.size(); i++) { if (records.get(i).orderNum == orderNum) { if (records.get(i).isDeleted == false) { records.get(i).isDeleted = true; } else { System.out.println("deduplication " + orderNum); } flag++; } } if (flag == 0) { System.out.println("delete error;"); return false; } return true; } } static class Table { Order order = new Order(); int num; LocalDateTime time; int phase;//时区,中午1,晚上2 int weekDay; long discountSum = 0; long sum = 0; ArrayList<Table> tables=new ArrayList<>(); void addRecords(Menu menu, String str1, String str2, int portion, int copies) { { order.records.add(order.addARecord(Integer.parseInt(str1), str2, portion, copies, menu)); } } void setWeekDay() { weekDay = time.getDayOfWeek().getValue(); } boolean inRange(){ if(!(time.isAfter(LocalDateTime.of(2022, 1, 1, 0, 0, 0)) &&time.isBefore(LocalDateTime.of(2024, 1, 1, 0, 0, 0)))) { return true; } return false; } void getSum() { for (Record record : order.records) { if (!record.isDeleted) { double price = record.getPrice(); sum += price; double discountPrice = getDiscountPrice(record, price); discountSum += discountPrice; } } } double getDiscountPrice(Record record, double price) { if (record.dish.isSpecial) { if (weekDay > 0 && weekDay < 6) { return Math.round(price * 0.7); } else { return price; } } else { if (weekDay > 0 && weekDay < 6) { if (time.getHour() >= 17 && time.getHour() < 20 || time.getHour() == 20 && time.getMinute() <= 30) { return Math.round(price * 0.8); } else if (time.getHour() >= 10 && time.getHour() < 14 || time.getHour() == 14 && time.getMinute() <= 30) { return Math.round(price * 0.6); } } return price; } } void setPhase(LocalDateTime time){ int phase=0; /**在中午*/ if(time.isAfter(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), 10, 30, 0)) &&time.isBefore(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), 14, 30, 0))) { phase=1; } /**在晚上*/ if(time.isAfter(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), 17, 0, 0)) &&time.isBefore(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), 20, 30, 0))) { phase= 2; } } boolean isOpen() { if (weekDay > 0 && weekDay < 6) { if ((time.getHour() >= 17 && time.getHour() < 20) || (time.getHour() == 20 && time.getMinute() <= 30) || (time.getHour() > 10 && time.getHour() < 14) || (time.getHour() == 10 && time.getMinute() >= 30) || (time.getHour() == 14 && time.getMinute() <= 30)) return true; } else { if ((time.getHour() > 9 && time.getHour() < 21) || (time.getHour() == 9 && time.getMinute() >= 30) || (time.getHour() == 21 && time.getMinute() <= 30)) return true; } return false; } Table isSamePhase(Table table){ int flag=-1; for (int i = 0; i < tables.size(); i++) { // 有重复的桌号 if (table.num == tables.get(i).num && tables.get(i).isOpen()) { Duration duration = Duration.between(table.time, tables.get(i).time); // 同一天 if (duration.toDays() == 0) { // 在周一到周五 if (table.weekDay > 0 && table.weekDay < 6) { // 在同一时间段 if (table.phase==tables.get(i).phase&&table.phase!=0) { flag=1; table = tables.get(i); return table; } } // 在周末 else { // 时间相差小于一小时 if (duration.toHours() < 3600) { flag=1; table = tables.get(i); return table; } } } } else if(table.num == tables.get(i).num && !tables.get(i).isOpen()){ System.out.println("table "+tables.get(i).num+" out of opening hours"); return table; } } /**没有重复的在同一时段的桌号*/ if(flag==-1){ System.out.println("table " + table.num + ": "); } return table; } boolean isExist(int num){ for (int j = 0; j < tables.size(); j++) { if (tables.get(j).num == num) { return true; } } return false; } } }菜单计价程序-4
1 import java.time.DateTimeException; 2 import java.time.Duration; 3 import java.time.LocalDateTime; 4 import java.util.*; 5 6 public class Main{ 7 8 public static void main(String[] args) { 9 10 Menu menu = new Menu(); 11 ArrayList<Table> tables = new ArrayList<Table>(); 12 ArrayList<User> users = new ArrayList<User>(); 13 Scanner input = new Scanner(System.in); 14 String data = new String(); 15 int i = 0; 16 int portion = 0, copies = 0; 17 18 /** 输入菜单*/ 19 while (true) { 20 Dish dish = new Dish(); 21 data = input.nextLine(); 22 if (data.matches("[\\S]* [1-9][\\d]*")) { 23 String[] letters = data.split(" "); 24 25 dish.setName(letters[0]); 26 dish.setUnit_price(Integer.parseInt(letters[1])); 27 28 if (dish.getUnit_price() > 300) { 29 System.out.println(dish.getName() + " price out of range " + dish.getUnit_price()); 30 continue; 31 } 32 33 menu.addDish(dish); 34 } 35 /**特色菜*/ 36 else if (data.matches("[\\S]* [\\S]* [\\d]* T")) { 37 String[] letters = data.split(" "); 38 /**麻婆豆腐 川菜 12 T*/ 39 dish.setName(letters[0]); 40 dish.setUnit_price(Integer.parseInt(letters[2])); 41 if (dish.getUnit_price() > 300) { 42 System.out.println(dish.getName() + " price out of range " + dish.getUnit_price()); 43 continue; 44 } 45 dish.setT(true); 46 if (letters[1].equals("川菜")) { 47 dish.setFlavorType("spicy");//辣度 48 dish.setMaxFlavor(5); 49 } else if (letters[1].equals("晋菜")) { 50 dish.setFlavorType("acidity");//酸度 51 dish.setMaxFlavor(4); 52 } else if (letters[1].equals("浙菜")) { 53 dish.setFlavorType("sweetness");//酸度 54 dish.setMaxFlavor(3); 55 } 56 menu.addDish(dish); 57 } else if (data.equals("end")) { 58 break; 59 } else if (data.matches("tab.*")) { 60 break; 61 } else { 62 System.out.println("wrong format"); 63 } 64 } 65 while (!data.equals("end")) { 66 Table table = new Table(); 67 68 boolean isRepeat = false; 69 int repeatNum = 0; 70 71 if (data.matches(".*t.*a.*")) { 72 if (data.matches( 73 "table [1-9][\\d]* : [\\S]* [\\d]* [\\d]*/[\\d][\\d]?/[\\d][\\d]? [\\d][\\d]?/[\\d][\\d]?/[\\d][\\d]?")) { 74 String[] letters = data.split(" "); 75 /** table 1 : tom 13605054400 2023/5/1 20/30/00 */ 76 if (letters[3].length() > 10) { 77 data = input.nextLine(); 78 System.out.println("wrong format"); 79 continue; 80 } 81 else 82 table.setUserName(letters[3]);//客户名 83 if (letters[4].length() != 11) { 84 data = input.nextLine(); 85 System.out.println("wrong format"); 86 continue; 87 } 88 else 89 table.setCallNum(letters[4]);//客户号码 90 String headNum = letters[4].substring(0, 3); 91 List<String> validHeadNums = Arrays.asList("180", "181", "189", "133", "135", "136"); 92 if (!validHeadNums.contains(headNum)) { 93 data = input.nextLine(); 94 System.out.println("wrong format"); 95 continue; 96 } 97 String[] Date = letters[5].split("/");//年月日 98 String[] Time = letters[6].split("/");//时分秒 99 int[] date = new int[3]; 100 int[] times = new int[3]; 101 for (i = 0; i < 3; i++) { 102 date[i] = Integer.parseInt(Date[i]); 103 times[i] = Integer.parseInt(Time[i]); 104 } 105 106 table.setNum(Integer.parseInt(letters[1])); 107 if (table.getNum() > 55) { 108 System.out.println(table.getNum() + " table num out of range"); 109 data = input.nextLine(); 110 continue; 111 } 112 try { 113 table.setTime( LocalDateTime.of(date[0], date[1], date[2], times[0], times[1], times[2])); 114 table.setWeekDay(); 115 table.setPhase(table.getTime()); 116 } catch (DateTimeException e) { 117 System.out.println(table.getNum()+ " date error"); 118 data = input.nextLine(); 119 continue; 120 } 121 if (!table.isOpen()) { 122 System.out.println("table " + table.getNum() + " out of opening hours"); 123 data = input.nextLine(); 124 continue; 125 } 126 if (table.inRange()) { 127 System.out.println("not a valid time period"); 128 data = input.nextLine(); 129 continue; 130 } 131 // 判断桌号是否重复 132 if (table.isOpen()) { 133 table = table.isSamePhase(table); 134 } 135 System.out.println("table " + table.getNum() + ": "); 136 } else { 137 System.out.println("wrong format"); 138 data = input.nextLine(); 139 continue; 140 } 141 // 本桌开始点菜 142 while (true) { 143 data = input.nextLine(); 144 //判断是否为非特色菜 145 /**1.非特色菜*/ 146 if (data.matches("[1-9][\\d]* [\\S]* [\\d] [1-9][\\d]*")) { 147 /**2 油淋生菜 2 1*/ 148 String[] letters = data.split(" "); 149 150 portion = Integer.parseInt(letters[2]); 151 copies = Integer.parseInt(letters[3]); 152 153 if (menu.searchDish(letters[1]) == null) { 154 System.out.println(letters[1] + " does not exist"); 155 } 156 else{ 157 Record record = new Record(); 158 record.setDish(menu.searchDish(letters[1])); 159 record.setOrderNum(Integer.parseInt(letters[0])); 160 record.setPortion(portion); 161 record.setCopies(copies); 162 table.addRecord(record); 163 System.out.println(record.getOrderNum()+ " " + letters[1] + " " + record.getPrice()); 164 } 165 } 166 //判断是否为特色菜 167 /** 1 麻婆豆腐 2 1 2 */ 168 /**2.是特色菜*/ 169 else if (data.matches("[1-9][\\d]* [\\S]* [\\d] [\\d] [1-9][\\d]*")) { 170 171 String[] letters = data.split(" "); 172 173 int flavorNum = Integer.parseInt(letters[2]); 174 175 if (flavorNum < 0 || flavorNum > menu.searchDish(letters[1]).getMaxFlavor()) { 176 System.out.println(menu.searchDish(letters[1]).getFlavorType()+ " num out of range :" + flavorNum); 177 continue; 178 } 179 180 portion = Integer.parseInt(letters[3]); 181 copies = Integer.parseInt(letters[4]); 182 183 if (menu.searchDish(letters[1]) == null) { 184 System.out.println(letters[1] + " does not exist"); 185 } 186 else{ 187 Record record = new Record(); 188 189 record.setFlavorNum(flavorNum); 190 record.setDish(menu.searchDish(letters[1])); 191 record.setOrderNum(Integer.parseInt(letters[0])); 192 record.setPortion(portion); 193 record.setCopies(copies); 194 table.addRecord(record); 195 System.out.println(record.orderNum + " " + letters[1] + " " + record.getPrice()); 196 } 197 } 198 // 判断是否为删除订单 199 else if (data.matches("[1-9][\\d]* delete")) { 200 201 String[] letters = data.split(" "); 202 int deleterNum = Integer.parseInt(letters[0]); 203 204 for (i = 0; i < table.records.size(); i++) { 205 if (table.records.get(i).getOrderNum() == deleterNum) { 206 if (!table.records.get(deleterNum).isDeleted) { 207 table.records.get(deleterNum).isDeleted = true; 208 } else System.out.println("deduplication :" + deleterNum); 209 break; 210 } 211 if (i == table.records.size() - 1) System.out.println("delete error"); 212 } 213 } 214 // 判断是否为夹杂菜单 215 else if (data.matches("[\\S]* [\\d]*")) { 216 System.out.println("invalid dish"); 217 continue; 218 } else if (data.matches("[\\S]* [\\S]* [\\d]* T")) { 219 System.out.println("invalid dish"); 220 continue; 221 } 222 // 判断是否为代点 223 else if (data.matches("[\\d]* [\\d]* [\\S].*")) { 224 String[] letters = data.split(" "); 225 // 判断代点桌号是否存在 226 boolean exist = false; 227 228 int j = 0; 229 for (j = 0; j < tables.size(); j++) { 230 if (tables.get(j).getNum() == Integer.parseInt(letters[0])) { 231 exist = true; 232 break; 233 } 234 } 235 236 if (exist) { 237 System.out.print(Integer.parseInt(letters[1]) + " table " + table.getNum() + " pay for table " 238 + Integer.parseInt(letters[0]) + " "); 239 Record insteadOrder = new Record(); 240 insteadOrder.setDish(menu.searchDish(letters[2])); 241 if ( insteadOrder.getDish().isT) { 242 insteadOrder.setFlavorNum(Integer.parseInt(letters[3])); 243 insteadOrder.setPortion(Integer.parseInt(letters[4])); 244 insteadOrder.setCopies(Integer.parseInt(letters[5])); 245 if ( insteadOrder.getDish().getFlavorType().equals("spicy")) { 246 tables.get(j).ChuanNum += insteadOrder.getCopies(); 247 tables.get(j).spicyType += insteadOrder.getFlavorNum() * insteadOrder.getCopies(); 248 } 249 else if ( insteadOrder.getDish().getFlavorType().equals("acidity")) { 250 tables.get(j).JinNum += insteadOrder.getCopies(); 251 tables.get(j).spicyType += insteadOrder.getFlavorNum()* insteadOrder.getCopies(); 252 } 253 else if ( insteadOrder.getDish().getFlavorType().equals("sweetness")) { 254 tables.get(j).ZheNum += insteadOrder.getCopies(); 255 tables.get(j).spicyType += insteadOrder.getFlavorNum()* insteadOrder.getCopies(); 256 } 257 } 258 else 259 { 260 insteadOrder.setPortion(Integer.parseInt(letters[3])); 261 insteadOrder.setCopies(Integer.parseInt(letters[4])); 262 } 263 System.out.print( insteadOrder.getPrice() + "\n"); 264 insteadOrder.isTreat = true; 265 table.addRecord(insteadOrder); 266 } 267 // 若不存在则输出内容 268 else { 269 System.out.println("Table number :" + Integer.parseInt(letters[0]) + " does not exist"); 270 } 271 } 272 else if (data.matches("table.*")) { 273 break; 274 } 275 else if (data.equals("end")) { 276 break; 277 } else { 278 System.out.println("wrong format"); 279 } 280 } 281 // 本桌点菜结束,进入下一桌 282 if (isRepeat) { 283 for (i = 0; i < tables.get(repeatNum).records.size(); i++) { 284 for (int j = 0; j < table.records.size(); j++) { 285 if (tables.get(repeatNum).records.get(i).dish.getName() == table.records.get(j).dish.getName()) { 286 if (tables.get(repeatNum).records.get(i).portion == table.records 287 .get(j).portion) { 288 tables.get(repeatNum).records.get(i).copies += table.records.get(j).copies; 289 table.records.remove(j); 290 } 291 } 292 } 293 294 } 295 tables.get(repeatNum).records.addAll(table.records); 296 continue; 297 } 298 tables.add(table); 299 } else { 300 data= input.nextLine(); 301 } 302 } 303 // 最终输出桌号订单信息 304 for (i = 0; i < tables.size(); i++) { 305 if (tables.get(i).isOpen()) { 306 tables.get(i).getSum(); 307 tables.get(i).getFlavorNum(); 308 if (i != 0) System.out.print("\n"); 309 tables.get(i).showEnd(); 310 boolean isRepeat = false; 311 for (int j = 0; j < users.size(); j++) { 312 if (tables.get(i).getUserName().equals(users.get(j).getUserName())) { 313 users.get(j).paidMoney += tables.get(i).sum; 314 isRepeat = true; 315 break; 316 } 317 } 318 if (!isRepeat) { 319 User user = new User(); 320 user.setUserName(tables.get(i).getUserName()); 321 user.setCallNum(tables.get(i).getCallNum()); 322 user.paidMoney = tables.get(i).sum; 323 users.add(user); 324 } 325 } 326 327 } 328 users.sort(new Comparator<User>() { 329 public int compare(User a, User b) { 330 return a.getUserName().compareTo(b.getUserName()); 331 } 332 }); 333 for (i = 0; i < users.size(); i++) { 334 System.out.print("\n" + users.get(i).getUserName() + " " + users.get(i).getCallNum() + " " + users.get(i).paidMoney); 335 } 336 } 337 } 338 class Dish { 339 private String name; 340 private String flavorType; 341 private int maxFlavor; 342 private int unit_price; 343 boolean isT = false; 344 345 public String getName() { 346 return name; 347 } 348 349 public void setName(String name) { 350 this.name = name; 351 } 352 353 public int getMaxFlavor() { 354 return maxFlavor; 355 } 356 357 public void setMaxFlavor(int maxFlavor) { 358 this.maxFlavor = maxFlavor; 359 } 360 361 public String getFlavorType() { 362 return flavorType; 363 } 364 365 public void setFlavorType(String flavorType) { 366 this.flavorType = flavorType; 367 } 368 369 public int getUnit_price() { 370 return unit_price; 371 } 372 373 public void setUnit_price(int unit_price) { 374 this.unit_price = unit_price; 375 } 376 377 public boolean isT() { 378 return isT; 379 } 380 381 public void setT(boolean t) { 382 isT = t; 383 } 384 385 public Dish() { 386 } 387 } 388 389 class Record { 390 int orderNum; 391 Dish dish; 392 int flavorNum; 393 int portion; 394 int copies; 395 boolean isDeleted = false; 396 boolean isTreat = false; 397 398 public Record() { 399 } 400 401 public int getOrderNum() { 402 return orderNum; 403 } 404 405 public void setOrderNum(int orderNum) { 406 this.orderNum = orderNum; 407 } 408 409 public Dish getDish() { 410 return dish; 411 } 412 413 public void setDish(Dish dish) { 414 this.dish = dish; 415 } 416 417 public int getFlavorNum() { 418 return flavorNum; 419 } 420 421 public void setFlavorNum(int flavorNum) { 422 this.flavorNum = flavorNum; 423 } 424 425 public int getPortion() { 426 return portion; 427 } 428 429 public void setPortion(int portion) { 430 this.portion = portion; 431 } 432 433 public int getCopies() { 434 return copies; 435 } 436 437 public void setCopies(int copies) { 438 this.copies = copies; 439 } 440 441 public boolean isDeleted() { 442 return isDeleted; 443 } 444 445 public void setDeleted(boolean deleted) { 446 isDeleted = deleted; 447 } 448 449 int getPrice() { 450 if (portion == 2) 451 return (int) Math.round(1.5 * dish.getUnit_price()) * copies; 452 else if (portion == 3) 453 return 2 * dish.getUnit_price() * copies; 454 else 455 return dish.getUnit_price() * copies; 456 } 457 } 458 459 class Menu { 460 461 ArrayList<Dish> dishes = new ArrayList<Dish>(); 462 463 public Menu() { 464 } 465 466 Dish searchDish(String dishName) { 467 for (int i = 0; i < dishes.size(); i++) { 468 if (dishName.equals(dishes.get(i).getName())) { 469 return dishes.get(i); 470 } 471 } 472 return null; 473 } 474 475 public void addDish(Dish dish){ 476 Dish temp=searchDish(dish.getName()); 477 if(temp==null) 478 dishes.add(dish); 479 else if(temp!=null){ 480 dishes.remove(temp); 481 dishes.add(dish); 482 } 483 } 484 } 485 486 class User{ 487 String userName; 488 String callNum; 489 long paidMoney; 490 491 public User() { 492 } 493 494 public String getUserName() { 495 return userName; 496 } 497 498 public void setUserName(String userName) { 499 this.userName = userName; 500 } 501 502 public String getCallNum() { 503 return callNum; 504 } 505 506 public void setCallNum(String callNum) { 507 this.callNum = callNum; 508 } 509 510 } 511 class Table { 512 ArrayList<Record> records = new ArrayList<Record>(); 513 int num; 514 int phase;//时区,中午1,晚上2 515 String userName; 516 String callNum; 517 LocalDateTime time; 518 int weekDay; 519 int ChuanNum = 0; 520 float spicyType = 0; 521 int JinNum = 0; 522 float acidType = 0; 523 int ZheNum = 0; 524 float sweetType = 0; 525 long sum = 0; 526 long origSum = 0; 527 ArrayList<Table> tables=new ArrayList<>(); 528 529 public LocalDateTime getTime() { 530 return time; 531 } 532 533 public void setTime(LocalDateTime time) { 534 this.time = time; 535 } 536 537 public int getNum() { 538 return num; 539 } 540 541 public void setNum(int num) { 542 this.num = num; 543 } 544 545 public String getUserName() { 546 return userName; 547 } 548 549 public void setUserName(String userName) { 550 this.userName = userName; 551 } 552 553 public String getCallNum() { 554 return callNum; 555 } 556 557 public void setCallNum(String callNum) { 558 this.callNum = callNum; 559 } 560 561 public Table() { 562 } 563 public void addRecord(Record record){ 564 records.add(record); 565 } 566 void setWeekDay() { 567 weekDay = time.getDayOfWeek().getValue(); 568 } 569 boolean inRange(){ 570 if(!(time.isAfter(LocalDateTime.of(2022, 1, 1, 0, 0, 0)) 571 &&time.isBefore(LocalDateTime.of(2024, 1, 1, 0, 0, 0)))) 572 { 573 return true; 574 } 575 return false; 576 } 577 Table isSamePhase(Table table){ 578 int flag=-1; 579 for (int i = 0; i < tables.size(); i++) { 580 // 有重复的桌号 581 if (table.num == tables.get(i).num && tables.get(i).isOpen()) { 582 Duration duration = Duration.between(table.time, tables.get(i).time); 583 // 同一天 584 if (duration.toDays() == 0) { 585 // 在周一到周五 586 if (table.weekDay > 0 && table.weekDay < 6) { 587 // 在同一时间段 588 if (table.phase==tables.get(i).phase&&table.phase!=0) { 589 flag=1; 590 table = tables.get(i); 591 return table; 592 } 593 } 594 // 在周末 595 else { 596 // 时间相差小于一小时 597 if (duration.toHours() < 3600) { 598 flag=1; 599 table = tables.get(i); 600 return table; 601 } 602 } 603 } 604 } 605 else if(table.num == tables.get(i).num && !tables.get(i).isOpen()){ 606 System.out.println("table "+tables.get(i).num+" out of opening hours"); 607 return table; 608 } 609 } 610 return table; 611 } 612 void getFlavorNum() { 613 for (Record record : records) { 614 if (record.dish.isT && !record.isDeleted && !record.isTreat) { 615 int copies = record.copies; 616 String flavorType = record.dish.getFlavorType(); 617 int flavorNum = record.flavorNum; 618 switch (flavorType) { 619 case "spicy": 620 ChuanNum += copies; 621 spicyType += flavorNum * copies; 622 break; 623 case "acidity": 624 JinNum += copies; 625 acidType += flavorNum * copies; 626 break; 627 case "sweetness": 628 ZheNum += copies; 629 sweetType += flavorNum * copies; 630 break; 631 } 632 } 633 } 634 if (ChuanNum != 0) spicyType = Math.round(spicyType / ChuanNum * 1.0); 635 if (JinNum != 0) acidType = Math.round(acidType / JinNum * 1.0); 636 if (ZheNum != 0) sweetType = Math.round(sweetType / ZheNum * 1.0); 637 } 638 639 void showEnd() { 640 StringBuilder sb = new StringBuilder(); 641 sb.append("table ").append(num).append(": ").append(origSum).append(" ").append(sum); 642 //输出川菜 643 if(ChuanNum!=0) { 644 sb.append(" 川菜 ").append(ChuanNum); 645 switch((int)spicyType) { 646 case 0 :sb.append(" 不辣");break; 647 case 1 :sb.append(" 微辣");break; 648 case 2 :sb.append(" 稍辣");break; 649 case 3 :sb.append(" 辣");break; 650 case 4 :sb.append(" 很辣");break; 651 case 5 :sb.append(" 爆辣");break; 652 } 653 } 654 //输出晋菜 655 if(JinNum!=0) { 656 sb.append(" 晋菜 ").append(JinNum); 657 switch((int)acidType) { 658 case 0 :sb.append(" 不酸");break; 659 case 1 :sb.append(" 微酸");break; 660 case 2 :sb.append(" 稍酸");break; 661 case 3 :sb.append(" 酸");break; 662 case 4 :sb.append(" 很酸");break; 663 } 664 } 665 //输出浙菜 666 if(ZheNum!=0) { 667 sb.append(" 浙菜 ").append(ZheNum); 668 switch((int)sweetType) { 669 case 0 :sb.append(" 不甜");break; 670 case 1 :sb.append(" 微甜");break; 671 case 2 :sb.append(" 稍甜");break; 672 case 3 :sb.append(" 甜");break; 673 } 674 } 675 System.out.print(sb.toString()); 676 } 677 678 void getSum() { 679 for (Record record : records) { 680 if (!record.isDeleted) { 681 double price = record.getPrice(); 682 origSum += price; 683 if (record.dish.isT) { 684 if (weekDay > 0 && weekDay < 6) { 685 sum += Math.round(price * 0.7); 686 } else { 687 sum += price; 688 } 689 } else { 690 if (weekDay > 0 && weekDay < 6) { 691 int hour = time.getHour(); 692 int minute = time.getMinute(); 693 if ((hour >= 17 && hour < 20) || (hour == 20 && minute <= 30)) { 694 sum += Math.round(price * 0.8); 695 } else if ((hour >= 10 && hour < 14) || (hour == 14 && minute <= 30)) { 696 sum += Math.round(price * 0.6); 697 } else { 698 sum += price; 699 } 700 } else { 701 sum += price; 702 } 703 } 704 } 705 } 706 } 707 708 void setPhase(LocalDateTime time){ 709 int phase=0; 710 /**在中午*/ 711 if(time.isAfter(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), 10, 30, 0)) 712 &&time.isBefore(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), 14, 30, 0))) 713 { 714 phase=1; 715 } 716 /**在晚上*/ 717 if(time.isAfter(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), 17, 0, 0)) 718 &&time.isBefore(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), 20, 30, 0))) 719 { 720 phase= 2; 721 } 722 } 723 boolean isOpen() { 724 if (weekDay > 0 && weekDay < 6) { 725 if ((time.getHour() >= 17 && time.getHour() < 20) || (time.getHour() == 20 && time.getMinute() <= 30) || (time.getHour() > 10 && time.getHour() < 14) || (time.getHour() == 10 && time.getMinute() >= 30) || (time.getHour() == 14 && time.getMinute() <= 30)) 726 return true; 727 } else { 728 if ((time.getHour() > 9 && time.getHour() < 21) || (time.getHour() == 9 && time.getMinute() >= 30) || (time.getHour() == 21 && time.getMinute() <= 30)) 729 return true; 730 } 731 return false; 732 } 733 }菜单计价程序-5
期中考试题目前两题相对简单,考察了同学们的基础知识储备,以下为大致设计方向:
1、设计Shape类实现Comparable接口。
2、Circle类和Rectangle类继承自Shape类。
类图如下:
期中考试最后一题代码:
1 import java.util.ArrayList; 2 import java.util.Comparator; 3 import java.util.Scanner; 4 5 public class Main { 6 7 public static void main(String[] args) { 8 Scanner input = new Scanner(System.in); 9 ArrayList<Shape> list = new ArrayList<>(); 10 11 int choice = input.nextInt(); 12 13 while (choice != 0) { 14 switch (choice) { 15 case 1:// Circle 16 double radiums = input.nextDouble(); 17 Shape circle = new Circle(radiums); 18 list.add(circle); 19 break; 20 case 2:// Rectangle 21 double x1 = input.nextDouble(); 22 double y1 = input.nextDouble(); 23 double x2 = input.nextDouble(); 24 double y2 = input.nextDouble(); 25 Point leftTopPoint = new Point(x1, y1); 26 Point lowerRightPoint = new Point(x2, y2); 27 Rectangle rectangle = new Rectangle(leftTopPoint, lowerRightPoint); 28 list.add(rectangle); 29 break; 30 } 31 choice = input.nextInt(); 32 } 33 34 list.sort(Comparator.naturalOrder());// 正向排序 35 36 for (int i = 0; i < list.size(); i++) { 37 System.out.print(String.format("%.2f", list.get(i).getArea()) + " "); 38 } 39 } 40 static void printArea(Shape shape) { 41 double f = shape.getArea(); 42 if (shape instanceof Circle) { 43 if (f <= 0) 44 System.out.print("Wrong Format"); 45 else { 46 String tmp = String.format("%.2f", f); 47 System.out.print(tmp); 48 } 49 } else { 50 String tmp = String.format("%.2f", f); 51 System.out.print(tmp); 52 } 53 } 54 55 } 56 57 class Point { 58 Point(double x, double y) { 59 this.x = x; 60 this.y = y; 61 } 62 63 public double getX() { 64 return x; 65 } 66 67 public void setX(double x) { 68 this.x = x; 69 } 70 71 public double getY() { 72 return y; 73 } 74 75 public void setY(double y) { 76 this.y = y; 77 } 78 79 double x, y; 80 81 } 82 83 class Shape implements Comparable<Shape> { 84 public Shape() { 85 86 } 87 88 public double getArea() { 89 return 0; 90 } 91 92 public int compareTo(Shape shape) { 93 double s1, s2; 94 s1 = getArea(); 95 s2 = shape.getArea(); 96 if (s1 > s2) 97 return 1; 98 else if (s1 < s2) 99 return -1; 100 return 0; 101 } 102 } 103 104 class Circle extends Shape { 105 double radius; 106 107 Circle(double r) { 108 radius = r; 109 } 110 111 public double getArea() { 112 return (double) (Math.PI * radius * radius); 113 } 114 115 } 116 117 class Rectangle extends Shape { 118 public Rectangle(Point topLeftPoint, Point lowerRightPoint) { 119 super(); 120 this.topLeftPoint = topLeftPoint; 121 this.lowerRightPoint = lowerRightPoint; 122 } 123 124 public Point getTopLeftPoint() { 125 return topLeftPoint; 126 } 127 128 public void setTopLeftPoint(Point topLeftPoint) { 129 this.topLeftPoint = topLeftPoint; 130 } 131 132 public Point getLowerRightPoint() { 133 return lowerRightPoint; 134 } 135 136 public void setLowerRightPoint(Point lowerRightPoint) { 137 this.lowerRightPoint = lowerRightPoint; 138 } 139 140 Point topLeftPoint; 141 Point lowerRightPoint; 142 143 double getLength() { 144 return Math.abs(topLeftPoint.x - lowerRightPoint.x); 145 146 } 147 148 double getHeight() { 149 return Math.abs(topLeftPoint.y - lowerRightPoint.y); 150 } 151 152 public double getArea() { 153 return getLength() * getHeight(); 154 } 155 156 }
二、采坑心得
1、循环:在菜单计价程序代码中有一个无限循环while (true)
,只有当输入的数据等于"end"时才能退出循环。然而,在写代码的过程中,粗心遗漏了一个“ } ”号,导致了死循环 。所以在使用循环的时候一定要注意这个问题。因为循环出现了问题导致我找错花费了不少时间。
2、异常处理:在代码中使用了LocalDateTime.of()
方法创建一个LocalDateTime
对象,但没有捕获可能抛出的DateTimeException
异常。应该在代码中添加相应的异常处理逻辑,例如输出错误信息并继续下一次循环。
3、精度问题:在期中考试里面,因为PAI是无限循环小数,所以精度的问题让我一直有一个测试点未过,但是后来努力还是好了。在写有关小数的代码时,一定要注意精度问题。
三、主要困难以及改进建议
(1)主要困难:
一、是知识点的补充,Comparable接口,Comparable
接口中只有一个方法,即 compareTo(Object obj)
方法。该方法用于比较调用对象与传入的参数对象 obj
的大小关系。它返回一个整数值,表示两个对象的比较结果:
- 如果调用对象小于传入对象,则返回负整数。
- 如果调用对象等于传入对象,则返回零。
- 如果调用对象大于传入对象,则返回正整数。
实现了 Comparable
接口的类必须提供实现 compareTo()
方法的具体逻辑,以决定对象之间的比较方式。通常情况下, compareTo()
方法会比较类的某个属性或多个属性的值,并按照一定的规则返回相应的比较结果。
通过实现 Comparable
接口,我们可以方便地使用 Java 提供的排序算法(如 Arrays.sort()
或 Collections.sort()
)对对象进行排序,也可以进行其他类似的比较操作。
二、对课程成绩统计程序的分析,对不同的要求要分析,最后总结是一个挺困难的事情。、
对菜单计价程序-5的分析:
新增特色菜品,并在菜单输入时增加特色菜的信息,包括菜品名、口味类型、基础价格和"T"。口味类型可以是川菜、晋菜或浙菜。 菜价的计算方法为:周一至周五打7折,周末全价。 特色菜的口味类型有对应的值:川菜的辣度值为0-5级,晋菜的酸度值为0-4级,浙菜的甜度值为0-3级。 口味度值的范围超过正常范围时,输出相应的错误信息。
以下为示例: 菜单输入:麻婆豆腐 川菜 9 T
订单记录输入:1 麻婆豆腐 4 1 9
处理后的信息输出: acidity num out of range : 5
(2)改进建议:
在菜单计价程序-4及菜单计价程序-5中(本文上方附有相关代码)
-
在主函数中,应该将Scanner对象input放在while循环内部,以便每次循环都能够获取用户输入。
-
在第一个while循环中,判断输入数据的格式的方式比较复杂,可以考虑使用正则表达式进行匹配,提高代码的可读性和易用性。
-
在第一个while循环中,对菜品价格的判断条件是硬编码的,建议将这个范围值作为变量或常量,在需要修改时更方便。
-
在第一个while循环中,判断菜品是否为特价菜的逻辑可以简化,可以直接根据传入参数的数量判断。
-
在第二个while循环外部定义了一个Table对象,但没有及时更新数据。建议在每次循环开始前创建一个新的Table对象。
-
对于日期和时间的处理可以使用Java提供的Date类或Calendar类进行处理,而不是自己手动解析和转换字符串。
-
在第二个while循环中,对桌号、日期和时间等用户输入的数据进行合法性判断时,可以使用正则表达式进行匹配。
-
在第二个while循环中,有几个错误处理的逻辑没有及时退出循环,导致重复执行下一次循环。需要添加break语句来终止循环。
- 在最后的if语句块中,读取用户输入数据的逻辑写在了循环内部,导致每次循环都会执行一次读取操作。可以将这部分代码放在循环外部,在需要时再读取用户输入。
四、总结
-
代码中存在一些待改进和优化的地方。首先,在输入菜单和点菜过程中,需要考虑更多的输入错误情况,并给出相应的提示信息。其次,代码可进一步模块化,将功能拆分成更小的函数,提高代码的可读性和可维护性。
-
在处理日期和时间时,代码使用了Java 8中的LocalDateTime类,可以在此基础上加以利用,通过调用更多的日期和时间相关方法来完成更多功能,比如判断时间段是否合法等。
-
对于输入数据的验证,代码使用了正则表达式来进行匹配,但是可以进一步完善验证逻辑,增加更多的条件判断和错误处理,以防止用户输入非法数据。
-
点菜记录的部分可以考虑使用更合适的数据结构,比如使用HashMap来存储订单记录,提高查询效率。
-
最后,代码可考虑添加注释、命名规范和异常处理等,以提高代码的可维护性和可测试性。