一、前言:
第四次PTA作业:难度较大,只有一道题,需要综合运用Java的各种技巧。
第五次PTA作业:难度较大,只有一道题,需要综合运用Java的各种技巧。
期中考试:除最后一题外,难度适中,有四道题。
二、设计与分析
第四次PTA作业:
1、设计分析:
这是一个关于设计点菜计价程序的问题。根据输入的信息,程序将计算并输出总价格。输入内容包括菜单和订单两部分,最后以"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类对应菜谱上一道菜的信息。 Menu类对应菜谱,包含饭店提供的所有菜的信息。 Record类保存订单上的一道菜品记录。 Order类保存用户点的所有菜的信息。
1 import java.util.Calendar; 2 import java.util.Scanner; 3 public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 Menu mu = new Menu(); 7 Table[] tablemes = new Table[10]; 8 int j = 0;//菜单数 9 int l = 0;//订单数 10 int k = 0;//代点菜数 11 Dish tt; 12 //int sum = 0; 13 int cntTable = 0;//桌号 14 int count; 15 String[] temp; 16 int a1,a2,a3,a4,a5; 17 18 while (true) { 19 String st = sc.nextLine(); 20 temp = st.split(" "); 21 if(st.equals("end")) 22 break; 23 count = temp.length; 24 if (count == 2) {//一个空格 25 //String[] temp1 = st.split(" "); 26 if (temp[1].equals("delete")) {//第二个为delete 27 a1 = Integer.parseInt(temp[0]); 28 int c = tablemes[cntTable].odt.delARecordByOrderNum(a1); 29 tablemes[cntTable].sum-=c; 30 } else {//菜单添加 31 a2 = Integer.parseInt(temp[1]); 32 mu.dishs[j] = mu.addDish(temp[0], a2); 33 j++; 34 } 35 //continue; 36 } 37 else if (count == 4) {//三个空格 38 //String[] temp2 = st.split(" "); 39 if (temp[0].equals("table")) {//桌号 40 cntTable++;//跳过0; 41 l = 0; 42 tablemes[cntTable] = new Table(); 43 //tablemes[cntTable].tableDtime = st; 44 tablemes[cntTable].AheadProcess(st); 45 46 System.out.println("table " + cntTable + ": "); 47 } else {//增加订单的情况; 48 a3 =Integer.parseInt(temp[0]); 49 a4 = Integer.parseInt(temp[2]); 50 a5=Integer.parseInt(temp[3]); 51 tablemes[cntTable].odt.addARecord(a3, temp[1],a4 , a5); 52 tt = mu.searthDish(temp[1]); 53 if (tt != null) { 54 tablemes[cntTable].odt.records[l].d = tt; 55 int a = tablemes[cntTable].odt.records[l].getPrice(); 56 System.out.println(tablemes[cntTable].odt.records[l].orderNum + " " + tt.name + " " +a ); 57 tablemes[cntTable].sum +=a; 58 } 59 l++; 60 } 61 //continue; 62 } 63 64 else if (count == 5) {//代点菜 65 //String[] temp3 = st.split(" "); 66 a1 = Integer.parseInt(temp[1]); 67 a2 = Integer.parseInt(temp[3]); 68 a3 = Integer.parseInt(temp[4]); 69 tablemes[cntTable].odt.addARecord( a1, temp[2], a2, a3); 70 tt = mu.searthDish(temp[2]); 71 if (tt != null) { 72 tablemes[cntTable].odt.records[l].d.unit_price = tt.unit_price; 73 int b = tablemes[cntTable].odt.records[l].getPrice(); 74 System.out.println(temp[1] + " table " + tablemes[cntTable].tableNum + " pay for table " + temp[0] + " " + b); 75 tablemes[cntTable].sum += b; 76 } 77 l++; 78 } 79 //st = sc.nextLine(); 80 81 } 82 for (int i = 1; i < cntTable + 1; i++) { 83 tablemes[i].Gettottalprice(); 84 } 85 } 86 } 87 class Table { 88 int tableNum; 89 String tableDtime; 90 int year,month,day,week,hh,mm,ss; 91 int sum = 0;//一桌价格 ; 92 // boolean f = true; 93 Order odt = new Order(); 94 //Order odre = new Order(); 95 float discnt = -1; 96 void Gettottalprice(){ 97 if(discnt>0){ 98 sum = Math.round(sum*discnt); 99 System.out.println("table " + tableNum + ": " + sum); 100 }else { 101 System.out.println("table " + tableNum + " out of opening hours"); 102 } 103 } 104 void AheadProcess(String tableDtime){ 105 this.tableDtime = tableDtime; 106 processTime(); 107 discount(); 108 //CheckAtime(); 109 } 110 111 112 void processTime(){//处理时间 113 String[] temp = tableDtime.split(" "); 114 tableNum = Integer.parseInt(temp[1]); 115 String[] temp1 = temp[2].split("/"); 116 String[] temp2 = temp[3].split("/"); 117 118 year = Integer.parseInt(temp1[0]); 119 month = Integer.parseInt(temp1[1]); 120 day = Integer.parseInt(temp1[2]); 121 122 Calendar c = Calendar.getInstance(); 123 c.set(year, (month-1), day); 124 week = c.get(Calendar.DAY_OF_WEEK); 125 if(week==1) 126 week = 7; 127 else 128 week--; 129 hh = Integer.parseInt(temp2[0]); 130 mm = Integer.parseInt(temp2[1]); 131 ss = Integer.parseInt(temp2[2]); 132 133 } 134 //void CheckAtime(){ 135 // f= !(discnt < 0); 136 // } 137 void discount(){ 138 if(week>=1&&week<=5) 139 { 140 if(hh>=17&&hh<20) 141 discnt=0.8F; 142 else if(hh==20&&mm<30) 143 discnt=0.8F; 144 else if(hh==20&&mm==30&&ss==0) 145 discnt=0.8F; 146 else if(hh>=11&&hh<=13||hh==10&&mm>=30) 147 discnt=0.6F; 148 else if(hh==14&&mm<30) 149 discnt=0.6F; 150 else if(hh==14&&mm==30&&ss==0) 151 discnt=0.6F; 152 } 153 else 154 { 155 if(hh>=10&&hh<=20) 156 discnt= 1.0F; 157 else if(hh==9&&mm>=30) 158 discnt= 1.0F; 159 else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0) 160 discnt= 1.0F; 161 } 162 } 163 } 164 class Order { 165 Record[] records = new Record[10];//保存订单上每一道的记录 166 int count = 0;//订单数量 167 //int forcount = 0;//代点菜的数量 168 /*int getTotalPrice(){ 169 int sum=0; 170 for(int i=0;i<count;i++){ 171 if(records[i].exist==0) 172 continue; 173 sum=sum+records[i].getPrice(); 174 } 175 return sum; 176 }//计算订单的总价*/ 177 void addARecord(int orderNum,String dishName,int portion,int num){ 178 records[count] = new Record(); 179 records[count].d.name = dishName; 180 records[count].orderNum = orderNum; 181 records[count].portion = portion; 182 records[count].num = num; 183 count++; 184 }//添加一条菜品信息到订单中。 185 /*Record TakeOdfor(int AnotherNUm,int orderNum,String dishName,int portion,int num){ 186 Record rd2 = new Record(); 187 rd2.d.name = dishName; 188 rd2.orderNum = orderNum; 189 rd2.portion = portion; 190 rd2.d.num = num; 191 rd2.AntherOrderNum = AnotherNUm; 192 //forcount++; 193 return rd2; 194 }*/ 195 int delARecordByOrderNum(int orderNum){ 196 if(orderNum>count||orderNum<=0){ 197 System.out.println("delete error;"); 198 return 0; 199 }else { 200 return records[orderNum - 1].getPrice(); 201 } 202 }//根据序号删除一条记录 203 } 204 class Record { 205 int orderNum;//序号\ 206 //int AntherOrderNum; 207 Dish d = new Dish();//菜品\ 208 int num = 0; 209 int portion;//份额(1/2/3代表小/中/大份)\ 210 //int exist = 1; 211 int getPrice(){ 212 return d.getPrice(portion)*num; 213 }//计价,计算本条记录的价格\ 214 } 215 class Menu { 216 Dish[] dishs = new Dish[10];//菜品数组,保存所有菜品信息 217 int count = 0; 218 Dish searthDish(String dishName){ 219 Dish temd = null; 220 for(int i=count-1;i>=0;i--){ 221 if(dishName.equals(dishs[i].name)){ 222 temd = dishs[i]; 223 break; 224 } 225 } 226 if(temd==null){ 227 System.out.println(dishName+" does not exist"); 228 } 229 return temd; 230 }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 231 Dish addDish(String dishName,int unit_price){ 232 Dish dh = new Dish(); 233 dh.name = dishName; 234 dh.unit_price = unit_price; 235 count++; 236 return dh; 237 }//添加一道菜品信息 238 } 239 class Dish { 240 String name;//菜品名称 241 int unit_price; //单价 242 //int num; 243 244 int getPrice(int portion) { 245 int peic = 0; 246 if (portion == 1) { 247 peic = unit_price ; 248 } else if (portion == 2) { 249 peic = Math.round((float) (unit_price * 1.5)) ; 250 } else if (portion == 3) { 251 peic = (unit_price * 2) ; 252 } 253 return peic;//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) 254 } 255 }
2、源码分析:
这些代码实现了一个点菜计价程序。程序中定义了几个类,包括Main、Table、Order、Record、Menu和Dish。
Main类是程序的入口点,它包含一个名为main的静态方法。在这个方法中,首先创建了一个名为sc的Scanner对象来读取用户输入。然后创建了一个名为mu的Menu对象来存储菜单信息,以及一个名为tablemes的数组来存储桌子信息。
接下来,程序进入一个循环,不断读取用户输入并进行处理。如果输入为"end",则退出循环。否则,根据输入内容的不同进行不同的处理。
如果输入内容包含两个部分(即包含一个空格),则判断第二部分是否为"delete"。如果是,则根据第一部分指定的序号删除对应的点菜记录。否则,将输入内容作为菜单信息添加到菜单中。
如果输入内容包含四个部分(即包含三个空格),则判断第一部分是否为"table"。如果是,则将输入内容作为桌号标识进行处理。否则,将输入内容作为点菜记录添加到订单中。
如果输入内容包含五个部分(即包含四个空格),则将输入内容作为代点菜信息进行处理。
在循环结束后,程序遍历所有桌子并输出每一桌的总价。
除了主类之外,还有其他几个类用于实现程序的功能。
Table类表示一张桌子。它包含若干个字段用于存储桌子的信息,如桌号、时间、总价等。它还包含若干个方法用于处理桌子相关的操作,如计算总价、处理时间和折扣等。Order类表示一张订单。它包含一个名为records的数组用于存储订单上的所有点菜记录。它还包含若干个方法用于处理订单相关的操作,如添加点菜记录、删除点菜记录等。Record类表示一条点菜记录。它包含若干个字段用于存储点菜记录的信息,如序号、菜品、份额、份数等。它还包含一个名为getPrice的方法用于计算本条记录的价格。Menu类表示菜单。它包含一个名为dishs的数组用于存储所有菜品信息。它还包含若干个方法用于处理菜单相关的操作,如查找菜品信息、添加菜品信息等。-
Dish类表示一道菜品。它包含若干个字段用于存储菜品的信息,如名称、单价等。它还包含一个名为getPrice的方法用于计算菜品的价格。该方法根据点菜的份额(输入数据只能是1/2/3,代表小/中/大份)来计算菜品的价格。这些类通过相互协作来实现点菜计价程序的功能。在程序运行过程中,用户可以输入菜单信息、桌号标识、点菜记录、删除记录和代点菜信息等内容。程序会根据输入内容进行相应的处理,并在最后输出每一桌的总价。
类图;

