首页 > 编程语言 >菜单前三次点菜程序总结

菜单前三次点菜程序总结

时间:2023-05-23 15:48:21浏览次数:36  
标签:菜单 int 代码 字符串 点菜 三次 LocalTime

(1)前言(2)设计与分析(3)采坑心得(4)主要困难以及改进建议(5)总结

前言:

 

题目

知识点

题量(※※※※※)

难度(※※※※※)

点菜1

1.区别和学会使用了对象和类;

2.基本语法,如输入输出,基本类型和包裹类型

3.常见的处理字符串的方法

4.方法静态和不静态的使用

5.类构造方法的使用

6.使用容器arraylist

##.基本的按照现实来设计点菜思路,做到尽可能贴近现实。

 

※※

(代码量小,主要是让我们先学会写多类文件)

※※(难度不太大。希望这个系列题目多公开测试数据,就两三个测试数据,就算这两三个测试数据过了,也不能全对。并不能理解,是不是和老师的思路有出入还是有的地方特别苛刻?)

点菜2

1.属性可以进行private私有保护,并用getter和setter方法进行修改,这样就封装好了一个成员。

2.开始使用try…catch…解决字符串解析过程可能会报的错误。比如将字符串(nextLine获得的)用(split按空格拆分),将拆分的第一个pieces[0]进行数字解析(parseInt)就会出错。这就是出现异常,之后再自己按照业务的逻辑进行处理。

3.对于错误格式等输入错误,学会了多次使用if语句一次次排查,虽然代码变得十分难看,但是能对用户输入错误格式进行排查,给出提示。或者说多次正确使用elsel if语句

4.能够区分equals和==。在菜单for each找菜返回菜时。equals比较内容之间返回,==比较对象(也就是比较引用,指针,地址)返回。这一点也给我后面点菜4,埋下了坑。(有些东西就是要new出来再返回,直接返回,就要考虑返回后会不会被使用。如果会被使用(也就是修改其中的数据属性时),是不是应该在此之前要new一下,体会体会)

※※※(代码量适中)

※※※(初学主要第一次对字符串进行处理可能会手足无措)

点菜3

1.学会代码提取和拆分,要是不进行拆分和提取,代码就会成为山,并且eclipse又不能折叠if语句和循环语句。

2.对于字符串要进行转换功能的解析,熟悉了字符串的拆分,组合,格式化输出。

3.对于准备桌子中要记录客人点菜的时间,刚开始学着使用Date类,后面发现Date和Calendar和GregorianCalendar,绝大多数方法过时,并且用法实在是啰嗦难用。后面就学习使用了LocalDateTime(也可以拆成两个子类LocalDate和LocalTIme),记录时间使用LocalDate,里面自带判断闰年等方法和Date差不多但是整合了Calendar的感觉。

4.对于时间的处理,java1.8中出现了Period、Duration,了解并且使用了其中的方法,对于营业时间处于在早上和下午之间有专门的时间处理。(后面又不用了),因为实在是没必要计算变得复杂,对字符串处理也有同样的效果。

5.计算菜的价格的时候有对数字严格要求,熟悉一下Math类中的方法。区分了round、floor、ceil这些怎么对数字取整的(是四舍五入还是向上或向下取整)。

※※※※(代码量,主要是体现在逻辑容易乱)

※※※※(时间处理是向来的难点,就是很需要多多留意。刚接触java,听老师讲的少了,用的也少)

 

设计与分析:

题目 类图(代码结构) SourceMonito(代码质量检测) 简单的看图分析
点菜1

整个工程不是很复杂,复杂度不高。

但是Main复杂度就挺高的,实际也还是正常的,毕竟所有的处理全交给了Main。

他这里的现实方法偏少,那么我以后写代码把Main中的过程提取成方法会不会就会有更好的可读性,或者降低复杂度呢?

只能以后试试了。

点菜2

工程kiviat metric图,除了最大复杂度超标,其他指标是正常的。也就是代码出现了头重脚轻的感觉,需要对特别复杂的代码进行优化。

尤其是到Main这里,方法少的可怜,复杂度全部超标,代码可能就只有自己看的懂把。

点菜3

这里Main图表示还是方法过少,整体复杂度高出了9倍。最大复杂度高出了3倍。这个图给我敲响警钟把,if-else或者是elif这类的分支,就是复杂度的一大凶手,需要大幅度改进。造成这么大的复杂度的原因也就是滥用分支。

对菜单一中具体的代码进行分析

