大作业分析-2
前言:
在第四次大作业,第五次大作业和期中考试过后,我(被折磨的不轻)熟练地使用了“面向对象”,并对类,抽象类和接口有了一个较深的理解。因为除去较为简单的期中考试,大作业难度都有较大提升,所以我接下来会着重分析一下大作业方面。
第四次大作业:
本次大作业着重了对大部分异常情况的处理,以及增加了特色菜和特殊的价格计算,处理上会更加的麻烦。这个就需要熟知各种异常情况以及它们的区别,然后做出不同的应对方式,以及特殊的价格计算。
第五次大作业:
本次大作业和第四次大作业是两个完全不同的方向,所以不能以第四次大作业的基础上来继续改,而是从第三次大作业的基础上来追加。本次大作业主要方向为新增特色菜,口味值,特殊的价格计算及单用户多桌菜。难度上比起第四次大作业较为简单,但也需要自己的理解在里面。
期中考试:
这个相较于前面两次大作业就容易上不少。主要难度还是集中在最后一题的接口。对于没见过Comparable接口的可能初次接触会比较困难,不过熟悉之后用起来还是较为简单。所以这个题目会简略地写。
接下来我会着重分析一下我认为最为重点的几道题目(虽然好像一共也没几道题)。
设计与分析及踩坑心得:
菜单计价程序-4:
代码:
import java.util.Scanner; import java.util.regex.Pattern; import java.time.*; import java.time.format.DateTimeFormatter; import java.util.Date; public class Main{ public static void main(String[] args) { Scanner in=new Scanner(System.in); int a=-1;//判断当前是第几桌 int d=0;//判断代点菜中桌号是否存在 int e=0;//判断本桌订单是否应被忽略 int f=-1;//判断总共有几桌 int n=0;//判断当前桌号是否相同 int i; Menu menu=new Menu(); Dish dish=new Dish(); Table[] table=new Table[10]; Table t=new Table(); Record record=new Record(); while(true) { String b=in.nextLine(); if(b.equals("end"))//读到end就结束 break; if(b.length()==0)//空行输入 { System.out.println("wrong format"); continue; } String[] c=b.split(" "); if(c[0].equals("table")) { if(c.length!=4||!c[1].matches("[0-9]+")||!t.tablenumlegal(c[1])||!t.formatlegality(c[2],c[3]))//判断非法格式输入(含桌号为非数字,时间格式错误) { System.out.println("wrong format"); e=1; } else if(Integer.parseInt(c[1])>55||Integer.parseInt(c[1])<1)//桌号超出范围 { System.out.println(c[1]+" table num out of range"); e=1; } else if(!t.datalegality(c[2],c[3]))//判断时间数据非法 { System.out.println(c[1]+" date error"); e=1; } else if(!t.validtime(c[2]))//时间数据有效但超出范围 { System.out.println("not a valid time period"); e=1; } else { n=0; if(t.aopeningtime(c[2],c[3]))//在开放时间内 { for(i=0;i<=f;i++) { if(Integer.parseInt(c[1])==table[i].num)//桌号相同 { if(table[i].samenum(c[2],c[3]))//在同一个时间段 { a=i; n=1; table[i].n++; table[i].order[table[i].n]=new Order(); break; } } } } else //不在开放时间内 { System.out.println("table "+c[1]+" out of opening hours"); e=1; continue; } e=0; System.out.println("table "+c[1]+": "); if(n==1) continue; f++; a=f; table[f]=new Table(); table[f].order[table[f].n]=new Order(); table[f].addATable(Integer.parseInt(c[1]),c[2],c[3]); } continue; } if(e==1)//错误桌号输入不考虑下面订单 continue; if(f==-1)//增加菜谱 { if(c.length>4) { e=1; System.out.println("wrong format"); continue; } if(!c[1].matches("[0-9]+")||!dish.pricelegal(c[1]))//菜价格式不对或不为整数 System.out.println("wrong format"); else if(Integer.parseInt(c[1])<1||Integer.parseInt(c[1])>299)//菜价超出范围 System.out.println(c[0]+" price out of range "+c[1]); else { if(c.length==3&&!c[2].equals("T")) System.out.println("wrong format"); else if(menu.searthDish(c[0])==null)//正常输入菜谱 { menu.addDish(c[0],Integer.parseInt(c[1])); if(c.length==3)//特色菜 menu.dishs[menu.n-1].specialty=true; } else//重复输入菜名 { menu.searthDish(c[0]).unit_price=Integer.parseInt(c[1]); if(c.length==3) menu.searthDish(c[0]).specialty=true; } } } else//开始订单 { if(c.length==2) { if(c[1].equals("delete"))//删除程序 { if(table[a].order[table[a].n].findRecordByNum(Integer.parseInt(c[0]))!=null)//序号存在 table[a].order[table[a].n].delARecordByOrderNum(table[a].order[table[a].n].findRecordByNum(Integer.parseInt(c[0]))); else//序号不存在,删除失败 System.out.println("delete error"); } else if(c[1].matches("[0-9]+"))//订单中混入菜谱 System.out.println("invalid dish"); else System.out.println("wrong format"); } else if(c.length==3) { if(c[2].equals("T"))//特价菜菜谱混入订单 System.out.println("invalid dish"); else//错误格式输入 System.out.println("wrong format"); } else if(c.length==4)//点菜 { if(!table[a].order[table[a].n].numlegal(c[0]))//序号格式不正确 System.out.println("wrong format"); else if(!table[a].order[table[a].n].judgesize(Integer.parseInt(c[0])))//本次点菜序号小于上一位 System.out.println("record serial number sequence error"); else if(menu.searthDish(c[1])==null)//菜谱上没有这道菜 { System.out.println(c[1]+" does not exist"); table[a].order[table[a].n].addNRecord(Integer.parseInt(c[0])); } else if(!record.portiontrue(c[2]))//份额不正确 { if(record.portionlegal(c[2])) System.out.println(c[0]+" portion out of range "+c[2]); else//份额超过一位 System.out.println("wrong format"); } else if(!record.numlegal(c[3]))//份数不为数值 System.out.println("wrong format"); else if(Integer.parseInt(c[3])>15)//份数超过15份 System.out.println(c[0]+" num out of range "+c[3]); else//正常点菜 { table[a].order[table[a].n].addARecord(Integer.parseInt(c[0]),menu.searthDish(c[1]),Integer.parseInt(c[2]),Integer.parseInt(c[3])); System.out.println(c[0]+" "+c[1]+" "+table[a].order[table[a].n].records[table[a].order[table[a].n].n-1].getPrice()); } } else if(c.length==5)//代点菜或其他 { if(!c[1].matches("[0-9]+"))//非法输入 System.out.println("wrong format"); else//代点菜 { d=0; for(i=0;i<f;i++) if(Integer.parseInt(c[0])==table[i].num) d=1; if(d==1)//桌号存在 { if(menu.searthDish(c[2])!=null)//代点菜存在 { table[a].order[table[a].n].addARecord(Integer.parseInt(c[1]),menu.searthDish(c[2]),Integer.parseInt(c[3]),Integer.parseInt(c[4])); System.out.println(c[1]+" table "+table[a].num+" pay for table "+c[0]+" "+table[a].order[table[a].n].records[table[a].order[table[a].n].n-1].getPrice()); } else//代点菜不存在 { System.out.println(c[2]+" does not exist"); table[a].order[table[a].n].addNRecord(Integer.parseInt(c[1])); } } else System.out.println("Table number :"+c[0]+" does not exist"); } } else//错误格式输入 System.out.println("wrong format"); } } //开始输出总价 for(i=0;i<=f;i++) { if(table[i].openingtime()) System.out.println("table "+table[i].num+": "+table[i].getTotalPrice()+" "+table[i].getDiscountPrice()); else System.out.println("table "+table[i].num+" out of opening hours"); } } } //菜品类:对应菜谱上一道菜的信息。 class Dish { String name;//菜名 int unit_price;//单价 boolean specialty=false;//标记是否是特色菜 int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) { double p=0; switch(portion) { case 1:p=unit_price;break; case 2:p=unit_price*1.5;break; case 3:p=unit_price*2;break; } return (int)Math.round(p); } boolean pricelegal(String p)//判断菜价格式是否正确 { if(p.length()>1&&p.charAt(0)=='0') return false; return true; } } //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 class Menu { Dish[] dishs =new Dish[10];//菜品数组,保存所有菜品信息 int n=0;//记录菜谱上的菜数 Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。 { int i; for(i=0;i<n;i++) if(dishName.equals(dishs[i].name)) return dishs[i]; return null; } void addDish(String dishName,int unit_price)//添加一道菜品信息 { dishs[n]=new Dish(); dishs[n].name=dishName; dishs[n].unit_price=unit_price; n++; } } //点菜记录类:保存订单上的一道菜品记录 class Record { int orderNum;//序号 Dish d;//菜品 int portion;//份额(1/2/3代表小/中/大份) int num;//份数 boolean delete=false;//判断本道订单是否被删除 boolean exit;//判断本道订单是否存在 int getPrice()//计价,计算本条记录的价格 { return d.getPrice(portion)*num; } boolean portionlegal(String p)//检测份额是否超出一位 { if(p.length()>1) return false; return true; } boolean numlegal(String n)//检测份数是否最高位为0 { if(n.length()>1&&n.charAt(0)=='0') return false; return true; } boolean portiontrue(String p)//判断份额是否正确 { if(p.matches("[1-3]")) return true; return false; } } //订单类:保存用户点的所有菜的信息。 class Order { Record[] records=new Record[10];//保存订单上每一道的记录 int n=0;//记录共有多少道订单 int getTotalPrice()//计算订单的总价 { int i,p=0; for(i=0;i<n;i++) if(records[i].delete==false&&records[i].exit) p+=records[i].getPrice(); return p; } void addARecord(int orderNum,Dish d,int portion,int num)//添加一条合法菜品信息到订单中。 { records[n]=new Record(); records[n].orderNum=orderNum; records[n].d=d; records[n].portion=portion; records[n].num=num; records[n].exit=true; n++; } void addNRecord(int orderNum)//添加一条非法菜品信息到订单中 { records[n]=new Record(); records[n].orderNum=orderNum; records[n].exit=false; n++; } void delARecordByOrderNum(Record record)//根据序号删除一条记录 { if(record.delete==false) record.delete=true; else System.out.println("deduplication "+record.orderNum); } boolean judgesize(int n)//判断是否这一次点菜记录是否大于上一次 { int p=-1,i; for(i=this.n-1;i>=0;i--) if(records[i].exit) { p=i; break; } if(p!=-1&&n<=records[p].orderNum) return false; return true; } Record findRecordByNum(int orderNum)//根据序号查找一条记录 { int i; for(i=0;i<n;i++) if(records[i].orderNum==orderNum) return records[i]; return null; } boolean numlegal(String n)//检测序号是否最高位为0 { if(n.length()>1&&n.charAt(0)=='0') return false; return true; } } //桌类:记录每一桌的信息 class Table { Order[] order=new Order[10];//本桌订单 int n=0;//记录当前有几次订单 int num;//记录桌号 String Date;//点菜日期 String Time;//点菜时间 void addATable(int num,String Date,String Time)//添加桌信息 { this.num=num; this.Date=Date; this.Time=Time; } boolean formatlegality(String Date,String Time)//判断格式是否合法 { String[] a=Date.split("/"); if(a[0].length()==4&&a[1].length()<=2&&a[2].length()<=2) { String[] b=Time.split("/"); if(b[0].length()<=2&&b[1].length()<=2&&b[2].length()<=2) return true; } return false; } boolean datalegality(String Date,String Time)//判断数据输入是否合法 { String[] a=Date.split("/"); String[] b=Time.split("/"); int[] c=new int[6]; c[0]=Integer.parseInt(a[1]); c[1]=Integer.parseInt(a[2]); c[2]=Integer.parseInt(b[0]); c[3]=Integer.parseInt(b[1]); c[4]=Integer.parseInt(b[2]); c[5]=Integer.parseInt(a[0]); if(c[0]<=12&&c[0]>0) if(c[2]<24&&c[2]>=0) if(c[3]>=0&&c[3]<60) if(c[4]>=0&&c[4]<60) { if(c[0]<=7&&c[0]%2==1) { if(c[1]<=31&&c[1]>0) return true; } else if(c[0]==2) { if((c[5]%4==0&&c[5]%100!=0)||(c[5]%400==0)) { if(c[1]<=29&&c[1]>0) return true; } else if(c[1]<=28&&c[1]>0) return true; } else if(c[0]>=8&&c[0]<=12&&c[0]%2==0) { if(c[1]<=31&&c[1]>0) return true; } else if(c[1]>0&&c[1]<=30) return true; } return false; } boolean validtime(String Date)//判断时间是否在2022.1.1-2023.12.31之间 { DateTimeFormatter fmt1 = DateTimeFormatter.ofPattern("yyyy/M/d"); LocalDate date = LocalDate.parse(Date, fmt1); LocalDate date1=LocalDate.parse("2021/12/31",fmt1); LocalDate date2=LocalDate.parse("2024/1/1",fmt1); if(date.isAfter(date1)&&date.isBefore(date2)) return true; return false; } boolean openingtime()//判断是否在开放时间内 { DateTimeFormatter fmt1 = DateTimeFormatter.ofPattern("yyyy/M/d"); LocalDate date = LocalDate.parse(Date, fmt1); DateTimeFormatter fmt2 = DateTimeFormatter.ofPattern("H/m/s"); LocalTime time=LocalTime.parse(Time,fmt2); int a=date.getDayOfWeek().getValue(); if(a<=5&&a>=1)//周一至周五 { LocalTime time1=LocalTime.parse("16/59/59",fmt2); LocalTime time2=LocalTime.parse("20/30/1",fmt2); LocalTime time3=LocalTime.parse("10/29/59",fmt2); LocalTime time4=LocalTime.parse("14/30/1",fmt2); if((time.isAfter(time1)&&time.isBefore(time2))||(time.isAfter(time3)&&time.isBefore(time4))) return true; } else//周末 { LocalTime time1=LocalTime.parse("9/29/59",fmt2); LocalTime time2=LocalTime.parse("21/30/1",fmt2); if(time.isAfter(time1)&&time.isBefore(time2)) return true; } return false; } int getDiscountPrice()//计算折扣价 { int i,a,n,j; double p=getTotalPrice(),q=0; DateTimeFormatter fmt1=DateTimeFormatter.ofPattern("yyyy/M/d"); LocalDate date=LocalDate.parse(Date,fmt1); DateTimeFormatter fmt2 = DateTimeFormatter.ofPattern("H/m/s"); LocalTime time=LocalTime.parse(Time,fmt2); a=date.getDayOfWeek().getValue(); if(a<=5&&a>=1)//周一至周五 { for(j=0;j<=this.n;j++) for(i=0;i<order[j].n;i++) if(!order[j].records[i].delete&&order[j].records[i].exit&&order[j].records[i].d.specialty) q+=order[j].records[i].getPrice(); p-=q;//减去特色菜,特色菜额外计算折扣 q=q*0.7;//计算特色菜折扣 LocalTime time1=LocalTime.parse("16/59/59",fmt2); LocalTime time2=LocalTime.parse("20/30/1",fmt2); if(time.isAfter(time1)&&time.isBefore(time2))//晚上八折 p=p*0.8; else//中午六折 p=p*0.6; n=(int)Math.round(p)+(int)Math.round(q); } else//周末全价 n=(int)p; return n; } boolean tablenumlegal(String n)//检测桌号是否最高位为0 { if(n.length()>1&&n.charAt(0)=='0') return false; return true; } boolean samenum(String Date,String Time)//判断桌号相同是否在一个时间段 { if(!this.Date.equals(Date)) return false; else { DateTimeFormatter fmt1=DateTimeFormatter.ofPattern("yyyy/M/d"); LocalDate date=LocalDate.parse(Date,fmt1); DateTimeFormatter fmt2 = DateTimeFormatter.ofPattern("H/m/s"); LocalTime time=LocalTime.parse(Time,fmt2); LocalTime time5=LocalTime.parse(this.Time,fmt2); int a=date.getDayOfWeek().getValue(); if(a<=5&&a>=1)//周一至周五 { LocalTime time1=LocalTime.parse("16/59/59",fmt2); LocalTime time2=LocalTime.parse("20/30/1",fmt2); LocalTime time3=LocalTime.parse("10/29/59",fmt2); LocalTime time4=LocalTime.parse("14/30/1",fmt2); if((time.isAfter(time1)&&time.isBefore(time2))&&(time5.isAfter(time1)&&time5.isBefore(time2))) return true; else if((time.isAfter(time3)&&time.isBefore(time4))&&(time5.isAfter(time3)&&time5.isBefore(time4))) return true; } else//周末 { if(time.minusHours(1).isBefore(time5)||time.plusHours(1).isAfter(time5)) return true; } return false; } } boolean aopeningtime(String Date,String Time)//判断是否在开放时间内 { DateTimeFormatter fmt1 = DateTimeFormatter.ofPattern("yyyy/M/d"); LocalDate date = LocalDate.parse(Date, fmt1); DateTimeFormatter fmt2 = DateTimeFormatter.ofPattern("H/m/s"); LocalTime time=LocalTime.parse(Time,fmt2); int a=date.getDayOfWeek().getValue(); if(a<=5&&a>=1)//周一至周五 { LocalTime time1=LocalTime.parse("16/59/59",fmt2); LocalTime time2=LocalTime.parse("20/30/1",fmt2); LocalTime time3=LocalTime.parse("10/29/59",fmt2); LocalTime time4=LocalTime.parse("14/30/1",fmt2); if((time.isAfter(time1)&&time.isBefore(time2))||(time.isAfter(time3)&&time.isBefore(time4))) return true; } else//周末 { LocalTime time1=LocalTime.parse("9/29/59",fmt2); LocalTime time2=LocalTime.parse("21/30/1",fmt2); if(time.isAfter(time1)&&time.isBefore(time2)) return true; } return false; } int getTotalPrice()//计算折前总价 { int i,p=0; for(i=0;i<=n;i++) p+=order[i].getTotalPrice(); return p; } }

这个图应该是有问题的。可能是软件问题,但我这个复杂度就是出不来……所以看看就好,咱先忽略这玩意。
本次作业相较于第三次大作业菜单题目,我并没有新增类,而是在类中增加了若干方法。例如判断格式错误等等。不过后面想到这部分可以用接口来做,但是我当时没想到……没办法了,下次再改吧。类方面就不过多分析了,主要挑几个我觉得重点的踩坑心得来分析。
踩坑心得:
1.关于“空行输入”:
一开始还真没想到有这个测试点,提交后才发现。当时专门新建了一个Java project来测试空行输入会是一个什么结果。
假设字符串b接受了空行输入,那么它的长度(b.length())就是等于0,可以根据此来判断是否有空行输入,如果有,就输出wrong format。
如下:

2.关于“桌号格式正确”:
这个我想了半天,还去网上找了一堆麻烦的接口,最后发现用正则表达式就能简单地解决判断桌号是否为数字的问题。
如下:

3.关于“判断桌号时间是否正确”:
实不相瞒,我上一次作业还在把数组分开然后一个个比大小,这次才慢慢学会使用时间相关方法。这里有点多就不一一分析了,但是比较值得注意的一点是时间格式输入应该是“yyyy/M/d”而不是“yyyy/MM/dd”,否者月份和日子只有一位数输入的时候就会报错。
如下:

4.关于“删除”:
这里主要不是本次作业的问题,而是上一次:直到第四次大作业出来,我才明白我第三次为什么错了一些测试点——第三次大作业根本没考虑重复删除的情况!!!我偏偏要作死去考虑……救命……
5.关于“菜谱输入”:
这个属于一开始没考虑。一开始输入菜谱只想到通过数组长度来判断是否有特价菜,不过后面才想到可能特价菜谱的输入最后一个输入不是T的情况。属于需要注意的地方。
6.关于“计算总价”:
其实这里我主要是想吐槽,特价菜真的纯纯增加计算负担量,而且如果我在周一至周五的中午吃特价菜还亏了……你做什么餐馆啊黑心商家。
关于第四次大作业最好的一点是它开放了部分测试数据,不用多找测试点真的很爽。但是真的努力到最后发现还是有两个测试点找不到……有点麻的。什么时候能开放全部测试点可恶啊。
菜单计价程序-5:
代码:
import java.util.Scanner; import java.util.regex.Pattern; import java.time.*; import java.time.format.DateTimeFormatter; import java.util.Date; public class Main { public static void main(String[] args) { Scanner in=new Scanner(System.in); int a=0;//计算点菜人数 int d=0;//判断菜单输入是否结束 int e=0;//计算桌数 int f=0;//判断当前是第几人 int g=0;//判断当前订单是否忽略 int h=0;//判断本桌是否有特色菜 int i,j; Man[] men=new Man[10]; Man man=new Man(); Menu menu=new Menu(); Table[] tables=new Table[10]; Table table=new Table(); while(true) { String b=in.nextLine(); if(b.equals("end"))//结束 break; String[] c=b.split(" "); if(c[0].equals("table"))//开始输入桌 { d=1; if(c.length==7&&c[1].matches("[0-9]+")&&man.name(c[3])&&man.phonenumber(c[4])&&table.aopeningtime(c[5],c[6]))//正常订单 { g=0; f=-1; for(i=0;i<a;i++) if(men[i].name.equals(c[3]))//名字相同,并入一起计算 { f=i; break; } if(f==-1)//名字不同,申请新人类和桌类 { f=a; men[f]=new Man(c[3],c[4]); a++; } tables[e]=new Table(); men[f].addTable(Integer.parseInt(c[1]),c[5],c[6]); tables[e]=men[f].table[men[f].n-1]; e++; System.out.println("table "+c[1]+": "); } else if(c.length!=7||!c[1].matches("[0-9]+")||!man.name(c[3])||!man.phonenumber(c[4]))//格式不正确 { System.out.println("wrong format"); g=1; } else //在开放时间外 { System.out.println("table "+c[1]+" out of opening hours"); g=1; } continue; } if(g==1) continue; if(d==0)//输入菜单 { if(c.length==2)//普通菜 { if(menu.searthDish(c[0])==null) menu.addDish(c[0],Integer.parseInt(c[1])); else//有重复菜单,以后者为准 { menu.searthDish(c[0]).specialty=false; menu.searthDish(c[0]).unit_price=Integer.parseInt(c[1]); } } else if(c.length==4)//特色菜 { if((c[1].equals("川菜")||c[1].equals("晋菜")||c[1].equals("浙菜"))&&c[3].equals("T"))//正常输入 { if(menu.searthDish(c[0])==null) menu.addTDish(c[0],c[1],Integer.parseInt(c[2])); else//有重复菜单,以后者为准 { menu.searthDish(c[0]).specialty=true; if(c[1].equals("川菜")) menu.searthDish(c[0]).taste=1; else if(c[1].equals("晋菜")) menu.searthDish(c[0]).taste=2; else menu.searthDish(c[0]).taste=3; menu.searthDish(c[0]).unit_price=Integer.parseInt(c[2]); } } else System.out.println("wrong format"); } else System.out.println("wrong format"); } else//开始订单 { if(c.length==2)//删除 { if(men[f].table[men[f].n-1].order.findRecordByNum(Integer.parseInt(c[0]))==null)//删除序号找不到订单 System.out.println("delete error"); else men[f].table[men[f].n-1].order.findRecordByNum(Integer.parseInt(c[0])).delete=true; } else if(c.length==4)//自点普通菜 { if(menu.searthDish(c[1])==null)//菜谱不存在此菜 { System.out.println(c[1]+" does not exist"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[0])); } else if(menu.searthDish(c[1]).specialty==true) { System.out.println("wrong format"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[0])); } else { men[f].table[men[f].n-1].order.addARecord(Integer.parseInt(c[0]),menu.searthDish(c[1]),Integer.parseInt(c[2]),Integer.parseInt(c[3])); System.out.println(c[0]+" "+c[1]+" "+men[f].table[men[f].n-1].order.records[men[f].table[men[f].n-1].order.n-1].getPrice()); } } else if(c.length==5)//点特色菜或代点普通菜 { if(c[1].matches("[0-9]+"))//代点菜 { if(menu.searthDish(c[2])==null)//菜谱不存在此菜 { System.out.println(c[2]+" does not exist"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[1])); } else if(menu.searthDish(c[2]).specialty==true) { System.out.println("wrong format"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[1])); } else { for(i=0;i<e;i++) if(tables[i].num==Integer.parseInt(c[0])) break; tables[i].order.addORecord(Integer.parseInt(c[1]),menu.searthDish(c[2]),Integer.parseInt(c[3]),Integer.parseInt(c[4])); men[f].table[men[f].n-1].order.addARecord(Integer.parseInt(c[1]),menu.searthDish(c[2]),Integer.parseInt(c[3]),Integer.parseInt(c[4])); men[f].table[men[f].n-1].order.records[men[f].table[men[f].n-1].order.n-1].byother=false; System.out.println(c[1]+" table "+men[f].table[men[f].n-1].num+" pay for table "+c[0]+" "+men[f].table[men[f].n-1].order.records[men[f].table[men[f].n-1].order.n-1].getPrice()); } } else//点特色菜 { if(menu.searthDish(c[1])==null)//菜谱不存在此菜 { System.out.println(c[1]+" does not exist"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[0])); } else if(menu.searthDish(c[1]).specialty==false) { System.out.println("wrong format"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[0])); } else { if(!menu.searthDish(c[1]).tasteoutofrange(Integer.parseInt(c[2])))//口味度超过正常范围 { switch(menu.searthDish(c[1]).taste) { case 1:System.out.print("spicy num out of range :"+c[2]);break; case 2:System.out.print("acidity num out of range :"+c[2]);break; case 3:System.out.print("sweetness num out of range :"+c[2]);break; } System.out.print("\n"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[0])); } else { men[f].table[men[f].n-1].order.addARecord(Integer.parseInt(c[0]),menu.searthDish(c[1]),Integer.parseInt(c[3]),Integer.parseInt(c[4])); men[f].table[men[f].n-1].order.records[men[f].table[men[f].n-1].order.n-1].tastenum=Integer.parseInt(c[2]); System.out.println(c[0]+" "+c[1]+" "+men[f].table[men[f].n-1].order.records[men[f].table[men[f].n-1].order.n-1].getPrice()); } } } } else if(c.length==6)//代点特色菜 { if(menu.searthDish(c[2])==null)//菜谱不存在此菜 { System.out.println(c[2]+" does not exist"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[1])); } else if(menu.searthDish(c[2]).specialty==false) { System.out.println("wrong format"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[1])); } else if(!menu.searthDish(c[2]).tasteoutofrange(Integer.parseInt(c[3])))//口味度超过正常范围 { switch(menu.searthDish(c[2]).taste) { case 1:System.out.print("spicy num out of range :"+c[3]);break; case 2:System.out.print("acidity num out of range :"+c[3]);break; case 3:System.out.print("sweetness num out of range :"+c[3]);break; } System.out.print("\n"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[1])); } else { for(i=0;i<e;i++) if(tables[i].num==Integer.parseInt(c[0])) break; if(i==e-1) { System.out.println("wrong format"); men[f].table[men[f].n-1].order.addNRecord(Integer.parseInt(c[1])); } tables[i].order.addORecord(Integer.parseInt(c[1]),menu.searthDish(c[2]),Integer.parseInt(c[4]),Integer.parseInt(c[5])); tables[i].order.records[tables[i].order.n-1].tastenum=Integer.parseInt(c[3]); men[f].table[men[f].n-1].order.addARecord(Integer.parseInt(c[1]),menu.searthDish(c[2]),Integer.parseInt(c[4]),Integer.parseInt(c[5])); men[f].table[men[f].n-1].order.records[men[f].table[men[f].n-1].order.n-1].byother=false; System.out.println(c[1]+" table "+men[f].table[men[f].n-1].num+" pay for table "+c[0]+" "+men[f].table[men[f].n-1].order.records[men[f].table[men[f].n-1].order.n-1].getPrice()); } } else System.out.println("wrong format"); } } for(i=0;i<e;i++) { h=0; System.out.print("table "+tables[i].num+": "+tables[i].order.getTotalPrice()+" "+tables[i].getDiscountPrice()); tables[i].printspicy(); tables[i].printacidity(); tables[i].printsweetness(); for(j=0;j<tables[i].order.n;j++) if(tables[i].order.records[j].d.specialty) h=1; if(h==0) System.out.print(" "); System.out.print("\n"); } for(i=0;i<a-1;i++) for(j=i+1;j<a;j++) if(men[i].name.charAt(0)>men[j].name.charAt(0)) { man=men[i]; men[i]=men[j]; men[j]=man; } for(i=0;i<a;i++) System.out.println(men[i].name+" "+men[i].number+" "+men[i].getTotalPrice()); } } //菜品类:对应菜谱上一道菜的信息。 class Dish { String name;//菜名 int unit_price;//单价 boolean specialty;//标记是否是特色菜 int taste;//口味,1为辣(川菜),2为酸(晋菜),3为甜(浙菜) int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) { double p=0; switch(portion) { case 1:p=unit_price;break; case 2:p=unit_price*1.5;break; case 3:p=unit_price*2;break; } return (int)Math.round(p); } boolean tasteoutofrange(int tastenum)//判断口味度是否超过范围 { switch(taste) { case 1:if(tastenum<=5&&tastenum>=0)//川菜,判断是否在0-5内 return true; else break; case 2:if(tastenum<=4&&tastenum>=0)//晋菜,判断是否在0-4内 return true; else break; case 3:if(tastenum<=3&&tastenum>=0)//浙菜,判断是否在0-3内 return true; else break; } return false; } } //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 class Menu { Dish[] dishs =new Dish[10];//菜品数组,保存所有菜品信息 int n=0;//记录菜谱上的菜数 Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。 { int i; for(i=0;i<n;i++) if(dishName.equals(dishs[i].name)) return dishs[i]; return null; } void addDish(String dishName,int unit_price)//添加一道菜品信息 { dishs[n]=new Dish(); dishs[n].name=dishName; dishs[n].specialty=false; dishs[n].unit_price=unit_price; n++; } void addTDish(String dishName,String taste,int unit_price)//添加一道特色菜品信息 { dishs[n]=new Dish(); dishs[n].name=dishName; dishs[n].unit_price=unit_price; dishs[n].specialty=true; if(taste.equals("川菜")) dishs[n].taste=1; else if(taste.equals("晋菜")) dishs[n].taste=2; else dishs[n].taste=3; n++; } } //点菜记录类:保存订单上的一道菜品记录 class Record { int orderNum;//序号 Dish d=new Dish();//菜品 int portion;//份额(1/2/3代表小/中/大份) int num;//份数 int tastenum;//口味度 boolean delete=false;//判断本道订单是否被删除 boolean exit;//判断本道订单是否存在 boolean other=false;//是否代点菜 boolean byother;//判断是否是自己桌上的 int getPrice()//计价,计算本条记录的价格 { return d.getPrice(portion)*num; } } //订单类:保存用户点的所有菜的信息。 class Order { Record[] records=new Record[10];//保存订单上每一道的记录 int n=0;//记录共有多少道订单 int getTotalPrice()//计算订单的总价 { int i,p=0; for(i=0;i<n;i++) if(records[i].delete==false&&records[i].exit&&records[i].other==false) p+=records[i].getPrice(); return p; } void addARecord(int orderNum,Dish d,int portion,int num)//添加一条合法菜品信息到订单中。 { records[n]=new Record(); records[n].orderNum=orderNum; records[n].d=d; records[n].portion=portion; records[n].num=num; records[n].exit=true; records[n].byother=true; n++; } void addNRecord(int orderNum)//添加一条非法菜品信息到订单中 { records[n]=new Record(); records[n].orderNum=orderNum; records[n].exit=false; records[n].byother=true; n++; } void addORecord(int orderNum,Dish d,int portion,int num)//添加一条代点菜菜品信息到订单中。 { records[n]=new Record(); records[n].orderNum=orderNum; records[n].d=d; records[n].portion=portion; records[n].num=num; records[n].exit=true; records[n].other=true; records[n].byother=true; n++; } void delARecordByOrderNum(Record record)//根据序号删除一条记录 { // if(record.delete==false) record.delete=true; // else // System.out.println("deduplication "+record.orderNum); } Record findRecordByNum(int orderNum)//根据序号查找一条记录 { int i; for(i=n-1;i>-1;i--) if(records[i].orderNum==orderNum) return records[i]; return null; } } //桌类:记录每一桌的信息 class Table { Order order=new Order();//本桌订单 // int n=0;//记录当前有几次订单 int num;//记录桌号 String Date;//点菜日期 String Time;//点菜时间 int getDiscountPrice()//计算折扣价 { int i,a,n=0; double p=1; DateTimeFormatter fmt1=DateTimeFormatter.ofPattern("yyyy/M/d"); LocalDate date=LocalDate.parse(Date,fmt1); DateTimeFormatter fmt2 = DateTimeFormatter.ofPattern("H/m/s"); LocalTime time=LocalTime.parse(Time,fmt2); a=date.getDayOfWeek().getValue(); if(a<=5&&a>=1)//周一至周五 { LocalTime time1=LocalTime.parse("16/59/59",fmt2); LocalTime time2=LocalTime.parse("20/30/1",fmt2); if(time.isAfter(time1)&&time.isBefore(time2))//晚上八折 p=0.8; else//中午六折 p=0.6; for(i=0;i<order.n;i++) if(!order.records[i].delete&&order.records[i].exit&&!order.records[i].other) { if(!order.records[i].d.specialty) n+=(int)Math.round(order.records[i].getPrice()*p); else n+=(int)Math.round(order.records[i].getPrice()*0.7); } } else//周末全价 n=order.getTotalPrice(); return n; } boolean aopeningtime(String Date,String Time)//判断是否在开放时间内 { DateTimeFormatter fmt1 = DateTimeFormatter.ofPattern("yyyy/M/d"); LocalDate date = LocalDate.parse(Date, fmt1); DateTimeFormatter fmt2 = DateTimeFormatter.ofPattern("H/m/s"); LocalTime time=LocalTime.parse(Time,fmt2); int a=date.getDayOfWeek().getValue(); if(a<=5&&a>=1)//周一至周五 { LocalTime time1=LocalTime.parse("16/59/59",fmt2); LocalTime time2=LocalTime.parse("20/30/1",fmt2); LocalTime time3=LocalTime.parse("10/29/59",fmt2); LocalTime time4=LocalTime.parse("14/30/1",fmt2); if((time.isAfter(time1)&&time.isBefore(time2))||(time.isAfter(time3)&&time.isBefore(time4))) return true; } else//周末 { LocalTime time1=LocalTime.parse("9/29/59",fmt2); LocalTime time2=LocalTime.parse("21/30/1",fmt2); if(time.isAfter(time1)&&time.isBefore(time2)) return true; } return false; } void printspicy()//输出川菜口味的口味度水平 { int i,a=0; float b=0;//a用来记录有几道菜,b用来记录口味度总值 for(i=0;i<order.n;i++) if(order.records[i].delete==false&&order.records[i].exit==true&&order.records[i].byother&&order.records[i].d.specialty==true&&order.records[i].d.taste==1) { a+=order.records[i].num; b+=order.records[i].tastenum*order.records[i].num; } if(a!=0) { System.out.print(" 川菜 "+a+" "); switch((int)Math.round(b*1.0/a)) { 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; } } } void printacidity()//输出晋菜的口味度水平 { int i,a=0; float b=0;//a用来记录有几道菜,b用来记录口味度总值 for(i=0;i<order.n;i++) if(order.records[i].delete==false&&order.records[i].exit==true&&order.records[i].byother&&order.records[i].d.specialty==true&&order.records[i].d.taste==2) { a+=order.records[i].num; b+=order.records[i].tastenum*order.records[i].num; } if(a!=0) { System.out.print(" 晋菜 "+a+" "); switch((int)Math.round(b*1.0/a)) { 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; } } } void printsweetness()//输出浙菜的口味度水平 { int i,a=0; float b=0;//a用来记录有几道菜,b用来记录口味度总值 for(i=0;i<order.n;i++) if(order.records[i].delete==false&&order.records[i].exit==true&&order.records[i].byother&&order.records[i].d.specialty==true&&order.records[i].d.taste==3) { a+=order.records[i].num; b+=order.records[i].tastenum*order.records[i].num; } if(a!=0) { System.out.print(" 浙菜 "+a+" "); switch((int)Math.round(b*1.0/a)) { case 0:System.out.print("不甜");break; case 1:System.out.print("微甜");break; case 2:System.out.print("稍甜");break; case 3:System.out.print("甜");break; } } } } //人类:记录该人类的点餐信息 class Man { Table[] table=new Table[10]; String name;//名字 String number;//手机号 int n=0;//判断一共点了多少桌 boolean name(String n)//判断名字是否超过十个字符 { if(n.length()>10) return false; return true; } boolean phonenumber(String num)//判断手机号是否正确 { if(num.length()!=11)//手机位数不为11 return false; if(num.substring(0,3).equals("180")||num.substring(0,3).equals("181")||num.substring(0,3).equals("189")||num.substring(0,3).equals("133")||num.substring(0,3).equals("135")||num.substring(0,3).equals("136")) return true; return false; } void addTable(int n,String date,String time)//增加一桌信息 { table[this.n]=new Table(); table[this.n].num=n; table[this.n].Date=date; table[this.n].Time=time; this.n++; } Man(String name,String number)//增加人信息 { this.name=name; this.number=number; } Man() { } int getTotalPrice()//计算该人需要付的价格 { int i,s=0; for(i=0;i<this.n;i++) s+=table[i].getDiscountPrice(); return s; } }

很奇怪的是大作业5的Source Monitor使用就正常了……这软件还挑呢。本次代码复杂度只有17,还行吧(看开)。
本次大作业5我认为是比大作业4要简单上许多的。不过为什么还没有大作业4的分数高呢……为什么呢……甚至还有一点格式错误。嗯……我不好说。
下面着重分析一些我认为重要的踩坑心得:
踩坑心得:
1.关于“输出口味值格式”:
我是真没想到在不输出口味度的时候居然还需要输出一个空格。一开始看到这个“格式错误”的时候人都傻了……还好还算好解决,但是解决方式比较丑陋就不放上来了。
2.关于“总输出按名字字母顺序排序”:
一开始还真没注意到这点,检查到样例感觉不太对,回去反复看题目才发现人名需要按字母顺序排序。最后用冒泡排序法解决了这个问题。不过现在想想,一开始是不是可以直接用HashSet和Comparable接口?不过关于这点我没仔细搞,不确定会不会有冲突的地方,下次作业用着试一试。
3.关于“菜价计算”:
我一开始计算的时候是把特色菜和非特色菜分开然后直接总价乘于折扣,所以在输出某个样例的时候折后价格四舍五入后少了一块钱(当时真的计算机点了半天)……最后发现要每道菜乘于折扣,四舍五入后再加上总价……黑心餐馆,这点钱都要贪。
这个题本身写起来还算顺利,但是一些细节错的我是真的头疼。下面记录一些在写代码中比较有意思的事。例如在过一个删除的测试点的时候,我发现我写代码的时候删了但没完全删,计算总价的时候照样记。然而这么大的问题居然只错了那一个测试点,当时我就停止思考了一会xxx
还有一个格式错误。我猜我代码应该是有问题的,但是时间实在是有点紧,当时也有点忙,所以也来不及一一看过去了……下次继续改,争取下次拿下满分。
所以到底为什么不开放全部测试点啊——一个个猜测试点真的好头疼——我不想猜测试点!
测验4-抽象类与接口:
代码:
import java.util.ArrayList; import java.util.Comparator; import java.util.Scanner; 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()) + " "); } } } class Point { private double x; private double y; Point() { } Point(double x,double y) { this.x=x; this.y=y; } double getX() { return x; } void setX(double x) { this.x=x; } double getY() { return y; } void sety(double y) { this.y=y; } } class Rectangle extends Shape { private Point topLeftPoint; private Point lowerRightPoint; Rectangle() { topLeftPoint=new Point(); lowerRightPoint=new Point(); } Rectangle(Point topLeftPoint,Point lowerRightPoint) { this.topLeftPoint=new Point(); this.lowerRightPoint=new Point(); this.topLeftPoint=topLeftPoint; this.lowerRightPoint=lowerRightPoint; } Point getTopLeftPoint() { return this.topLeftPoint; } void setTopLeftPoint(Point topLeftPoint) { this.topLeftPoint=topLeftPoint; } Point getLowerRightPoint() { return this.lowerRightPoint; } void setLowerRightPoint(Point lowerRightPoint) { this.lowerRightPoint=lowerRightPoint; } double getLength() { return Math.abs(topLeftPoint.getY()-lowerRightPoint.getY()); } double getHeight() { return Math.abs(topLeftPoint.getX()-lowerRightPoint.getX()); } double getArea() { return getLength()*getHeight(); } @Override public int compareTo(Shape o) { if(this.getArea()>o.getArea()) return 1; else if(this.getArea()==o.getArea()) return 0; else return -1; } } class Circle extends Shape { private double r; Circle(double r) { this.r=r; } double getArea() { return Math.PI*r*r; } @Override public int compareTo(Shape o) { if(this.getArea()>o.getArea()) return 1; else if(this.getArea()==o.getArea()) return 0; else return -1; } } abstract class Shape implements Comparable<Shape> { Shape() { } abstract double getArea(); }
在用这里的时候Source Monitor彻底崩掉了打不开,我暂时救不回来,不过这里主程序代码还是题目本身给的,没什么必要去测一下,所以就暂时不放图了……
这道题最有意思的就算要是有Comparable接口,这个我一开始是完全不熟悉的(不过后面我想起来以前用过……不过忘光了就当没见过吧),所以全靠万能的编译器慢慢摸索写出来了……挺感动的,感谢Eclipse,暂时不骂你了。
这道题给的提示是:Shape类要实现Comparable接口。
所以在一开始我先给Shape接上了Comparable接口。

