一、前言
这几次作业主要是对菜单计价程序的完善,第四次作业中的菜单计价程序2是在菜单计价程序1的基础上进行完善,添加了输入菜单和份额的要求,难度还在可以接受的范围。第四次作业中的菜单计价程序3则是在菜单计价程序2的基础上添加了一系列的要求,包括添加桌号、代点菜等要求等,本次作业相较于在菜单计价程序2难度则是有了很大的增加,且测试的时间限制太短,最终本次作业有一个测试点没有过。第五次作业的菜单计价程序4则是在菜单计价程序3的基础上进行完善,不仅增加了特色菜的概念,更是增加了很多的异常情况,本次作业主要考验的是我们是异常处理情况,难度很大。第六次作业的菜单计价程序5同样是在菜单计价程序3的基础上进行完善,不过是和菜单计价程序4不同的分支,本次作业侧重的是在对特色菜的处理上面,难度与菜单计价程序4的难度相当。这几次作业涉及到的知识点有类的设计,异常处理,集合的使用等等。
二、设计与分析
1、菜单计价程序2
import java.util.ArrayList; import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); Order order = new Order(); Menu menu = new Menu(); String s = sc.nextLine(); while (!s.equals("end")){ String[] str = s.split(" "); if(str.length==2&&!str[1].equals("delete")){ String name = str[0]; int portion = Integer.parseInt(str[1]); menu.addDish(name, portion); } else if(str.length == 2){ int ordernum = Integer.parseInt(str[0]); order.delARecordByOrderNum(ordernum); } else if(str.length==4){ int orderNum = Integer.parseInt(str[0]); String name = str[1]; int portion = Integer.parseInt(str[2]); int num = Integer.parseInt(str[3]); if(menu.searthDish(name)!=null) { order.addARecord(orderNum, name, portion, num,menu); } else { System.out.println(name+" does not exist"); } } s = sc.nextLine(); } System.out.println(order.getTotalPrice()); } } class Dish { String name;//菜品名称 int unit_price; //单价 int getPrice(int portion){ double[] arr = {0,1,1.5,2}; return (int) Math.round(this.unit_price*arr[portion]); } } //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 class Menu { ArrayList<Dish> dishs = new ArrayList<>();//菜品数组,保存所有菜品信息 Dish searthDish(String dishName){ for (int i = 0; i < this.dishs.size(); i++) { if (this.dishs.get(i).name.equals(dishName)){ return this.dishs.get(i); } } return null; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 int searthDishIndix(String dishName){ for (int i = 0; i < this.dishs.size(); i++) { if (this.dishs.get(i).name.equals(dishName)){ return i; } } return -1; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 Dish addDish(String dishName,int unit_price){ Dish dish = new Dish(); dish.name = dishName; dish.unit_price = unit_price; if(this.searthDish(dishName)==null) { dishs.add(dish); } else { int flag = this.searthDishIndix(dishName); dishs.set(flag,dish); } return dish; } } // 点菜记录类:保存订单上的一道菜品记录 class Record { int orderNum; Dish d;//菜品 int portion;//份额(1/2/3代表小/中/大份) int num; int getPrice(){ return d.getPrice(this.portion)*this.num; }//计价,计算本条记录的价格 } // 订单类:保存用户点的所有菜的信息。 class Order { ArrayList<Record> records=new ArrayList<>();//保存订单上每一道的记录 int getTotalPrice(){ int price = 0; for (Record record : records) { price += record.getPrice(); } return price; } //添加一条菜品信息到订单中。 Record addARecord(int orderNum,String dishName,int portion,int num,Menu menu){ Record record = new Record(); Dish dish = menu.searthDish(dishName); record.orderNum=orderNum; record.d = dish; record.portion=portion; record.num=num; records.add(record); System.out.println(record.orderNum + " " + record.d.name + " " + record.getPrice()); return record; } //根据序号删除一条记录 void delARecordByOrderNum(int orderNum){ for (int i = 0; i < records.size(); i++) { if(records.get(i).orderNum==orderNum){ records.remove(i); return; } } System.out.println("delete error;"); } }
类图设计:
本题的设计思路为设计Dish类存放菜品基本信息,包括名字和基础价格,并添加一个getPrice()方法根据份额计算菜品价格;设计Menu类保存菜品信息,里面添加addDish()方法,每当输入一个菜品信息,则将该菜品添加进菜单;
设计Record类保存客户的单条点菜信息。设计Order类存放所有的点菜信息,添加addRcord()方法根据菜单计算此菜品记录的价格和将该记录存入Record集合中,
并添加计算客户点菜总价的方法。将输入的菜单信息存入Menu类,在Order类中建立一个Record类的集合,在Order类中添加添加点菜信息和删除点菜信息的方法,将输入的点菜信息先存入Record集合中,并在此时输出菜品信息。在Main类中完成信息的输入,根据输入的信息将菜品信息和点菜信息分别存入Menu中和records中。在结束输入后调用Order类中的getTotalPrice()方法,输出总价格。
2、菜单计价程序3
题目要求:在菜单计价程序2的基础上,添加以下要求:
订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。
桌号标识独占一行,包含两个信息:桌号、时间。
桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。
点菜记录包含:序号、菜名、份额、份数。份额可选项包括: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"
源码分析:
import java.util.*; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); Order order = new Order(); Menu menu = new Menu(); String time = ""; String s = sc.nextLine(); while (!s.equals("end")){ int flag = 0; boolean flag1 = s.matches("[\\S]*\\s[0-9]*"); boolean flag2 = s.matches("table\\s\\d*\\s\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}/\\d{1,2}/\\d{1,2}"); boolean flag3 = s.matches("\\d*\\s[\\S]*\\s\\d\\s\\d*"); boolean flag4 = s.matches("\\d*\\s\\d*\\s[\\S]*\\s\\d\\s\\d*"); boolean flag5 = s.matches("\\d*\\sdelete"); String[] str = s.split(" "); if(flag1){ String name = str[0]; int portion = Integer.parseInt(str[1]); menu.addDish(name, portion); } else if(flag2){ time = s; System.out.println(time.substring(0,7) + ": "); } else if(flag3){ int orderNum = Integer.parseInt(str[0]); String name = str[1]; int portion = Integer.parseInt(str[2]); int num = Integer.parseInt(str[3]); if(menu.searthDish(name)!=null) { order.addARecord(orderNum, name, portion, num,menu,time,flag); } else { System.out.println(name+" does not exist"); } } else if(flag4){ flag = Integer.parseInt(str[0]); int orderNum = Integer.parseInt(str[1]); String name = str[2]; int portion = Integer.parseInt(str[3]); int num = Integer.parseInt(str[4]); if(menu.searthDish(name)!=null) { order.addARecord(orderNum, name, portion, num,menu,time,flag); } else { System.out.println(name+" does not exist"); } } else if(flag5){ int ordernum = Integer.parseInt(str[0]); order.delARecordByOrderNum(ordernum); } s = sc.nextLine(); } order.tableprice = order.getTotalPrice(); Set<String> keys = order.tableprice.keySet(); for (String key : keys) { int value = order.tableprice.get(key); if(value!=-1) { if(key.equals(time)) { System.out.print(key.substring(0, 7) + ": " + value); } else { System.out.println(key.substring(0, 7) + ": " + value); } } } } } class Dish { String name;//菜品名称 int unit_price; //单价 int getPrice(int portion){ double[] arr = {0,1,1.5,2}; return (int) Math.round(this.unit_price*arr[portion]); } } //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 class Menu { ArrayList<Dish> dishs = new ArrayList<>();//菜品数组,保存所有菜品信息 Dish searthDish(String dishName){ for (int i = 0; i < this.dishs.size(); i++) { if (this.dishs.get(i).name.equals(dishName)){ return this.dishs.get(i); } } return null; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 int searthDishIndix(String dishName){ for (int i = 0; i < this.dishs.size(); i++) { if (this.dishs.get(i).name.equals(dishName)){ return i; } } return -1; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 Dish addDish(String dishName,int unit_price){ Dish dish = new Dish(); dish.name = dishName; dish.unit_price = unit_price; if(this.searthDish(dishName)==null) { dishs.add(dish); } else { int flag = this.searthDishIndix(dishName); dishs.set(flag,dish); } return dish; } } // 点菜记录类:保存订单上的一道菜品记录 class Record { String time; int orderNum; Dish d;//菜品 int portion;//份额(1/2/3代表小/中/大份) int num; int getPrice(){ return d.getPrice(this.portion)*this.num; }//计价,计算本条记录的价格 } // 订单类:保存用户点的所有菜的信息。 class Order { double discount; ArrayList<Record> records=new ArrayList<>();//保存订单上每一道的记录 LinkedHashMap<String,Integer> tableprice = new LinkedHashMap<>(); LinkedHashMap<String,Integer> getTotalPrice(){ Set<String> keys = tableprice.keySet(); for (String key : keys) { int price = 0; boolean flagg = whetherTimeRight(key); if(!flagg){ System.out.println(key.substring(0,7) + " out of opening hours"); continue; } for (Record record : records){ if(record.time.equals(key)){ price += record.getPrice(); } } price=(int)Math.round(price*this.discount); tableprice.put(key,price); } return this.tableprice; } //添加一条菜品信息到订单中。 void addARecord(int orderNum,String dishName,int portion,int num,Menu menu,String time,int flag){ String table_num = time.substring(0,7); tableprice.put(time,-1); Record record = new Record(); Dish dish = menu.searthDish(dishName); record.orderNum=orderNum; record.d = dish; record.portion=portion; record.num=num; record.time = time; records.add(record); if(flag!=0){ System.out.println(record.orderNum +" " + table_num + " pay for table " + flag +" "+ record.getPrice()); } else { System.out.println(record.orderNum + " " + record.d.name + " " + record.getPrice()); } } //根据序号删除一条记录 void delARecordByOrderNum(int orderNum){ for (int i = 0; i < records.size(); i++) { if(records.get(i).orderNum==orderNum){ records.remove(i); return; } } System.out.println("delete error;"); } boolean whetherTimeRight(String time){ String[] str = time.split(" "); Date time1 = new Date(str[2]); Calendar cal = Calendar.getInstance(); cal.setTime(time1); int[] arr = {7,1,2,3,4,5,6}; int week = arr[cal.get(Calendar.DAY_OF_WEEK)-1]; String time2 = str[3]; String[] str1 = time2.split("/"); int hour = Integer.parseInt(str1[0]); int min = Integer.parseInt(str1[1]); if(week<6){ if(hour<10||(hour>14&&hour<17)||hour>20){ return false; } else if((hour==10&&min<30) ||(hour==14&&min>30)||(hour==20&&min>30)){ return false; } else { if(hour<=14){ this.discount = 0.6; } else { this.discount = 0.8; } } } else{ if(hour<9||hour>21){ return false; } else if((hour==9&&min<30) ||(hour==21&&min>30)){ return false; } this.discount =1; } return true; } }
本题代码是在菜单计价程序2的基础上进行完善,因此大的类图设计基本没有改变,主要是在类中的方法,以及输入时的判断进行了改变。首先是在Order类中添加了一个discount属性,用来记录每个时间段的折扣;同时在Order类中添加了判断时间的方法whetherTimeRight(),这个方法一方面可以判断订单时间是否合理,同时又可以判断出订单所处时间段用来计算折扣。这里判断时间用到了Calendar类的知识用来计算订单所属星期。
同时我还在Order类中添加了一个用来保存桌号与时间信息的属性tableprice,类型为LinkedHashMap<String,Integer>;以及在Record类中添加了Time属性,同样用来保存桌号与时间信息。这样每当有新的点菜信息时,都将时间信息存入点菜信息中,到最后计算每一桌的总价时,只需要点菜信息中的时间和tableprice中的时间信息相比较,即可计算出每一桌的总价。
同时在Order类中的addARecord()方法中添加代点菜信息的处理方法。
在输入时,判断输入信息属于哪一种类型,我则是用到了正则表达式,通过判断输入信息符合哪一个正则表达式来判断输入的是菜品信息还是桌号信息、点菜信息、代点菜信息或者是删除记录信息。
3、菜单计价程序4
题目要求:在菜单计价程序3的基础上,添加以下要求:
本次课题比菜单计价系列-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折, 周末全价。
源码分析:
import java.time.DateTimeException; import java.time.LocalDate; import java.util.*; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); Order order = new Order(); Menu menu = new Menu(); boolean tnum = false; boolean tablefomat = true; String time = ""; boolean mixmenu = true; String s = sc.nextLine(); while (!s.equals("end")){ int flag = 0; boolean flag1 = s.matches("[\\S]*\\s[0-9]*"); boolean flag2 = s.matches("table\\s[^0\\s]\\S*\\s\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}/\\d{1,2}/\\d{1,2}"); boolean flag3 = s.matches("[1-9]\\d*\\s[\\S]*\\s\\d\\s\\d*"); boolean flag4 = s.matches("[1-9]\\d*\\s\\d*\\s[\\S]*\\s\\d\\s\\d*"); boolean flag5 = s.matches("\\d*\\sdelete"); boolean flag6 = s.matches("[\\S]*\\s[0-9]*\\sT"); String[] str = s.split(" "); if((flag1||flag6)){ if((!mixmenu)&& tnum){ System.out.println("invalid dish"); } else { String name = str[0]; int price = Integer.parseInt(str[1]); if(price<=0||price>=300){ System.out.println(name+ " " + "price out of range " + price); } else { if (!flag6) { menu.addDish(name, price, "F"); } else { menu.addDish(name, price, "T"); } } } } else if(flag2){ mixmenu = false; time = s; try { String[] strings = s.split(" "); int num = Integer.parseInt(strings[1]); tablefomat = true; if(!(num>0&&num<=55)){ System.out.println(num + " table num out of range"); tnum = false; tablefomat = false; } else { try { String[] s1 = strings[2].split("/"); LocalDate ld = LocalDate.of(Integer.parseInt(s1[0]), Integer.parseInt(s1[1]), Integer.parseInt(s1[2])); if (!isTimeInRange(strings[2])) { System.out.println("not a valid time period"); tnum = false; tablefomat = false; } else if (!order.whetherTimeRight(time)) { System.out.println(strings[0] + " " + strings[1] + " out of opening hours"); tnum = false; tablefomat = false; } else { tnum = true; Table table = new Table(s, -1, -1); order.tables.add(table); System.out.println(strings[0] + " " + num + ": "); } } catch (DateTimeException e) { tnum = false; System.out.println(strings[1] + " date error"); } } }catch (NumberFormatException e){ tnum = false; tablefomat = false; System.out.println("wrong format"); } } else if(flag3){ if(tnum) { int orderNum = Integer.parseInt(str[0]); String name = str[1]; int portion = Integer.parseInt(str[2]); int num = Integer.parseInt(str[3]); if (menu.searthDish(name) != null) { order.addARecord(orderNum, name, portion, num, menu, time, flag); } else { System.out.println(name + " does not exist"); } } } else if(flag4){ if(tnum) { flag = Integer.parseInt(str[0]); if(!order.isTableNumisExist(flag)){ System.out.println("Table number :" + flag +" does not exist"); } else { int orderNum = Integer.parseInt(str[1]); String name = str[2]; int portion = Integer.parseInt(str[3]); int num = Integer.parseInt(str[4]); if (menu.searthDish(name) != null) { order.addARecord(orderNum, name, portion, num, menu, time, flag); } else { System.out.println(name + " does not exist"); } } } } else if(flag5){ if(tnum) { int ordernum = Integer.parseInt(str[0]); order.delARecordByOrderNum(ordernum, time); } } else { if(str[0].equals("table")){ tnum = false; tablefomat = false; System.out.println("wrong format"); } if (tablefomat) { System.out.println("wrong format"); } } s = sc.nextLine(); } order.tables = order.getTotalPrice(); for (Table table : order.tables) { String[] strings = table.tablenum.split(" "); if(Integer.parseInt(strings[1])>=1&&Integer.parseInt(strings[1])<=55) { if (table.primprice != -1) { System.out.println(strings[0] +" " +strings[1]+ ": " + table.primprice + " " + table.lastprice); } } } } private static boolean isTimeInRange(String time){ String[] strings = time.split("/"); int year = Integer.parseInt(strings[0]); int month = Integer.parseInt(strings[1]); int day = Integer.parseInt(strings[2]); LocalDate localDate1 = LocalDate.of(2022,1,1); LocalDate localDate2 = LocalDate.of(2023,12,31); LocalDate localDate3 = LocalDate.of(year,month,day); if(localDate3.isBefore(localDate1)||localDate3.isAfter(localDate2)) { return false; } return true; } } class Dish { String name;//菜品名称 int unit_price; //单价 String type; int getPrice(int portion){ double[] arr = {0,1,1.5,2}; return (int) Math.round(this.unit_price*arr[portion]); } } //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 class Menu { ArrayList<Dish> dishs = new ArrayList<>();//菜品数组,保存所有菜品信息 Dish searthDish(String dishName){ for (int i = 0; i < this.dishs.size(); i++) { if (this.dishs.get(i).name.equals(dishName)){ return this.dishs.get(i); } } return null; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 int searthDishIndix(String dishName){ for (int i = 0; i < this.dishs.size(); i++) { if (this.dishs.get(i).name.equals(dishName)){ return i; } } return -1; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 Dish addDish(String dishName,int unit_price,String type){ Dish dish = new Dish(); dish.name = dishName; dish.unit_price = unit_price; dish.type = type; if(this.searthDish(dishName)==null) { dishs.add(dish); } else { int flag = this.searthDishIndix(dishName); dishs.set(flag,dish); } return dish; } } // 点菜记录类:保存订单上的一道菜品记录 class Record { String time; int orderNum; Dish d;//菜品 int portion;//份额(1/2/3代表小/中/大份) int num; int getPrice(){ return d.getPrice(this.portion)*this.num; }//计价,计算本条记录的价格 } // 订单类:保存用户点的所有菜的信息。 class Order { double discount1; double discount2; int countNum = -1; ArrayList<Record> records=new ArrayList<>();//保存订单上每一道的记录 ArrayList<Record> repeaatrecords=new ArrayList<>();//保存订单上每一道的记录 ArrayList<Table> tables = new ArrayList<>(); ArrayList<Table> getTotalPrice(){ tables = caculatelastprice(tables); for (int i = 0; i < tables.size(); i++) { int price = 0; int price1 = 0; int price2 = 0; int price3 = 0; boolean flagg = whetherTimeRight(tables.get(i).tablenum); for (Record record : records){ if(isTheSameTime(record.time,tables.get(i).tablenum)){ price += record.getPrice(); if(record.d.type.equals("T")){ price2+=record.getPrice(); } else { price3+=record.getPrice(); } } } price1 = (int) Math.round(price2 * this.discount2) + (int) Math.round(price3 * this.discount1); Table table = new Table(tables.get(i).tablenum,price,price1); tables.set(i,table); } return this.tables; } //添加一条菜品信息到订单中。 void addARecord(int orderNum,String dishName,int portion,int num,Menu menu,String time,int flag){ String[] strings = time.split(" "); boolean ordernumisright = true; if(flag==0) { if (this.countNum != -1) { if (records.get(this.countNum).time.equals(time)) { if (records.get(this.countNum).orderNum >= orderNum) { System.out.println("record serial number sequence error"); ordernumisright = false; } } } } if(ordernumisright) { Record record = new Record(); Dish dish = menu.searthDish(dishName); record.orderNum = orderNum; record.d = dish; record.portion = portion; record.num = num; record.time = time; if (portion != 1 && portion != 2 && portion != 3) { System.out.println(orderNum + " portion out of range " + portion); } else if (num > 15) { System.out.println(orderNum + " num out of range " + num); } else { records.add(record); this.countNum++; if (flag != 0) { System.out.println(record.orderNum + " " + strings[0] + " " + strings[1] + " pay for table " + flag + " " + record.getPrice()); } else { System.out.println(record.orderNum + " " + record.d.name + " " + record.getPrice()); } } } } //根据序号删除一条记录 void delARecordByOrderNum(int orderNum,String time){ for (int i = 0; i < records.size(); i++) { if(records.get(i).time.equals(time)) { if (records.get(i).orderNum == orderNum) { Record record = records.remove(i); this.countNum--; repeaatrecords.add(record); return; } } } if(ifRepeatDelete(orderNum,time)){ System.out.println("deduplication " + orderNum); } else { System.out.println("delete error;"); } } boolean ifRepeatDelete(int orderNum,String time){ for (Record repeaatrecord : repeaatrecords) { if(repeaatrecord.orderNum==orderNum&&repeaatrecord.time.equals(time)){ return true; } } return false; } boolean isTableNumisExist(int num){ for (Table table : tables) { String[] strings = table.tablenum.split(" "); if(Integer.parseInt(strings[1])==num){ return true; } } return false; } boolean whetherTimeRight(String time){ String[] str = time.split(" "); Date time1 = new Date(str[2]); Calendar cal = Calendar.getInstance(); cal.setTime(time1); int[] arr = {7,1,2,3,4,5,6}; int week = arr[cal.get(Calendar.DAY_OF_WEEK)-1]; String time2 = str[3]; String[] str1 = time2.split("/"); int hour = Integer.parseInt(str1[0]); int min = Integer.parseInt(str1[1]); if(week<6){ if(hour<10||(hour>14&&hour<17)||hour>20){ return false; } else if((hour==10&&min<30) ||(hour==14&&min>30)||(hour==20&&min>30)){ return false; } else { this.discount2 = 0.7; if(hour<=14){ this.discount1 = 0.6; } else { this.discount1 = 0.8; } } } else{ if(hour<9||hour>21){ return false; } else if((hour==9&&min<30) ||(hour==21&&min>30)){ return false; } this.discount1 =1; this.discount2 =1; } return true; } ArrayList<Table> caculatelastprice(ArrayList<Table> tables){ if(tables.size()>=2) { for (int i = 0; i < tables.size() - 1; i++) { for (int j = i + 1; j < tables.size(); j++) { if (isTheSameTime(tables.get(i).tablenum, tables.get(j).tablenum)) { tables.remove(j); } } } } return tables; } boolean isTheSameTime(String time1,String time2){ String[] strings1 = time1.split(" "); String[] strings2 = time2.split(" "); if(strings1[1].equals(strings2[1]) &&strings1[2].equals(strings2[2])) { String[] str1 = strings1[3].split("/"); String[] str2 = strings2[3].split("/"); int hour1 = Integer.parseInt(str1[0]); int min1 = Integer.parseInt(str1[1]); int second1 = Integer.parseInt(str1[2]); int hour2 = Integer.parseInt(str2[0]); int min2 = Integer.parseInt(str2[1]); int second2 = Integer.parseInt(str2[2]); if(weekday(time1)<6){ if((hour1<=14 && hour2<=14) || (hour1>=17 && hour2>=17)){ return true; } } else { long sencond = 0; if(hour1 > hour2){ sencond = (hour1 - hour2) * 3600 + min1 * 60 + second1 - min2 * 60 -second2; } else if(hour1 == hour2){ return true; } else if(hour1 < hour2){ sencond = (hour2 - hour1) * 3600 + min2 * 60 + second2 - min1 * 60 -second1; } if(sencond < 3600){ return true; } } } return false; } int weekday(String time){ String[] str = time.split(" "); Date time1 = new Date(str[2]); Calendar cal = Calendar.getInstance(); cal.setTime(time1); int[] arr = {7,1,2,3,4,5,6}; int week = arr[cal.get(Calendar.DAY_OF_WEEK)-1]; return week; } } class Table{ String tablenum; int primprice; int lastprice; public Table() { } public Table(String tablenum, int primprice, int lastprice) { this.tablenum = tablenum; this.primprice = primprice; this.lastprice = lastprice; } }
本题代码在菜单计价程序3的基础上进行修改。首先是类设计方面,舍弃了菜单计价程序3中将价格以属性的形式存放在Order类中,而实将其抽象出一个Table类,用来存放桌号信息以及记录每一桌打折前和打折后的价格。在Dish类中,添加一个属性type,用来区分是否为特色菜。在Order类中添加属性discount2,用来存放特色菜的打折信息。添加countNum属性则是为了处理每桌的点菜记录的序号没有按从小到大的顺序排列时的异常状况而设计的,主要是为了判断在添加新的点菜记录前有没有新的点菜记录。ArrayList<Table>类型的tables属性则是取代了菜单计价程序3中的tableprice属性,用来记录每一桌的情况。添加ArrayList<Record>类型的repeaatrecords属性则是为了解决重复删除时的输出问题。在Order类的方法中,也有了很大的改变,首先是计算总价的方法getTotalPrice(),添加了计算打折前和打折后价钱的代码。
在addARecord()方法中同样有些改变,主要是处理每桌的点菜记录的序号没有按从小到大的顺序排列时的异常状况。
同时也在Order类原有的基础上添加了一些新的方法。ifRepeatDelete()方法用来判断是否有重复删除订单记录,weekday()方法用来判断桌号日期为星期几。isTheSameTime()用来判断点菜信息是否在同一个时间段从而判断是否是是重复的桌号信息。caculatelastprice()用来合并重复的桌号信息。isTableNumisExist()方法用来判断带点菜信息时代点的桌号是否存在。
在Main类中的输入方面也有了一些改变,首先是判断输入方面,增加了一个正则表达式flag6用来判断输入的数据是否是特色菜的信息。
其次在数据处理方面,添加了一些异常处理的情况,主要是为了处输入桌号异常时的情况。
最后在Main类中添加了判断日期是否在指定的日期放范围内的方法isTimeInRange()。
4、菜单计价程序5
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+英文空格+桌号+:+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格
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金额都要累加。
import java.beans.PropertyEditorManager; import java.util.*; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); Order order = new Order(); Menu menu = new Menu(); boolean timeflag = false; String time = ""; String s = sc.nextLine(); while (!s.equals("end")){ int flag = 0; boolean flag1 = s.matches("[\\S]*\\s[0-9]*"); boolean flag2 = s.matches("table\\s[1-9]\\d*\\s:\\s[\\S]{1,10}\\s(180||181||189||133||135||136)\\d{8}\\s\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}/\\d{1,2}/\\d{1,2}"); boolean flag3 = s.matches("\\d*\\s[\\S]*\\s\\d\\s\\d*"); boolean flag4 = s.matches("\\d*\\s\\d*\\s[\\S]*\\s\\d\\s\\d*");//带点菜 boolean flag5 = s.matches("\\d*\\sdelete"); boolean flag6 = s.matches("[\\S]*\\s[\\S]*\\s[0-9]*\\sT"); boolean flag7 = s.matches("\\d*\\s[\\S]*\\s\\d*\\s\\d\\s\\d*"); boolean flag8 = s.matches("\\d*\\s\\d*\\s[\\S]*\\s\\d*\\s\\d\\s\\d*");//带点菜 String[] str = s.split(" "); if(flag1||flag6){ String name = str[0]; if (!flag6) { int price = Integer.parseInt(str[1]); menu.addDish(name, price, "F","nomal"); } else { int price = Integer.parseInt(str[2]); String vary = str[1]; menu.addDish(name, price, "T",vary); } } else if(flag2){ time = s; String[] strings = time.split(" "); Table table = new Table(); if(!order.whetherTimeRight(time)){ System.out.println(strings[0] + " " + strings[1] + " out of opening hours"); } else { timeflag = true; table.tablenum = time; table.primprice = -1; table.lastprice = -1; table.chuannum = 0; table.chuanflag = 0; table.zheflag = 0; table.jinflag = 0; table.jinaverageleve = 0; table.jinnum = 0; table.chuanaverageleve = 0; table.zheaverageleve = 0; table.zhenum = 0; order.tables.add(table); System.out.println(strings[0] + " " + strings[1] + ": "); } } else if(flag3||flag7){ if(timeflag) { int orderNum = Integer.parseInt(str[0]); String name = str[1]; if (!flag7) { int portion = Integer.parseInt(str[2]); int num = Integer.parseInt(str[3]); if (menu.searthDish(name) != null) { order.addARecord(orderNum, name, portion, num, menu, time, flag, -1); } else { System.out.println(name + " does not exist"); } } else { int level = Integer.parseInt(str[2]); int portion = Integer.parseInt(str[3]); int num = Integer.parseInt(str[4]); if (menu.searthDish(name) != null) { Dish dish = menu.searthDish(name); if (dish.isTastRight(dish.varies, level)) { order.addARecord(orderNum, name, portion, num, menu, time, flag, level); } } else { System.out.println(name + " does not exist"); } } } } else if(flag4 ||flag8){ if(timeflag) { flag = Integer.parseInt(str[0]); int orderNum = Integer.parseInt(str[1]); String name = str[2]; int portion; int num; if (!flag8) { portion = Integer.parseInt(str[3]); num = Integer.parseInt(str[4]); if (menu.searthDish(name) != null) { order.addARecord(orderNum, name, portion, num, menu, time, flag, -1); } else { System.out.println(name + " does not exist"); } } else { int level = Integer.parseInt(str[3]); portion = Integer.parseInt(str[4]); num = Integer.parseInt(str[5]); if (menu.searthDish(name) != null) { Dish dish = menu.searthDish(name); if (dish.isTastRight(dish.varies, level)) { order.addARecord(orderNum, name, portion, num, menu, time, flag, level); } } else { System.out.println(name + " does not exist"); } } } } else if(flag5){ int ordernum = Integer.parseInt(str[0]); order.delARecordByOrderNum(ordernum,time); } else { System.out.println("wrong format"); } s = sc.nextLine(); } order.tables = order.getTotalPrice(); String[] chuan = {"不辣","微辣","稍辣","辣","很辣","爆辣"}; String[] jin = {"不酸","微酸","稍酸","酸","很酸","爆辣"}; String[] zhe = {"不甜","微甜","稍甜","甜"}; for (Table table : order.tables) { String[] strings = table.tablenum.split(" "); if(table.primprice!=-1) { System.out.print(strings[0] +" " +strings[1]+ ": " + table.primprice + " " + table.lastprice); if(table.chuanflag!=0){ System.out.print(" 川菜 " + table.chuannum); System.out.print(" " + chuan[table.chuanaverageleve]); } if(table.jinflag!=0){ System.out.print(" 晋菜 " + table.jinnum); System.out.print(" " + jin[table.jinaverageleve]); } if(table.zheflag!=0){ System.out.print(" 浙菜 " + table.zhenum); System.out.print(" " + zhe[table.zheaverageleve]); } if(table.chuannum==0&&table.jinnum==0&&table.zhenum==0){ System.out.print(" "); } System.out.println(); } } order.lastprice(); } } class Dish { String name;//菜品名称 int unit_price; //单价 String varies; String type; int getPrice(int portion){ double[] arr = {0,1,1.5,2}; return (int) Math.round(this.unit_price*arr[portion]); } boolean isTastRight(String vary,int level){ if(vary.equals("川菜") && level >= 0&& level <= 5){ return true; } else if(vary.equals("川菜")){ System.out.println("spicy num out of range :" + level); return false; } else if(vary.equals("晋菜") && level >= 0&& level <= 4){ return true; } else if(vary.equals("晋菜")){ System.out.println("acidity num out of range :" + level); return false; } else if(vary.equals("浙菜") && level >= 0&& level <= 3){ return true; } else if(vary.equals("浙菜")){ System.out.println("sweetness num out of range :" + level); return false; } return false; } } //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 class Menu { ArrayList<Dish> dishs = new ArrayList<>();//菜品数组,保存所有菜品信息 Dish searthDish(String dishName){ for (int i = 0; i < this.dishs.size(); i++) { if (this.dishs.get(i).name.equals(dishName)){ return this.dishs.get(i); } } return null; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 int searthDishIndix(String dishName){ for (int i = 0; i < this.dishs.size(); i++) { if (this.dishs.get(i).name.equals(dishName)){ return i; } } return -1; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 Dish addDish(String dishName,int unit_price,String type,String vary){ Dish dish = new Dish(); dish.name = dishName; dish.unit_price = unit_price; dish.type = type; dish.varies = vary; if(this.searthDish(dishName)==null) { dishs.add(dish); } else { int flag = this.searthDishIndix(dishName); dishs.set(flag,dish); } return dish; } } // 点菜记录类:保存订单上的一道菜品记录 class Record { String time; int orderNum; Dish d;//菜品 int portion;//份额(1/2/3代表小/中/大份) int num; int Leve; int getPrice(){ return d.getPrice(this.portion)*this.num; }//计价,计算本条记录的价格 } // 订单类:保存用户点的所有菜的信息。 class Order { double discount1; double discount2; ArrayList<Record> records=new ArrayList<>();//保存订单上每一道的记录 ArrayList<Table> tables = new ArrayList<>(); ArrayList<Table> getTotalPrice(){ for (int i = 0; i < tables.size(); i++) { int price = 0; int price1 = 0; int price2 = 0; int firstprice = 0; boolean flagg = whetherTimeRight(tables.get(i).tablenum); for (Record record : records){ if(record.time.equals(tables.get(i).tablenum)){ firstprice +=record.getPrice(); if(record.d.type.equals("T")){ price1+=(int)Math.round(record.getPrice()*this.discount2); if(record.d.varies.equals("川菜")){ tables.get(i).chuannum += record.num; tables.get(i).chuanaverageleve+=(record.Leve*record.num); tables.get(i).chuanflag++; } else if(record.d.varies.equals("晋菜")){ tables.get(i).jinnum += record.num; tables.get(i).jinaverageleve+=(record.Leve*record.num); tables.get(i).jinflag++; } else if(record.d.varies.equals("浙菜")){ tables.get(i).zhenum += record.num; tables.get(i).zheaverageleve+=(record.Leve*record.num); tables.get(i).zheflag++; } } else { price2+=(int)Math.round(record.getPrice() * this.discount1); } } } price = price1 +price2; Table table = new Table(); table.tablenum = tables.get(i).tablenum; table.primprice = firstprice; table.lastprice = price; table.chuannum = tables.get(i).chuannum; table.jinnum = tables.get(i).jinnum; table.zhenum = tables.get(i).zhenum; table.zheflag = tables.get(i).zheflag; table.chuanflag = tables.get(i).chuanflag; table.jinflag = tables.get(i).jinflag; table.chuanaverageleve = (int)Math.round(tables.get(i).chuanaverageleve/(tables.get(i).chuannum *1.00)); table.jinaverageleve = (int)Math.round(tables.get(i).jinaverageleve/(tables.get(i).jinnum *1.00)); table.zheaverageleve = (int)Math.round(tables.get(i).zheaverageleve/(tables.get(i).zhenum *1.00)); tables.set(i,table); } return this.tables; } //添加一条菜品信息到订单中。 void addARecord(int orderNum,String dishName,int portion,int num,Menu menu,String time,int flag,int level){ String[] strings = time.split(" "); Record record = new Record(); Dish dish = menu.searthDish(dishName); record.Leve = level; record.orderNum=orderNum; record.d = dish; record.portion=portion; record.num=num; record.time = time; records.add(record); if(flag!=0){ int tn = Integer.parseInt(strings[1]); if(dish.varies.equals("川菜")) { tables.get(isTableNumisExist(flag)).chuannum += num; tables.get(isTableNumisExist(flag)).chuanaverageleve += (level*num); tables.get(isTableNumisExist(flag)).chuanflag++; tables.get(isTableNumisExist(tn)).chuannum -= num; tables.get(isTableNumisExist(tn)).chuanaverageleve -= (level*num); tables.get(isTableNumisExist(tn)).chuanflag--; } else if(dish.varies.equals("晋菜")) { tables.get(isTableNumisExist(flag)).jinnum += num; tables.get(isTableNumisExist(flag)).jinaverageleve += (level*num); tables.get(isTableNumisExist(flag)).jinflag++; tables.get(isTableNumisExist(tn)).jinnum -= num; tables.get(isTableNumisExist(tn)).jinaverageleve -= (level*num); tables.get(isTableNumisExist(tn)).jinflag--; } else if(dish.varies.equals("浙菜")) { tables.get(isTableNumisExist(flag)).zhenum += num; tables.get(isTableNumisExist(flag)).zheaverageleve += (level*num); tables.get(isTableNumisExist(flag)).zheflag++; tables.get(isTableNumisExist(tn)).zhenum -= num; tables.get(isTableNumisExist(tn)).zheaverageleve -= (level*num); tables.get(isTableNumisExist(tn)).zheflag--; } System.out.println(record.orderNum + " " + strings[0] + " " + strings[1] + " pay for table " + flag + " " + record.getPrice()); } else { System.out.println(record.orderNum + " " + record.d.name + " " + record.getPrice()); } } //根据序号删除一条记录 void delARecordByOrderNum(int orderNum,String time){ for (int i = 0; i < records.size(); i++) { if(records.get(i).time.equals(time)) { if (records.get(i).orderNum == orderNum) { records.remove(i); return; } } } System.out.println("delete error;"); } boolean whetherTimeRight(String time){ String[] str = time.split(" "); Date time1 = new Date(str[5]); Calendar cal = Calendar.getInstance(); cal.setTime(time1); int[] arr = {7,1,2,3,4,5,6}; int week = arr[cal.get(Calendar.DAY_OF_WEEK)-1]; String time2 = str[6]; String[] str1 = time2.split("/"); int hour = Integer.parseInt(str1[0]); int min = Integer.parseInt(str1[1]); if(week<6){ if(hour<10||(hour>14&&hour<17)||hour>20){ return false; } else if((hour==10&&min<30) ||(hour==14&&min>30)||(hour==20&&min>30)){ return false; } else { this.discount2 = 0.7; if(hour<=14){ this.discount1 = 0.6; } else { this.discount1 = 0.8; } } } else{ if(hour<9||hour>21){ return false; } else if((hour==9&&min<30) ||(hour==21&&min>30)){ return false; } this.discount1 =1; this.discount2 =1; } return true; } ArrayList<Table> lastprice(){ for (int i = 0; i < tables.size()-1; i++) { String[] strings = tables.get(i).tablenum.split(" "); for (int j = i + 1; j < tables.size(); j++) { String[] strings1 = tables.get(j).tablenum.split(" "); if(strings1[3].equals(strings[3]) && strings1[4].equals(strings[4])){ Table table = new Table(tables.get(i).tablenum,tables.get(i).primprice+tables.get(j).primprice,tables.get(i).lastprice+tables.get(j).lastprice); Table table1 = new Table(tables.get(i).tablenum,-1,-1); tables.set(i,table); tables.set(j,table1); } } } Collections.sort(tables, new Comparator<Table>() { @Override public int compare(Table o1, Table o2) { String[] string1 = o1.tablenum.split(" "); String[] string2 = o2.tablenum.split(" "); return string1[3].compareTo(string2[3]); } }); for (Table table : tables) { String[] strings = table.tablenum.split(" "); if(table.primprice>-1) { System.out.println(strings[3] + " " + strings[4] + " " + table.lastprice); } } return tables; } int isTableNumisExist(int num){ for (int i = 0; i < tables.size(); i++) { String[] strings = tables.get(i).tablenum.split(" "); if(Integer.parseInt(strings[1])==num){ return i; } } return -1; } } class Table{ String tablenum; int primprice; int lastprice; int chuannum; int chuanaverageleve; int chuanflag; int jinflag; int zheflag; int jinnum; int jinaverageleve; int zhenum; int zheaverageleve; public Table() { } public Table(String tablenum, int primprice, int lastprice) { this.tablenum = tablenum; this.primprice = primprice; this.lastprice = lastprice; } }
类图设计:
本次作业同样是在菜单计价程序3的基础上进行修改。类设计方面跟菜单计价程序4比较相似,但在具体的属性和方法上却有较大区别。首先是Dish类,添加了菜品种类属性type和菜品品系varies。在桌号类Table中添加了大量的属性,主要是为了计算川菜、浙菜、晋菜的数量、平均口味程度以及是否有该菜系。在Record类中也添加了一个属性Leve,用来记录所点菜的口味。Order类中,相较于菜单计价程序3,仅仅是增加了discount2用来记录特色菜的折扣,同时用ArrayList<Table> 类型的tables来代替原来的用来记录每一桌的信息,与菜单计价程序4比较相似。方法方面修改比较大的则是计算总价格时额外添加代码计算了特色菜的份数与平均口味程度。
同样改变的还有添加点菜信息的方法addARecord(),主要修改的是对带点菜信息是特色菜时的处理。在Order类中还添加了lastprice()方法用来计算同一个人的花费总价格。这里用到了Collections类的排序方法,最后按照以人名排序输出结果。
在Main类中,主要在输入方面做了处理,主要体现在增加了一些正则表达式用来处理数据以及修改原来桌号信息的正则表达式让其符合本题要求。
5、期中考试
期中考试主要的时编程题的最后一题,要求实现接口。
题目要求:在测验3的题目基础上,重构类设计,实现列表内图形的排序功能(按照图形的面积进行排序)。
提示:题目中Shape类要实现Comparable接口。
源码分析:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); ArrayList<Shape> list = new ArrayList<>(); int choice = input.nextInt(); while(choice != 0) { switch(choice) { case 1://Circle double 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()) + " "); } } static private void printArea(Shape shape){ System.out.println(String.format("%.2f",shape.getArea())); } } class Rectangle extends Shape{ Point toLeftPoint; Point toRightPoint; public Rectangle() { } public Rectangle(Point toLeftPoint, Point toRightPoint) { this.toLeftPoint = toLeftPoint; this.toRightPoint = toRightPoint; } double getlenght(){ double len = this.toRightPoint.x-this.toLeftPoint.x > 0?this.toRightPoint.x-this.toLeftPoint.x:this.toLeftPoint.x-this.toRightPoint.x; return len; } double getHeight(){ return this.toLeftPoint.y-this.toRightPoint.y>0?this.toLeftPoint.y-this.toRightPoint.y:this.toRightPoint.y-this.toLeftPoint.y; } @Override double getArea() { return this.getHeight()*this.getlenght(); } } class Point{ double x; double y; public Point() { } public Point(double x, double y) { this.x = x; this.y = y; } } class Circle extends Shape{ private double r; public Circle() { } public Circle(double r) { if(r>0) { this.r = r; } else { System.out.println("Wrong Format"); } } public double getR() { return r; } public void setR(double r) { this.r = r; } @Override double getArea() { return this.r * this.r * Math.PI; } } class Shape implements Comparable<Shape>{ double getArea(){ return 0; } @Override public int compareTo(Shape o) { return (int)(this.getArea()*100)-(int)(o.getArea()*100); } }
主要的代码都有提供,我要实现的主要是Shape类对Comparable接口的实现,实现代码就如上所示。
三、采坑心得
1、菜单计价程序2
2、菜单计价程序3
后面发现时删除点菜记录时会出现错误。
当第二桌菜删除桌号2中没有,桌号1中有时的订单记录时,就会出现错误。我也是在最后补练时才发现。将删除记录的代码修改为:
即可通过测试:
3、菜单计价程序4
4、菜单计价程序5
这题主要要注意的一是价格计算方面要严格遵守题目的计算方法,否则在计算时容易出现错误。比如出现以下错误。
其次是在代点菜方面,要注意代点菜的口味要计入其他桌而非本桌。否则容易出现以下错误。
最后还需要注意一下桌号的格式问题。我就是最后也没有发现哪一个桌号格式出现问题而剩下一个测试点。
5、期中考试
主要是接口没按正确的格式实现的话会出现错误。
实现接口时在接口后面的类指定为Shape类,然后实现方法重定义即可解决问题。
四、改进建议
类的设计可能并没有做到最合理,更加合理的类设计可能可以大大的简化代码量;对各种异常的处理比较分散,如何能够做到对所有的异常类进行统一处理可能不仅能简化代码,还能通过原来没通过的测试点。对方法的设计不够完美,每当添加了新的要求时,都不可避免的会对方法的变量、内容进行修改,如果能进行更好的方法设计,或许就能解决这些问题。
五、总结
通过这几次作业,加深了我对类的设计的理解,以及提高了我对处理几个类之间关系的能力。但应对一些异常情况的能力还明显不足。
通过期中测试,让我明白了我在接口部分的薄弱以及在一些理论部分的不足。
此外,基本上在数据处理的部分,都用到了正则表达式,加深了我对正则表达式的理解。