Dish类中的计算价格
public int getPrice(int portion) {
    int price = 0;
    if (portion == 1) {
        price = Math.round(1 * unit_price);
    }
    if (portion == 2) {
        price = (int) Math.round(1.5 * unit_price);
    }
    if (portion == 3) {
        price = Math.round(2 * unit_price);
    }
    return price;
}
Record类中的计算价格
public int getPrice() {
    return d.getPrice(portion);
}
Order类中的计算价格
public int getTotalPrice() {
    int sum = 0;
    for (Record ck : records) {
        sum += ck.getPrice();
    }
    return sum;
}

如上述代码一样,Order计算价钱的方法就是遍历每个Record,唤醒Record的计算价钱记录相加。而Record的唤醒Dish的计算价钱,层层调用,实际就和现实情况一样的。Dish自己根据份额计算属与自己份额的价钱返回给Record,这里Record就直接什么都不做就返回给Order(后面的Record有点菜的数量,就可以将Dish返回的价钱乘以数量,再返回给Order)。Order就算完成了任务(如果Order以后会出现折扣,对总和之后再乘以折扣。如果Order以后会有代点菜的话,也可以在计算价钱的总和进行处理)

对菜单二中比较难想的代码的分析

①如何对字符串解析。

最终我想的方法是,每次读取一行字符串(nextLine方法),我记为line。对line根据空格进行拆分(用spilt方法),记成pieces。重点来了。

如果拆分出来的pieces有2个就是准备菜单。

如果拆分出来的pieces有4个就是点菜。

如果拆分出来的pieces有2个并且pieces[1]是delete的话(pieces[1].equals("delete"))就是删除已经点了的菜。

这样我就解析了字符串,下面是代码草稿。

