PTA题目集4、5以及期中考试的总结性Blog

发布时间 2023-06-30 22:39:34作者: 5926

第4、5次大作业只有一题菜单的迭代,虽然题目量不多,但是难度却是大大增加,更加考验大家的学习自觉性和Java的功底,这两次的大作业均是在菜单系列-3的基础上迭代,是菜单系列-3的两个不同分支。自然而然,与菜单系列-3的代码结构的完整性和可复用性等关联就很大,菜单系列-3设计的好可以为后续的这两个迭代分支大大减少麻烦,节约时间、降低难度,期中考试的题目集难度相对来说就小了许多。

三次题目集的总结:

第4次题目集有1道题,题量少但难度高,主要难度在于对正则表达式的更改,要多次调试正则表达式才能达到目的。除此之外,还要改一些其他的部分;

第5次题目集有1道题,主要考的内容就是对类的使用,运用正则表达式,数组列表,对数组列表的接口类Comparable,还有对字符串的分割,对字符串的部分截取,对输入的数据的解析,比较字符串,控制输出的格式等等;

期中考试题目集有4道题,题量较少且难度中等,题量少但难度高,主要就是考了对类的使用,和不同类间的相互配合使用,还有对于一个程序的不断循环使用。

二、设计与分析

第4次题目集

菜单计价程序-4

设计点菜计价程序,根据输入的信息,计算并输出总价格。

输入内容按先后顺序包括两部分:菜单、订单,最后以"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+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价

代码如下:

import java.util.Scanner;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;