第五次PTA作业:
1、设计分析:
这是一个关于点菜计价程序的问题。在输入菜单时,可以增加特色菜。特色菜的输入格式为:菜品名+英文空格+口味类型+英文空格+基础价格+“T”。例如:麻婆豆腐 川菜 9 T。
特色菜的口味类型包括川菜、晋菜和浙菜。川菜增加辣度值,辣度0-5级;对应辣度水平为:不辣、微辣、稍辣、辣、很辣、爆辣。晋菜增加酸度值,酸度0-4级;对应酸度水平为:不酸、微酸、稍酸、酸、很酸。浙菜增加甜度值,甜度0-3级;对应酸度水平为:不甜、微甜、稍甜、甜。
输入订单记录时,如果是特色菜,则需要添加口味度(辣/酸/甜度)值。格式为:序号+英文空格+菜名+英文空格+口味度值+英文空格+份额+英文空格+份数。
单条信息在处理时,如果口味度超过正常范围,输出"spicy/acidity/sweetness num out of range : "+口味度值,spicy/acidity/sweetness(辣度/酸度/甜度)根据菜品类型择一输出。
输出一桌的信息时,按辣、酸、甜度的顺序依次输出本桌菜各种口味的口味度水平。如果没有某个类型的菜,则对应的口味(辣/酸/甜)度不输出,只输出已点的菜的口味度。口味度水平由口味度平均值确定,口味度平均值只综合对应口味菜系的菜计算,不做所有菜的平均。
一桌信息的输出格式为:table+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格+“川菜”+数量+辣度+英文空格+“晋菜”+数量+酸度+英文空格+“浙菜”+数量+甜度。
如果整桌菜没有特色菜,则只输出table的基本信息。
计算口味度时要累计本桌各类菜系所有记录的口味度总和(每条记录的口味度乘以菜的份数),再除以对应菜系菜的总份数,最后四舍五入。
此外,还需要考虑客户订多桌菜的情况。输入时桌号时,需要增加用户的信息。格式为:table+英文空格+桌号+英文空格+": "+英文空格+客户姓名+英文空格+手机号+日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)。
约束条件:客户姓名不超过10个字符,手机号11位,前三位必须是180、181、189、133、135、136其中之一。
输出结果时,先按要求输出每一桌的信息,最后按字母顺序依次输出每位客户需要支付的金额。不考虑各桌时间段的问题,同一个客户的所有table金额都要累加。