后面根据提示在Circle类和Rectangle类中加上了compareTo的方法。在一开始编译器是直接给return 0的。然后此时编译不出问题了,但是依旧没有排序。所以我想了半天老师怎么说的,才慢慢改出这份代码。

可喜可贺的是没有更多需要更改的地方。写好这里后直接通过了测试点。不幸中的万幸……
主要困难及改进建议:
- 在一开始思考题目往往不够全面,在改一部分测试点的时候往往需要大改,这个时候会比较痛苦。不过比起上次已经好太多了。后面还是需要尽力先全看一遍,把各种情况分析清楚,再去写代码。
- 猜测试点。第四次大作业好歹放了部分测试数据,第五次是一点没放,猜起来真的很困难。不知道自己最后到底漏掉了哪些情况,真的会比较痛苦。而且有些时候尽力猜了大改了结果最后发现不是测试点真的会比较难过。嗯……我还是那句话,什么时候能多放几个测试数据啊——
- 我在前面五次大作业都没有用ArrayList。本身很适合但是因为我当时不会用所以一直拖着没用……不过现在算是比较熟悉了,所以下次会尝试用ArrayList及HashSet。嗯……又要大改一遍代码,加油吧。
- 我真的!很容易!忘事!像Comparable接口和HashSet我都是以前用过的……但是现在是真的一点都不记得一点都不会用……还是需要多复习巩固,不然真的容易忘记。
- 最重要的困难:我太菜了。建议是没有建议,下辈子不要选软件。
- 多预习,多复习,多花时间在了解语法上面,争取不要在用的时候不会,甚至完全不知道。
总结:
- 教师与课程方面:感觉老师讲课是不是有点太跳脱了……每节课都联系不上来的感觉。而且没有办法复习老师课上讲的东西,导致容易遗忘课上讲过什么。
- 作业方面:老师完全没讲过作业啊……很多测不出来的测试点也只能被迫放了。真的测不出来啊……挺遗憾的。
- 实验方面:实验感觉还是挺有用的,很多都是经常需要用上的东西,可以作为很好的复习材料。
- 课上方面:希望老师能多发一些课上讲过的资料啊语法啊之类的方便复习,毕竟他讲的书上是真的没有。真的很容易忘记课上讲过什么。

浙公网安备 33010602011771号