public class Main {
public static void main(String[] args) {

Main main = new Main();
Scanner scanner = new Scanner(System.in);
ArrayList<String> messageList = new ArrayList<String>();
ArrayList<String> arrayList = new ArrayList<String>();
ArrayList<Table> tArrayList = new ArrayList<Main.Table>();
String string = "";

while (true) {
string = scanner.nextLine();
if ("end".equals(string)) {
break;
}
arrayList.add(string);
}
Menu menu = main.new Menu();
menu.dishs = new Dish[0];
int n = 0;
for (int i = 0; i < arrayList.size(); i++) {
String[] strings = arrayList.get(i).split(" ");
if (strings.length==0) {
messageList.add("wrong format");
break;
}
if (strings.length > 3&&strings[0].charAt(0)=='t') {
n = i;
break;
}else if(strings.length > 3){
messageList.add("wrong format");
continue;
}
String dName = strings[0];
String dPrice = strings[1];
if (dPrice.charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
int hp = 0;
try {
hp = Integer.parseInt(dPrice);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (hp >= 300 || hp <= 0) {
messageList.add(dName + " price out of range "+hp);
continue;
}
if (menu.searthDish(dName) != null) {
for (int j = 0; j < menu.dishs.length; j++) {
if (menu.dishs[j].equals(dName)) {
menu.dishs[j].unit_price = hp;
}
}
} else {
Dish dish = main.new Dish();
if (strings.length == 2) {
dish.name = dName;
dish.unit_price = hp;
} else if (strings.length == 3) {
dish.name = dName;
dish.unit_price = hp;
dish.isT = true;
}
menu.addDish(dish);
}
}
ArrayList<Integer> arrayLista = new ArrayList<Integer>();// 桌号开始下标
for (int i = n; i < arrayList.size(); i++) {
if (arrayList.get(i).split(" ")[0].length() > 2 && arrayList.get(i).split(" ")[0].charAt(0) == 't') {
arrayLista.add(i);
}
}

for (int i = 0; i < arrayLista.size(); i++) {
Table table = main.new Table();
Order order = main.new Order();
order.records = new Record[0];
table.order = order;
int t1 = arrayLista.get(i);
String[] strings = arrayList.get(t1).split(" ");
if (strings.length==0) {
messageList.add("wrong format");
continue;
}
if (strings[0].equals("table")) {
if (strings[1].charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
int tNum = 0;
try {
tNum = Integer.parseInt(strings[1]);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (tNum > 55 && tNum <= 0) {
messageList.add(tNum + " num out of range");
continue;
}
if (strings[2].split("/")[0].length() != 4) {// year
messageList.add("wrong format");
continue;
}
if (strings[2].split("/")[1].length() > 2 || strings[2].split("/")[1].length() < 1) {// month
messageList.add("wrong format");
continue;
}
if (strings[2].split("/")[2].length() > 2 || strings[2].split("/")[2].length() < 1) {// day
messageList.add("wrong format");
continue;
}
if (strings[3].split("/")[0].length() > 2 || strings[3].split("/")[0].length() < 1) {// hour
messageList.add("wrong format");
continue;
}
if (strings[3].split("/")[1].length() > 2 || strings[3].split("/")[1].length() < 1) {// minute
messageList.add("wrong format");
continue;
}
if (strings[3].split("/")[2].length() > 2 || strings[3].split("/")[2].length() < 1) {// moment
messageList.add("wrong format");
continue;
}
DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss");
sdf.setLenient(false);
Date date = null;
try {
date = sdf.parse(strings[2] + " " + strings[3]);
} catch (ParseException e) {
messageList.add(tNum + " date error");
continue;
}
table.date = date;
table.tableNum = tNum;
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd");
SimpleDateFormat sdf2 = new SimpleDateFormat("HH/mm/ss");
Date date1 = null;
Date date2 = null;
try {
date1 = sdf1.parse("2022/1/1");
date2 = sdf1.parse("2023/12/31");
if (date1.compareTo(sdf1.parse(strings[2])) > 0 || date2.compareTo(sdf1.parse(strings[2])) < 0) {
messageList.add("not a valid time period");
continue;
}
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int dayNum = calendar.get(Calendar.DAY_OF_WEEK) - 1;
Date bdate = null;
Date edate = null;
Date bdate1 = null;
Date edate1 = null;
Date bdate2 = null;
Date edate2 = null;
Date nowDate = null;
try {
bdate = sdf2.parse("9/29/59");
edate = sdf2.parse("21/30/00");
bdate1 = sdf2.parse("10/30/00");
edate1 = sdf2.parse("14/30/00");
bdate2 = sdf2.parse("16/59/59");
edate2 = sdf2.parse("20/30/00");
nowDate = sdf2.parse(strings[3]);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (dayNum == 6 || dayNum == 0) {// 周末
if (timeCalendar(nowDate, bdate, edate)) {// 全价
table.dicount = 1.0;
} else {
messageList.add("table " + tNum + " out of opening hours");
continue;
}
} else {// 工作日
if (timeCalendar(nowDate, bdate1, edate1)) {// 6折
table.dicount = 0.6;
} else if (timeCalendar(nowDate, bdate2, edate2)) {// 8折
table.dicount = 0.8;
} else {
messageList.add("table " + tNum + " out of opening hours");
continue;
}
}
messageList.add("table"+" "+tNum + ": ");
if (t1 == arrayList.size()-1) {
} else {
int fNum;
if (arrayLista.get(arrayLista.size()-1) == t1) {
fNum = arrayList.size();
} else {
fNum = arrayLista.get(i + 1);
}
ArrayList<Integer> delNumArrayList = new ArrayList<Integer>();
int numb = 0;
for (int j = t1 + 1; j < fNum; j++) {// 点菜记录
String[] strings2 = arrayList.get(j).split(" ");
if (strings2.length==0) {
messageList.add("wrong format");
continue;
}
int Num1;
try {
Num1 = Integer.parseInt(strings2[0]);
} catch (Exception e) {
messageList.add("invalid dish");
continue;
}
if (strings2[0].charAt(0)=='0') {
messageList.add("wrong format");
continue;
}
if (strings2.length == 5) {// 代点菜
boolean flag = false;

if (tArrayList.get(0).tableNum == Num1)
flag = true;
if (flag) {
messageList.add("Table number :" + Num1 + " does not exist");
continue;
}
if (strings2[3].length() > 1) {
messageList.add("wrong format");
continue;
} else {
String dishName = strings2[2];// 菜名
int dishP;
int dishN;
if (strings2[4].charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
try {
dishP = Integer.parseInt(strings2[3]);
dishN = Integer.parseInt(strings2[4]);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (menu.searthDish(dishName) == null) {
messageList.add(dishName + " does not exist");
continue;
}
Dish dish = menu.searthDish(dishName);
if (dish.isT) {
if (dishP != 1 && dishP != 3&& dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
} else {
if (dishP != 1 && dishP != 3 && dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
}
if (dishN > 15 || dishN < 1) {
messageList.add(Num1 + " num out of range " + dishN);
continue;
}
boolean f1 = true;
if (f1) {
table.order.addARecord(Num1, dish, dishP, dishN);
}
}
} else if (strings2.length == 2) {
if (!strings2[1].equals("delete")) {
messageList.add("wrong format");
continue;
} else {
boolean flag = false;
for (Integer n2 : delNumArrayList) {
if (n2 == Num1) {
flag = true;
}
}
if (flag) {
messageList.add("deduplication " + Num1);
continue;
}
if (table.order.findRecordByNum(Num1) == -1) {
messageList.add("delete error");
continue;
}
table.order.delARecordByOrderNum(Num1);
delNumArrayList.add(Num1);
}
} else if (strings2.length == 4) {
if (strings2[2].length() > 1) {
messageList.add("wrong format");
continue;
} else {
String dishName = strings2[1];// 菜名
int dishP;
int dishN;
if (strings2[3].charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
try {
dishP = Integer.parseInt(strings2[2]);
dishN = Integer.parseInt(strings2[3]);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (Num1 <= numb) {
messageList.add("record serial number sequence error");
continue;
}
if (menu.searthDish(dishName) == null) {
messageList.add(dishName + " does not exist");
continue;
}
Dish dish = menu.searthDish(dishName);
if (dish.isT) {
if (dishP != 1 && dishP != 3&& dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
} else {
if (dishP != 1 && dishP != 3 && dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
}
if (dishN > 15 || dishN < 1) {
messageList.add(Num1 + " num out of range " + dishN);
continue;
}
numb = Num1;
boolean f1 = true;
for (int k = 0; k < table.order.records.length; k++) {
if (table.order.records[k].d.name.equals(dishName)
&& table.order.records[k].portion == dishP) {
table.order.records[k].num = table.order.records[k].num + dishN;
f1 = false;
}
}
if (f1) {
table.order.addARecord(Num1, dish, dishP, dishN);
messageList.add(Num1 + " " + dishName + " " + dish.getPrice(dishP) * dishN);
}
}
} else {
messageList.add("wrong format");
continue;
}
}
}
} else {
messageList.add("wrong format");
if (t1 == arrayList.size()-1) {
} else {
int fNum;
if (arrayLista.get(arrayLista.size() - 1) == t1) {
fNum = arrayList.size();
} else {
fNum = arrayLista.get(i + 1)+1;
}
Table table2 = tArrayList.get(tArrayList.size()-1);
ArrayList<Integer> delNumArrayList = new ArrayList<Integer>();
int numb = table2.order.records[table2.order.records.length-1].orderNum;

for (int j = t1 + 1; j < fNum; j++) {// 点菜记录
String[] strings2 = arrayList.get(j).split(" ");
if (strings2.length==0) {
messageList.add("wrong format");
continue;
}
int Num1;
try {
Num1 = Integer.parseInt(strings2[0]);
} catch (Exception e) {
messageList.add("invalid dish");
continue;
}
if (strings2[0].charAt(0)=='0') {
messageList.add("wrong format");
continue;
}
if (strings2.length == 5) {// 代点菜
boolean flag = true;
for (int k = 0; k < tArrayList.size(); k++) {

if (tArrayList.get(k).tableNum == Num1) {
flag = false;
}
}
if (flag) {
messageList.add("Table number :" + Num1 + " does not exist");
continue;
}
if (strings2[3].length() > 1) {
messageList.add("wrong format");
continue;
} else {
String dishName = strings2[2];// 菜名
int dishP;
int dishN;
if (strings2[4].charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
try {
dishP = Integer.parseInt(strings2[3]);
dishN = Integer.parseInt(strings2[4]);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (menu.searthDish(dishName) == null) {
messageList.add(dishName + " does not exist");
continue;
}
Dish dish = menu.searthDish(dishName);
if (dish.isT) {
if (dishP != 1 && dishP != 3) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
} else {
if (dishP != 1 && dishP != 3 && dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
}
if (dishN > 15 || dishN < 1) {
messageList.add(Num1 + " num out of range " + dishN);
continue;
}
boolean f1 = true;
if (f1) {
table2.order.addARecord(Num1, dish, dishP, dishN);
}
}
} else if (strings2.length == 2) {
if (!strings2[1].equals("delete")) {
messageList.add("wrong format");
continue;
} else {
boolean flag = false;
for (Integer n2 : delNumArrayList) {
if (n2 == Num1) {
flag = true;
}
}
if (flag) {
messageList.add("deduplication " + Num1);
continue;
}
if (table2.order.findRecordByNum(Num1) == -1) {
messageList.add("delete error");
continue;
}
table2.order.delARecordByOrderNum(Num1);
delNumArrayList.add(Num1);
}
} else if (strings2.length == 4) {
if (strings2[2].length() > 1) {
messageList.add("wrong format");
continue;
} else {
String dishName = strings2[1];// 菜名
int dishP;
int dishN;
if (strings2[3].charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
try {
dishP = Integer.parseInt(strings2[2]);
dishN = Integer.parseInt(strings2[3]);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (Num1 <= numb) {
messageList.add("record serial number sequence error");
continue;
}
if (menu.searthDish(dishName) == null) {
messageList.add(dishName + " does not exist");
continue;
}
Dish dish = menu.searthDish(dishName);
if (dish.isT) {
if (dishP != 1 && dishP != 3) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
} else {
if (dishP != 1 && dishP != 3 && dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
}
if (dishN > 15 || dishN < 1) {
messageList.add(Num1 + " num out of range " + dishN);
continue;
}
numb = Num1;
boolean f1 = true;
for (int k = 0; k < table2.order.records.length; k++) {
if (table2.order.records[k].d.name.equals(dishName)
&& table2.order.records[k].portion == dishP) {
table2.order.records[k].num = table2.order.records[k].num + dishN;
f1 = false;
}
}
if (f1) {
table2.order.addARecord(Num1, dish, dishP, dishN);
messageList.add(Num1 + " " dishNam+" " + dish.getPrice(dishP) *dishN);
}
}
} else {
messageList.add("wrong format");
continue;
}
}
}
}
if (table.tableNum!=0) {
tArrayList.add(table);
}
}
for (int j = 0; j < messageList.size(); j++) {
System.out.println(messageList.get(j));
}
for (int j = 0; j < tArrayList.size()-1; j++) {
if (tArrayList.get(0).tableNum<tArrayList.get(1).tableNum) {
Table table = main.new Table();
table = tArrayList.get(1);
tArrayList.set(1, tArrayList.get(0));
tArrayList.set(0, table);
}
}
for (int j = 0; j < tArrayList.size(); j++) {
int tableNum = tArrayList.get(j).tableNum;
Order order =tArrayList.get(j).order;
int sum = 0;
int sumP = 0;
for (int i = 0; i < order.records.length; i++) {
Record record = order.records[i];
if (record.d.isT&&tArrayList.get(j).dicount!=1.0) {
sum +=(int)Math.round(record.getPrice());
sumP +=(int)Math.round(record.getPrice()*0.7);
}else {
sum +=record.getPrice();
sumP +=(int)Math.round(record.getPrice()*tArrayList.get(j).dicount);
}
}
if (j==tArrayList.size()-1) {
System.out.print("table"+" "+tableNum+":"+" "+sum+" "+sumP);
}else {
System.out.println("table"+" "+tableNum+":"+" "+sum+" "+sumP);
}
}
}

// 菜品类
class Dish {
String name;// 菜品名称
int unit_price; // 单价
boolean isT = false;

int getPrice(int portion) {// 计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
double money = 0;
switch (portion) {
case 1:// 小份
money = this.unit_price * 1.0;
break;
case 2:// 中份
money = 1.5 * this.unit_price;
break;
case 3:// 大份
money = this.unit_price * 2.0;
break;
}
return (int) Math.round(money);
}
}

// 菜谱类:对应菜谱,包含饭店提供的所有菜的信息
class Menu {

Dish[] dishs;// 菜品数组,保存所有菜品信息

Dish searthDish(String dishName) {
for (int i = 0; i < dishs.length; i++) {
if (dishs[i].name.equals(dishName)) {
return dishs[i];
}
}
return null;
}

Dish addDish(Dish dish) {// 添加一道菜品信息
Dish[] dishs1 = new Dish[dishs.length + 1];

for (int i = 0; i < dishs.length; i++) {
dishs1[i] = dishs[i];
}
dishs1[dishs.length] = dish;
dishs = dishs1;
return dish;
}
}

// 点菜记录类:保存订单上的一道菜品记录
class Record {

int orderNum;// 序号
Dish d;// 菜品
int portion;// 份额(1/2/3代表小/中/大份)
int num;// 份数

int getPrice() {// 计价,计算本条记录的价格
return (int) Math.round(this.d.getPrice(this.portion) * num);
}

}

// 订单类:保存用户点的所有菜的信息
class Order {
Record[] records;// 保存订单上每一道的记录

int getTotalPrice() {// 计算订单的总价
int sum = 0;
for (int i = 0; i < records.length; i++) {
sum += records[i].getPrice();
}
return sum;
}

// 添加一条菜品信息到订单中
Record addARecord(int orderNum, Dish dish, int portion, int num) {

Record record = new Record();
record.orderNum = orderNum;
record.d = dish;
record.portion = portion;
record.num = num;
Record[] records1 = new Record[this.records.length + 1];
for (int i = 0; i < this.records.length; i++) {
records1[i] = this.records[i];
}
records1[this.records.length] = record;
this.records = records1;
return record;
}

// 根据序号删除一条记录
void delARecordByOrderNum(int orderNum) {
int n = this.findRecordByNum(orderNum);
Record[] records1 = new Record[this.records.length - 1];
for (int i = 0; i < this.records.length; i++) {
if (i == n) {
continue;
}
if (i > n) {
records1[i] = this.records[i - 1];
} else {
records1[i] = this.records[i];
}
}
this.records = records1;
}

// 根据序号查找一条记录
int findRecordByNum(int orderNum) {
int n = -1;
for (int i = 0; i < this.records.length; i++) {
if (this.records[i].orderNum == orderNum) {
n = i;
}
}
return n;
}
}

class Table {
int tableNum;
Order order;
Date date;
double dicount = 0;
}

public static boolean timeCalendar(Date nowTime, Date beginTime, Date endTime) {
Calendar date = Calendar.getInstance();// 设置当前时间
date.setTime(nowTime);
Calendar begin = Calendar.getInstance();// 设置开始时间
begin.setTime(beginTime);// 开始时间
Calendar end = Calendar.getInstance();// 设置结束时间
end.setTime(endTime);// 上午结束时间
if ((date.after(begin) && date.before(end))) {// 判断是否处于开始时间之后和结束时间之前
return true;
} else {
return false;
}
}
}

 这道题在菜单计价程序-3的基础上增加了特色菜的处理以及大量异常输入的处理,增加的异常大多其实在菜单计价程序-3也可以出现,只是没有测试点而已。两者的思路都一样,将主函数分为两部分,一部分是菜单,另一部分是点菜。这次题目主要就是算对正则表达式的更改,要不断去调试。

第5次题目集

 菜单计价程序-5

设计点菜计价程序,根据输入的信息,计算并输出总价格。

输入内容按先后顺序包括两部分:菜单、订单,最后以"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+英文空格+桌号+“:”+英文空格+当前桌的计算折扣后总价+英文空格+辣度平均值+英文空格+酸度平均值+英文空格+甜度平均值+英文空格

最后按拼音顺序输出每位客户(不考虑客户同名或拼音相同的情况)的支付金额,格式: 用户姓名+英文空格+手机号+英文空格+支付总金额,按输入顺序排列。

代码如下:

import java.util.Arrays;
import java.util.Scanner;
import java.util.regex.Pattern;public class Mainstatic CmdProcess cmdPro = new CmdProcess();

static View view = new View();
static boolean isLocked = false;
public static void main(String[] args){
String command = "";
do{
command = view.input();
cmdProcess(command);
}while(!command.equals("end"));
return;
}
/**
* 处理单个指令
* 分发至cmdPro
* @param command
*/
public static void cmdProcess(String command) {
//分割指令
String[] values = command.split(" ");
int commandId = cmdSort(command);
if(isLocked && !(commandId == 2 || commandId == 0)) return;
//以下为情况分辨不同类型指令
switch(commandId) {
//结束
case 0:{
cmdPro.end();
}break;
/*
* 输入菜谱
*/
case 1:{
String dishName = values[0];//菜名
int unitPrice = Integer.parseInt(values[1]);//价格
cmdPro.inputMenu(dishName, unitPrice, 0);
}break;
/*
* 输入桌号
*/
case 2:{
// String pattern = "^table [1-9]\\d* \\d{4}/\\d{1,2}/\\d{1,2} \\d{1,2}/\\d{1,2}/\\d{1,2}$";
// if(!Pattern.matches(pattern, command)) {
// view.wrongFormat();
// isLocked = true;
// break;
// }
int tableID = Integer.parseInt(values[1]);//桌号
String orderName = values[3];
String orderTel = values[4];
String date = values[5];//日期
String time = values[6];//时间
isLocked = !cmdPro.addTable(tableID, date, time, orderName, orderTel);
}break;
/*
* 输入点菜信息
* 点菜记录 序号 菜名 份额 份数
*/
case 3:{
int orderNum = Integer.parseInt(values[0]);//序号
String dishName = values[1];//菜名
int portion= Integer.parseInt(values[2]);//份额
int num= Integer.parseInt(values[3]);//份数
//cmdPro.orderDish(command);
cmdPro.orderDish(orderNum, dishName, portion, num);
}break;
/*
* 输入删除信息
*/
case 4:{
int orderNum = Integer.parseInt(values[0]);//序号
cmdPro.deleteDish(orderNum);
}break;
/*
* 输入代点信息
*/
case 5:{
int profitTableNum = Integer.parseInt(values[0]);
int orderNum = Integer.parseInt(values[1]);//序号
String dishName = values[2];//菜名
int portion= Integer.parseInt(values[3]);//份额
int num= Integer.parseInt(values[4]);
cmdPro.orderOthers(profitTableNum, orderNum, dishName, portion, num);
}break;
/*
* 输入特色菜
*/
case 6:{
//菜名
String dishName = values[0];
//菜系
int tStyle = 0;
String styleStr = values[1];
if(styleStr.equals("川菜")) tStyle = 1;
else if(styleStr.equals("晋菜")) tStyle = 2;
else if(styleStr.equals("浙菜")) tStyle = 3;
else {
cmdPro.unknowCmd();
break;
}
//价格
int unitPrice = Integer.parseInt(values[2]);
cmdPro.inputMenu(dishName, unitPrice, tStyle);
}break;
/*
* 点特色菜
*/
case 7:{
int orderNum = Integer.parseInt(values[0]);//序号
String dishName = values[1];//菜名
int tasteLevel = Integer.parseInt(values[2]);
int portion= Integer.parseInt(values[3]);//份额
int num= Integer.parseInt(values[4]);//份数
//cmdPro.orderDish(command);
cmdPro.orderDish(orderNum, dishName, portion, num, tasteLevel);
}break;
/*
* 代点特色菜
*/
case 8:{
int profitTableNum = Integer.parseInt(values[0]);
int orderNum = Integer.parseInt(values[1]);//序号
String dishName = values[2];//菜名
int tasteLevel = Integer.parseInt(values[3]);
int portion= Integer.parseInt(values[4]);//份额
int num= Integer.parseInt(values[5]);
cmdPro.orderOthers(profitTableNum, orderNum, dishName, portion, num, tasteLevel);
}break;
default: cmdPro.unknowCmd();
}
}
/**
* 指令分类
* 用来分析这一行指令是用来干嘛的
* @param command 一行指令
* @return
* 0-结束
* 1-输入菜谱
* 2-输入桌号
* 3-输入点菜信息
* 4-输入删除信息
* 5-输入代点信息
* 6-特色菜菜谱
* 7-点特色菜
* 8-代点特色菜
*/
public static int cmdSort(String command) {
String[] patterns = {
"^end$",//0
"^\\S+ [1-9]\\d*$",//1
"^table [1-9]\\d* : \\S{1,10} (180|181|189|133|135|136)\\d{8} \\d{4}/\\d{1,2}/\\d{1,2} \\d{1,2}/\\d{1,2}/\\d{1,2}$",//2
"^[1-9]\\d* \\S+ \\d [1-9]\\d*$",//3
"^[1-9]\\d* delete$",//4
"^[1-9]\\d* [1-9]\\d* \\S+ \\d [1-9]\\d*$",//5
"^\\S+ \\S+ [1-9]\\d* T$",//6
"^[1-9]\\d* \\S+ \\d \\d [1-9]\\d*$",//7
"^[1-9]\\d* [1-9]\\d* \\S+ \\d \\d [1-9]\\d*$",//8
};
for(int i = 0; i < patterns.length; i++) {
if(Pattern.matches(patterns[i], command)) return i;
}
return -1;
}
}

/**
* 指令处理类
*/
class CmdProcess{
private View view = new View();
private Menu menu = Menu.getMenu();
private Order[] orders = new Order[0];
private Order currentOrder;
private Table[] tables = new Table[0];
private Table currentTable;
private int[] deletedNums = new int[0];
/**
*
*/
public void end() {
for(Table table : this.tables) {
int id = table.getId();
int price = table.getPrice();
int discountedPrice = table.getDiscountedPrice();
int[] pepperyLevel = table.getPepperyLevel();
int[] acidLevel = table.getAcidLevel();
int[] sweetLevel = table.getSweetLevel();
this.view.outputPrice(id, price, discountedPrice, pepperyLevel, acidLevel, sweetLevel);
}

Arrays.sort(this.orders);

for(Order order : this.orders) {
String name = order.getName();
String tel = order.getTel();
int price = order.getPrice();
this.view.outputOrderPrice(name, tel, price);
}
}
/**
* 菜单输入
* 菜名 基础价格
* @param dishName 菜名
* @param unitPrice 单位价格
*/
public void inputMenu(String dishName, int unitPrice, int tStyle) {
//菜谱信息与订单信息混合
if(this.orders.length > 0) {
this.view.invalidDish();
return;
}
//超出范围
if(unitPrice <= 0 || unitPrice >= 300) {
this.view.priceOut(dishName, unitPrice);
return;
}
this.menu.addDish(dishName, unitPrice, tStyle);
}
/**
* 桌号标识
* TODO 桌号的查重等
* @param id
* @param date
* @param time
*/
public boolean addTable(int id, String date, String time, String orderName, String orderTel) {
this.currentOrder = null;
//桌号超出范围
if(id < 1 || id > 55) {
this.view.tableIdOut(id);
return false;
}
//添加新点菜实例
Table newTable = new Table(id, date, time, this.currentOrder);
//时间非法
if(!newTable.getDate().checkInputValidityIgnoreYear() ||
!newTable.getTime().check()) {
this.view.dateErr(id);
return false;
}
//时间超出范围
if(!newTable.isValidTime()) {
this.view.dateOut();
return false;
}
//不在营业时间
if(!newTable.isInOpeningTime()) {
this.view.closingHour(id);
return false;
}
for(Order order : this.orders) {
if(order.getName().equals(orderName) &&
order.getTel().equals(orderTel)) {
this.currentOrder = order;
break;
}
}
if(this.currentOrder == null) {
Order[] newOrders = new Order[this.orders.length + 1];
for(int i = 0; i < this.orders.length; i++) {
newOrders[i] = this.orders[i];
}
this.currentOrder = new Order(orderName, orderTel);
newOrders[this.orders.length] = this.currentOrder;
this.orders = newOrders;
}
//查找相同桌号
for(Table table : this.tables) {
if(table.getId() == id) {
if(table.isInTheSameTime(newTable)) {
this.currentTable = table;
this.view.outputTable(id);
return true;
}
break;
}
}
Table[] newTables = new Table[this.tables.length + 1];
for(int i = 0; i < this.tables.length; i++){
newTables[i] = this.tables[i];
}
newTables[this.tables.length] = newTable;
this.tables = newTables;
this.currentTable = newTable;
this.view.outputTable(id);
this.currentOrder.chooseTable(newTable);
return true;
}
/**
*
* @param command
*/
public void orderDish(String command) {
if(this.currentOrder == null) return;
if(!Pattern.matches("^[1-9]\\d* \\S+ \\d [1-9]\\d*$", command)) {
this.view.wrongFormat();
return;
}
String[] values = command.split(" ");

int orderNum = Integer.parseInt(values[0]);//序号
String dishName = values[1];//菜名
int portion= Integer.parseInt(values[2]);//份额
int num= Integer.parseInt(values[3]);//份数
this.orderDish(orderNum, dishName, portion, num);
}
/**
* 点菜
* @param index
* @param dishName
* @param portion
* @param num
*/
public void orderDish(int orderId, String dishName, int portion, int num) {
this.orderDish(orderId, dishName, portion, num, -1);
}
/**
* 点菜
* @param index
* @param dishName
* @param portion
* @param num
*/
public void orderDish(int orderId, String dishName, int portion, int num, int tasteLevel) {
if(this.currentOrder == null) return;
//菜名不存在
if(this.menu.searchDish(dishName) == null){
this.view.notTheDish(dishName);
return;
}
//份额超出范围
if(!this.menu.searchDish(dishName).hasPortion(portion)) {
this.view.portionOut(orderId, portion);
return;
}
//份数超出范围
// if(num > 15 || num < 1) {
// this.view.numOut(orderId, num);
// return;
// }
//不是从小到大
// if(this.currentTable.getMaxOrderId() >= orderId) {
// this.view.seqErr();
// return;
// }
Dish dish = Menu.getMenu().searchDish(dishName);
if(dish instanceof TDish) {
if(tasteLevel > 6 - ((TDish)dish).getSytle()) {
this.view.tasteLevelOut(tasteLevel, ((TDish)dish).getSytle());
return;
}
}
Record record = this.currentTable.addARecord(orderId, dishName, portion, num, tasteLevel);
this.view.outputRecord(record);
}
/**
* 删除所点菜品
* @param orderNum
*/
public void deleteDish(int orderNum) {
//判断是否有重复
for(int deletedNum : this.deletedNums) {
if(deletedNum == orderNum) {
this.view.dedu(orderNum);
return;
}
}
//记录已删除序号
int length = this.deletedNums.length;
int[] newDeleteNums = new int[length + 1];
for(int i = 0; i < length; i++) {
newDeleteNums[i] = this.deletedNums[i];
}
newDeleteNums[length] = orderNum;
this.deletedNums = newDeleteNums;
if(this.currentTable.findRecordByNum(orderNum) == null){
this.view.deleteErr();
return;
}
this.currentTable.delARecordByOrderNum(orderNum);
}

/**
* 代点菜
* @param othersId
* @param orderNum
* @param dishName
* @param portion
* @param num
*/
public void orderOthers(int othersId, int orderNum, String dishName, int portion, int num) {
this.orderOthers(othersId, orderNum, dishName, portion, num, -1);
}
/**
* 代点菜
* @param othersId
* @param orderNum
* @param dishName
* @param portion
* @param num
*/
public void orderOthers(int othersId, int orderNum, String dishName, int portion, int num, int tasteLevel) {
Table otherTable = null;
for(Table table : this.tables) {
if(table.getId() == othersId) {
otherTable = table;
break;
}
}
if(otherTable == null) {
this.view.notTheTable(othersId);
return;
}
//TODO
Record record = this.currentTable.addAGiveRecord(orderNum, dishName, portion, num, otherTable, tasteLevel);
this.view.payForOthers(orderNum, this.currentTable.getId(), othersId, record.getDiscountedPrice());
// Order profitTableOrder = this.orders[othersId];
// if(menu.searchDish(dishName) == null){
// System.out.println(dishName + " does not exist");
// continue;
// }
//
// if(this.currentOrder.getTotalPrice() == -1){
// continue;
// }
// Record record =this.currentOrder.addAGiveRecord(orderNum, dishName, portion, num, profitTableOrder);
//
// System.out.printf("%d table %d pay for table %d %d\n", orderNum, tableID, profitTableNum, record.getPrice());
//
}
public void unknowCmd() {
this.view.wrongFormat();
}
}

/**
* 界面
*/
class View{
private Scanner input = new Scanner(System.in);
public String input() {
return this.input.nextLine();
}
/**
*
* @param id
*/
public void outputTable(int id) {
System.out.println("table " + id + ": ");
}
public void outputRecord(Record record) {
System.out.printf("%d %s %d\n", record.getOredrId(), record.getDish().getName(),
record.getPrice());
}
public void outputPrice(int id, int price, int discountedPrice, int[] peppery, int[] acid, int[] sweet) {
System.out.print("table " + id + ": " + price + " " + discountedPrice);
if(peppery[0] != 0) {
System.out.print(" 川菜 " + peppery[0]);
switch(peppery[1]) {
case 0: System.out.print(" 不辣"); break;
case 1: System.out.print(" 微辣"); break;
case 2: System.out.print(" 稍辣"); break;
case 3: System.out.print(" 辣"); break;
case 4: System.out.print(" 很辣"); break;
case 5: System.out.print(" 爆辣"); break;
}
}
if(acid[0] != 0) {
System.out.print(" 晋菜 " + acid[0]);
switch(acid[1]) {
case 0: System.out.print(" 不酸"); break;
case 1: System.out.print(" 微酸"); break;
case 2: System.out.print(" 稍酸"); break;
case 3: System.out.print(" 酸"); break;
case 4: System.out.print(" 很酸"); break;
}
}
if(sweet[0] != 0) {
System.out.print(" 浙菜 " + sweet[0]);
switch(sweet[1]) {
case 0: System.out.print(" 不甜"); break;
case 1: System.out.print(" 微甜"); break;
case 2: System.out.print(" 稍甜"); break;
case 3: System.out.print(" 甜"); break;
}
}
System.out.println("");
}
public void outputOrderPrice(String name, String tel, int price) {
System.out.println(name + " " + tel + " " + price);
}
public void payForOthers(int id, int idFrom, int idTo, int price) {
System.out.println(id + " table " + idFrom + " pay for table " + idTo + " " + price);
}
/**
*
*/
public void deleteErr() {
System.out.println("delete error");
}
/**
*
* @param id
*/
public void closingHour(int id) {
System.out.println("table " + id + " out of opening hours");
}
/**
*
*/
public void invalidDish() {
System.out.println("invalid dish");
}
/**
*
*/
public void dateErr(int id) {
System.out.println(id + " date error");
}
/**
*
* @param index
*/
public void dedu(int index) {
System.out.println("deduplication " + index);
}
/**
*
* @param id
*/
public void notTheTable(int id) {
System.out.println("Table number :" + id + " does not exist");
}
/**
*
* @param name
*/
public void notTheDish(String name) {
System.out.println(name + " does not exist");
}
/**
*
* @param index
* @param portion
*/
public void portionOut(int index, int portion) {
System.out.println(index + " portion out of range " + portion);
}

/**
*
* @param index
* @param num
*/
public void numOut(int index, int num) {
System.out.println(index + " num out of range " + num);
}
/**
*
* @param id
*/
public void tableIdOut(int id) {
System.out.println(id + " table num out of range");
}
/**
* 12 菜价超出范围
* @param name
* @param price
*/
public void priceOut(String name, int price) {
System.out.println(name + " price out of range " + price);
}
/**
*
*/
public void dateOut() {
System.out.println("not a valid time period");
}
public void tasteLevelOut(int tasteLevel, int style) {
switch(style) {
case 1: System.out.print("spicy"); break;
case 2: System.out.print("acidity"); break;
case 3: System.out.print("sweetness"); break;
}
System.out.println(" num out of range :" + tasteLevel);
}
/**
*
*/
public void seqErr() {
System.out.println("record serial number sequence error");
}
/**
*
*/
public void wrongFormat() {
System.out.println("wrong format");
}
}

/**
* 菜品类
*/
class Dish {
private String name;//菜品名称
private int unit_price; //单价

public Dish(String name, int unitPrice){
this.name = name;
this.unit_price = unitPrice;
}
/**
* 是否存在该份额
* @param portion
* @return
*/
public boolean hasPortion(int portion) {
switch(portion) {
case 1: return true;
case 2:
//if(this.isT) return false;
return true;
case 3: return true;
default: return false;
}
}
/**
* 计算菜品价格的方法,输入参数是
* @param portion 点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
* @return
*/
public int getPrice(int portion){
switch(portion){
case 1: return this.unit_price;
case 2:
//if(this.isT) return 0;
return (int)(this.unit_price * 1.5 + 0.5);
case 3: return this.unit_price * 2;
default: return 0;
}
}
public String getName(){
return this.name;
}
public void setUnitPrice(int unitPrice){
this.unit_price = unitPrice;
}
}

class TDish extends Dish{
/**
* 类别
* 1-川菜 辣
* 2-晋菜 酸
* 3-浙菜 甜
*/
private int style = 0;

/**
*
* @param name
* @param unitPrice
* @param style
* 1-川菜 辣
* 2-晋菜 酸
* 3-浙菜 甜
*/
public TDish(String name, int unitPrice, int style) {
super(name, unitPrice);
this.style = style;
}
/**
* 获取类型
* @return
* 1-川菜 辣
* 2-晋菜 酸
* 3-浙菜 甜
*/
public int getSytle() {
return this.style;
}
}

/**
* 菜谱类
* 对应菜谱,包含饭店提供的所有菜的信息。
*/
class Menu {
private Dish[] dishs;//菜品数组,保存所有菜品信息
private static Menu menu;
private Menu(){
this.dishs = new Dish[0];
}
public static Menu getMenu() {
if(menu == null) menu = new Menu();
return menu;
}
/**
* 查找菜品信息
* @param dishName 菜名
* @return Dish对象
*/
public Dish searchDish(String dishName){
for(Dish dish : this.dishs){
if(dish.getName().compareTo(dishName) == 0){
return dish;
}
}
return null;
}
/**
* 添加一道菜品信息
* @param dishName
* @param unit_price
* @return 此菜品
*/
public Dish addDish(String dishName, int unit_price, int tStyle){
//查找菜单中是否有相同的菜
Dish dish = this.searchDish(dishName);
if(dish != null){
dish.setUnitPrice(unit_price);
return dish;
}
//添加菜品
Dish[] newDishs = new Dish[this.dishs.length + 1];
for(int i = 0; i < this.dishs.length; i++){
newDishs[i] = this.dishs[i];
}
Dish newDish;
if(tStyle == 0) {
newDish = new Dish(dishName, unit_price);
}else {
newDish = new TDish(dishName, unit_price, tStyle);
}
newDishs[this.dishs.length] = newDish;
this.dishs = newDishs;
return newDish;
}

}

/**
* 点菜记录类
* 保存订单上的一道菜品记录
*/
class Record {
private int orderId;//序号
private Dish d;//菜品
private int portion;//份额(1/2/3代表小/中/大份)
private int num;
private int tasteLevel = 0;

private DateUtil date;
private TimeUtil time;

public Record(DateUtil date, TimeUtil time, int orderId, String dishName, int portion,int num){
this.orderId = orderId;
this.d = Menu.getMenu().searchDish(dishName);
this.portion = portion;
this.num = num;
this.date = date;
this.time = time;
}
public Record(DateUtil date, TimeUtil time, int orderId, String dishName, int portion,int num, int tasteLevel){
this.orderId = orderId;
this.d = Menu.getMenu().searchDish(dishName);
this.portion = portion;
this.num = num;
this.date = date;
this.time = time;
this.tasteLevel = tasteLevel;
}
public int getTasteLevel() {
return this.tasteLevel;
}
/**
*
* @return
* 0-无
* 1-川辣
* 2-晋酸
* 3-浙甜
*/
public int getTStyle() {
if(!(this.d instanceof TDish)) return 0;
return ((TDish)this.d).getSytle();
}
public int getNum() {
return num;
}

public void setNum(int num) {
this.num = num;
}
public DateUtil getDate() {
return this.date;
}
public TimeUtil getTime() {
return this.time;
}
public int getPortion() {
return portion;
}

public int getOredrId(){
return this.orderId;
}
public Dish getDish(){
return this.d;
}
/**
* 计价
* 计算本条记录的价格
* @return
*/
public int getPrice(){
return this.d.getPrice(this.portion) * this.num;
}
/**
* 计折扣价
* 计算本条记录打折后的价格
* @return
*/
public int getDiscountedPrice(){
return (int)(this.getPrice() * this.getDiscount() + 0.5);
}
/**
* 计算折扣
* @return
*/
public double getDiscount(){
int week = this.date.getWeek();
if(week >= 1 && week <= 5){
if(this.time.isBetween(new TimeUtil(17, 0, 0), new TimeUtil(20, 30, 0))) {
if(this.d instanceof TDish) return 0.7;
return 0.8;
}
if(this.time.isBetween(new TimeUtil(10, 30, 0), new TimeUtil(14, 30, 0))) {
if(this.d instanceof TDish) return 0.7;
return 0.6;
}
return -1;
}
if(this.time.isBetween(new TimeUtil(9, 30, 0), new TimeUtil(21, 30, 0))) return 1.0;
return -1;
}
}

class Order implements Comparable<Order>{
private String name = "";
private String tel = "";
private Table[] tables = new Table[0];
public Order(String name, String tel) {
this.name = name;
this.tel = tel;
}
@Override
public int compareTo(Order order) {
return this.name.compareTo(order.getName());
}
public String getName() {
return this.name;
}
public String getTel() {
return this.tel;
}
//TODO
public int getPrice() {
int price = 0;
for(Table table : this.tables) {
price += table.getDiscountedPrice();
}
return price;
}
public Table[] getTables() {
return this.tables;
}
public int getTablesCount() {
return this.tables.length;
}
public void chooseTable(Table table) {
Table[] newTables = new Table[this.tables.length + 1];
for(int i = 0; i < this.tables.length; i++) {
newTables[i] = this.tables[i];
}
newTables[this.tables.length] = table;
this.tables = newTables;
}
}

/**
* 餐桌类
* 保存用户点的所有菜的信息
*/
class Table {
//保存订单上每一道的记录
private Record[] records = new Record[0];
private Record[] profitRecords = new Record[0];
private DateUtil orderDate;
private TimeUtil orderTime;
private int id = 0;
private Order master = null;
private Record[] givenRecords = new Record[0];
/**
*
* @param tableId
* @param date
* @param time
* @param master
*/
public Table(int id, String date, String time, Order master){
this.id = id;
String[] dateData = date.split("/");
int year = Integer.parseInt(dateData[0]);
int month = Integer.parseInt(dateData[1]);
int day = Integer.parseInt(dateData[2]);
this.orderDate = new DateUtil(year, month, day);
String[] timeData = time.split("/");
int hour = Integer.parseInt(timeData[0]);
int minute = Integer.parseInt(timeData[1]);
int second = Integer.parseInt(timeData[2]);
this.orderTime = new TimeUtil(hour, minute, second);
this.master = master;
}
public Order getMaster() {
return this.master;
}
public DateUtil getDate() {
return this.orderDate;
}
public TimeUtil getTime() {
return this.orderTime;
}
public int getId() {
return this.id;
}
public Record[] getSimpleRecords() {
Record[] records = new Record[0];
for(Record record : this.records) {
boolean hasTheSame = false;
for(Record rec : records) {
if(record.getDish().getName().equals(rec.getDish().getName()) &&
record.getPortion() == rec.getPortion()) {
rec.setNum(rec.getNum() + record.getNum());
hasTheSame = true;
}
}
if(!hasTheSame) {
Record[] newRecords = new Record[records.length + 1];
for(int i = 0; i < records.length; i++) {
newRecords[i] = records[i];
}
newRecords[records.length] = new Record(record.getDate(), record.getTime(), 0, record.getDish().getName(), record.getPortion(), record.getNum());
records = newRecords;
}
}
return records;
}
/**
* 计算订单的总价
* @return
*/
public int getPrice(){
Record[] records = this.getSimpleRecords();
int priceSum = 0;
for(Record record : records){
priceSum += record.getPrice();
}
for(Record record : this.givenRecords){
priceSum += record.getDiscountedPrice();
}
return priceSum;
}
/**
* 计算订单打折后的总价
* @return
*/
public int getDiscountedPrice(){
Record[] records = this.getSimpleRecords();
int priceSum = 0;
for(Record record : records){
priceSum += record.getDiscountedPrice();
}
for(Record record : this.givenRecords){
priceSum += record.getDiscountedPrice();
}
return priceSum;
}
/**
*
* @return
*/
public int getMaxOrderId() {
int max = 0;
for(Record record : this.records) {
int orderId = record.getOredrId();
if(max < orderId) max = orderId;
}
return max;
}
public int[] getPepperyLevel() {
int count = 0;
int levelSum = 0;
for(Record record : this.records) {
if(record.getTStyle() == 1) {
levelSum += record.getTasteLevel() * record.getNum();
count += record.getNum();
}
}
for(Record record : this.profitRecords) {
if(record.getTStyle() == 1) {
levelSum += record.getTasteLevel() * record.getNum();
count += record.getNum();
}
}
if(count == 0) {
int[] result = {0, -1};
return result;
}
int[] result = {count, (int)((double)levelSum / count + 0.5)};
return result;
}
public int[] getAcidLevel() {
int count = 0;
int levelSum = 0;
for(Record record : this.records) {
if(record.getTStyle() == 2) {
levelSum += record.getTasteLevel() * record.getNum();
count += record.getNum();
}
}
if(count == 0) {
int[] result = {0, -1};
return result;
}
int[] result = {count, (int)((double)levelSum / count + 0.5)};
return result;
}
public int[] getSweetLevel() {
int count = 0;
int levelSum = 0;
for(Record record : this.records) {
if(record.getTStyle() == 3) {
levelSum += record.getTasteLevel() * record.getNum();
count += record.getNum();
}
}
if(count == 0) {
int[] result = {0, -1};
return result;
}
int[] result = {count, (int)((double)levelSum / count + 0.5)};
return result;
}
public boolean isValidTime() {
if(!this.orderDate.compareDates(new DateUtil(2022, 1, 1))) return false;
if(this.orderDate.compareDates(new DateUtil(2024, 1, 1))) return false;
return true;
}
public boolean isInOpeningTime() {
int week = this.orderDate.getWeek();
if(week >= 1 && week <= 5){
if(this.orderTime.isBetween(new TimeUtil(17, 0, 0), new TimeUtil(20, 30, 0))) {
return true;
}
if(this.orderTime.isBetween(new TimeUtil(10, 30, 0), new TimeUtil(14, 30, 0))) {
return true;
}
return false;
}
if(this.orderTime.isBetween(new TimeUtil(9, 30, 0), new TimeUtil(21, 30, 0))) return true;
return false;
}
public boolean isInTheSameTime(Table table) {
if(!this.isInOpeningTime()) return false;
if(!table.isInOpeningTime()) return false;
if(!this.orderDate.equalTwoDates(table.getDate())) return false;
int week = this.orderDate.getWeek();
if(week >= 1 || week <= 5) {
boolean isThisInNoon = this.orderTime.isEarlyThan(new TimeUtil(16, 0, 0));
boolean isThatInNoon = table.getTime().isEarlyThan(new TimeUtil(16, 0, 0));
if(isThisInNoon == isThatInNoon) return true;
return false;
}
if(this.orderTime.compareTo(orderTime) < 60 * 60) return true;
return false;
}
/**
*
* @param dishName
* @param portion
* @return
*/
public Record searchRecord(String dishName, int portion) {
for(Record record : records) {
if(record.getDish().getName().equals(dishName) &&
record.getPortion() == portion) {
return record;
}
}
return null;
}
/**
* 添加一条菜品信息到订单中
* @param orderNum
* @param dishName
* @param portion
* @param num
* @return
*/
public Record addARecord(int orderNum,String dishName,int portion,int num, int tasteLevel){
// Record record = this.searchRecord(dishName, portion);
// if(record != null) {
// record.setNum(record.getNum() + num);
// return record;
// }
//创建新记录
Record newRecord = new Record(this.orderDate, this.orderTime, orderNum, dishName, portion, num, tasteLevel);
//创建新记录数组
Record[] newRecords = new Record[this.records.length + 1];
//复制原记录数组至新记录数组
for(int i = 0; i < this.records.length; i++){
newRecords[i] = this.records[i];
}
//添加新记录至新记录数组
newRecords[this.records.length] = newRecord;
//应用新记录数组
this.records = newRecords;
return newRecord;
}
//TODO
/**
* 添加一条受益菜品信息到订单中
* @param orderNum
* @param dishName
* @param portion
* @param num
* @return
*/
public Record addAProfitRecord(int orderNum,String dishName,int portion,int num, int tasteLevel){
//创建新记录
Record newRecord = new Record(this.orderDate, this.orderTime, orderNum, dishName, portion, num, tasteLevel);
//创建新记录数组
Record[] newRecords = new Record[this.profitRecords.length + 1];
//复制原记录数组至新记录数组
for(int i = 0; i < this.profitRecords.length; i++){
newRecords[i] = this.profitRecords[i];
}
//添加新记录至新记录数组
newRecords[this.profitRecords.length] = newRecord;
//应用新记录数组
this.profitRecords = newRecords;
return newRecord;
}
/**
* 添加一条给予菜品信息到订单中
* @param orderNum
* @param dishName
* @param portion
* @param num
* @param profitTable
* @return
*/
public Record addAGiveRecord(int orderNum, String dishName, int portion, int num, Table profitTable, int tasteLevel){
profitTable.addAProfitRecord(orderNum, dishName, portion, num, tasteLevel);
Record newRecord = new Record(this.orderDate, this.orderTime, orderNum, dishName, portion, num, tasteLevel);
Record[] newRecords = new Record[this.givenRecords.length + 1];
for(int i = 0; i < this.givenRecords.length; i++) {
newRecords[i] = this.givenRecords[i];
}
newRecords[this.givenRecords.length] = newRecord;
this.givenRecords = newRecords;
return newRecord;
}
/**
* 根据序号删除一条记录
* @param orderNum
* @return
*/
public Record delARecordByOrderNum(int orderNum){
for(int i = 0; i < this.records.length; i++){
Record record = this.records[i];
if(record.getOredrId() == orderNum){
Record[] newRecords = new Record[this.records.length - 1];
for(int j = 0; j < i; j++){
newRecords[j] = this.records[j];
}
for(int j = i; j < this.records.length - 1; j++){
newRecords[j] = this.records[j + 1];
}
this.records = newRecords;
return record;
}
}
return null;
}
/**
* 根据序号查找一条记录
* @param orderNum
* @return
*/
public Record findRecordByNum(int orderNum){
for(int i = 0; i < this.records.length; i++){
if(this.records[i].getOredrId() == orderNum){
return this.records[i];
}
}
return null;
}
}

class TimeUtil{
int hour;
int minute;
int second;
public TimeUtil(int hour, int minute, int second){
this.hour = hour;
this.minute = minute;
this.second = second;
}
public int getTolalSeconds() {
return (this.hour * 60 + this.minute) * 60 + this.second;
}
public boolean isEarlyThan(TimeUtil a){
if(this.hour < a.hour) return true;
if(this.hour > a.hour) return false;
if(this.minute < a.minute) return true;
if(this.minute > a.minute) return false;
if(this.second < a.second) return true;
return false;
}
public boolean isBetween(TimeUtil a, TimeUtil b){
if(a.isEarlyThan(b)){
if(!this.isEarlyThan(a) && !b.isEarlyThan(this)) return true;
return false;
} else {
if(!this.isEarlyThan(a) || !b.isEarlyThan(this)) return true;
return false;
}
}
public int compareTo(TimeUtil time) {
return Math.abs(this.getTolalSeconds() - time.getTolalSeconds());
}
public boolean check() {
if(this.hour < 0 || this.hour > 23) return false;
if(this.minute < 0 || this.minute > 59) return false;
if(this.second < 0 || this.second > 59) return false;
return true;
}
}

class DateUtil{
private int year;
private int month;
private int day;
private static int[] mon_maxnum = new int[]{31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
public DateUtil(){
}
public DateUtil(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
public int getYear(){
return this.year;
}
public void setYear(int year){
this.year = year;
}
public int getMonth(){
return this.month;
}
public void setMonth(int month){
this.month = month;
}
public int getDay(){
return this.day;
}
public void setDay(int day){
this.day = day;
}
public static boolean isLeapYear(int year){
if(year % 400 == 0 || year % 100 != 0 && year % 4 == 0)return true;
return false;
}
public boolean checkInputValidityIgnoreYear(){
if(this.month < 1 || this.month > 12) return false;
if(this.day < 1 || this.month != 2 && this.day > mon_maxnum[month]) return false;
if(this.month == 2){
if(isLeapYear(this.year) && day > 29) return false;
if(!isLeapYear(this.year) && day > 28) return false;
}
return true;
}
public DateUtil getNextDate(){
DateUtil nextDate = new DateUtil(this.year, this.month, this.day + 1);
if(nextDate.checkInputValidityIgnoreYear()) return nextDate;
nextDate.setDay(1);
nextDate.setMonth(this.month + 1);
if(nextDate.checkInputValidityIgnoreYear()) return nextDate;
nextDate.setMonth(1);
nextDate.setYear(this.year + 1);
return nextDate;
}
public boolean compareDates(DateUtil date){
if(this.year < date.getYear()) return false;
if(this.year > date.getYear()) return true;
if(this.month < date.getMonth()) return false;
if(this.month > date.getMonth()) return true;
if(this.day < date.getDay()) return false;
return true;
}
public boolean equalTwoDates(DateUtil date){
if(this.year == date.getYear() &&
this.month == date.getMonth() &&
this.day == date.getDay())
return true;
return false;
}
public int getDaysofDates(DateUtil date){
if(this.equalTwoDates(date)) return 0;
if(this.compareDates(date)){
DateUtil nextDate = date;
int n = 0;
while(!this.equalTwoDates(nextDate)){
nextDate = nextDate.getNextDate();
n++;
}
return n;
}
DateUtil nextDate = this;
int n = 0;
while(!nextDate.equalTwoDates(date)){
nextDate = nextDate.getNextDate();
n++;
}
return n;
}
public int getWeek(){
DateUtil anchorDate = new DateUtil(2000, 1, 2);
return this.getDaysofDates(anchorDate) % 7;
}
}

菜单系列-5与菜单系列-4同属于菜单系列-3的两个不同方向的迭代分支:菜单系列-5主要是添加了口味度的判断以及单用户多桌菜,多用户多桌菜的情况,而且增加了口味度,在最后对每桌菜订单数据的输出增加了按英文字典顺序输出。难点是代点菜是价格加到本桌,而口味度加到被点桌。在删除时在删除本桌该条记录价格的同时,还要删除被点桌的口味度值。

期中考试题目集

(1)继承与多态

将测验1与测验2的类设计进行合并设计,抽象出Shape父类(抽象类),Circle及Rectangle作为子类,类图如下所示:


image.png

试编程完成如上类图设计,主方法源码如下(可直接拷贝使用):

    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,不考虑无效输入)
对应图形的参数(圆或矩形)

输出格式:

图形的面积(保留两位小数)

代码如下:

import java.util.Scanner;
abstract class Shape {
    protected double area;
    
    public abstract void calculateArea();
    
    public double getArea() {
        return area;
    }
}

class Circle extends Shape {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public void calculateArea() {
        area = Math.PI * radius * radius;
    }
}

class Rectangle extends Shape {
    private Point leftTop;
    private Point lowerRight;
    
    public Rectangle(Point leftTop, Point lowerRight) {
        this.leftTop = leftTop;
        this.lowerRight = lowerRight;
    }
    
    @Override
    public void calculateArea() {
        double width = Math.abs(lowerRight.getX() - leftTop.getX());
        double height = Math.abs(lowerRight.getY() - leftTop.getY());
        area = 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);
                
                Shape rectangle = new Rectangle(leftTopPoint, lowerRightPoint);
                printArea(rectangle);
                break;
        }
    }
    
    public static void printArea(Shape shape) {
        shape.calculateArea();
        System.out.printf("%.2f\n", shape.getArea());
    }
}
(2)抽象类与接口

在测验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:结束输入)

输入图形所需参数

输出格式:

按升序排序输出列表中各图形的面积(保留两位小数),各图形面积之间用空格分隔。

代码如下:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;

interface Shape extends Comparable<Shape>{
double getArea();
}

class Circle implements Shape {
private double radius;

public Circle(double radius) {
    this.radius = radius;
}

@Override
public double getArea() {
    return Math.PI * radius * radius;
}

@Override
public int compareTo(Shape other) {
    double diff = this.getArea() - other.getArea();
    if (diff < 0) {
        return -1;
    } else if (diff > 0) {
        return 1;
    } else {
        return 0;
    }
}
}

class Rectangle implements Shape {
private Point leftTop;
private Point lowerRight;

public Rectangle(Point leftTop, Point lowerRight) {
    this.leftTop = leftTop;
    this.lowerRight = lowerRight;
}

@Override
public double getArea() {
    return Math.abs(lowerRight.getX() - leftTop.getX()) * Math.abs(lowerRight.getY() - leftTop.getY());
}

@Override
public int compareTo(Shape other) {
    double diff = this.getArea() - other.getArea();
    if (diff < 0) {
        return -1;
    } else if (diff > 0) {
        return 1;
    } else {
        return 0;
    }
}
}

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);
ArrayList<Shape> list = new ArrayList<>();

    int choice = input.nextInt();

    while (choice != 0) {
        switch (choice) {
            case 1: // Circle
                double radius = input.nextDouble();
                Shape circle = new Circle(radius);
                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. 编译错误:PTA上的题目往往需要使用Java的类库,如果没有正确导入这些类库,就会出现编译错误。在做题之前,要先阅读题目中所提到的类库,并将其导入到代码中。

2. 输入输出问题:PTA平台会提供多组测试数据,所以要注意输入输出格式。在处理输入时,应该使用Scanner等工具类;在输出时,应该注意格式控制。

3. 数组越界错误:数组越界错误是一个常见的运行时错误。要避免这个错误,可以使用for循环或者List等Java集合代替原生数组。

4. 逻辑错误:有些PTA题目需要考虑边界和特殊情况。在编写代码之前,要认真阅读题目并理解需求,在代码实现过程中考虑各种可能性,并对每个分支进行测试。

5. 在使用Scanner类获取用户输入时,要注意避免空格、回车等非数字字符的干扰。可以在获取完数字后使用nextLine()方法将其余字符清空。

四、改进建议:

1.优化算法和数据结构:确保你所使用的算法和数据结构是高效的,并且能够满足程序的需求。在适当的情况下,可以考虑使用更高效的数据结构或算法,以提高程序的性能。

2.减少内存使用:Java程序在内存管理方面拥有一定的优势,但仍然需要注意内存使用情况。确保及时释放不再使用的对象,避免内存泄漏问题。可以使用一些内存分析工具来监测和解决内存问题。

3.多线程和并发处理:对于需要处理大量并发请求或需要执行长时间任务的程序,可以考虑使用多线程或并发处理来提高程序的性能和响应能力。使用Java提供的线程池和并发工具可以简化并发编程的复杂性。

4.异常处理:合理处理异常对于程序的稳定性和可靠性很重要。使用try-catch语句来捕获和处理异常,并根据具体情况选择适当的异常处理策略,如重试、回滚或记录错误信息。

5.代码重构:对于复杂或冗长的代码,可以考虑进行重构,以提高代码的可读性、易维护性和性能。使用设计模式和优化技巧来改善代码结构和性能。

6.性能测试和优化:定期进行性能测试,并使用性能分析工具来找出程序的瓶颈。根据测试结果进行适当的优化,以提高程序的响应时间和吞吐量。

7.代码规范和可维护性:遵循统一的代码规范和最佳实践,使代码易于阅读、理解和维护。使用注释和文档来解释代码的逻辑和功能。

8.引入第三方库和框架:合理使用一些优秀的第三方库和框架,可以提高开发效率和程序的功能性。但要注意选择稳定、活跃维护且符合项目需求的库和框架。

五、总结:

通过一段对java的学习,发现自己对java的基础知识有很多的欠缺,基础的知识还是有些不知道,需要继续努力的学习,总是出现bug,但是还是只能静下心来一点一点的学习,请教同学和网上搜集资料,只有学好这些基础的类知识,才能为后面更好的学习做准备,需要学习更多的结构、语法知识来充实java的学习。在优化代码和减少复杂度的方面有所欠缺,需要在这方面改进。上课认真听课,课后也需要自己多了解java的知识,许多知识还需要自学,多巩固基础函数语法知识,更易于理解和吸收,防止在平常编写代码时忘记一些基础知识。要学会在解决一道题时,提前考虑好要用什么方法才能更好的解决这个问题,才能更好的优化此题。