前言:
题目集 1~3 的知识点、题量、难度等情况如下:
-
知识点:JAVA基础,基础算法,面向对象程序设计
-
题量:共计 3 道题目
-
难度:题目从易到难,分为三个层次,分别为入门、中等和高级
设计与分析:
本次 Blog 重点分析菜单计价系列题目,即题目集 2 的 7-1、7-2 以及题目集 3 的 7-1。这三个题目都具有典型的菜单计价特征,需要对菜单进行设计并实现相应的计价算法。
-
7-1:给出多个订单,计算指定菜品的组合总价。该题目主要是考察类的创建,输入数据格式的判断,以及方法的构造。该题目只需要构造两个类和一个方法便可以实现
1 static class Dish { 2 String name; 3 int unit_price; 4 } 5 6 static class Record { 7 int orderNum; 8 Dish d; 9 int portion; 10 int quota; 11 12 int getPrice () { 13 if (portion == 2) { 14 return (int) Math.round (1.5 * d.unit_price) * quota; 15 } 16 else if (portion == 3) { 17 return 2 * d.unit_price * quota; 18 } 19 else { 20 return d.unit_price * quota; 21 } 22 } 23 } 24
- 7-2:给出一个菜单和多个订单,计算订单中菜品的组合总价。该题目主要是考察对类对象的访问以及成员变量的存储。在实现过程中,需要区分菜单信息和订单信息格式上的不同,以免发生方法调用上的错误。在7-1的基础上,本题需要设计方法来手动输入菜单信息,我选择构造一个新的类来实现这些方法
static class Menu { Dish[] dishs = new Dish[20]; int searchDish () { //TO-DO } Dish addDish () { //TO-DO } }
其次,本题新增了对订单类的删改信息,同样,也是构造新的方法来实现这些功能
1 static class Order { 2 Record[] records = new Record[20]; 3 4 Record addARecord () { 5 //TO-DO12 } 13 14 boolean delARecordByOrderNum () { 15 //TO-DO29 } 30 }
- 7-1:给出一个菜单和多个桌号信息,每个桌号包含多个订单信息,计算每桌订单中菜品的组合总价。该题目主要是考察类和方法的创建和使用,对变量的存储和访问。在实现过程中,需要区分菜单信息、桌号信息和订单信息格式上的不同,以免发生数据丢失。相比于上一次菜单题目,本次题目增添了table类,其中包含结账和增添新订单等操作(实际就是之前的Order类新增一些内部成员变量,但是写的时候没注意到就胡乱的增添了一个类)
1 static class Table { 2 Order order = new Order (); 3 int num; 4 int order_count = 0; 5 LocalDateTime time; 6 long sum = 0; 7 8 void od (Menu menu, int menu_count, String str1, String str2, int portion, int quota) { 9 if (str2.equals ("delete")) { 10 if (order.delARecordByOrderNum (Integer.parseInt (str1), order_count)) { 11 order_count--; 12 } 13 } 14 else { 15 if (menu.searchDish (str2, menu_count) != -1) { 16 order.records[order_count] = new Record (); 17 order.records[order_count] = order.addARecord (Integer.parseInt (str1), str2, portion, quota, menu_count, menu); 18 order_count++; 19 } 20 else { 21 System.out.println (str2 + " does not exist"); 22 } 23 } 24 } 25 26 void getSum () { 27 int weekday = time.getDayOfWeek ().getValue (); 28 for (int i = 0; i < order_count; i++) { 29 sum += order.records[i].getPrice (); 30 } 31 if (weekday > 0 && weekday < 6) { 32 if (time.getHour () >= 17 && time.getHour () < 20) sum = Math.round (sum * 0.8); 33 if (time.getHour () == 20) { 34 if (time.getMinute () <= 30) sum = Math.round (sum * 0.8); 35 } 36 if (time.getHour () >= 10 && time.getHour () < 14) sum = Math.round (sum * 0.6); 37 if (time.getHour () == 14) { 38 if (time.getMinute () <= 30) sum = Math.round (sum * 0.6); 39 } 40 } 41 } 42 43 boolean isOpen () { 44 int weekday = time.getDayOfWeek ().getValue (); 45 if (weekday > 0 && weekday < 6) { 46 if (time.getHour () >= 17 && time.getHour () < 20) return true; 47 if (time.getHour () == 20) { 48 if (time.getMinute () <= 30) return true; 49 } 50 if (time.getHour () > 10 && time.getHour () < 14) return true; 51 if (time.getHour () == 10) { 52 if (time.getMinute () >= 30) return true; 53 } 54 if (time.getHour () == 14) { 55 if (time.getMinute () <= 30) return true; 56 } 57 } 58 else { 59 if (time.getHour () > 9 && time.getHour () < 21) return true; 60 if (time.getHour () == 9) { 61 if (time.getMinute () >= 30) return true; 62 } 63 if (time.getHour () == 21) { 64 if (time.getMinute () <= 30) return true; 65 } 66 } 67 return false; 68 69 } 70 }
采坑心得:
在提交源码的过程中,我遇到了很多问题,总结如下:
- 对格式错误的数据的处理问题:在读入并判断输入数据格式时,要注意对错误格式的信息进行忽略并报错,否则会导致程序崩溃。
- 数组下标越界问题:在删除订单信息时,要注意数组下标是否越界,否则会导致程序崩溃。
- 对不同格式信息的区分问题:在读入数据后,格式的判断一定要严谨,否则会导致数据的丢失。
- 类的结构过于混乱:在编写程序时一定要注意程序的结构是否可拓展和可读,避免后期维护产生问题。
主要困难以及改进建议:
在解题过程中,我遇到了以下主要困难:
- 对时间类的使用不够熟练:在解决储存每桌对应的时间时,我发现测试样例中时间的格式不统一,时而是单数时而是双数,导致使用SimpleDataFormat(yyyy/MM/dd HH/mm/ss)
的时候出现报错。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss"); Date date = new Date(); date= sdf.parse(time);
- 算法的实现不够高效:对于多桌菜的情况,处理大量数据时因为循环结构过多导致耗时很长,无法达到预期结果。
- 编码能力有待提高:在解题过程中,我发现自己编码能力还有待提高,主要体现在代码的可读性和可维护性上,难以在原有的结构基础上拓展新的功能。因此,需要加强对编码技巧的掌握,提高代码的可读性和可维护性。
改进建议:
- 对于时间类需要有更多的理解,在寻找上述中提到的时间格式问题的解决方法时,我在网络上领教到了一种较为方便的解决方法:
将data类转化为Instant类,再由时区转换为LocalDateTime类,这样就可以避免因为输入格式的不统一造成的错误了。
1 Date date = new Date(); 2 date= sdf.parse(time); 3 Instant instant = date.toInstant(); 4 ZoneId zone = ZoneId.systemDefault(); 5 tables[table_count].time= LocalDateTime.ofInstant(instant, zone);
- 对于提高代码可拓展性上,我将原本的很多功能重构成了方法,也增加了类的使用频率,让代码整体的结构更加紧密和可拓展。
- 对于格式的判断,我率先想到的就是判断数据的某个元素是否可以转化为数字,以将不同的数据分割开处理,因此,我构造了isNumeric方法来判断是否可以转化成数字
1 public static boolean isNumeric (String string) { 2 int intValue; 3 try { 4 intValue = Integer.parseInt (string); 5 return true; 6 } catch (NumberFormatException e) { 7 return false; 8 } 9 }
当然,这个方法并不是很好,一方面每个数据都要判断一遍导致运行速度大大降低,另一方面可扩展性不高,后期添加新的功能时需要大量改动原有代码。但当时不会更加高效的判断方法,也是无奈之举。
- 针对删除订单信息的方法中出现的数组越界问题,我引用了新的计数变量count,来记录数组的长度,从而防止数组下标越界的问题(其实可以直接调用数组的lenth方法,只是当时脑抽了)
1 boolean delARecordByOrderNum(int orderNum,int count){ 2 int i=0,j=0,flag=0; 3 for(i=0;i<count;i++){ 4 if(records[i].orderNum==orderNum){ 5 for(j=i;j<count-1;j++){ 6 records[j]=records[j+1]; 7 } 8 flag++; 9 } 10 } 11 if(flag==0){System.out.println("delete error;");return false;} 12 return true; 13 }
- 多参与讨论和交流:多参与讨论和交流,向其他同学和老师学习,拓宽自己的思路和知识面。
仍未解决的问题:
- 即使优化了代码的结构,代码的运行效率依旧达不到预期的水准,个人猜测是由于判断输入数据格式的方法太过笨拙。
- 使用不可拓展容器来储存变量,有超出容器容量的风险,应当换用ArrayList等容器。这样不仅解决了容器大小的问题,又可以让数据的增删改查更加方便。
- 由于胡乱的增加类,导致类与类的关系变得混乱,应当将Table类与Order类结合起来,可以增加代码的可读性。
总结:
现在回顾这一系列题目感觉难度并不是很大,思路相对来说还算比较清晰,各种方法实现起来还算比较简单。但对于当时第一次接触两百行以上的项目的我来说无疑是个大挑战,我很庆幸自己可以突破这个难关,虽然使用的方法并不好,用了许多“笨方法”,代码的结构也不够清晰,可读性也比较差,不过通过这次综合性训练我学到了很多新知识。在此之前我从未接触过parse方法,也不知道LocalDateTime的使用方法。总体而言,这套菜单系统让我学到了很多新知识,并且使我对代码结构的理解更加深刻,意识到了代码可拓展性的重要。
标签:count,getHour,总结性,题目,int,Blog,time,order From: https://www.cnblogs.com/kuangyv/p/17418777.html