一、作业总结
该次博客作业是对第4次PTA、菜单计价程序-4、菜单计价程序-5、期中测试的一次总结。这次的菜单计价程序在之前的基础上进行了更完善的更改升级,菜单计价程序-4在菜单计价程序-3的基础上增加了异常情况的处理,菜单计价程序-5在菜单计价程序-3的基础上增加了特色菜的深入特殊化处理,期中测试则是考察以面向对象思想的编程能力。在这几次的作业中,我对自己的代码在之前的基础上进行了一定的更改,目的是增强自己代码的可读性和灵活性,让自己的代码更完善,通过更合理的分工以及数据的合理储存,让相应的类完成本该属于自己的工作,以及相应的数据放到合理的类中,以达到代码工作和数据处理的合理分配和储存。这几次的作业让我对Java中的面向对象思想更加深刻,对其有了更完善的了解,对于每个分出的类,其中的数据和方法做到谁的工作和数据,就放到对应的类中,这样能做到代码更清晰可读,在符合逻辑的基础上,对代码的更改完善也会变得更轻松简单,一旦发现问题,无论是逻辑上的出错还是编译时代码写错,都能能迅速发现和更改。同时为了完成该次作业,我也学会了try-catch的使用,以及正则表达式的使用。但这几次的作业也同样让我认识到逻辑思维的严谨对一个程序来说有多么重要,这几次的作业都没拿到满分甚至是高分,有很大一部分原因真是因为我考虑的不够严谨,所想的程序总是会遗漏一些特殊情况导致扣分。接下来是我对这三次作业的简要分析。
二、对各个作业的简要分析
菜单计价程序-4
这道题在菜单计价程序-3的基础上增加了特色菜的处理以及大量异常输入的处理,对于该题我发现原有的代码主体部分不足以满足要求,不好进行增加特色菜和异常处理的代码更改,于是我进行了一定的调整。
一些知识点:
-
类和对象:在代码中定义了几个类,如
MenuItem
(菜单项)、OrderItem
(订单项)、TableOrder
(桌子订单)和Table
(桌子),它们用于组织和存储相关的数据和行为。 -
集合类的使用:使用
ArrayList
来存储菜单项、订单项和桌子订单等列表数据。通过添加、删除和遍历集合元素来管理订单信息。 -
条件语句和循环:使用
if-else
语句和for-each
循环来处理不同的条件和迭代订单项。 -
方法的定义和调用:定义了一些方法来实现订单处理的逻辑,如添加订单项、删除订单项、计算菜品价格等。这些方法可以在需要的时候被调用。
-
字符串处理:使用
String
类的方法来比较字符串、转换大小写等。 -
数学运算:使用
Math.round()
函数对总价格进行四舍五入。
import java.util.Scanner; import java.util.Calendar; import java.time.YearMonth; class Dish { String name;//菜品名称 boolean isSpecial = false;//是不是特色菜 int unit_price; //单价 boolean exist = true; //int num; int getPrice(int portion) { int peic = 0; if (portion == 1) { peic = unit_price ; } else if (portion == 2) { peic = Math.round((float) (unit_price * 1.5)) ; } else if (portion == 3) { peic = (unit_price * 2) ; } return peic;//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) } } class Menu { Dish[] dishs = new Dish[10];//菜品数组,保存所有菜品信息 int count = 0; Dish searthDish(String dishName){ Dish temd = null; for(int i=count-1;i>=0;i--){ if(dishName.equals(dishs[i].name)&&dishs[i].exist){ temd = dishs[i]; break; } } if(temd==null){ System.out.println(dishName+" does not exist"); } return temd; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 Dish addDish(String dishName,int unit_price){ Dish dh = new Dish(); dh.name = dishName; dh.unit_price = unit_price; count++; if(unit_price<1||unit_price>300) { dh.exist = false; System.out.println(dishName+" price out of range "+unit_price); } return dh; }//添加一道菜品信息 } class Record { int orderNum;//序号\ Dish d = new Dish();//菜品\ int num = 0; int portion;//份额(1/2/3代表小/中/大份)\ boolean noNeed = true; int exist = 1; float realdiscnt = 1; //int asum = 0; boolean isTaked = false;//是否是给别人点的 int getPrice(){ return Math.round(d.getPrice(portion)*num); }//计价,计算本条记录的价格\ float Checkportion(float discnt){//数量输入检查,计算价格 if(portion>3||portion<1) { System.out.println(orderNum + " portion out of range " + portion); exist = 0; noNeed = false; }else if(num<1||num>15) { System.out.println(orderNum + " num out of range" +" "+num); exist = 0; noNeed = false; }else{ if(d.isSpecial) if(discnt==0.8F||discnt==0.6F) realdiscnt = 0.7F; if(exist==1&&!isTaked) { System.out.println(orderNum + " " + d.name + " " + getPrice()); } } return realdiscnt; } boolean Checkahead(){ if(num<1||num>15) { return false; }else return portion <= 3 && portion >= 1; } } class Order { Record[] records = new Record[100];//保存订单上每一道的记录 int count = 0;//订单数量 int getTotalPrice(){ int sum=0; for(int i=0;i<count;i++){ if(records[i].exist==0) continue; sum=sum+records[i].getPrice(); } return sum; }//计算订单的总价 Record addARecord(int orderNum, String dishName, int portion, int num){ boolean flag = true; for(int i=0;i<count;i++){//不能点份额一样的菜 if (records[i].d.name.equals(dishName) && records[i].portion == portion) { flag = false; break; } } count++; records[count] = new Record(); records[count].d.name = dishName; records[count].orderNum = orderNum; records[count].portion = portion; records[count].num = num; records[count].noNeed = flag; return records[count]; }//添加一条菜品信息到订单中。 Record TakeOdfor(int mynum,Table[] table, int AnotherNum, int orderNum, String dishName, int portion, int num){ boolean flag = false; for(Table t : table) { if(t==null) continue; if (t.tableNum != mynum&&t.tableNum==AnotherNum) { flag = true; break; } } if(flag) { count++; records[count] = new Record(); records[count].d.name = dishName; records[count].orderNum = orderNum; records[count].portion = portion; records[count].num = num; return records[count]; }else{ System.out.println("Table number :" + AnotherNum + " does not exist"); return null; } } void delARecordByOrderNum(int orderNum){ if(orderNum>count||orderNum<=0){ System.out.println("delete error;"); }else { if(records[orderNum-1].exist==0) { System.out.println("deduplication "+orderNum); return; } records[orderNum-1].exist = 0; } }//根据序号删除一条记录 } class Table { int tableNum; boolean inputIsvalid = false; boolean istoSum = false;//判断是否要合并计算 String tableDtime; int year,month,day,week,hh,mm,ss; int sum = 0;//一桌价格 ; int primesum = 0; Order odt = new Order(); float discnt = -1; float rediscnt = 1; void Gettottalprice(){ if(discnt>0){ primesum = odt.getTotalPrice(); if(primesum==0) sum=0; System.out.println("table " + tableNum + ": " +primesum+" "+sum); } } void AheadProcess(String tableDtime){ this.tableDtime = tableDtime; processTime(); discount(); } void processTime(){//处理时间 String[] temp = tableDtime.split(" "); tableNum = Integer.parseInt(temp[1]); String[] temp1 = temp[2].split("/"); String[] temp2 = temp[3].split("/"); year = Integer.parseInt(temp1[0]); month = Integer.parseInt(temp1[1]); day = Integer.parseInt(temp1[2]); Calendar c = Calendar.getInstance(); c.set(year, (month-1), day); week = c.get(Calendar.DAY_OF_WEEK); if(week==1) week = 7; else week--; hh = Integer.parseInt(temp2[0]); mm = Integer.parseInt(temp2[1]); ss = Integer.parseInt(temp2[2]); } boolean DateisValid(){ if(year<1000) return false; if(month<1||month>12) return false; YearMonth mytime = YearMonth.of(year,month); return mytime.isValidDay(day); } boolean Daterande(){ boolean flag = year >= 2022 && year <= 2023; if(!flag){ System.out.println("not a valid time period"); inputIsvalid = false; } return flag; } void discount(){ if(week>=1&&week<=5) { if(hh>=17&&hh<20) discnt=0.8F; else if(hh==20&&mm<30) discnt=0.8F; else if(hh==20&&mm==30&&ss==0) discnt=0.8F; else if(hh>=11&&hh<=13||hh==10&&mm>=30) discnt=0.6F; else if(hh==14&&mm<30) discnt=0.6F; else if(hh==14&&mm==30&&ss==0) discnt=0.6F; } else { if(hh>=10&&hh<=20) discnt= 1.0F; else if(hh==9&&mm>=30) discnt= 1.0F; else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0) discnt= 1.0F; } } boolean CheckSameTime(Table table){ if(tableNum!=table.tableNum) return false; if(week==table.week&&week>=1&&week<=5){ return discnt == table.discnt; }else if(week==table.week&&week==6||week==7){ int subtime = hh*3600+mm*60+ss-table.hh*3600-table.mm*60-ss; return Math.abs(subtime) < 3600; } return false; } } public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); Menu mu = new Menu(); Table[] tablemes = new Table[57];//桌号1-55; int j = 0;//菜单数 int l = 0;//订单数 //代点菜数 //遍历桌 int cntTab = 0;//桌号 String[] temp;//字符串存储 int tempordernum = 0;//临时存上一个有效序号 String input; String regex = "[\\u4e00-\\u9fa5]* \\d*";//非特色菜菜谱 String regex1 = "[\\u4e00-\\u9fa5]* \\d* T";//特色菜谱 String regex2 = "\\d (delete)";//删除情况 String regex3 = "(table) ([1-4][0-9]*|5[0-5]*) \\d{4}/\\d+/\\d{1,2} ([0-1]?[0-9]|2[0-3])/([0-5][0-9])/([0-5][0-9])";//添桌子的情况 String regex4 = "([1-9]|[1-9][0-9]*) [\\u4e00-\\u9fa5]+ \\d+ \\d+";//点菜记录的添加; String regex5 = "([1-4][0-9]*|5[0-5]*|[1-9]) \\d [\\u4e00-\\u9fa5]+ [123] (1[0-5]|[1-9])";//代点菜 while (true) { int count;//空格数量; input = sc.nextLine();//获取输入,每行 if(input.equals("end")) break; if(input.isEmpty()) { System.out.println("wrong format"); continue; } temp = input.split(" ");//分割 /* * 判断输入的类型*/ count = temp.length; if(count==2){//非特色菜菜谱,或者删除菜; if(input.matches(regex2)){//删除的情况桌子有效才删除 if (tablemes[cntTab] != null && tablemes[cntTab].inputIsvalid) { tablemes[cntTab].odt.delARecordByOrderNum(Integer.parseInt(temp[0]));//删除 } }else if(input.matches(regex)){//非特色菜谱添加 if (cntTab == 0) { mu.dishs[j] = new Dish(); mu.dishs[j] = mu.addDish(temp[0], Integer.parseInt(temp[1])); j++; } else if(tablemes[cntTab].inputIsvalid){ System.out.println("invalid dish"); } }else { System.out.println("wrong format"); } }else if(count==3){//特色菜菜谱 if(input.matches(regex1)) { if(cntTab!=0) { if(tablemes[cntTab].inputIsvalid) System.out.println("invalid dish"); else continue; } mu.dishs[j] = new Dish(); mu.dishs[j] = mu.addDish(temp[0], Integer.parseInt(temp[1])); mu.dishs[j].isSpecial = true;//是特色菜 j++; }else System.out.println("wrong format"); } //桌子的添加,点菜记录的添加, else if(temp[0].equals("table")||input.contains("/")) { cntTab++; tablemes[cntTab] = new Table(); if(temp[0].equals("table")){ if(input.matches(regex3)) tablemes[cntTab].AheadProcess(input); tablemes[cntTab].inputIsvalid=true; if (input.matches(regex3)) { if(tablemes[cntTab].inputIsvalid&&!tablemes[cntTab].DateisValid()){//检查日期 System.out.println(tablemes[cntTab].tableNum+" date error"); tablemes[cntTab].inputIsvalid=false; continue; } if(tablemes[cntTab].inputIsvalid&&!tablemes[cntTab].Daterande()){ tablemes[cntTab].inputIsvalid=false; continue; } for(int i =1;i<cntTab;i++){ if (tablemes[i].inputIsvalid && tablemes[cntTab].CheckSameTime(tablemes[i])) {//同一时间段 tablemes[cntTab].istoSum = true; } else { l = 0; } tempordernum = 0; } if(tablemes[cntTab].discnt>0) System.out.println("table " + tablemes[cntTab].tableNum + ": "); else { System.out.println("table " + tablemes[cntTab].tableNum + " out of opening hours"); tablemes[cntTab].inputIsvalid = false; } continue; } else {//第一个是table但不合法 tablemes[cntTab].inputIsvalid = false; if(!temp[1].isEmpty() &&temp[1].charAt(0)>='1'&&temp[1].charAt(0)<='9'&&!temp[1].contains("/")){ if(Integer.parseInt(temp[1])<1||Integer.parseInt(temp[1])>55){ System.out.println(Integer.parseInt(temp[1])+" table num out of range"); continue; } } } } System.out.println("wrong format"); tablemes[cntTab].inputIsvalid = false; if(!temp[0].equals("table")) tablemes[cntTab].istoSum = true; }else if(count==4){ if (tablemes[cntTab] != null && input.matches(regex4) && (tablemes[cntTab].inputIsvalid || tablemes[cntTab].istoSum)) {//点菜记录 Dish tem; int aheadcntTab = cntTab - 1; if (!tablemes[cntTab].istoSum) {//不需要合并 tablemes[cntTab].odt.records[l] = new Record(); tablemes[cntTab].odt.records[l] = tablemes[cntTab].odt.addARecord(Integer.parseInt(temp[0]), temp[1], Integer.parseInt(temp[2]), Integer.parseInt(temp[3])); if (l - 1 >= 0) {//判断记录序号是否递增 tempordernum = getTempordernum(tablemes, l, cntTab, temp, tempordernum); } else {//特殊情况 if (tablemes[cntTab].odt.records[l].Checkahead()) tempordernum = tablemes[cntTab].odt.records[l].orderNum; } if ((tem = mu.searthDish(temp[1])) != null) { float temdiscnt;//临时储存折扣 tablemes[cntTab].odt.records[l].d = tem; temdiscnt = tablemes[cntTab].odt.records[l].Checkportion(tablemes[cntTab].discnt); if (temdiscnt != 1F) tablemes[cntTab].rediscnt = temdiscnt;//最终折扣 if (tablemes[cntTab].odt.records[l].exist == 1 && tablemes[cntTab].odt.records[l].noNeed) { if (tablemes[cntTab].rediscnt != 1) { tablemes[cntTab].sum += Math.round(tablemes[cntTab].odt.records[l].getPrice() * tablemes[cntTab].rediscnt); tablemes[cntTab].rediscnt = 1.0F; } else tablemes[cntTab].sum += Math.round(tablemes[cntTab].odt.records[l].getPrice() * tablemes[cntTab].discnt); } } if (!tablemes[cntTab].istoSum) {//如果份额名字未重复; l++; } } else {//需要合并计算 tablemes[aheadcntTab].odt.records[l] = new Record(); tablemes[aheadcntTab].odt.records[l] = tablemes[aheadcntTab].odt.addARecord(Integer.parseInt(temp[0]), temp[1], Integer.parseInt(temp[2]), Integer.parseInt(temp[3])); if (l - 1 >= 0) {//判断记录序号是否递增 tempordernum = getTempordernum(tablemes, l, aheadcntTab, temp, tempordernum); } if ((tem = mu.searthDish(temp[1])) != null) { float temdiscnt;//临时储存折扣 tablemes[aheadcntTab].odt.records[l].d = tem; temdiscnt = tablemes[aheadcntTab].odt.records[l].Checkportion(tablemes[aheadcntTab].discnt);//计算折扣 if (temdiscnt == 0.7F)//如果需要调整 tablemes[aheadcntTab].rediscnt = temdiscnt;//最终折扣//更改折扣 if (tablemes[aheadcntTab].odt.records[l].exist == 1) {//必须存在 if (tablemes[aheadcntTab].rediscnt != 1) { tablemes[aheadcntTab].sum += Math.round(tablemes[aheadcntTab].odt.records[l].getPrice() * tablemes[aheadcntTab].rediscnt); tablemes[aheadcntTab].rediscnt = 1.0F; } else tablemes[aheadcntTab].sum += Math.round(tablemes[aheadcntTab].odt.records[l].getPrice() * tablemes[cntTab].discnt) - 1; } } l++; } } } else if (tablemes[cntTab] != null && count == 5 && tablemes[cntTab].inputIsvalid) {//代点菜 int temSum = 0; if (input.matches(regex5)) { int AnothNum = Integer.parseInt(temp[0]); tablemes[cntTab].odt.records[l] = tablemes[cntTab].odt.TakeOdfor(tablemes[cntTab].tableNum, tablemes, AnothNum, Integer.parseInt(temp[1]), temp[2], Integer.parseInt(temp[3]), Integer.parseInt(temp[4])); Dish tem; if ((tem = mu.searthDish(temp[2])) != null && tablemes[cntTab].odt.records[l] != null) { tablemes[cntTab].odt.records[l].isTaked = true;//给别人diade float temdiscnt;//临时储存折扣 tablemes[cntTab].odt.records[l].d = tem; temdiscnt = tablemes[cntTab].odt.records[l].Checkportion(tablemes[cntTab].discnt); if (temdiscnt != 1F) tablemes[cntTab].rediscnt = temdiscnt;//最终折扣 if (tablemes[cntTab].odt.records[l].exist == 1 && tablemes[cntTab].odt.records[l].noNeed) { if (tablemes[cntTab].rediscnt != 1) { tablemes[cntTab].sum += Math.round((temSum = tablemes[cntTab].odt.records[l].getPrice()) * tablemes[cntTab].rediscnt); tablemes[cntTab].rediscnt = 1.0F; } else tablemes[cntTab].sum += Math.round((temSum = tablemes[cntTab].odt.records[l].getPrice()) * tablemes[cntTab].discnt); } System.out.println(temp[1] + " table " + tablemes[cntTab].tableNum + " pay for table " + temp[0] + " " + temSum); } if (tablemes[cntTab].odt.records[l] != null) l++; } else System.out.println("wrong format"); } } for(int i=1;i<=cntTab;i++){ if(tablemes[i].inputIsvalid&&!tablemes[i].istoSum) tablemes[i].Gettottalprice(); } } private static int getTempordernum(Table[] tablemes, int l, int cntTab, String[] temp, int tempordernum) { if (Integer.parseInt(temp[0]) <= tempordernum) { System.out.println("record serial number sequence error"); tablemes[cntTab].odt.records[l].exist = 0; } else if (tablemes[cntTab].odt.records[l] != null && tablemes[cntTab].odt.records[l].noNeed) tempordernum = tablemes[cntTab].odt.records[l].orderNum; return tempordernum; } }
分好类之后,就要根据不同的部分进行相应的操作,输入菜谱这块的话,需要先用split方法将字符串以空格分隔,然后将分好的存进一个数组当中,接着把菜名和菜价存进已经new好的dish数组当中,这就是菜谱的存储方法,接着就是像订单啊之类的操作。其实和这个都有所相似,细节不同而已。
然后将代点菜的操作完成之后,删除的代码也补上,就到了最后的计算总价的环节了,这里要注意时间不同打的折扣也不同,所以还要进行四舍五入的操作,然后根据tables数组的顺序,依次输出每桌的折扣前的价格和折扣后的价格
菜单计价程序-5
这一题的输入方面的处理其实和菜单计价4没什么太大的差距,都是使用正则表达式来控制区分输入的是哪一种处理,但是菜单计价5多了一个新的功能,就是增加了川菜浙菜等菜系的特色,在菜单的增加方面,其实和菜单4是一样的,只不过我加了一个record的新属性,就是flag,我把普通菜的glag当作0,而特色菜分别flag为1,2,3
一些知识点:
-
异常处理:通过
try-catch
语句块捕获并处理ParseException
异常。 -
集合和数据结构:使用了
ArrayList
和HashMap
集合来存储菜单信息、订单信息以及其他数据。 -
字符串处理:使用了字符串的分割、拼接等操作,以及字符串的比较和匹配。
-
枚举类型(Enum):定义了一个
DishType
枚举类型来表示菜品类型。 -
自定义类和对象:定义了
Dish
、Menu
、Record
、Table
等类,并创建了相应的对象进行数据存储和操作。 -
时间和日期处理:使用了
SimpleDateFormat
类来解析和格式化日期和时间。 -
条件判断和逻辑运算:使用
if-else
语句对输入进行条件判断和处理。 -
数组操作:使用数组来存储字符串和数字等数据。
-
排序和比较:使用了
Comparator
接口和sort
方法对字符串进行排序。 -
面向对象编程:代码中使用了面向对象的封装、继承、多态等概念,通过类和对象的组织和交互来实现功能。
import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); String menuMessage = input.nextLine(); Menu menu = new Menu(); int j = 0; while (!menuMessage.startsWith("table")) { String string[] = menuMessage.split(" "); if (checkDishValidity(menuMessage)) {// 基础格式 if (menu.searthDish(string[0]) == null) {// 没有找到相同名称的菜 if (string.length > 2) {// 特色菜 menu.addDish(string[0], string[1], Integer.parseInt(string[2])); } else {// 非特色菜 menu.addDish(string[0], null, Integer.parseInt(string[1])); } } else {// 找到了相同名称的菜 if (string.length == 4) {// 找到的是特色菜 menu.searthDish(string[0]).unit_price = Integer.parseInt(string[2]); } else { menu.searthDish(string[0]).unit_price = Integer.parseInt(string[1]); } } } else {// 非法输入 System.out.println("wrong format"); } menuMessage = input.nextLine(); j++; } String tableMessage = menuMessage;// 上述循环会多读一条 ArrayList<Table> tables = new ArrayList<Table>(); ArrayList<User> users = new ArrayList<User>(); while (true) { Order order = new Order();// 开始读订单信息 if (checkTableValidity(tableMessage)) {// 基础格式正确 String[] string = tableMessage.split(" "); String userName = string[3]; String phoneNum = string[4]; String[] Time1 = string[5].split("/"); String[] Time2 = string[6].split("/"); int day = Integer.parseInt(Time1[2]); int month = Integer.parseInt(Time1[1]); int year = Integer.parseInt(Time1[0]); int hour = Integer.parseInt(Time2[0]); int minute = Integer.parseInt(Time2[1]); int second = Integer.parseInt(Time2[2]); int tableNum = Integer.parseInt(string[1]); if (checkTimeValidity(year, month, day, hour, minute, second)) {// 时间是否合法 if (isBusinessTime(year, month, day, hour, minute, second)) {// 在营业时间 String recordMessage = input.nextLine(); while (true) {// 读入各桌菜品记录 if (recordMessage.startsWith("table") || recordMessage.startsWith("end")) { break; } String string1[] = recordMessage.split(" "); String dname = string1[1]; if (checkRecordValidity(recordMessage) == 2) {/////////////// 格式正确,非特色菜格式 String number = string1[0]; int portion = Integer.parseInt(string1[2]); int copies = Integer.parseInt(string1[3]); if (menu.searthDish(dname) == null) { System.out.println(dname + " does not exist"); } else { if (menu.searthDish(dname).taste == null) { if (portion > 3) { portion = 3; } Record record = new Record(number, menu.searthDish(dname), 0, portion, copies); order.addARecord(record); } else { System.out.println("wrong format"); } } } else if (checkRecordValidity(recordMessage) == 1) {////////////////////// 格式正确,特色菜格式 String number = string1[0]; int portion = Integer.parseInt(string1[3]); int copies = Integer.parseInt(string1[4]); int degree = Integer.parseInt(string1[2]); if (menu.searthDish(dname) == null) { System.out.println(dname + " does not exist"); } else { if (menu.searthDish(dname).taste == null) { System.out.println("wrong format"); } else { if (portion > 3) { portion = 3; } Record record = new Record(number, menu.searthDish(dname), degree, portion, copies); order.addARecord(record); } } } else if (checkDeleteValidity(recordMessage)) {// 删除基础格式正确 String[] deleteMessage = recordMessage.split(" "); if (!order.findRecordByNum(deleteMessage[0])) { System.out.println("delete error"); } else { order.delARecordByOrderNum(deleteMessage[0]); } } else { System.out.println("wrong format"); } recordMessage = input.nextLine(); tableMessage = recordMessage;/* * 如果是当前订单最后一条菜品记录,但已经读了下一条, * 所以此时让tableMessage=recordMessage,就算不是循环也不会停 */ } Table table = new Table(tableNum, order); table.time[0] = year; table.time[1] = month; table.time[2] = day; table.time[3] = hour; table.time[4] = minute; table.time[5] = second; tables.add(table); int flag = 0; if (users.isEmpty()) { User user = new User(); user.setName(userName); user.setPhonenum(phoneNum); user.tables.add(table); users.add(user); } else { for (int k = 0; k < users.size(); k++) { if (users.get(k).name.equals(userName)) {// 一人多桌 users.get(k).tables.add(table); flag = 1; } } if (flag == 0) { User user = new User(); user.setName(userName); user.setPhonenum(phoneNum); user.tables.add(table); users.add(user); } } } else { System.out.println("table " + tableNum + " out of opening hours"); tableMessage = input.nextLine(); while (true) { if (tableMessage.startsWith("table") || tableMessage.startsWith("end")) { break; } tableMessage = input.nextLine(); } } } else {// 非法输入 System.out.println("wrong format"); tableMessage = input.nextLine(); while (true) { if (tableMessage.startsWith("table") || tableMessage.startsWith("end")) { break; } tableMessage = input.nextLine(); } } } else {// 非法输入 System.out.println("wrong format"); tableMessage = input.nextLine(); while (true) { if (tableMessage.startsWith("table") || tableMessage.startsWith("end")) { break; } tableMessage = input.nextLine(); } } if (tableMessage.startsWith("end")) { break; } } for (int k = 0; k < tables.size(); k++) { // 输出桌信息 System.out.println("table " + tables.get(k).tableNum + ": "); for (int l = 0; l < tables.get(k).order.records.size(); l++) {// 输出对应桌的菜品信息 if (tables.get(k).order.records.get(l).degree > 5 && tables.get(k).order.records.get(l).d.taste.equals("川菜")) { System.out.println("spicy num out of range :" + tables.get(k).order.records.get(l).degree); } else if (tables.get(k).order.records.get(l).degree > 4 && tables.get(k).order.records.get(l).d.taste.equals("晋菜")) { System.out.println("acidity num out of range :" + tables.get(k).order.records.get(l).degree); } else if (tables.get(k).order.records.get(l).degree > 3 && tables.get(k).order.records.get(l).d.taste.equals("浙菜")) { System.out.println("sweetness num out of range :" + tables.get(k).order.records.get(l).degree); } else { System.out.print(tables.get(k).order.records.get(l).orderNum + " " + tables.get(k).order.records.get(l).d.name + " "); System.out.println(Math.round(tables.get(k).order.records.get(l).getPrice1()));// 输出每条记录的菜价 } } } for (int k = 0; k < tables.size(); k++) {// 输出对应桌的菜品信息 System.out.print("table " + tables.get(k).tableNum + ": "); System.out.print(tables.get(k).getPrice1() + " ");// 输出每桌原价 System.out.print(tables.get(k).getPrice2());// 输出每桌总价 if (tables.get(k).isContainSichuancuisine()) { if (tables.get(k).isContainJincuisine() || tables.get(k).isContainZhejiangcuisine()) { System.out.print( " 川菜 " + tables.get(k).getTotallcopies("川菜") + " " + tables.get(k).getFinalDegree("川菜")); } else System.out.println( " 川菜 " + tables.get(k).getTotallcopies("川菜") + " " + tables.get(k).getFinalDegree("川菜")); } if (tables.get(k).isContainJincuisine()) { if (tables.get(k).isContainZhejiangcuisine()) { System.out.print( " 晋菜 " + tables.get(k).getTotallcopies("晋菜") + " " + tables.get(k).getFinalDegree("晋菜")); } else System.out.println( " 晋菜 " + tables.get(k).getTotallcopies("晋菜") + " " + tables.get(k).getFinalDegree("晋菜")); } if (tables.get(k).isContainZhejiangcuisine()) { System.out.println( " 浙菜 " + tables.get(k).getTotallcopies("浙菜") + " " + tables.get(k).getFinalDegree("浙菜")); } } for (int m = 0; m < users.size(); m++) {// 排列用户信息 for (int n = 0; n < users.size() - m - 1; n++) { for (int p = 0; p < users.get(n).name.length(); p++) { if (users.get(n).name.toLowerCase().charAt(p) > users.get(n + 1).name.toLowerCase().charAt(p)) { User temp = new User(); temp = users.get(n); users.set(n, users.get(n + 1)); users.set(n + 1, temp); break; } if (users.get(n).name.toLowerCase().charAt(p) < users.get(n + 1).name.toLowerCase().charAt(p)) break; } } } for (int m = 0; m < users.size(); m++) {// 输出用户信息 System.out.println(users.get(m).name + " " + users.get(m).phonenum + " " + users.get(m).getPrice()); } } public static boolean isBusinessTime(int year, int month, int day, int hour, int minute, int second) { int week = (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 3) % 7; if (week >= 1 && week <= 5) {// 周一到周五 if (hour > 10 && hour < 14 || (hour == 10 && minute >= 30) || (hour == 14 && minute <= 30)) {// 中午 return true; } else if (hour >= 17 && hour < 20 || (hour == 20 && minute <= 30)) {// 晚上 return true; } else {// 不在周一至周五的营业时间 return false; } } else {// 周末 if (hour > 9 && hour < 21 || (hour == 9 && minute >= 30) || (hour == 21 && minute <= 30)) { return true; } else {// 不在周末的营业时间 return false; } } } public static boolean checkTimeValidity(int year, int month, int day, int hour, int minute, int second) { int[] mon_maxnum = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (year >= 1000 && month >= 1 && month <= 12 && day >= 1) { if ((year % 400 == 0 || year % 4 == 0 && year % 100 != 0) && month == 2) { if (day <= 29 && hour <= 24 && hour >= 0 && minute >= 0 && minute <= 60 && second >= 0 && second <= 60) { return true; } else { return false; } } else if (day <= mon_maxnum[month] && hour <= 24 && hour >= 0 && minute >= 0 && minute <= 60 && second >= 0 && second <= 60) return true; else return false; } else return false; } public static boolean checkDishValidity(String menuMessage) { if (menuMessage.matches(".+\\s[1-9][\\d]{0,}+")) { return true; } if (menuMessage.matches(".+\\s.+\\s[1-9][\\d]{0,}\\sT")) { return true; } return false; } public static boolean checkTableValidity(String tableMessage) { if (tableMessage.matches( "table\\s[\\d]+\\s:\\s.{1,11}\\s(180|181|189|133|135|136)[\\d]{8}\\s[\\d]+/[\\d]+/[\\d]+\\s[\\d]+/[\\d]+/[\\d]+")) { return true; // table+英文空格+桌号+英文空格+":"+英文空格+客户姓名+英文空格+手机号+日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: // HH/MM/SS) } else { return false; } } public static int checkRecordValidity(String recordMessage) { if (recordMessage.matches("[\\d]\\s.+\\s[\\d]+\\s[\\d]+\\s[\\d]+")) { return 1;// 序号+英文空格+菜名+英文空格+口味度值+英文空格+份额+英文空格+份数 } if (recordMessage.matches("[\\d]\\s.+\\s[\\d]+\\s[\\d]+")) { return 2; } return 0; } public static boolean checkDeleteValidity(String recordMessage) { if (recordMessage.matches("[\\d]+\\sdelete")) { return true; } else { return false; } } } class Dish { String name;// 菜品名称 int unit_price; // 单价 String taste; public Dish() { super(); // TODO Auto-generated constructor stub } public Dish(String name, int unit_price, String taste) { super(); this.name = name; this.unit_price = unit_price; this.taste = taste; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getUnit_price() { return unit_price; } public void setUnit_price(int unit_price) { this.unit_price = unit_price; } public int getPrice(int portion) {// 计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) return (int) Math.round(unit_price * (1 + (portion - 1) * 0.5)); } } class Menu { ArrayList<Dish> dishs = new ArrayList<Dish>();// 菜品数组,保存所有菜品信息 public ArrayList<Dish> getDishs() { return dishs; } public void setDishs(ArrayList<Dish> dishs) { this.dishs = dishs; } public Menu(ArrayList<Dish> dishs) { super(); this.dishs = dishs; } public Menu() { super(); // TODO Auto-generated constructor stub } public Dish searthDish(String dishName) {// 根据菜名在菜谱中查找菜品信息,返回Dish对象。 if (dishs == null) return null; for (int i = 0; i < dishs.size(); i++) { if (dishName.equals(dishs.get(i).name)) { return dishs.get(i); } } return null; } public Dish addDish(String dishName, String taste, int unit_price) {// 添加一道菜品信息 Dish dish = new Dish(dishName, unit_price, taste); dishs.add(dish); return dish; } } class Record { String orderNum;// 序号 Dish d;// 菜品 int degree;// 口味度 int portion;// 份额(1/2/3代表小/中/大份) int amout;// 份数 boolean state = true; public String getOrderNum() { return orderNum; } public void setOrderNum(String orderNum) { this.orderNum = orderNum; } public Dish getD() { return d; } public void setD(Dish d) { this.d = d; } public int getPortion() { return portion; } public void setPortion(int portion) { this.portion = portion; } public Record(String orderNum, Dish d, int degree, int portion, int amout) { super(); this.orderNum = orderNum; this.d = d; this.degree = degree; this.portion = portion; this.amout = amout; } public Record(String orderNum, Dish d, int portion, int amout) { super(); this.orderNum = orderNum; this.d = d; this.portion = portion; this.amout = amout; } public Record() { super(); // TODO Auto-generated constructor stub } public int getPrice() {// 计价,计算本条记录的价格 if ((degree > 5 && d.taste.equals("川菜")) || (degree > 4 && d.taste.equals("晋菜")) || (degree > 3 && d.taste.equals("浙菜")) || (state == false)) { return 0; } return d.getPrice(portion) * amout; } public int getPrice1() {// 计价,计算本条记录的价格 if ((degree > 5 && d.taste.equals("川菜")) || (degree > 4 && d.taste.equals("晋菜")) || (degree > 3 && d.taste.equals("浙菜"))) { return 0; } return d.getPrice(portion) * amout; } } class Order { ArrayList<Record> records = new ArrayList<Record>();// 保存订单上每一道的记录 public ArrayList<Record> getRecords() { return records; } public void setRecords(ArrayList<Record> records) { this.records = records; } public Order(ArrayList<Record> records) { super(); this.records = records; } public Order() { super(); // TODO Auto-generated constructor stub } public void addARecord(Record record) {// 添加一条菜品信息到订单中。 records.add(record); } public void delARecordByOrderNum(String orderNum) {// 根据序号删除一条记录 for (int i = 0; i < records.size(); i++) { if (records.get(i).orderNum.equals(orderNum)) { records.get(i).state = !records.get(i).state; } } } public boolean findRecordByNum(String orderNum) {// 根据序号查找一条记录 for (int i = 0; i < records.size(); i++) { if (records.get(i).orderNum.equals(orderNum)) { return true; } } return false; } } class Table { int tableNum; Order order; int[] time = new int[6]; public Table() { super(); // TODO Auto-generated constructor stub } public int getTableNum() { return tableNum; } public void setTableNum(int tableNum) { this.tableNum = tableNum; } public Order getOrder() { return order; } public void setOrder(Order order) { this.order = order; } public Table(int tableNum, Order order) { super(); this.tableNum = tableNum; this.order = order; } public long getPrice2() { long totallPrice = 0; for (int i = 0; i < order.records.size(); i++) { int year = time[0]; int month = time[1]; int day = time[2]; int hour = time[3]; int minute = time[4]; int second = time[5]; int week = (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 1) % 7; if (week >= 1 && week <= 5 && order.records.get(i).d.taste != null) { totallPrice += Math.round(order.records.get(i).getPrice() * 0.7); } else if (week >= 1 && week <= 5 && order.records.get(i).d.taste == null && hour >= 17 && hour < 20 || (hour == 20 && minute <= 30)) { totallPrice += Math.round(order.records.get(i).getPrice() * 0.8); } else if (week >= 1 && week <= 5 && order.records.get(i).d.taste == null && hour > 10 && hour < 14 || (hour == 10 && minute >= 30) || (hour == 14 && minute <= 30)) { totallPrice += Math.round(order.records.get(i).getPrice() * 0.6); } else { totallPrice += Math.round(order.records.get(i).getPrice()); } } return totallPrice; } public int getPrice1() { int totallPrice = 0; for (int i = 0; i < order.records.size(); i++) { totallPrice += Math.round(order.records.get(i).getPrice()); } return totallPrice; } public boolean isContainSichuancuisine() { for (int i = 0; i < order.records.size(); i++) { if (order.records.get(i).d.taste != null) { if (order.records.get(i).d.taste.equals("川菜") && order.records.get(i).state == true) { return true; } } } return false; } public boolean isContainZhejiangcuisine() { for (int i = 0; i < order.records.size(); i++) { if (order.records.get(i).d.taste != null) { if (order.records.get(i).d.taste.equals("浙菜") && order.records.get(i).state == true) { return true; } } } return false; } public boolean isContainJincuisine() { for (int i = 0; i < order.records.size(); i++) { if (order.records.get(i).d.taste != null) { if (order.records.get(i).d.taste.equals("晋菜") && order.records.get(i).state == true) { return true; } } } return false; } public int getAverageDegree(String taste) { double totall = 0; double num = 0; for (int i = 0; i < order.records.size(); i++) { if (order.records.get(i).d.taste != null) { if (order.records.get(i).d.taste.equals(taste)) { if ((order.records.get(i).degree > 5 && order.records.get(i).d.taste.equals("川菜")) || (order.records.get(i).degree > 4 && order.records.get(i).d.taste.equals("晋菜")) || (order.records.get(i).degree > 3 && order.records.get(i).d.taste.equals("浙菜")) || (order.records.get(i).state == false)) { ; } else { totall += order.records.get(i).degree * order.records.get(i).amout; num += order.records.get(i).amout; } } } } return (int) Math.round(totall / num); } public int getTotallcopies(String taste) { int totall = 0; for (int i = 0; i < order.records.size(); i++) { if (order.records.get(i).d.taste != null) { if (order.records.get(i).d.taste.equals(taste)) { if ((order.records.get(i).degree > 5 && order.records.get(i).d.taste.equals("川菜")) || (order.records.get(i).degree > 4 && order.records.get(i).d.taste.equals("晋菜")) || (order.records.get(i).degree > 3 && order.records.get(i).d.taste.equals("浙菜")) || (order.records.get(i).state == false)) { ; } else { totall += order.records.get(i).amout; } } } } return Math.round(totall); } public String getFinalDegree(String taste) { if (taste.equals("川菜")) { if (getAverageDegree("川菜") == 0) {// 不辣、微辣、稍辣、辣、很辣、爆辣 return "不辣"; } else if (getAverageDegree("川菜") == 1) { return "微辣"; } else if (getAverageDegree("川菜") == 2) { return "稍辣"; } else if (getAverageDegree("川菜") == 3) { return "辣"; } else if (getAverageDegree("川菜") == 4) { return "很辣"; } else { return "爆辣"; } } if (taste.equals("晋菜")) {// 不酸、微酸、稍酸、酸、很酸 if (getAverageDegree("晋菜") == 0) { return "不酸"; } else if (getAverageDegree("晋菜") == 1) { return "微酸"; } else if (getAverageDegree("晋菜") == 2) { return "稍酸"; } else if (getAverageDegree("晋菜") == 3) { return "酸"; } else { return "很酸"; } } if (taste.equals("浙菜")) {// 不甜、微甜、稍甜、甜 if (getAverageDegree("浙菜") == 0) { return "不甜"; } else if (getAverageDegree("浙菜") == 1) { return "微甜"; } else if (getAverageDegree("浙菜") == 2) { return "稍甜"; } else { return "甜"; } } return null; } } class User { String name; String phonenum; ArrayList<Table> tables = new ArrayList<Table>(); public User() { super(); // TODO 自动生成的构造函数存根 } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhonenum() { return phonenum; } public void setPhonenum(String phonenum) { this.phonenum = phonenum; } public ArrayList<Table> getTables() { return tables; } public void setTables(ArrayList<Table> tables) { this.tables = tables; } public User(String name, String phonenum, ArrayList<Table> tables) { super(); this.name = name; this.phonenum = phonenum; this.tables = tables; } public int getPrice() { int totallPrice = 0; for (int i = 0; i < tables.size(); i++) { totallPrice += tables.get(i).getPrice2(); } return totallPrice; } }
期中考试
一些知识点:
- 使用ArrayList存储Shape对象。
- 使用while循环根据用户选择创建不同类型的形状对象并添加到ArrayList中。
- 使用Comparator接口的naturalOrder()方法对列表进行排序。
- 实现Comparable接口来定义Shape对象之间的比较规则。
- 创建Point类来表示坐标点。
- 创建抽象类Shape,并在子类Circle和Rectangle中实现抽象方法
7-2 测验2-类结构设计
设计一个矩形类,其属性由矩形左上角坐标点(x1,y1)及右下角坐标点(x2,y2)组成,其中,坐标点属性包括该坐标点的X轴及Y轴的坐标值(实型数),求得该矩形的面积。
分析:这题原题给了类图,难度也不大,直接根据类图去设计代码即可。
import java.util.Scanner; public class Main { 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); } static class Rectangle { private double x1; private double y1; private double x2; private double 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; } } }
7-3 测验3-继承与多态
将测验1与测验2的类设计进行合并设计,抽象出Shape父类(抽象类),Circle及Rectangle作为子类,这题其实就只是在第一题和第二题的基础上添加一个父类,第一题第二题只要写出来了,那第三题其实也大差不差了。
import java.util.Scanner; abstract class Shape { public abstract double getArea(); } class Circle extends Shape { private double radius; public Circle(double radius) { this.radius = radius; } public 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; } public double getArea() { double width = Math.abs(lowerRightPoint.getX() - leftTopPoint.getX()); double height = Math.abs(lowerRightPoint.getY() - leftTopPoint.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(); if (radius <= 0) { System.out.println("Wrong Format"); } else { 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) { double area = shape.getArea(); System.out.printf("%.2f\n", area); } }
7-4 测验4-抽象类与接口
import java.util.ArrayList; import java.util.Comparator; import java.util.Scanner; abstract class Shape implements Comparable<Shape> { public abstract double getArea(); public int compareTo(Shape shape) { double area1 = this.getArea(); double area2 = shape.getArea(); if (area1 < area2) { return -1; } else if (area1 > area2) { return 1; } else { return 0; } } } class Circle extends Shape { private double radius; public Circle(double radius) { this.radius = radius; } public 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; } public double getArea() { double width = Math.abs(lowerRightPoint.getX() - leftTopPoint.getX()); double height = Math.abs(lowerRightPoint.getY() - leftTopPoint.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); ArrayList<Shape> list = new ArrayList<>(); int choice = input.nextInt(); while (choice != 0) { switch (choice) { case 1:// Circle double radius = input.nextDouble(); if (radius <= 0) { System.out.println("Wrong Format"); } else { 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); Shape 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()) + " "); } } }
在测验3的题目基础上,重构类设计,实现列表内图形的排序功能
三、设计与分析
菜单计价程序-4:
题目的基本构架还是与第三次菜单计价系统相似,与之比较明显的区别就是增加了对异常状态处理的分析。
Java 语言定义了一些异常类在 java.lang 标准包中。
标准运行时异常类的子类是最常见的异常类。由于 java.lang 包是默认加载到所有的 Java 程序的,所以大部分从运行时异常类继承而来的异常都可以直接使用。
使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地
Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。
如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。
我个人收集了以下几点,觉得应该是异常处理时候应该要注意的
1.了解异常类型:Java中有很多异常类型,包括运行时异常和受检异常。了解这些异常类型的特点和使用方式,可以帮助我们更好地处理异常。
2.使用try-catch语句:在可能会抛出异常的代码块中使用try-catch语句,可以捕获并处理异常,避免程序崩溃。
3.避免空指针异常:空指针异常是Java中最常见的异常之一。在使用变量或对象之前,应该先进行非空判断,避免出现空指针异常。
4.记录异常信息:当程序抛出异常时,应该记录异常信息,以便后续进行调试和修改。可以使用日志系统或者打印异常堆栈信息的方式记录异常信息。
5.抛出合适的异常:在自定义异常时,应该根据异常的类型和特点,选择合适的异常类来继承或实现。这样可以使异常的语义更加明确,提高代码的可读性和可维护性。
6.异常处理方式的选择:对于不同的异常情况,应该采取不同的异常处理方式。有些异常可以直接忽略,有些异常需要进行修复或重试,有些异常需要提示用户或中断程序运行等。
7.异常处理的位置:在程序中,应该将异常处理的逻辑放在合适的位置,避免出现逻辑错误或异常处理不到位的情况。一般来说,应该将异常处理放在调用异常方法的地方,而不是在被调用的方法中处理异常。
菜单计价程序-5:
本题在菜单计价程序-3的基础上增加了部分内容,增加的内容用加粗字体标识。
注意不是菜单计价程序-4,本题和菜单计价程序-4同属菜单计价程序-3的两个不同迭代分支。
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。
菜单由一条或多条菜品记录组成,每条记录一行
每条菜品记录包含:菜名、基础价格 三个信息。
订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。
桌号标识独占一行,包含两个信息:桌号、时间。
桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。
点菜记录包含:序号、菜名、份额、份数。份额可选项包括:1、2、3,分别代表小、中、大份。
不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。
删除记录格式:序号 delete
标识删除对应序号的那条点菜记录。
如果序号不对,输出"delete error"
代点菜信息包含:桌号 序号 菜品名称 口味度 份额 份数
代点菜是当前桌为另外一桌点菜,信息中的桌号是另一桌的桌号,带点菜的价格计算在当前这一桌。
程序最后按输入的先后顺序依次输出每一桌的总价(注意:由于有代点菜的功能,总价不一定等于当前桌上的菜的价格之和)。
每桌的总价等于那一桌所有菜的价格之和乘以折扣。如存在小数,按四舍五入规则计算,保留整数。
折扣的计算方法(注:以下时间段均按闭区间计算):
周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。
周末全价,营业时间:9:30-21:30
如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"
参考以下类的模板进行设计:菜品类:对应菜谱上一道菜的信息。
Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }
菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
Menu {
Dish[] dishs ;//菜品数组,保存所有菜品信息
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
Dish addDish(String dishName,int unit_price)//添加一道菜品信息
}
点菜记录类:保存订单上的一道菜品记录
Record {
int orderNum;//序号\\
Dish d;//菜品\\
int portion;//份额(1/2/3代表小/中/大份)\\
int getPrice()//计价,计算本条记录的价格\\
}
订单类:保存用户点的所有菜的信息。
Order {
Record[] records;//保存订单上每一道的记录
int getTotalPrice()//计算订单的总价
Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。
delARecordByOrderNum(int orderNum)//根据序号删除一条记录
findRecordByNum(int orderNum)//根据序号查找一条记录
}
类设计如下:
- 我先创建一个Menu对象来存储菜单信息。
- 通过Scanner对象从控制台读入菜单信息,按照特定的格式进行解析,将菜品信息添加到Menu对象中。
- 创建一个ArrayList来存储Table对象和一个ArrayList来存储顾客姓名。
- 通过Scanner对象从控制台读入订单信息,按照特定的格式进行解析,根据订单类型进行相应的操作。
- 将Table对象添加到Tables列表中,并检查订单的合法性和时间是否在营业时间范围内。
- 最后,根据需求打印输出订单信息和统计信息。
整个代码由多个类组成,每个类都有特定的功能:
- Dish类表示菜品,包含菜品名称、单价和菜品类型。
- Menu类表示菜单,包含一个菜品列表和相关的操作方法。
- Record类表示订单记录,包含订单编号、菜品、份数、数量、口味等信息。
- Table类表示餐桌,包含订单记录列表、餐桌号、顾客姓名、电话号码、日期、时间等信息,以及相关的操作方法。
代码还使用了枚举类型DishType来表示菜品类型(川菜、晋菜、浙菜)。
总体而言,该代码通过读取用户输入的菜单和订单信息,进行解析和处理,最后输出订单信息和统计信息。它实现了简单的餐厅订单管理功能。
四、踩坑心得
在菜单四中我遇到的一些问题和踩坑心得:
-
输入格式验证:确保输入的格式符合要求,例如正确的桌号格式、时间格式以及菜单、订单的格式。对于不合法的输入,需要进行适当的错误处理。
-
数据结构选择:选择合适的数据结构来存储菜谱、订单和点菜记录等信息。在这个问题中,使用哈希表(HashMap、TreeMap)可以方便地进行快速查找和存储。
-
菜谱信息与订单信息分离:在处理输入时,需要将菜谱信息和订单信息分开处理,并进行合适的操作。菜谱信息应添加到菜单对象中,订单信息应根据桌号查找或创建订单对象。
-
删除记录和合并记录:在处理删除记录时,需要注意删除的合法性和重复删除的情况。另外,如果有相同桌号、菜名和份额的点菜记录,应将它们合并为一条记录进行计算,避免四舍五入误差的累积。
-
营业时间和折扣计算:根据问题描述中提供的营业时间和折扣规则,需要编写逻辑来判断是否在营业时间内,并计算相应的折扣。
-
异常情况处理:在代码中应该考虑各种异常情况,并进行适当的错误处理。例如,处理不存在的桌号、重复的菜谱信息、重复的删除记录等情况,给出合适的错误提示。
在菜单五中我遇到的一些问题和踩坑心得:
-
访问修饰符错误:忘记添加正确的访问修饰符(如
public
、private
)可能导致无法访问或访问权限错误。 -
参数传递错误:在调用方法或构造函数时,传递的参数类型、顺序或数量与方法定义不匹配,这会导致编译错误或运行时错误。
-
空指针异常:使用未初始化的对象或空引用调用方法或访问属性会导致空指针异常。在使用对象之前,要确保其已经被正确地初始化。
-
下标越界:在访问数组、集合或字符串时,使用超出其索引范围的下标会导致下标越界异常。要确保使用有效的索引。
-
对象比较错误:使用
==
比较对象时,比较的是对象的引用而不是内容。要比较对象的内容,应使用equals()
方法。 -
循环条件错误:在编写循环时,循环条件的判断错误可能导致死循环或无法执行循环体。
在期中考试中我遇到的一些问题和踩坑心得:
1.参数错误,使用构造方法时需要注意参数的类型和顺序是否正确,否则会出现编译错误或运行时错误。
2.循环的范围有误。
五、改进建议
代码除了能否运行之外,还要注重代码本身的稳定性和健壮性,在相应题目的编码改进方面,
我觉得可以考虑通过优化算法、增加注释、精简代码等方式来提高代码质量和可读性。另外,在提交源码之前,要仔细检查代码的逻辑和精度,确保答案的正确性。
1.类的封装:考虑将每个类放在单独的文件中,并使用适当的访问修饰符(如private、protected、public)来限制成员变量和方法的访问权
2.操作符的连续使用:在使用Scanner读取输入时,可以考虑使用操作符的连续使用来简化代码。例如,可以将以下代码段:
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double x2 = input.nextDouble();
double y2 = input.nextDouble();
简化为
double x1, y1, x2, y2;
x1 = input.nextDouble();
y1 = input.nextDouble();
x2 = input.nextDouble();
y2 = input.nextDouble();
菜单系类:
- 在使用try-catch块捕获异常时,尽量避免捕获所有异常,可以只捕获需要处理的特定异常类型,以便更好地处理异常情况。
- 在比较字符串时,推荐使用
equals()
方法而不是"=="运算符,以确保比较的是字符串的内容而不是引用。 - 考虑使用更简洁的语法来初始化集合。例如,可以使用更现代的方式初始化HashMap,如
Map<String, String> map = Map.of("川菜", "Chuan", "晋菜", "Jin", "浙菜", "Zhe");
。
4.重写toString()方法:在Shape、Circle和Rectangle类中,可以重写toString()方法以提供更有意义的字符串表示形式。这将有助于调试和输出对象时的可读性
5. 将 Reord
类中的 flag
属性改为 isValid
或 isFlagged
,更能表达其含义。
6.将 Record
类中的 givenId
属性改为 givenTableId
,以更清晰地表示其含义。
7.考虑将 Record
类的一些逻辑(如价格计算和级别检查)封装为方法,以提高代码的可读性和可维护性。
六.总结
首先,通过实现Comparable接口,我学会了如何对自定义类进行比较和排序。在实现Comparable接口时,我需要重写compareTo方法,根据自定义的比较规则来比较两个对象的大小。实现Comparable接口让我更深入地理解了面向对象程序设计的思想。通过比较对象的某个属性或多个属性,我可以根据需要对对象进行排序或判断它们之间的大小关系。这种思想可以应用于各种场景,例如对学生成绩进行排序、对员工按照薪资进行排序等。实现Comparable接口也提高了我的编程能力。通过编写compareTo方法,我需要考虑到各种情况下对象的比较结果,并返回适当的值。这要求我在编写代码时思考问题更全面,考虑到各种边界情况,提高了我的逻辑思维和编程能力。实现Comparable接口还让我的代码更加规范和易于维护。通过实现Comparable接口,我可以直接使用Java提供的排序方法(如Collections.sort())对对象进行排序,而不需要额外编写比较器。这样可以减少代码量,使代码更加简洁和易读。通过编写这个菜单系类,我学会了如何使用Java编程语言来构建一个基本的命令行应用程序,了解了面向对象编程的基本概念和原则,并将其应用到了项目中。学习了类的定义和使用,对象的创建和操作,以及如何设计和组织代码结构。掌握了异常处理的方法和技巧,以及如何在程序中有效地处理错误和异常情况。学会了使用集合类(如ArrayList和HashMap)来存储和管理数据,并应用它们来实现系统的各项功能。通过自己的思考和查阅相关资料,我成功地解决了一些问题并提高了对Java编程的理解能力。一步一步逐渐完善自己设计,这是个艰辛但成果很愉悦的过程。还有就是编程思维得到了训练和提升,掌握了一些基础题目的编程思想。了解了开闭原则,及继承和多态的使用,对面向对象又有了一层新的认识。在写PTA的过程中我意识到自己代码的可读性十分差,条理性还不够清晰,我应注重代码书写习惯。所以学习JAVA,不仅对我们以后学习其他语言有很大的好处,而且也让我们知道了和理解了作为一个编程人员首先应具有的良好心理素质,那是冷静思考和专心致志。对待学术知识应该是严谨和认真。路漫漫其修远兮。相较于之前三次大作业,这几次经验也变的更足了,但是能力方面还是有点没跟上,也希望自己总结了之前的优缺点之后总结,能够让自己的能力更上一层楼。同时,我也意识到了代码质量和精度对于程序正确性的重要性,需要在以后的学习中不断提高自己的编程水平。
标签:tablemes,int,BLOG2,records,&&,get,public From: https://www.cnblogs.com/1111I/p/17842057.html