String line=in.nextLine();
String[] pieces=line.split(" ");
int ln=pieces.length;
if(ln==2&&!pieces[1].equals("delete")){
    准备菜单;
}
else if(ln==2&&pieces[1].equals("delete"){
    删除菜单;
}   
if(ln==4){
    点菜;
}

②如何处理点菜2中的异常情况。

其中比较有点困难的就是这个了,在准备菜单的时候,当输入多次同名菜时,菜单只保存最后一次菜的信息。

Menu.remove(Menu.searthDish(dishName));
Menu.add(dishName, unitPrice);

对菜单3的难想的点的分析

Ⅰ.对于订单时间的记录

我一开始使用的是,创建指定日期格式的simpleDateFormat对象,解析时间返回一个Date对象,放入到Order中,便于之后的处理。后面发现时间出错了。后来查阅了一下资料发现,yyyy和YYYY是不一样的,mm和MM是不一样的。yyyy才是我们现在说的公历的年份,而YYYY不是,YYYY是ISO年份,具体我就不是很清楚,总之年份用yyyy不要用YYYY,要不然有些特别的日期记录的年份就会出错。mm是minute而MM是month,这个我一开始也搞错了。

SimpleDateFormat format=new SimpleDateFormat("YYYY/MM/dd HH/mm/ss");//这个就是错误的
SimpleDateFormat format=new SimpleDateFormat("yyyy/MM/dd HH/mm/ss");//这个就是正确的
LocalDateTime dateTime=format.parse(有关于时间的字符串);

后面的话,我就弃用这个simpleDataFormat对象中的parse方法了,转向LocalDateTIme。因为我很容易搞错simpleDateFormat,除非我上网复制粘贴别人写好的。直接对时间字符串进行split("/"),被字符串被拆分成六个部分分别Integer.parseInt,得到年月日时分秒。用LocalDateTime中的of方法,放入年月日时分秒,返回一个LocalDateTime对象,放入Order中。这样就记录了时间。

 

Ⅱ.按订单时间算折扣

首先需要判断是否是周末,后面是不是营业时间,才能按要求计算折扣,记录在Order中。

后面使用了LocalDateTime后,在计算折扣的时候。可以取出其中部分作为LocalDate(toLocalDate方法),LocalDate又能取出是一周的哪一天(getDayOfWeek),枚举对象能取出对于的值,这里DayOfWeek的枚举是能去取出int值(使用getValue方法)。最后比较这个取出的int值,就可以判断是不是周末了。

//这里只是示意
LocalDateTime a=LocalDateTime.of(年,月,日,时,分,秒);
LocalDate b=a.toLocalDate();
int day=b.getDayOfWeek().getValue();
boolean isWeekend=false;
if(day==6||day==7){
    isWeekend=true;
}

判断完是不是周末,就要判断是否是营业时间。

先确定折扣时间段的起点和终点,然后进行如果是在指定的范围就打折,不在营业范围提示错误输出。下面的示例代码会比我讲的文字更清楚。

LocalTime WeekdayDinnerTime1 = LocalTime.of(16, 59, 59);
LocalTime WeekdayDinnerTime2 = LocalTime.of(20, 31);
LocalTime WeekdayLunchTime1 = LocalTime.of(10, 29, 59);
LocalTime WeekdayLunchTime2 = LocalTime.of(14, 31);
LocalTime weekendOpenningTime1 = LocalTime.of(9, 29, 59);
LocalTime weekendOpenningTime2 = LocalTime.of(21, 31, 00);

if (!isWeekend) {
    if (isIn(订单时间, weekdayDinnerTime1, weekdayDinnerTime2))
        discount = 0.8;
    else if (isIn(订单时间, weekdayLunchTime1, weekdayLunchTime2))
        discount = 0.6;
    else 
        System.out.println("table " + tableNum + " out of opening hours");
} else {
    if (isIn(订单时间, weekendOpenningTime1, weekendOpenningTime2)){
        discount = 1.0;//由于我的代码最后的总价一定会乘以discount,这一行不能省略。
    }else{
        System.out.println("table " + tableNum + " out of opening hours");
    }
}

 

Ⅲ.代点菜部分

首先查找要给哪个桌子代点菜,找到这个table。然后再解析要代点的菜,进行的相对应的处理。

我先写了一个找桌子的方法,然后当前的桌子currentTable是实时按照输入更新的,currentTable就给找到的桌子增加订单,addARecord给找到的table,自己currentTable则只是记录一下要付的钱(extraMoney),而找到的table的extraMoney就是相反数。最后总价计算,还是符合题意,就草草就这样完成了个代点菜功能。我觉得代点菜,我这里可能没有符合现实。所以有点困惑,后面看到某个老师写的代码,发现现实生活中的确,订单就要分自己吃的菜,和自己高兴给别人点的菜,订单是都应该记录在自己currentTable。而不是像我一样,记录在找到的table上,不符合现实逻辑。

踩坑心得: 

1.simpleDateFormat解析的坑,yyyy与YYYY;

2.使用for-each循环遍历dishes(菜单上的菜),直接返回菜单上的菜这个对象,后面对这个返回值进行创建新的订单,这就难免会对这个返回值进行修改。这就直接对菜单进行修改了,可是菜单是不会变的,一开始由店家的输入就确定了。后面如果要用返回值的修改的话,就进行new一下再返回,这样就不用担心菜单会在创建订单的过程中改变,也就避免牵一发而动全身了。

3.周末的discount没有赋值,导致最后在周末的桌子清算价格的时候全是0。(特别小的坑,很快就解决了)。

4.订单价格和预期价格总是差1元。找了很久发现是四舍五入的顺序出错了。可是我后面按照题目的顺序只有80%的订单是可以得到正确的价格的,其他的20%都会差1元,真的很心累吧。现在之间还未解决。

其他的坑不太显著,就是很快就能解决,以上写的就是卡了很久的坑。

主要困难已经改进建议:

1.对订单价格的计算,如设计与分析中的菜单一中代码分析。

2.对字符串的解析,如设计与分析中的菜单二而的难点分析。

3.日期的处理,如设计与分析中菜单三的难想到的点的分析。

4.后面想了想字符串的解析,可以匹配正则表达式的方法,也在菜单4后面的代码体现了。

5.后面的delete duplication可以用set容器,有查重的功能,如果已经在集合存在了,那么就输出删除重复语句。

具体的主要困难,在分析代码的时候就已经体现,分析代码就是面对主要困难时的心路体现。具体的改进其实也有体现。

总结:

学到了什么,哪些地方需要进一步学习及研究,对教师、课程、作业、实验、课上及课下组织方式等方面的改进建议及意见。

菜单这个程序对新手来说难度还是很大的,尤其时像我这种刚入门的,在这里只能说,难有难的好吧。难可以把许多知识点一起复习带过,但是不能很容易让初学者满分,甚至可以初学者没有一次满分过,有点打击自信心。如果点菜系列的公开测试点不是简略的5、6个。或者一些苛刻的点给出模板样例,不要只用文字寥寥几笔带过。有的时候你不知道提示难点一下,就能过去绝大多数测试点,能给很多自信。

总之还是收获,难有难的好,可以提升和进阶。简单又简单的妙处,也能让自己熟悉使用一些基本语法。

需要进一步学习的就是对字符串的处理方法。和如果自己程序正常出现题目中所给的错误输入的话,怎么样才能不要一直if-esle这样一坨一坨的堆叠代码,难维护的代码,又复杂度的增高,势必会对以后程序可持续化加大难度。这不就体现在菜单4吗,菜单4中17个异常情况,用实验3的代码来说,全在那里加if-else,像座山的代码,实现了其中的异常处理功能。这样的代码是真正想要的吗?自己做了菜单才能理解,有些封装是必要的,如果没有封装,则需要大刀阔斧的修改。也是做了菜单才能理解,有些看起来方便的if-else,可能是危险累计的开始,对于异常的处理,越独立越好,如果能减少分支也是给维护人员的一口喘息把。

最大的建议和意见,希望不要只是寥寥在题目集上面写一段提示文字,而是给多测试点,有的时候都过去了测试点,就是不能全对,现在的pta又关闭了测试点中的标准输出,自己去想测试样对目前的自己还是很难的。或者多给一点代码提示,尤其是价格计算的时候,你以为你按照题目做清楚功能了,结果就差个1,无论你怎么样修改(int)和(Math.round)的位置,增加还是删除(Math.round),能过去大部分的点,别的小点,最终又是答案错误,又看不到标准的输出应该是什么。

这个题目收获不止如此,只能说学java做到就是赚到把。

标签:菜单,int,代码,字符串,点菜,三次,LocalTime
From: https://www.cnblogs.com/liujiantao/p/17410161.html

相关文章

  • vue3 左侧菜单栏默认展开关闭
    <el-menuclass="mainMenu"routerbackground-color="transparent"active-text-color="#fff":unique-opened="true":collapse-transition="false"......
  • CentOS 跳过开机启动菜单(无需等待)
    sudo-i//转成root用户vim/etc/grub2.cfg//vim编辑这个文件 保存退出,重启查看效果kali和centOS跳过开机启动菜单(无需等待)_kali跳过设置用户_秋叶依剑的博客-CSDN博客......
  • 菜单题目集1~3
    一、前言 Java这三次题目集中第一周的九题:题目难度较低,比较基础,适合过渡。第二周的四题:题目难度较第一周有较大升级,java的面向对象性开始体现,类间关系及类与类之间属性方法的调用难度加大,java的难处初显。第三周的七题:第三周的题目难易混杂,7-1菜单计价程序-3是第二周两个菜......
  • 第四五次菜单计价及期中考试分析与总结
    前言:经过五次大作业的洗礼与折磨,相信大家已经被折磨疯掉了吧,经过上一次的blog总结经验我现在已经学会了blog的总结经验,接下来,我将会从这两次大作业即一次期中考试所涉及的知识点,难度以及题量还有我对这三次作业的看法这四个方面展开,有针对的展开一次总结性blog!1.题量:(1).......
  • 菜单系列及考试分析
    一、前言大一下学期开始,我们开始接触java这门语言,Java具有大部分编程语言所共有的一些特征,被特意设计用于互联网的分布式环境。Java具有类似于C++语言的形式和感觉,但它要比C++语言更易于使用,而且在编程时彻底采用了一种以对象为导向的方式。  Pta作业已经写了五次,除了第一次题......
  • TCP三次握手和四次挥手的详细过程
     TCP连接建立时采用三次握手,释放时采用四次挥手,目的是进行连接的建立和释放。 三次握手的过程: 客户端发送SYN消息,表示客户端准备建立连接。服务器接收SYN消息,响应ACK消息(同时包含自己的SYN消息),表示服务器已接收客户端的SYN,也准备建立连接。客户端接收到服务器的SYN+A......
  • MFC程序隐藏托盘+右键关闭菜单
    背景介绍:我的程序是启动后,默认就隐藏到托盘中,等待http请求后,显示界面。所以最小化到托盘的代码,我是写在初始化里面。  正文:一、自定义消息WM_SHOWTASK#defineWM_SHOWTASK(WM_USER+101)  二、在类向导中添加消息处理点击【类向导】、【消息】......
  • Element UI el-menu菜单 子级选中后,删除父级下划线
    1.子级选中,父级也选中样式修改: .el-submenu.is-active>.el-submenu__title {color:#FFFFFF;background-color:#7E8796!important;}2.子级选中后,父级有下划线,可以通过以下样式修改去除下划线 .el-menu--horizontal>.el-submenu.el-submenu__title ......
  • TCP三次握手四次挥手
    1.三次握手三次握手(Three-wayHandshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。实质上其实就是连接服务器指定端口,建立TCP连接,并......
  • Windows 11 恢复经典的右键全量菜单
    设置打开windows命令行终端输入并回车(下列代码为同一行):regaddHKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32/ve/d""/f退出命令行终端退出并重新登录账号或重启资源管理器或重启电脑恢复默认打开windows命令行终端输入并回......