(1)前言:
这次blog主要是第四,五次pta练习以及期中考试的内容,pta的练习还是两道菜单类题目,是之前几次菜单题的升级版,难度有所提升,有了更多要求比如说口味度和折扣安排。期中的题目就是类的设计,还要抽象类与接口的使用。
(2)设计与分析
第四次题目集
本体大部分内容与菜单计价程序-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+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价
输入样例:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9 T
table 31 2023/2/1 14/20/00
1 麻婆豆腐 1 16
2 油淋生菜 1 2
2 delete
2 delete
end
输出样例:
在这里给出相应的输出。例如:
table 31:
1 num out of range 16
2 油淋生菜 18
deduplication 2
table 31: 0 0
输入样例1:
份数超出范围+份额超出范围。例如:
麻婆豆腐 12
油淋生菜 9 T
table 31 2023/2/1 14/20/00
1 麻婆豆腐 1 16
2 油淋生菜 4 2
end
输出样例1:
份数超出范围+份额超出范围。例如:
table 31:
1 num out of range 16
2 portion out of range 4
table 31: 0 0
输入样例2:
桌号信息错误。例如:
麻婆豆腐 12
油淋生菜 9 T
table a 2023/3/15 12/00/00
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
输出样例2:
在这里给出相应的输出。例如:
wrong format
输入样例3:
混合错误:桌号信息格式错误+混合的菜谱信息(菜谱信息忽略)。例如:
麻婆豆腐 12
油淋生菜 9 T
table 55 2023/3/31 12/000/00
麻辣香锅 15
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
输出样例3:
在这里给出相应的输出。例如:
wrong format
输入样例4:
错误的菜谱记录。例如:
麻婆豆腐 12.0
油淋生菜 9 T
table 55 2023/3/31 12/00/00
麻辣香锅 15
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
输出样例4:
在这里给出相应的输出。例如:
wrong format
table 55:
invalid dish
麻婆豆腐 does not exist
2 油淋生菜 14
table 55: 14 10
输入样例5:
桌号格式错误(以“table”开头)+订单格式错误(忽略)。例如:
麻婆豆腐 12
油淋生菜 9 T
table a 2023/3/15 12/00/00
1 麻婆 豆腐 1 1
2 油淋生菜 2 1
end
输出样例5:
在这里给出相应的输出。例如:
wrong format
输入样例6:
桌号格式错误,不以“table”开头。例如:
麻婆豆腐 12
油淋生菜 9 T
table 1 2023/3/15 12/00/00
1 麻婆豆腐 1 1
2 油淋生菜 2 1
tab le 2 2023/3/15 12/00/00
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
输出样例6:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 12
2 油淋生菜 14
wrong format
record serial number sequence error
record serial number sequence error
table 1: 26 17
其他用例请参考公开的测试用例
2.类图
3.题目分析
主要就是每个类要写的内容
- Main类:主类,包含程序的入口函数main。负责处理用户输入和输出结果。
- UserInformation类:用户信息类,用于保存用户的点菜信息和价格。负责合并相同用户的订单,并计算用户的总价格。
- Dish类:菜品类,保存菜品的名称和单价。负责计算菜品价格。
- SpecialDish类:特殊菜类,继承自Dish类,保存特殊菜的信息。负责计算特殊菜的总价格和查询特殊菜的价格。
- Menu类:菜单类,保存菜单上所有菜品的信息。负责查询菜品和添加菜品。
- Order类:订单类,保存用户点的菜品信息和口味信息。负责计算订单的总价格和口味平均值。
- Record类:记录类,保存订单上的一道菜品记录。负责计算菜品的价格。
- Table类:桌子类,保存桌子的序号、日期和时间。负责判断桌子的合法性和是否有相同桌号的订单。
- UpsideDown类:排序类,负责对订单按照用户姓名进行排序。
4.源代码
import java.util.Scanner; import java.util.regex.Pattern; import java.time.LocalDate; import java.time.LocalTime; import java.time.temporal.ChronoUnit; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); Menu menu = new Menu(); Order order = new Order(); Table table = new Table(); for (int i = 0; i < table.order.length; i++) { table.order[i] = new Order(); for (int i1 = 0; i1 < order.records.length; i1++) { table.order[i].records[i1] = new Record(); table.order[i].s[i1] = new SpecialDish(); } } for (int i = 0; i < menu.dishes.length; i++) { menu.dishes[i] = new Dish(); menu.dishes[i].name = " "; } int invalidFlag = 0, tablei = 0; int tableFlag = 0; int orderFlag1 = 0, orderFlag2 = 0; int j = 0; //j用来看订单的序号 int stringFlag = 0; int combineFlag = 0; //判断是否要合并桌 while (true) { String signal = sc.nextLine(); if (signal.equals("end")) { break; } String str[] = signal.split(" "); //菜单的输入、订单的输入和删除序号 if (str.length == 2 || str.length == 4) { //菜单的输入 if (str.length == 4) { //此时是订单的输入 if (isInteger(str[0])) { if (tableFlag == 1) { j = 0; tableFlag = 0; } if (tablei - 1 > -1) { if(menu.searchDish(str[1]) !=null){ table.order[tablei - 1].records[j].d = menu.searchDish(str[1]); table.order[tablei - 1].addARecord(Integer.parseInt(str[0]), str[1], Integer.parseInt(str[2]), Integer.parseInt(str[3])); System.out.println(str[0] + " " + str[1] + " " + table.order[tablei - 1].records[j].getPrice()); } else{ System.out.println(str[1] + " does not exist"); //记录错误菜品名 continue; } } j++; } //特殊菜 if (signal.matches("(\S+)( )(川菜|晋菜|浙菜)( )([^0])(\d*)( )(T?)")) { menu.addSpecial(true); menu.addType(str[1]); menu.addDish(str[0], Integer.parseInt(str[2])); } } else if (str[0].length() != 1) { menu.addDish(str[0], Integer.parseInt(str[1])); } //删除 else { if (tablei - 1 < 0) { continue; } if (menu.findSpecial(str[0], table.order[tablei - 1])) { SpecialDish s1 = table.order[tablei - 1].findSpecialDish(Integer.parseInt(str[0])); table.order[tablei - 1].pretendDelRecordByOrderNum(Integer.parseInt(str[0]), s1); int recordNumber = table.order[tablei - 1].findRecordByNumber(Integer.parseInt(str[0])); table.order[tablei - 1].deleteTaste(menu, table.order[tablei - 1].records[recordNumber].d.name, table.order[tablei - 1].records[recordNumber].degree, table.order[tablei - 1].records[recordNumber].count); int specialNumber = table.order[tablei - 1].findSpecialRecordByNumber(Integer.parseInt(str[0])); table.order[tablei - 1].s[specialNumber].ifDelete = true; } else { table.order[tablei - 1].delARecordByOrderNum(Integer.parseInt(str[0])); } } } //订单的输入(给自己点菜, 并且此时只能是特殊菜) else if (str.length == 5) { //订单的输入 if (isInteger(str[0])) { if (stringFlag == 1) { continue; } if (stringFlag == 1) { continue; } //点的菜在菜单上存在 if (menu.searchDish(str[1]) != null) { if (tableFlag == 1) { j = 0; tableFlag = 0; } if (tablei - 1 > -1) { if (table.order[tablei - 1].ifAddTaste(menu, str[1], Integer.parseInt(str[2]))) { table.order[tablei - 1].s[j].addDish(menu, str[1], str[3], str[4]); table.order[tablei - 1].s[j].num = Integer.parseInt(str[0]); System.out.println(str[0] + " " + str[1] + " " + table.order[tablei - 1].s[j].searchPrice(str[1])); table.order[tablei - 1].records[j].d = menu.searchDish(str[1]); table.order[tablei - 1].addARecord(Integer.parseInt(str[0]), str[1], Integer.parseInt(str[3]), Integer.parseInt(str[4])); //把口味的count添加到口味当中 table.order[tablei - 1].addTaste(menu, str[1], Integer.parseInt(str[2]), table.order[tablei - 1].records[j].count); table.order[tablei - 1].records[j].degree = Integer.parseInt(str[2]); table.order[tablei - 1].pretendToDelete(Integer.parseInt(str[0])); j++; } else { table.order[tablei - 1].printTasteOutOf(menu, str[1], Integer.parseInt(str[2])); } } } //点的菜在菜单上不存在 else { System.out.println(str[1] + " does not exist"); //记录错误菜品名 continue; } } } //代点菜(应该有大问题) else if (str.length == 6) { if (!isInteger(str[0])) { System.out.println("wrong format"); } //代点菜存在 if (menu.searchDish(str[2]) != null) { if (tableFlag == 1) { j = 0; tableFlag = 0; } if (table.num[tablei - 1] != Integer.parseInt(str[0]) && table.ifExistTableNum(Integer.parseInt(str[0]))) { if (menu.searchSpecial(str[2])) { if (tablei - 1 > -1) { table.order[tablei - 1].s[j].addDish(menu, str[2], str[4], str[5]); table.order[tablei - 1].s[j].num = Integer.parseInt(str[1]); System.out.println(str[1] + " table " + table.num[tablei - 1] + " pay for table " + str[0] + " " + Math.round(Integer.parseInt(str[5]) * menu.searchDish(str[2]).getPrice(Integer.parseInt(str[4])))); table.order[tablei - 1].records[j].d = menu.searchDish(str[2]); table.order[tablei - 1].addARecord(Integer.parseInt(str[1]), str[2], Integer.parseInt(str[4]), Integer.parseInt(str[5])); table.order[tablei - 1].pretendToDelete(Integer.parseInt(str[1])); int number = table.searchSameTableOrder(Integer.parseInt(str[0])); if (number != -1) { Dish d = menu.searchDish(str[2]); if (d.type.equals("川菜")) { table.order[number].spicyCount += Integer.parseInt(str[5]); } else if (d.type.equals("晋菜")) { table.order[number].acidCount += Integer.parseInt(str[5]); } else if (d.type.equals("浙菜")) { table.order[number].sweetCount += Integer.parseInt(str[5]); } table.order[number].addTaste(menu, str[2], Integer.parseInt(str[3]), Integer.parseInt(str[5])); } j++; } } else { System.out.println(str[1] + " table " + table.num[tablei - 1] + " pay for table " + str[0] + " " + Math.round(Integer.parseInt(str[4]) * menu.searchDish(str[2]).getPrice(Integer.parseInt(str[3])))); table.order[tablei - 1].records[j].d = menu.searchDish(str[2]); j++; table.order[tablei - 1].addARecord(Integer.parseInt(str[1]), str[2], Integer.parseInt(str[3]), Integer.parseInt(str[4])); } } else { System.out.println("Table number :" + str[0] + " does not exist"); } } //代点菜不存在 else { System.out.println(str[2] + " does not exist"); continue; } } //输入桌号 else if (str.length == 7) { if (str[0].equals("table")) { if (!table.ifLegal(signal)) { System.out.println("wrong format"); stringFlag = 1; continue; } table.num[tablei] = Integer.parseInt(str[1]); table.date[tablei] = str[5]; table.time[tablei] = str[6]; table.order[tablei].workFlag = 0; if (!table.isValidDate(tablei)) { System.out.println(str[1] + " date error"); stringFlag = 1; continue; } if (!table.judgeDiscount(tablei)) { System.out.println("wrong format"); stringFlag = 1; continue; } if (table.order[tablei].workFlag != 0) { System.out.println("table " + table.num[tablei] + " out of opening hours"); stringFlag = 1; continue; } table.order[tablei].owner = str[3]; table.order[tablei].phoneNumber = str[4]; stringFlag = 0; table.specialDiscount(tablei); if (table.ifSameOwner(table.order[tablei].owner, tablei)) { combineFlag = 1; } System.out.println("table " + table.num[tablei] + ": "); table.order[tablei].tableNum = Integer.parseInt(str[1]); tablei++; tableFlag = 1; } else { System.out.println("wrong format"); } } else { System.out.println("wrong format"); stringFlag = 1; continue; } } int sum1 = 0, sum2 = 0; for (int i = 0; i < tablei; i++) { sum1 = 0; sum2 = 0; System.out.print("table " + table.num[i] + ": "); table.order[i].getTotalPrice(); table.order[i].getTotalSpecialPrice(); sum1 = table.order[i].totalPrice; // 正常菜的价格 sum2 = table.order[i].specialTotalPrice; //特殊菜的价格 System.out.print(sum1 + sum2 + " "); table.order[i].getAfterTotalPrice(menu); table.order[i].getAfterSpecialTotalPrice(); int sum = table.order[i].afterDiscountTotalPrice + table.order[i].afterDiscountSpecialTotalPrice; System.out.print(sum); if (sum2 != 0) { table.order[i].getTotalSpecialCount(menu); table.order[i].getConcreteDegree(); int degreeFlag = 0; System.out.print(" "); if (table.order[i].spicyLength != 0) { System.out.print("川菜" + " " + table.order[i].spicyCount + " " + table.order[i].spicyString); degreeFlag = 1; } if (table.order[i].acidLength != 0) { if (degreeFlag == 1) { System.out.print(" "); } degreeFlag = 1; System.out.print("晋菜" + " " + table.order[i].acidCount + " " + table.order[i].acidString); } if (table.order[i].sweetLength != 0) { if (degreeFlag == 1) { System.out.print(" "); } System.out.print("浙菜" + " " + table.order[i].sweetCount + " " + table.order[i].sweetString); } } else { System.out.print(" "); } System.out.println(); } UpsideDown u = new UpsideDown(); u.changeOrder(table); UserInformation UI = new UserInformation(); for (int i = 0; i < tablei; i++) { table.order[i].userPriceAddTo(); } UI.combineUserInformation(table); for (int i = 0; i < UI.orderLength; i++) { System.out.println(UI.order[i].owner + " " + UI.order[i].phoneNumber + " " + UI.order[i].userPrice); } } public static boolean isInteger(String str) { Pattern pattern = Pattern.compile("^[-\+]?[\d]*$"); return pattern.matcher(str).matches(); } } class UserInformation { Order order[] = new Order[100]; int orderLength = 0; public void outSetOrder() { for (int i = 0; i < order.length; i++) { order[i] = new Order(); order[i].owner = ""; } } public void combineUserInformation(Table table) { outSetOrder(); for (int i = 0; i < table.order.length; i++) { int flag = 0; for (int i1 = 0; i1 < order.length; i1++) { if (order[i1].owner.equals(table.order[i].owner)) { flag = 1; order[i1].userPrice += table.order[i].userPrice; break; } } if (flag == 0 && table.order[i].owner != null) { order[orderLength++] = table.order[i]; } } } } class Dish { //对应菜谱上一道菜的信息。 String name; //菜品名称 int unit_price; //单价 boolean special; //是否是特殊菜 String type;//判断是川菜、浙菜、晋菜 public int getPrice(int portion) { //计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) double price = 0; if (portion == 1) { price = unit_price; } else if (portion == 2) { price = unit_price * 1.5; } else if (portion == 3) { price = unit_price * 2; } int price1 = (int) (run(price)); return price1; } double run(double num) { double a = Math.signum(num); //判断是正数负数还是0,负数返回-1.0,正数返回1.0 if (a < 0.0) return 0.0 - Math.round(Math.abs(num)); return Math.round(num); } } class SpecialDish { Dish d[] = new Dish[100]; int length = 0; int totalSpecialPrice = 0; int num = 0; boolean ifDelete = false; public void addDish(Menu m, String dishName, String portion, String count) { d[length] = new Dish(); d[length].name = dishName; d[length].unit_price = m.searchDish(dishName).getPrice(Integer.parseInt(portion)) * Integer.parseInt(count); length++; } public int searchPrice(String dishName) { for (int i = 0; i < d.length; i++) { if (d[i].name.equals(dishName)) { return d[i].unit_price; } } return 0; } public int getSpecialPrice() { int price = 0; for (int i = 0; d[i] != null; i++) { price += d[i].unit_price; } return price; } } class Menu { //对应菜谱,包含饭店提供的所有菜的信息。 Dish[] dishes = new Dish[100];//菜品数组,保存所有菜品信息 int length = 0; Dish searchDish(String dishName) { for (int i = dishes.length - 1; i >= 0; i--) { if (dishes[i].name.equals(dishName)) { return dishes[i]; } } return null; //未找到 } boolean searchSpecial(String dishName) { if (searchDish(dishName).special) { return true; } return false; } boolean findSpecial(String orderNum, Order o) { for (int i = 0; i < o.records.length && o.records[i] != null; i++) { if (o.records[i].orderNum == Integer.parseInt(orderNum)) { if (searchSpecial(o.records[i].d.name)) { return true; } } } return false; } void addDish(String dishName, int unit_price) { dishes[length].name = dishName; dishes[length].unit_price = unit_price; length++; } void addType(String type){ dishes[length].type = type; } void addSpecial(boolean special) { dishes[length].special = special; } } class Order { //保存用户点的所有菜的信息 Record[] records = new Record[100]; //保存订单上每一道的记录 SpecialDish[] s = new SpecialDish[100]; //特殊菜 int tableNum = 0; int length = 0; double discount; int workFlag = 0; int totalPrice = 0; int userPrice = 0; //输出人名时的价格 int specialTotalPrice = 0; int afterDiscountTotalPrice = 0; int afterDiscountSpecialTotalPrice = 0; int delete[] = new int[100]; int deleteFlag = 0; double specialDiscount; int workOrRelaxFlag = 0; //周一到周五的中午为1,晚上为2,周日为3 int spicyDegree[] = new int[100]; int spicyDegreeCount[] = new int[100]; int spicyLength = 0; int acidityDegree[] = new int[100]; int acidDegreeCount[] = new int[100]; int acidLength = 0; int sweetnessDegree[] = new int[100]; int sweetDegreeCount[] = new int[100]; int sweetLength = 0; int spicyAver = 0; int acidAver = 0; int sweetAver = 0; String spicyString; String acidString; String sweetString; String owner; String phoneNumber; int spicyCount = 0; int acidCount = 0; int sweetCount = 0; public void printTasteOutOf(Menu menu, String dishName, int degree) { Dish d = menu.searchDish(dishName); if (d != null) { if (d.type.equals("川菜")) { if (degree > 5) { System.out.println("spicy num out of range :" + degree); } } else if (d.type.equals("晋菜")) { if (degree > 4) { System.out.println("acidity num out of range :" + degree); } } else if (d.type.equals("浙菜")) { if (degree > 3) { System.out.println("sweetness num out of range :" + degree); } } } } public boolean ifAddTaste(Menu menu, String dishName, int degree) { Dish d = menu.searchDish(dishName); if (d != null) { if (d.type.equals("川菜")) { if (degree <= 5) { return true; } return false; } else if (d.type.equals("晋菜")) { if (degree <= 4) { return true; } return false; } else if (d.type.equals("浙菜")) { if (degree <= 3) { return true; } return false; } } return false; } public boolean addTaste(Menu menu, String dishName, int degree, int count) { Dish d = menu.searchDish(dishName); if (d != null) { if (d.type.equals("川菜")) { if (addSpicy(degree, count)) { return true; } return false; } else if (d.type.equals("晋菜")) { if (addAcid(degree, count)) { return true; } return false; } else if (d.type.equals("浙菜")) { if (addSweet(degree, count)) { return true; } return false; } } return false; } public void getAverage() { double s1 = 0, a = 0, s2 = 0; for (int i = 0; i < spicyLength; i++) { s1 += spicyDegree[i] * spicyDegreeCount[i]; } for (int i = 0; i < acidLength; i++) { a += acidityDegree[i] * acidDegreeCount[i]; } for (int i = 0; i < sweetLength; i++) { s2 += sweetnessDegree[i] * sweetDegreeCount[i]; } spicyAver = (int) Math.round(s1 / spicyCount); acidAver = (int) Math.round(a / acidCount); sweetAver = (int) Math.round(s2 / sweetCount); } public void getConcreteDegree() { getAverage(); if (spicyAver == 0) { spicyString = "不辣"; } else if (spicyAver == 1) { spicyString = "微辣"; } else if (spicyAver == 2) { spicyString = "稍辣"; } else if (spicyAver == 3) { spicyString = "辣"; } else if (spicyAver == 4) { spicyString = "很辣"; } else if (spicyAver == 5) { spicyString = "爆辣"; } if (acidAver == 0) { acidString = "不酸"; } else if (acidAver == 1) { acidString = "微酸"; } else if (acidAver == 2) { acidString = "稍酸"; } else if (acidAver == 3) { acidString = "酸"; } else if (acidAver == 4) { acidString = "很酸"; } if (sweetAver == 0) { sweetString = "不甜"; } else if (sweetAver == 1) { sweetString = "微甜"; } else if (sweetAver == 2) { sweetString = "稍甜"; } else if (sweetAver == 3) { sweetString = "甜"; } } public boolean addSpicy(int spicDegree, int count) { if (spicDegree <= 5) { spicyDegree[spicyLength] = spicDegree; spicyDegreeCount[spicyLength++] = count; return true; } return false; } public boolean addAcid(int acidDegree, int count) { if (acidDegree <= 4) { acidityDegree[acidLength] = acidDegree; acidDegreeCount[acidLength++] = count; return true; } return false; } public boolean addSweet(int sweetDegree, int count) { if (sweetDegree <= 3) { sweetnessDegree[sweetLength] = sweetDegree; sweetDegreeCount[sweetLength++] = count; return true; } return false; } void getTotalPrice() { //计算订单的总价 for (Record record : records) { totalPrice += record.getPrice(); } } public void getTotalSpecialPrice() { for (SpecialDish specialDish : s) { specialTotalPrice += specialDish.getSpecialPrice(); } } //添加一条菜品信息到订单中 void addARecord(int orderNum, String dishName, int portion, int count) { records[length].d.name = dishName; records[length].portion = portion; records[length].count = count; records[length].orderNum = orderNum; length++; } void pretendToDelete(int orderNum) { for (int i = 0; i < length; i++) { if (records[i].orderNum == orderNum) { totalPrice -= Math.toIntExact(Math.round(records[i].getPrice())); } } } //根据序号找到一个特殊菜 SpecialDish findSpecialDish(int Num) { for (int i = 0; s[i] != null; i++) { if (s[i].num == Num) { return s[i]; } } return null; } void pretendDelRecordByOrderNum(int orderNum, SpecialDish s) { int flag = 0; for (int i = 0; i < deleteFlag; i++) { if (delete[i] == orderNum) { //System.out.println("deduplication " + orderNum); return; } } for (int i = 0; i < length; i++) { if (records[i].orderNum == orderNum) { flag = 1; delete[deleteFlag++] = orderNum; afterDiscountSpecialTotalPrice -= s.searchPrice(records[i].d.name); specialTotalPrice -= s.searchPrice(records[i].d.name); } } if (flag == 0) { System.out.println("delete error;"); } } void delARecordByOrderNum(int orderNum) { int flag = 0; for (int i = 0; i < deleteFlag; i++) { if (delete[i] == orderNum) { System.out.println("deduplication " + orderNum); return; } } for (int i = 0; i < length; i++) { if (records[i].orderNum == orderNum) { flag = 1; delete[deleteFlag++] = orderNum; totalPrice -= Math.toIntExact(Math.round(records[i].getPrice())); } } if (flag == 0) { System.out.println("delete error;"); } } public void getTotalSpecialCount(Menu m) { for (int i = 0; i < records.length; i++) { Dish d = m.searchDish(records[i].d.name); if (d != null && d.special) { if (d.type.equals("川菜")) { spicyCount += records[i].count; } else if (d.type.equals("晋菜")) { acidCount += records[i].count; } else if (d.type.equals("浙菜")) { sweetCount += records[i].count; } } } } public void getAfterTotalPrice(Menu menu) { for (int i = 0; i < records.length; i++) { Dish d = menu.searchDish(records[i].d.name); if (d != null && !d.special) { afterDiscountTotalPrice += Math.round(records[i].getPrice() * discount); } } if (afterDiscountTotalPrice < 0) { afterDiscountTotalPrice = 0; } } public void getAfterSpecialTotalPrice() { for (SpecialDish specialDish : s) { if (specialDish.ifDelete) { afterDiscountSpecialTotalPrice += specialDish.getSpecialPrice(); } else { afterDiscountSpecialTotalPrice += Math.round(specialDish.getSpecialPrice() * specialDiscount); } } } public void deleteTaste(Menu menu, String dishName, int degree, int count) { Dish d = menu.searchDish(dishName); if (d != null) { if (d.type.equals("川菜")) { for (int i = 0; i < spicyDegree.length; i++) { if (spicyDegree[i] == degree && spicyDegreeCount[i] == count) { spicyDegree[i] -= degree; spicyDegreeCount[i] -= count; spicyCount -= count; spicyLength--; break; } } } else if (d.type.equals("晋菜")) { for (int i = 0; i < acidityDegree.length; i++) { if (acidityDegree[i] == degree && acidDegreeCount[i] == count) { acidityDegree[i] -= degree; acidDegreeCount[i] -= count; acidCount -= count; acidLength--; break; } } } else if (d.type.equals("浙菜")) { for (int i = 0; i < sweetnessDegree.length; i++) { if (sweetnessDegree[i] == degree && sweetDegreeCount[i] == count) { sweetnessDegree[i] -= degree; sweetDegreeCount[i] -= count; sweetCount -= count; sweetLength--; break; } } } } } public int findRecordByNumber(int number) { for (int i = 0; i < records.length; i++) { if (records[i].orderNum == number) { return i; } } return -1; } public int findSpecialRecordByNumber(int number) { for (int i = 0; i < s.length; i++) { if (s[i].num == number) { return i; } } return -1; } public void userPriceAddTo() { userPrice += afterDiscountTotalPrice + afterDiscountSpecialTotalPrice; } } class Record { //保存订单上的一道菜品记录 Dish d = new Dish(); //菜品 int orderNum; int count;//订单上的份数 int portion; //份额(1/2/3代表小/中/大份) int degree; //口味的程度 int getPrice(){ return count * d.getPrice(portion); } } class Table { Order order[] = new Order[100]; int num[] = new int[100];//桌子的序号 String date[] = new String[100]; String time[] = new String[100]; public void specialDiscount(int i) { String d[] = date[i].split("/"); LocalDate d1 = LocalDate.of(Integer.parseInt(d[0]), Integer.parseInt(d[1]), Integer.parseInt(d[2])); int day = d1.getDayOfWeek().getValue(); if (day != 6 && day != 7) { order[i].specialDiscount = 0.7; } else { order[i].specialDiscount = 1; } } // boolean judgeIfOutYear(int i) { // String d[] = date[i].split("/"); // LocalDate d1 = LocalDate.of(Integer.parseInt(d[0]), Integer.parseInt(d[1]), Integer.parseInt(d[2])); // LocalDate startYear = LocalDate.of(2022, 1, 1); // LocalDate endYear = LocalDate.of(2023, 12, 31); // if (d1.isAfter(endYear) || d1.isBefore(startYear)) { // return false; // } // return true; // } boolean judgeDiscount(int i) { String d[] = date[i].split("/"); String t[] = time[i].split("/"); LocalDate d1 = LocalDate.of(Integer.parseInt(d[0]), Integer.parseInt(d[1]), Integer.parseInt(d[2])); LocalTime d2 = LocalTime.of(Integer.parseInt(t[0]), Integer.parseInt(t[1]), Integer.parseInt(t[2])); LocalTime dRelaxStart = LocalTime.of(9, 30); LocalTime dRelaxEnd = LocalTime.of(21, 30); LocalTime dWorkStart1 = LocalTime.of(10, 30); LocalTime dWorkStart2 = LocalTime.of(17, 0); LocalTime dWorkEnd1 = LocalTime.of(14, 30); LocalTime dWorkEnd2 = LocalTime.of(20, 30); int day = d1.getDayOfWeek().getValue(); if (day == 6 || day == 7) { if (d2.isAfter(dRelaxEnd) || d2.isBefore(dRelaxStart)) { order[i].workFlag = 1; } else { order[i].workOrRelaxFlag = 3; order[i].discount = 1; } } else { if ((d2.isAfter(dWorkStart1) && d2.isBefore(dWorkEnd1)) || (d2.until(dWorkStart1, ChronoUnit.SECONDS) == 0 || d2.until(dWorkEnd1, ChronoUnit.SECONDS) == 0)) { order[i].discount = 0.6; order[i].workOrRelaxFlag = 1; } else if ((d2.isAfter(dWorkStart2) && d2.isBefore(dWorkEnd2)) || (d2.until(dWorkStart2, ChronoUnit.SECONDS) == 0 || d2.until(dWorkEnd2, ChronoUnit.SECONDS) == 0)) { order[i].workOrRelaxFlag = 2; order[i].discount = 0.8; } else { order[i].workFlag = 1; } } String pattern = "([0-1]?[0-9]|2[0-3])/([0-5][0-9])/([0-5][0-9])"; String timeString = ""; char[] c = time[i].toCharArray(); for (int i1 = 0; i1 < c.length; i1++) { timeString += c[i1]; } if (timeString.matches(pattern)) { return true; } else { return false; } } boolean isValidDate(int i) { String str[] = date[i].split("/"); // 接下来需要检查年月日是否都是数字,并且是否分别在合法的范围内 try { int year = Integer.parseInt(str[0]); int month = Integer.parseInt(str[1]); int day = Integer.parseInt(str[2]); if (year < 1 || month < 1 || month > 12) { return false; } if (day < 1 || day > getDaysInMonth(year, month)) { return false; } } catch (NumberFormatException e) { return false; } // 如果以上条件都满足,则说明是一个合法的日期 return true; } /** 获取某个月份的天数 @param year 年份 @param month 月份(1~12) @return 指定月份的天数 */ public static int getDaysInMonth(int year, int month) { switch (month) { case 2: return isLeapYear(year) ? 29 : 28; case 4: case 6: case 9: case 11: return 30; default: return 31; } } /** 判断某一年是否是闰年 @param year 年份 @return 如果是闰年,则返回true,否则返回false */ public static boolean isLeapYear(int year) { if (year % 4 == 0 && year % 100 != 0) { return true; } else if (year % 400 == 0) { return true; } else { return false; } } public boolean ifLegal(String str) { if (str.matches("(table)( )([^0])(\d*)( )(:)( )(\S{1,10})( )(180|181|189|133|135|136)(\d{8})( )(\d{4})(/)([1-9]|0[1-9]|\d{2})(/)(\d{1,2})( )(\d{1,2})(/)(\d{1,2})(/)(\d{1,2})")) { return true; } return false; } public boolean ifSameDay(int tablei) { String d1[] = date[tablei].split("/"); LocalDate day = LocalDate.of(Integer.parseInt(d1[0]), Integer.parseInt(d1[1]), Integer.parseInt(d1[2])); for (int i1 = tablei - 1; i1 >= 0; i1--) { String d[] = date[i1].split("/"); LocalDate d_ = LocalDate.of(Integer.parseInt(d[0]), Integer.parseInt(d[1]), Integer.parseInt(d[2])); if (d_.getDayOfWeek().getValue() == day.getDayOfWeek().getValue()) { return true; } } return false; } public boolean ifSameTime(int tablei) { if (!ifSameDay(tablei)) { return false; } for (int i1 = tablei - 1; i1 >= 0; i1--) { if (order[i1].workOrRelaxFlag == order[tablei].workOrRelaxFlag) { return true; } } return false; } public boolean ifExistTableNum(int tableNum) { for (int i = 0; i < num.length; i++) { if (num[i] == tableNum) { return true; } } return false; } public boolean ifSameOwner(String name, int tablei) { for (int i = tablei - 1; i >= 0; i--) { if (order[i].owner.equals(name)) { return true; } } return false; } public int searchSameTableOrder(int number){ for (int i = 0; i < order.length; i++) { if(order[i].tableNum == number){ return i; } } return -1; } } class UpsideDown { public void changeOrder(Table table) { for (int i = 0; table.order[i].owner != null && i < table.order.length - 1; i++) { for (int i1 = 0; table.order[i1].owner != null && i1 < table.order.length - 1 - i; i1++) { if (table.order[i1 + 1].owner != null) { if (table.order[i1].owner.compareTo(table.order[i1 + 1].owner) > 0) { Order o; o = table.order[i1]; table.order[i1] = table.order[i1 + 1]; table.order[i1 + 1] = o; } } } } }
第五次题目集
本题在菜单计价程序-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:
桌号时间超出营业范围。例如:
麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 21/30/00
1 麻婆豆腐 3 1 2
2 油淋生菜 2 1
3 麻婆豆腐 2 3 2
end
输出样例1:
在这里给出相应的输出。例如:
table 1 out of opening hours
输入样例2:
一种口味的菜品。例如:
麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 20/30/00
1 麻婆豆腐 2 1 2
2 油淋生菜 2 1
3 麻婆豆腐 2 3 2
end
输出样例2:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 24
2 油淋生菜 14
3 麻婆豆腐 48
table 1: 86 62 川菜 4 稍辣
tom 13605054400 62
输入样例3:
辣度值超出范围。例如:
麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 18/30/00
1 麻婆豆腐 6 1 2
2 油淋生菜 1 1
3 麻婆豆腐 5 3 2
end
输出样例3:
在这里给出相应的输出。例如:
table 1:
spicy num out of range :6
2 油淋生菜 9
3 麻婆豆腐 48
table 1: 57 41 川菜 2 爆辣
tom 13605054400 41
输入样例4:
同一用户对应多桌菜。例如:
麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 18/30/00
1 麻婆豆腐 1 1 2
2 油淋生菜 1 1
3 麻婆豆腐 2 2 2
table 2 : tom 13605054400 2023/5/6 18/30/00
1 麻婆豆腐 2 1 2
2 麻辣鸡丝 2 2
3 麻婆豆腐 2 1 1
end
输出样例4:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 24
2 油淋生菜 9
3 麻婆豆腐 36
table 2:
1 麻婆豆腐 24
2 麻辣鸡丝 30
3 麻婆豆腐 12
table 1: 69 49 川菜 4 稍辣
table 2: 66 66 川菜 3 稍辣
tom 13605054400 115
输入样例5:
多用户多桌菜。例如:
东坡肉 浙菜 25 T
油淋生菜 9
蜜汁灌藕 浙菜 10 T
刀削面 晋菜 10 T
醋浇羊肉 晋菜 30 T
麻婆豆腐 川菜 12 T
麻辣鸡丝 川菜 15 T
table 1 : tom 13605054400 2023/5/6 12/30/00
1 醋浇羊肉 4 1 1
3 刀削面 1 1 3
2 东坡肉 3 2 1
4 麻辣鸡丝 2 1 1
table 2 : jerry 18100334566 2023/5/1 12/30/00
1 醋浇羊肉 1 1 2
3 麻婆豆腐 2 2 1
4 麻辣鸡丝 2 3 3
table 3 : jerry 18100334566 2023/5/1 12/30/00
1 醋浇羊肉 2 1 1
3 蜜汁灌藕 1 1 2
2 东坡肉 2 2 1
4 麻辣鸡丝 5 1 1
end
输出样例5:
在这里给出相应的输出。例如:
table 1:
1 醋浇羊肉 30
3 刀削面 30
2 东坡肉 38
4 麻辣鸡丝 15
table 2:
1 醋浇羊肉 60
3 麻婆豆腐 18
4 麻辣鸡丝 90
table 3:
1 醋浇羊肉 30
3 蜜汁灌藕 20
2 东坡肉 38
4 麻辣鸡丝 15
table 1: 113 113 川菜 1 稍辣 晋菜 4 稍酸 浙菜 1 甜
table 2: 168 118 川菜 4 稍辣 晋菜 2 微酸
table 3: 103 73 川菜 1 爆辣 晋菜 1 稍酸 浙菜 3 微甜
jerry 18100334566 191
tom 13605054400 113
输入样例6:
多用户多桌菜含代点菜。例如:
东坡肉 浙菜 25 T
油淋生菜 9
蜜汁灌藕 浙菜 10 T
刀削面 晋菜 10 T
醋浇羊肉 晋菜 30 T
麻婆豆腐 川菜 12 T
麻辣鸡丝 川菜 15 T
table 1 : tom 13605054400 2023/5/6 12/30/00
1 醋浇羊肉 4 1 1
3 刀削面 1 1 3
2 东坡肉 3 2 1
4 麻辣鸡丝 2 1 1
table 2 : jerry 18100334566 2023/5/1 12/30/00
1 1 醋浇羊肉 0 1 2
3 麻婆豆腐 2 2 1
4 麻辣鸡丝 2 3 3
table 3 : lucy 18957348763 2023/5/1 12/30/00
1 醋浇羊肉 2 1 1
3 蜜汁灌藕 1 1 2
2 东坡肉 2 2 1
4 麻辣鸡丝 5 1 1
end
输出样例6:
在这里给出相应的输出。例如:
table 1:
1 醋浇羊肉 30
3 刀削面 30
2 东坡肉 38
4 麻辣鸡丝 15
table 2:
1 table 2 pay for table 1 60
3 麻婆豆腐 18
4 麻辣鸡丝 90
table 3:
1 醋浇羊肉 30
3 蜜汁灌藕 20
2 东坡肉 38
4 麻辣鸡丝 15
table 1: 113 113 川菜 1 稍辣 晋菜 6 微酸 浙菜 1 甜
table 2: 168 118 川菜 4 稍辣
table 3: 103 73 川菜 1 爆辣 晋菜 1 稍酸 浙菜 3 微甜
jerry 18100334566 118
lucy 18957348763 73
tom 13605054400 113
输入样例7:
错误的菜品记录和桌号记录,用户丢弃。例如:
东坡肉 25 T
油淋生菜 9
table 1 : tom 136050540 2023/5/1 12/30/00
2 东坡肉 3 2 1
end
输出样例7:
在这里给出相应的输出。例如:
wrong format
wrong format
2.类图
3.题目分析
相较于上一次增加了一些内容,以下是要写的类的具体分析
-
Main类:包含程序的入口方法main(),负责接收用户输入并处理订单和菜单信息。
-
Dish类:表示菜品的类,包含菜品的名称、单价和口味等信息。
-
Menu类:表示菜单的类,包含菜单上所有菜品的信息,并提供根据菜名查找菜品的方法。
-
Order类:表示订单的类,包含订单上的所有菜品记录,并提供计算订单总价的方法。
-
Record类:表示订单中的一条菜品记录,包含菜品名称、份额、数量等信息,并提供计算价格的方法。
-
Table类:表示餐桌的类,包含餐桌号、客人姓名、联系电话等信息,并管理订单信息,提供计算折扣和口味平均值的方法。
4.源代码
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<Table> tablemes = new ArrayList<>(); List<String> stringList = new ArrayList<>(); Menu menu = new Menu(); Scanner scanner = new Scanner(System.in); Table currentTable = null; while (true) { String input = scanner.nextLine(); if (input.equals("end")) { break; } String[] temp = input.split(" "); if (input.endsWith("delete")) { // 1 delete if (!currentTable.order.delARecordByOrderNum(Integer.parseInt(temp[0]))) { stringList.add("delete error;"); } continue; } if (input.endsWith("T")) { if (temp.length != 4) { stringList.add("wrong format"); continue; } menu.addDish(temp[0], temp[1], Integer.parseInt(temp[2]));//添加新的菜到菜单里面 continue; } if (temp.length == 2) { // 麻婆豆腐 12 menu.addDish(temp[0], "", Integer.parseInt(temp[1]));//添加新的菜到菜单里面 continue; } if (input.startsWith("table")) { if (temp.length != 7) { stringList.add("wrong format"); break; } if (temp[3].length() > 10) { stringList.add("wrong format"); break; } if (!(temp[4].startsWith("180") || temp[4].startsWith("181") || temp[4].startsWith("189") || temp[4].startsWith("133") || temp[4].startsWith("135") || temp[4].startsWith("136"))) { stringList.add("wrong format"); break; } if (temp[4].length() != 11) { stringList.add("wrong format"); break; } currentTable = new Table(temp[1], temp[3], temp[4], temp[5], temp[6]); currentTable.order.menu = menu; currentTable.order.table = currentTable; tablemes.add(currentTable); stringList.add("table " + temp[1] + ": "); continue; } if (temp.length == 4 || temp.length == 5) { String dishName = temp[1]; Dish dish = menu.searthDish(dishName); if (dish == null) { stringList.add(dishName + " does not exist"); continue; } if (temp.length == 4) { currentTable.order.addARecord(Integer.parseInt(temp[0]), dishName, 0, Integer.parseInt(temp[2]), Integer.parseInt(temp[3]), currentTable.name); Record record = currentTable.order.records.get(currentTable.order.records.size() - 1); stringList.add(record.orderNum + " " + dish.name + " " + record.getPrice()); continue; } else { String kind = dish.kind; if (kind.equals("川菜") && (Integer.parseInt(temp[2]) > 5 || Integer.parseInt(temp[2]) < 0)) { stringList.add("spicy num out of range :" + Integer.parseInt(temp[2])); continue; } else if (kind.equals("晋菜") && (Integer.parseInt(temp[2]) > 4 || Integer.parseInt(temp[2]) < 0)) { stringList.add("acidity num out of range :" + Integer.parseInt(temp[2])); continue; } else if (kind.equals("浙菜") && (Integer.parseInt(temp[2]) > 3 || Integer.parseInt(temp[2]) < 0)) { stringList.add("sweetness num out of range :" + Integer.parseInt(temp[2])); continue; } } currentTable.order.addARecord(Integer.parseInt(temp[0]), dishName, Integer.parseInt(temp[2]), Integer.parseInt(temp[3]), Integer.parseInt(temp[4]), currentTable.name); Record record = currentTable.order.records.get(currentTable.order.records.size() - 1); stringList.add(record.orderNum + " " + dish.name + " " + record.getPrice()); continue; } if (temp.length == 6) { String dishName = temp[2]; Dish dish = menu.searthDish(dishName); if (dish == null) { stringList.add(dishName + " does not exist"); continue; } if (Integer.parseInt(temp[0]) > tablemes.size()) { stringList.add(dishName + " does not exist"); continue; } Table table = tablemes.get(Integer.parseInt(temp[0]) - 1); table.order.addARecord(Integer.parseInt(temp[1]), temp[2], Integer.parseInt(temp[3]), Integer.parseInt(temp[4]), Integer.parseInt(temp[5]), currentTable.name); currentTable.order.addOtherARecord(Integer.parseInt(temp[1]), temp[2], Integer.parseInt(temp[3]), Integer.parseInt(temp[4]), Integer.parseInt(temp[5]), currentTable.name); Record record = table.order.records.get(table.order.records.size() - 1); stringList.add(record.orderNum + " table " + currentTable.tableNum + " pay for table " + temp[0] + " " + record.getPrice()); continue; } /*if (temp.length == 7) { String dishName = temp[1]; Dish dish = menu.searthDish(dishName); if (dish == null) { stringList.add(dishName + " does not exist"); continue; } Table table = tablemes.get(Integer.parseInt(temp[0])); table.order.addARecord(Integer.parseInt(temp[1]), temp[2],0, Integer.parseInt(temp[3]), Integer.parseInt(temp[4])); Record record = currentTable.order.records.get(currentTable.order.records.size() - 1); stringList.add(record.orderNum + " " + dish.name + " " + record.getPrice()); }*/ } Map<String, Integer> costMap = new HashMap<>(); List<String> stringList1 = new ArrayList<>(); for (int i = 0; i < tablemes.size(); i++) { if (tablemes.get(i).getDiscount() > 0f) { Table table = tablemes.get(i); String tableText = "table " + table.tableNum + ": " + (table.order.getOrignCommonTotalPrice() + table.order.getOrignSpeicalTotalPrice()) + " " + (table.order.getCommonTotalPrice() + table.order.getSpeicalTotalPrice()); if (table.getHotCount() > 0) { tableText += " 川菜 " + table.getHotCount() + " " + table.getHotText(); } if (table.getAcidCount() > 0) { tableText += " 晋菜 " + table.getAcidCount() + " " + table.getAcidText(); } if (table.getSweetCount() > 0) { tableText += " 浙菜 " + table.getSweetCount() + " " + table.getSweetText(); } stringList.add(tableText); String key = table.name + " " + table.tel; if (costMap.get(key) == null) { costMap.put(key, (table.order.getCommonTotalPrice() + table.order.getSpeicalTotalPrice())); stringList1.add(key); } else { costMap.put(key, costMap.get(key) + (table.order.getCommonTotalPrice() + table.order.getSpeicalTotalPrice())); } } else { stringList.clear(); stringList.add("table " + tablemes.get(i).tableNum + " out of opening hours"); } } stringList1 = stringList1.stream().sorted(String::compareTo).collect(Collectors.toList()); for (String s : stringList1) { stringList.add(s + " " + costMap.get(s)); } for (String s : stringList) { System.out.println(s); } } } class Dish { String name;//菜品名称 int unit_price; //单价 String kind;// 口味 public Dish(String name, String kind, int unit_price) { this.name = name; this.kind = kind; this.unit_price = unit_price; } //计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) int getPrice(int portion) { if (portion == 1) { return unit_price; } if (portion == 2) { return Math.round(this.unit_price * 1.5f); } return unit_price * 2; } } class Menu { // 菜品数组,保存所有菜品信息 List<Dish> dishs = new ArrayList<>(); //根据菜名在菜谱中查找菜品信息,返回Dish对象。 Dish searthDish(String dishName) { for (Dish dish : dishs) { if (dish.name.equals(dishName)) { return dish; } } return null; } //添加一道菜品信息 Dish addDish(String dishName, String taste, int unit_price) { Dish dish = new Dish(dishName, taste, unit_price); Dish existsDish = searthDish(dishName); if (existsDish != null) { dishs.remove(existsDish); } dishs.add(dish); return dish; } } class Order { List<Record> records = new ArrayList();//保存订单上每一道的记录 List<Record> otherRecord = new ArrayList<>(); Menu menu; Table table; int getOrignCommonTotalPrice() { int totalPrice = 0; for (Record record : records) { if ("".equals(record.d.kind) && record.name.equals(table.name)) { totalPrice += record.getPrice(); } } for (Record record : otherRecord) { if ("".equals(record.d.kind) && record.name.equals(table.name)) { totalPrice += record.getPrice(); } } return totalPrice; } //计算订单的总价 int getCommonTotalPrice() { int totalPrice = 0; for (Record record : records) { if ("".equals(record.d.kind) && record.name.equals(table.name)) { totalPrice += Math.round(record.getPrice() * table.getDiscount()); } } for (Record record : otherRecord) { if ("".equals(record.d.kind) && record.name.equals(table.name)) { totalPrice += Math.round(record.getPrice() * table.getDiscount()); } } return totalPrice; } int getOrignSpeicalTotalPrice() { int totalPrice = 0; for (Record record : records) { if (!"".equals(record.d.kind) && record.name.equals(table.name)) { totalPrice += record.getPrice(); } } for (Record record : otherRecord) { if (!"".equals(record.d.kind) && record.name.equals(table.name)) { totalPrice += record.getPrice(); } } return totalPrice; } int getSpeicalTotalPrice() { int totalPrice = 0; for (Record record : records) { if (!"".equals(record.d.kind) && record.name.equals(table.name)) { totalPrice += Math.round(record.getPrice() * table.getSpecialDiscount()); } } for (Record record : otherRecord) { if (!"".equals(record.d.kind) && record.name.equals(table.name)) { totalPrice += Math.round(record.getPrice() * table.getSpecialDiscount()); } } return totalPrice; } /** * 添加一条菜品信息到订单中。 * * @param orderNum * @param dishName * @param tasteLevel * @param portion * @param num * @return */ Record addARecord(int orderNum, String dishName, int tasteLevel, int portion, int num, String name) { Dish dish = menu.searthDish(dishName); if (dish == null) { dish = new Dish(dishName + " does not exist", "", 0); } Record record = new Record(orderNum, dish, tasteLevel, portion, num, name); records.add(record); return record; } Record addOtherARecord(int orderNum, String dishName, int tasteLevel, int portion, int num, String name) { Dish dish = menu.searthDish(dishName); if (dish == null) { dish = new Dish(dishName + " does not exist", "", 0); } Record record = new Record(orderNum, dish, tasteLevel, portion, num, name); otherRecord.add(record); return record; } //根据序号删除一条记录 boolean delARecordByOrderNum(int orderNum) { Record record = findRecordByNum(orderNum); return records.remove(record); } //根据序号查找一条记录 Record findRecordByNum(int orderNum) { for (Record record : records) { if (record.orderNum == orderNum) { return record; } } return null; } } class Record { /** * 序号 */ int orderNum; /** * 菜品 */ Dish d; /** * 份额(1/2/3代表小/中/大份) */ int portion; int tasteLevel; /** * 份数 */ int num; String name; public Record(int orderNum, Dish d, int tasteLevel, int portion, int num, String name) { this.orderNum = orderNum; this.d = d; this.tasteLevel = tasteLevel; this.portion = portion; this.num = num; this.name = name; } /** * 计价,计算本条记录的价格 * * @return */ int getPrice() { return d.getPrice(this.portion) * num; } } class Table { int tableNum; String name; String tel; String tableDate; String tableTime; Order order; String[] hotLevel = new String[]{"不辣", "微辣", "稍辣", "辣", "很辣", "爆辣"}; String[] acidLevel = new String[]{"不酸", "微酸", "稍酸", "酸", "很酸"}; String[] sweetLevel = new String[]{"不甜", "微甜", "稍甜", "甜"}; public Table() { } public Table(String tableNum, String name, String tel, String tableDate, String tableTime) { this.tableNum = Integer.parseInt(tableNum); this.name = name; this.tel = tel; this.tableDate = tableDate; this.tableTime = tableTime; this.order = new Order(); } float getDiscount() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss"); Date dateTime = null; try { dateTime = simpleDateFormat.parse(tableDate + " " + tableTime); } catch (ParseException e) { throw new RuntimeException(e); } Calendar calendar = Calendar.getInstance(); calendar.setTime(dateTime); int week = calendar.get(Calendar.DAY_OF_WEEK); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); float discount = 0f; if (week >= 1 && week <= 5) { if (hour >= 17 && hour < 20) discount = 0.8F; else if (hour == 20 && minute < 30) discount = 0.8F; else if (hour == 20 && minute == 30 && second == 0) discount = 0.8F; else if (hour >= 11 && hour <= 13 || hour == 10 && minute >= 30) discount = 0.6F; else if (hour == 14 && minute < 30) discount = 0.6F; else if (hour == 14 && minute == 30 && second == 0) discount = 0.6F; } else { if (hour >= 10 && hour <= 20) discount = 1.0F; else if (hour == 9 && minute >= 30) discount = 1.0F; else if (hour == 21 && minute < 30 || hour == 21 && minute == 30 && second == 0) discount = 1.0F; } return discount; } float getSpecialDiscount() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss"); Date dateTime = null; try { dateTime = simpleDateFormat.parse(tableDate + " " + tableTime); } catch (ParseException e) { throw new RuntimeException(e); } Calendar calendar = Calendar.getInstance(); calendar.setTime(dateTime); int week = calendar.get(Calendar.DAY_OF_WEEK); float discount = 0f; if (week >= 1 && week <= 5) { discount = 0.7f; } else { discount = 1.0f; } return discount; } int getHotAvg() { int total = 0; int count = 0; for (Record record : this.order.records) { if (record.d.kind.equals("川菜")) { total += (record.tasteLevel * record.num); count += record.num; } } return Math.round((float) total / count); } String getHotText() { int hotAvg = getHotAvg(); return hotLevel[hotAvg]; } int getHotCount() { int count = 0; for (Record record : this.order.records) { if (record.d.kind.equals("川菜")) { count += record.num; } } return count; } int getAcidAvg() { int total = 0; int count = 0; for (Record record : this.order.records) { if (record.d.kind.equals("晋菜")) { total += (record.tasteLevel * record.num); count += record.num; } } return Math.round((float) total / count); } int getAcidCount() { int count = 0; for (Record record : this.order.records) { if (record.d.kind.equals("晋菜")) { count += record.num; } } return count; } String getAcidText() { int acidAvg = getAcidAvg(); return acidLevel[acidAvg]; } int getSweetAvg() { int total = 0; int count = 0; for (Record record : this.order.records) { if (record.d.kind.equals("浙菜")) { total += (record.tasteLevel * record.num); count += record.num; } } return Math.round((float) total / count); } int getSweetCount() { int count = 0; for (Record record : this.order.records) { if (record.d.kind.equals("浙菜")) { count += record.num; } } return count; } String getSweetText() { int sweetAvg = getSweetAvg(); return sweetLevel[sweetAvg]; } }
期中考试题目
创建一个圆形类(Circle),私有属性为圆的半径,从控制台输入圆的半径,输出圆的面积
输入格式:
输入圆的半径,取值范围为(0,+∞)
,输入数据非法,则程序输出Wrong Format
,注意:只考虑从控制台输入数值的情况
输出格式:
输出圆的面积(保留两位小数,可以使用String.format(“%.2f”,输出数值)控制精度)
输入样例:
在这里给出一组输入。例如:
2.35
输出样例:
在这里给出相应的输出。例如:
17.35
2.类图
3.题目分析
题目要求设计一个圆形类,包括私有属性圆的半径和输出圆的面积的方法。输入圆的半径,输出圆的面积。
- 定义一个Circle类,包括私有属性radius和公有方法getArea。
- 在getArea方法中,计算圆的面积,公式为π * radius * radius。
- 在主函数中,从控制台输入圆的半径,创建Circle对象,调用getArea方法计算并输出圆的面积。
4.源代码
import java.util.Scanner; public class Circle { private double radius; public Circle() { this.radius = 0; } public Circle(double radius) { this.radius = radius; } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } public double getArea() { return Math.PI * radius * radius; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); double radius = sc.nextDouble(); if (radius <= 0) { System.out.println("Wrong Format"); } else { Circle circle = new Circle(radius); System.out.println(String.format("%.2f", circle.getArea())); } } }
设计一个矩形类,其属性由矩形左上角坐标点(x1,y1)及右下角坐标点(x2,y2)组成,其中,坐标点属性包括该坐标点的X轴及Y轴的坐标值(实型数),求得该矩形的面积。类设计如下图:
输入格式:
分别输入两个坐标点的坐标值x1,y1,x2,y2。
输出格式:
输出该矩形的面积值(保留两位小数)。
输入样例:
在这里给出一组输入。例如:
6 5.8 -7 8.9
输出样例:
在这里给出相应的输出。例如:
40.30
3.题目分析
根据题目要求定义一个矩形类Rectangle,其中包含了矩形的四个坐标点(x1, y1, x2, y2)和计算矩形面积的方法getArea()。
在主函数中,通过Scanner类从控制台输入四个坐标点的值,并创建一个Rectangle对象。然后调用Rectangle对象的getArea()方法计算矩形的面积,并使用System.out.printf()方法将结果输出到控制台。
4.源代码
import java.util.Scanner; public class Rectangle { private double x1, y1, x2, y2; public Rectangle(double x1, double y1, double x2, double y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } public double getArea() { double width = Math.abs(x2 - x1); double height = Math.abs(y2 - y1); return width * height; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); double x1 = scanner.nextDouble(); double y1 = scanner.nextDouble(); double x2 = scanner.nextDouble(); double y2 = scanner.nextDouble(); Rectangle rectangle = new Rectangle(x1, y1, x2, y2); double area = rectangle.getArea(); System.out.printf("%.2f", area); scanner.close(); } }
将测验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
3.题目分析
根据题目要定义一个抽象类Shape和两个子类Circle和Rectangle,分别表示圆形和矩形。每个子类都实现了抽象方法getArea(),用于计算形状的面积。还要定义一个Point类,用于表示坐标点。Rectangle类使用两个Point对象表示矩形的左上角和右下角坐标。
在Main类的main方法中,用户可以输入1或2来选择要计算面积的形状。如果选择1,用户需要输入圆形的半径,然后创建一个Circle对象并调用printArea方法来打印圆形的面积。如果选择2,用户需要输入矩形的左上角和右下角坐标,然后创建一个Rectangle对象并调用printArea方法来打印矩形的面积。
printArea方法接受一个Shape类型的参数,然后调用该参数的getArea方法来计算面积,并使用printf方法将结果打印出来。
4.源代码
import java.util.Scanner; abstract class Shape { abstract double getArea(); } class Circle extends Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override double getArea() { return Math.PI * radius * radius; } } class Rectangle extends Shape { private Point leftTopPoint; private Point lowerRightPoint; public Rectangle(Point leftTopPoint, Point lowerRightPoint) { this.leftTopPoint = leftTopPoint; this.lowerRightPoint = lowerRightPoint; } @Override double getArea() { double width = Math.abs(leftTopPoint.getX() - lowerRightPoint.getX()); double height = Math.abs(leftTopPoint.getY() - lowerRightPoint.getY()); return width * height; } } class Point { private double x; private double y; public Point(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int choice = input.nextInt(); switch(choice) { case 1://Circle double radius = input.nextDouble(); Shape circle = new Circle(radius); 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; } } public static void printArea(Shape shape) { System.out.printf("%.2f\n", shape.getArea()); } }
在测验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
根据题目要求定义一个Shape类作为所有图形的基类,其中包含了一个抽象方法getArea()用于计算图形的面积。Circle类和Rectangle类分别继承自Shape类,并实现了getArea()方法来计算圆形和矩形的面积。在主函数中,通过使用Scanner类获取用户输入的选择和参数,并根据选择创建相应的图形对象。然后,使用ArrayList存储这些图形对象,并使用Comparator对列表进行排序。最后,通过循环遍历列表,并调用每个图形对象的getArea()方法打印出面积。还要定义一个printArea()方法,用于打印图形的面积。此方法根据图形的类型进行不同的处理,并使用String.format()方法将面积格式化为保留两位小数的字符串。
4.源代码
import java.util.ArrayList; 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 void printArea(Shape shape) { double f = shape.getArea(); if (shape instanceof Circle) { if (f <= 0) System.out.print("Wrong Format"); else { String tmp = String.format("%.2f", f); System.out.print(tmp); } } else { String tmp = String.format("%.2f", f); System.out.print(tmp); } } } class Point { Point(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } double x, y; } class Shape implements Comparable<Shape> { public Shape() { } public double getArea() { return 0; } public int compareTo(Shape shape) { double s1, s2; s1 = getArea(); s2 = shape.getArea(); if (s1 > s2) return 1; else if (s1 < s2) return -1; return 0; } } class Circle extends Shape { double radius; Circle(double r) { radius = r; } public double getArea() { return (double) (Math.PI * radius * radius); } } class Rectangle extends Shape { public Rectangle(Point topLeftPoint, Point lowerRightPoint) { super(); this.topLeftPoint = topLeftPoint; this.lowerRightPoint = lowerRightPoint; } public Point getTopLeftPoint() { return topLeftPoint; } public void setTopLeftPoint(Point topLeftPoint) { this.topLeftPoint = topLeftPoint; } public Point getLowerRightPoint() { return lowerRightPoint; } public void setLowerRightPoint(Point lowerRightPoint) { this.lowerRightPoint = lowerRightPoint; } Point topLeftPoint; Point lowerRightPoint; double getLength() { return Math.abs(topLeftPoint.x - lowerRightPoint.x); } double getHeight() { return Math.abs(topLeftPoint.y - lowerRightPoint.y); } public double getArea() { return getLength() * getHeight(); } }
(3)采坑心得:
对与数据精度度处理,比如题目限制float,但使用double会超出范围。