OO第二次大作业

前言

前言的前言

第二篇blog跟上一篇只隔了将近一个月,但是感觉心境上好像发生了很多的变化,认识到了自己存在的很多不足(可能是菜单折磨的),感觉对很多东西都一知半解,希望在写完这篇总结性blog之后,我能清晰一点。如果对我blog的内容有任何修正或者建议可以评论让我知道,谢谢你愿意点开我的blog并给出建议🌹。

第四次作业

涉及知识点

类的构造、类与类之间关系的设计(hardest🥀)、Collections(容器)、字符串、Override(覆写)、封装性、LocalDate类。

题量

一共7题,题量不大,但是顺序开题惨遭滑铁卢,综合性比较强,涉及到类与类之间关系的设计,容器的使用等。

难度

第一题🌟🌟难度相比之前的题目稍大,我相信以后还有更难的🥀。2、3、4我认为都是针对容器的训练(不过在和同学交流的时候,发现有同学没有用容器也完成了题目,所以我不是很确定),题目给的提示都比较明显,比较容易选择合适的容器。值得一提的是,我在第4题,自定义了TreeSet的比较器,让它来适应题目,但是,后面有同学告诉我有现成的方法可以调QAQ。(我写的时候被折磨了好久,那时候的小的蒟蒻还不知道Override、Overload,看了好几篇文章才浅浅知道了一点)

第五次作业

涉及知识点

正则表达式、构造类、类与类之间的关系、读类图。

题量

一共6题,跟第一次作业题量差不多,最后两题代码量偏大一点点,但也只是一点点。

难度

难度不是很大,主要是正则表达式的基本运用,一开始我都是按下面的写法写的,因为罗老师的课都是这样写的,后面跟同学交流了一下,发现不需要这得这么复杂,字符串匹配的操作本身就是if返回值是boolean类型,可以直接写在if的判断条件里面QAQ

import java.util.Objects;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        String s = input.nextLine();//读入字符串
        
        String regStr = "^[1-9][0-9]{4,14}";//用正则表达式判断字符是否规则
        
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(s);
        
        while (matcher.find()){//寻找符合规则的字符串
            if(s.equals(matcher.group(0))) {//如果找到的字符串跟原来的字符串一样
                System.out.println("你输入的QQ号验证成功");//说明原字符串符合规则
                return;
            }
        }
        
        System.out.println("你输入的QQ号验证失败");//反之,不符合
    }
}

关于题目的一点看法

我在做日期的题目的时候,有一个点一直过不去,我就做了一些边界值的测试,发现确实有问题,但是修改了之后,测试点还是没有过去,说明测试点还是不够全面。(我上一篇blog的代码也存在相同的问题,但是没有被检测出来🥀,现已补充说明😊)

第六次作业

涉及知识点

构造类、类与类之间关系的设计。

题量

仅一题,题目量最少,代码量目前来说最大.(我相信还会有更大的)

难度

老师多次声明题目并不难,所以我深刻认识到了自己蒟蒻的本质。

一些题外话

我在结束之后找满分的同学要了代码看,非常感谢他愿意给我,最明显的就是他把代码进行了封装,都写成了方法。在思维和逻辑上也毕竟清晰,跟我在主方法里面放了大量的if-else形成鲜明的对比。总而言之,我"还差得远呢",还有很多东西要学,还有很多习惯要改。

三次作业总结

被菜单折磨的稀里糊涂,让我更直观的看到了自己和别人之间的差距。

设计与分析

写在前面

这次的设计与分析我想把日期问题的几次迭代做一个小的总结,可能不是很全面也不是很正确。在这里不过多分析菜单问题是因为我两次作业菜单问题都做得不好,我对这个题目没有太多的话语权。

回顾

先回顾一下日期问题的迭代情况

日期问题-1

第一次出现在OOP02的7-9,题目仅要求求下一天的日期,只需要把给出的方法写在主类里面就可以。

日期问题-2

第二次出现在OOP03的7-4,要求构造出日期类,日期类中的方法方法基本给出,功能增加到:1、求前n天的日期;2、求后n天的日期;3、求两日期的时间差。

日期问题-3

第三次出现在OOP05的7-5,要求构造出日期类、年类、月类、日类,类图已给出。虽然类图给出的类间关系是聚合,但是我认为是组合关系,这几个类的生存期是相同的,并且我用idea把我写好的代码生成的类图也是组合关系,类图都放在下面了。

日期问题-4

第四次出现在OOP05的7-6,要求构造出日期类、年类、月类、日类,类图已给出。给出的类图跟代码生成类图有跟上述一样的问题存在,不赘述。

3、4对比

我画了一个Venn图来表达一下我对两种类的关系的理解

日期问题-3

源码

package OOP05;


import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int year;
        int month;
        int day;

        int choice = input.nextInt();

        if (choice == 1) { // test getNextNDays method
            int m;
            //获取年月日
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            //构造DateUtil对象
            DateUtil date = new DateUtil(day, month, year);

            //判断日期是否合法
            if (!date.checkInputValidity()) {
                System.out.println("Wrong Format");
                System.exit(0);
            }

            m = input.nextInt();//获取天数

            if (m < 0) {//天数不合法
                System.out.println("Wrong Format");
                System.exit(0);
            }
            System.out.println(date.getNextNDays(m).showDate());

        } else if (choice == 2) { // test getPreviousNDays method
            int n;
            //获取年月日
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            //构造DateUtil对象
            DateUtil date = new DateUtil(day, month, year);

            //判断日期是否合法
            if (!date.checkInputValidity()) {
                System.out.println("Wrong Format");
                System.exit(0);
            }

            n = input.nextInt();//获取天数

            if (n < 0) {//天数不合法
                System.out.println("Wrong Format");
                System.exit(0);
            }

            System.out.println(date.getPreviousNDays(n).showDate());
        } else if (choice == 3) {    //test getDaysofDates method
            //获取第一个日期
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            //获取另一个日期
            int anotherYear = Integer.parseInt(input.next());
            int anotherMonth = Integer.parseInt(input.next());
            int anotherDay = Integer.parseInt(input.next());

            //构造两个日期类
            DateUtil fromDate = new DateUtil(day, month, year);
            DateUtil toDate = new DateUtil(anotherDay, anotherMonth, anotherYear);

            //判断两个日期是否都合法
            if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
                System.out.println(fromDate.getDaysofDates(toDate));
            } else {
                System.out.println("Wrong Format");
                System.exit(0);
            }
        } else{
            System.out.println("Wrong Format");
            System.exit(0);
        }
    }
}
class DateUtil{


    private Day day = new Day();
    //无参构造
    public DateUtil(){

    }
    //有参构造
    public DateUtil(int d,int m,int y){
        this.getDay().setValue(d);
        this.getDay().getMonth().setValue(m);
        this.getDay().getMonth().getYear().setValue(y);
    }
    public Day getDay() {
        return this.day;
    }

    public void setDay(Day d) {
        this.day = d;
    }
    public boolean checkInputValidity(){//判断日期是否合法
        if(this.getDay().getMonth().getYear().isLeapYear()){
            this.getDay().resetMon_maxnum1();//把日期设置成29天
        }
        else {
            this.getDay().resetMon_maxnum2();//把日期设置成28天
        }
        if (!this.getDay().getMonth().getYear().validate()){
            return false;
        }
        else if(!this.getDay().getMonth().validate()){
            return false;
        }
        else if(!this.getDay().validate()){
            return false;
        }
        return true;
    }
    public boolean compareDates(DateUtil date){//比较两个日期的先后
        if(this.getDay().getMonth().getYear().getValue() > date.getDay().getMonth().getYear().getValue()){
            return true;
        }
        else if(this.getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()){
            if(this.getDay().getMonth().getValue() > date.getDay().getMonth().getValue()){
                return true;
            }
            else if(this.getDay().getMonth().getValue() == date.getDay().getMonth().getValue()){
                if(this.getDay().getValue() >= this.getDay().getValue()){
                    return true;
                }
                return false;
            }
            return false;
        }
        return false;
    }
    public boolean equalTwoDates(DateUtil date){//判断两个日期是否相等
        if((this.getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue())
                && (this.getDay().getMonth().getValue() == date.getDay().getMonth().getValue()) && (this.getDay().getValue() == date.getDay().getValue())){
            return true;
        }
        return false;
    }
    public String showDate(){//输出格式控制
        return this.getDay().getMonth().getYear().getValue() + "-" + this.getDay().getMonth().getValue() + "-" + this.getDay().getValue();
    }
    //下n天
    public DateUtil getNextNDays(int n){
        //判断今年是不是闰年,下n天可能进过2月的最后一天
        if(this.getDay().getMonth().getYear().isLeapYear()){
            this.getDay().resetMon_maxnum1();//把2月设置成29天
        }
        else {
            this.getDay().resetMon_maxnum2();//把2月设置成28天
        }
        while (n > 0){
            //逐月处理
            for(int i = this.getDay().getMonth().getValue();i <= 12;i++) {
                if (n - ( this.getDay().getMon_maxnum(this.getDay().getMonth().getValue()) - this.getDay().getValue() + 1) > 0) {//如果天数能加到下个月的1日

                    this.getDay().getMonth().monthIncrement();//月份加1
                    //如果变成13月
                    if (!this.getDay().getMonth().validate()) {

                        this.getDay().getMonth().resetMin();//将月变成1月
                        this.getDay().getMonth().getYear().yearIncrement();//年份加1

                        if(this.getDay().getMonth().getYear().isLeapYear()){//根据年份修重新设置2月的天数
                            this.getDay().resetMon_maxnum1();//把2月设置成29天
                        } else {
                            this.getDay().resetMon_maxnum2();//把2月设置成28天
                        }
                    }
                    n -= this.getDay().getMon_maxnum(i) - this.getDay().getValue() + 1;//原天数减去加到下个月1日的天数
                    this.getDay().resetMin();//变成1日
                } else {//天数不能加到下个月的1日,表示年份和月份已经确定
                    this.getDay().setValue(this.getDay().getValue() + n);
                    n -= n;
                    break;
                }
            }
        }
        return this;
    }
    public DateUtil getPreviousNDays(int n){
        //判断今年是不是闰年,前n天可能进过2月的最后一天
        if(this.getDay().getMonth().getYear().isLeapYear()){
            this.getDay().resetMon_maxnum1();//把2月设置成29天
        } else {
            this.getDay().resetMon_maxnum2();//把2月设置成28天
        }
        while (n > 0){
            for(int i = this.getDay().getMonth().getValue();i >= 1;i++) {
                if (n  - this.getDay().getValue() >= 0) {//如果天数能减到上个月的最后一天

                    this.getDay().getMonth().monthReduction();//月份减1
                    //如果变成0月
                    if (!this.getDay().getMonth().validate()) {

                        this.getDay().getMonth().resetMax();//将月变成12月
                        this.getDay().getMonth().getYear().yearReduction();//年份减1

                        if(this.getDay().getMonth().getYear().isLeapYear()){//根据年份修重新设置2月的天数
                            this.getDay().resetMon_maxnum1();//把2月设置成29天
                        } else {
                            this.getDay().resetMon_maxnum2();//把2月设置成28天
                        }
                    }
                    n -= this.getDay().getValue();//原天数减去减到上个月最后一天的天数
                    this.getDay().resetMax();//变成该月最后一天
                } else {//天数不能加到下个月的1日,表示年份和月份已经确定
                    this.getDay().setValue(this.getDay().getValue() - n);
                    n -= n;
                    break;
                }
            }
        }
        return this;
    }
    public int getDaysofDates(DateUtil date){

        int sum1 = 0,sum2 = 0;
        //寻找两个日期中较小的年份
        int year = Math.min(date.getDay().getMonth().getYear().getValue(), this.getDay().getMonth().getYear().getValue());
        int month = 1;
        int day = 1;

        //构造日期类
        DateUtil dateUtil = new DateUtil(day,month,year);

        if(this.equalTwoDates(date)) {//如果两个日期相等
            return sum2 - sum1;
        } else {
            //逐年计算date到dateUtil的天数
            while (dateUtil.getDay().getMonth().getYear().getValue() < date.getDay().getMonth().getYear().getValue()) {
                if (dateUtil.getDay().getMonth().getYear().isLeapYear()) {
                    sum1 += 366;
                }
                else {
                    sum1 += 365;
                }
                dateUtil.getDay().getMonth().getYear().yearIncrement();
            }

            if(date.getDay().getMonth().getYear().isLeapYear()){
                date.getDay().resetMon_maxnum1();//把2月设置成29天
            }
            else {
                date.getDay().resetMon_maxnum2();//把2月设置成28天
            }
            //逐月计算date到dateUtil的天数
            for(int i = 1;i < date.getDay().getMonth().getValue();i++) {
                sum1 += date.getDay().getMon_maxnum(i);
            }
            sum1 += date.getDay().getValue() - 1;//加上天数

            //将dateUtil重新初始化
            dateUtil.getDay().getMonth().getYear().setValue(year);
            dateUtil.getDay().getMonth().setValue(month);
            dateUtil.getDay().setValue(day);

            //逐年计算this到dateUtil的天数
            while (dateUtil.getDay().getMonth().getYear().getValue() < this.getDay().getMonth().getYear().getValue()) {
                if (dateUtil.getDay().getMonth().getYear().isLeapYear()) {
                    sum2 += 366;
                }
                else {
                    sum2 += 365;
                }
                dateUtil.getDay().getMonth().getYear().yearIncrement();
            }
            //逐月计算this到dateUtil的天数
            if(this.getDay().getMonth().getYear().isLeapYear()){
                this.getDay().resetMon_maxnum1();//把2月设置成29天
            }
            else {
                this.getDay().resetMon_maxnum2();//把2月设置成28天
            }

            for (int i = month; i < this.getDay().getMonth().getValue(); i++) {
                sum2 += this.getDay().getMon_maxnum(i);
            }

            sum2 += this.getDay().getValue() - 1;//加上天数

            return Math.abs(sum2 - sum1);//求两者的差
        }
    }
}
class Day{
    private int value;
    private Month month = new Month();
    private int[] mon_maxnum = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    //无参构造
    public Day(){

    }
    //有参构造
    public Day(int yearValue,int monthValue,int dayValue) {
        this.value = dayValue;
        this.month.setValue(monthValue);
        this.month.getYear().setValue(yearValue);
    }
    public int getValue() {
        return this.value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Month getMonth() {
        return this.month;
    }

    public void setMonth(Month value) {
        this.month = value;
    }

    public void resetMin(){//把天数归1
        this.value = 1;
    }
    public void resetMax(){//让天数等于该月的最大
        this.value = mon_maxnum[month.getValue()];
    }
    public boolean validate(){//判断天数是否合法
        if(this.value < 1 || this.value > mon_maxnum[this.month.getValue()]){
            return false;
        }
        return  true;
    }
    public void dayIncrement(){//天数加1
        this.value ++;
    }
    public void dayReduction(){//天数减1
        this.value --;
    }
    public int getMon_maxnum(int month){//获取某月的最大值
        return this.mon_maxnum[month];
    }
    public void resetMon_maxnum1(){//把2月设置成29天
        this.mon_maxnum[2] = 29;
    }
    public void resetMon_maxnum2(){//把2月设置成28天
        this.mon_maxnum[2] = 28;
    }

}
class Month{
    private int value;
    private Year year = new Year();
    //无参构造
    public Month(){

    }
    //有参构造
    public Month(int yearValue,int monthValue){
        this.value = monthValue;
        this.year.setValue(yearValue);
    }
    public int getValue() {
        return this.value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Year getYear() {
        return this.year;
    }

    public void setYear(Year year) {
        this.year = year;
    }
    public void resetMin(){//月份归1
        this.value = 1;
    }
    public void resetMax(){//月份最大
        this.value = 12;
    }
    public boolean validate(){//判断月份是否非法
        if(this.value < 1 || this.value > 12){
            return false;
        }
        return true;
    }
    public void monthIncrement(){//月份加1
        this.value ++;
    }
    public void monthReduction(){//月份减1
        this.value --;
    }
}
class Year{
    private int value;
    //无参构造
    public Year() {

    }
    //有参构造
    public Year(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
    public boolean isLeapYear(){//判断是否是闰年
        if((this.value % 4 == 0 && this.value % 100 != 0) || this.value % 400 == 0){
            return true;
        }
        return false;
    }
    public boolean validate(){//判断年份是否非法
        if(this.value < 1900 || this.value > 2050){
            return false;
        }
        return true;
    }
    public void yearIncrement(){//年份加1
        this.value ++;
    }
    public void yearReduction(){//年份减1
        this.value --;
    }
}

这是疯狂套娃的写法,可以从代码中看到,要调用方法的话,要层层深入。我个人觉得这个比较巧妙,很好地把Day、Month和Year绑在一起,有多个日期的时候不会出现匹配错误。

类图

这张是老师给出的类图

这张是我的代码生成的类图

可以看到两个类图除了类间关系不同之外,我还加了几个方法,用来获取当月的最大天数,来判断日期是否合法;以及根据是否是闰年来改变2月的最大天数
图有点长,如果有能调整的方法,请dd我

代码分析



从图上可以看到,平均复杂度和最大复杂度都有点超标。我搜索了一下怎样降低函数复杂度,有博主建议:函数应该尽可能简单,并且符合单一职责原则。分析了一下我的代码,圈复杂度主要是被那三个功能方法影响了,那就说明我的算法还不是很好,有待改进。希望有更好算法的佬可以评论让我知道🌹。

日期问题-4

源码

package OOP05;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int year;
        int month;
        int day;

        int choice = input.nextInt();

        if (choice == 1) { // test getNextNDays method
            int m;
            //获取年月日
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            //构造DateUtil对象
            DateUtil date = new DateUtil(day, month, year);

            //判断日期是否合法
            if (!date.checkInputValidity()) {
                System.out.println("Wrong Format");
                System.exit(0);
            }

            m = input.nextInt();//获取天数

            if (m < 0) {//天数不合法
                System.out.println("Wrong Format");
                System.exit(0);
            }
            System.out.print(date.getYear().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " next " + m + " days is:");
            System.out.println(date.getNextNDays(m).showDate());

        } else if (choice == 2) { // test getPreviousNDays method
            int n;
            //获取年月日
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            //构造DateUtil对象
            DateUtil date = new DateUtil(day, month, year);

            //判断日期是否合法
            if (!date.checkInputValidity()) {
                System.out.println("Wrong Format");
                System.exit(0);
            }

            n = input.nextInt();//获取天数

            if (n < 0) {//天数不合法
                System.out.println("Wrong Format");
                System.exit(0);
            }
            System.out.print(date.getYear().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " previous " + n + " days is:");
            System.out.println(date.getPreviousNDays(n).showDate());
        } else if (choice == 3) {    //test getDaysofDates method
            //获取第一个日期
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            //获取另一个日期
            int anotherYear = Integer.parseInt(input.next());
            int anotherMonth = Integer.parseInt(input.next());
            int anotherDay = Integer.parseInt(input.next());

            //构造两个日期类
            DateUtil fromDate = new DateUtil(day, month, year);
            DateUtil toDate = new DateUtil(anotherDay, anotherMonth, anotherYear);

            //判断两个日期是否都合法
            if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
                System.out.println("The days between " + fromDate.showDate() +
                        " and " + toDate.showDate() + " are:"
                        + fromDate.getDaysofDates(toDate));
            } else {
                System.out.println("Wrong Format");
                System.exit(0);
            }
        } else{
            System.out.println("Wrong Format");
            System.exit(0);
        }
    }
}
class DateUtil {

    private Year year = new Year();
    private Month month = new Month();
    private Day day = new Day();
    private int[] mon_maxnum = {0,31,28,31,30,31,30,31,31,30,31,30,31};


    //无参构造
    public DateUtil() {

    }
    //有参构造
    public DateUtil(int d,int m,int y){
        this.getDay().setValue(d);
        this.getMonth().setValue(m);
        this.getYear().setValue(y);
    }

    public Year getYear() {
        return year;
    }

    public void setYear(Year year) {
        this.year = year;
    }

    public Month getMonth() {
        return month;
    }

    public void setMonth(Month month) {
        this.month = month;
    }

    public Day getDay() {
        return day;
    }

    public void setDay(Day day) {
        this.day = day;
    }
    public void setDayMin(){//把天数归1
        this.getDay().setValue(1);
    }
    public void setDayMax(){//让天数等于该月的最大
        this.getDay().setValue(mon_maxnum[month.getValue()]);
    }
    public boolean checkInputValidity(){//判断日期是否合法
        if(this.getYear().isLeapYear()){
            this.mon_maxnum[2] = 29;//把日期设置成29天
        }
        else {
            this.mon_maxnum[2] = 28;//把日期设置成28天
        }
        if (!this.getYear().validate()){
            return false;
        }
        else if(!this.getMonth().validate()){
            return false;
        }
        else if(this.getDay().getValue() < 1 || this.getDay().getValue() > this.mon_maxnum[this.getMonth().getValue()]){
            return false;
        }
        return true;
    }
    public DateUtil getNextNDays(int n){
        //判断今年是不是闰年,下n天可能进过2月的最后一天
        if(this.getYear().isLeapYear()){
            this.mon_maxnum[2] = 29;//把2月设置成29天
        }
        else {
            this.mon_maxnum[2] = 28;//把2月设置成28天
        }
        while (n > 0){
            //逐月处理
            for(int i = this.getMonth().getValue();i <= 12;i++) {
                if (n - ( this.mon_maxnum[this.getMonth().getValue()] - this.getDay().getValue() + 1) > 0) {//如果天数能加到下个月的1日

                    this.getMonth().monthIncrement();//月份加1
                    //如果变成13月
                    if (!this.getMonth().validate()) {

                        this.getMonth().resetMin();//将月变成1月
                        this.getYear().yearIncrement();//年份加1

                        if(this.getYear().isLeapYear()){//根据年份修重新设置2月的天数
                            this.mon_maxnum[2] = 29;//把2月设置成29天
                        } else {
                            this.mon_maxnum[2] = 28;//把2月设置成28天
                        }
                    }
                    n -= this.mon_maxnum[i] - this.getDay().getValue() + 1;//原天数减去加到下个月1日的天数
                    this.setDayMin();//变成1日
                } else {//天数不能加到下个月的1日,表示年份和月份已经确定
                    this.getDay().setValue(this.getDay().getValue() + n);
                    n -= n;
                    break;
                }
            }
        }
        return this;
    }
    public DateUtil getPreviousNDays(int n){
        //判断今年是不是闰年,前n天可能进过2月的最后一天
        if(this.getYear().isLeapYear()){
            this.mon_maxnum[2] = 29;//把2月设置成29天
        } else {
            this.mon_maxnum[2] = 28;//把2月设置成28天
        }
        while (n > 0){
            for(int i = this.getMonth().getValue();i >= 1;i++) {
                if (n  - this.getDay().getValue() >= 0) {//如果天数能减到上个月的最后一天

                    this.getMonth().monthReduction();//月份减1
                    //如果变成0月
                    if (!this.getMonth().validate()) {

                        this.getMonth().resetMax();//将月变成12月
                        this.getYear().yearReduction();//年份减1

                        if(this.getYear().isLeapYear()){//根据年份修重新设置2月的天数
                            this.mon_maxnum[2] = 29;//把2月设置成29天
                        } else {
                            this.mon_maxnum[2] = 28;//把2月设置成28天
                        }
                    }
                    n -= this.getDay().getValue();//原天数减去减到上个月最后一天的天数
                    this.setDayMax();//变成该月最后一天
                } else {//天数不能加到下个月的1日,表示年份和月份已经确定
                    this.getDay().setValue(this.getDay().getValue() - n);
                    n -= n;
                    break;
                }
            }
        }
        return this;
    }
    public boolean compareDates(DateUtil date){//比较两个日期的先后
        if(this.getYear().getValue() > date.getYear().getValue()){
            return true;
        }
        else if(this.getYear().getValue() == date.getYear().getValue()){
            if(this.getMonth().getValue() > date.getMonth().getValue()){
                return true;
            }
            else if(this.getMonth().getValue() == date.getMonth().getValue()){
                if(this.getDay().getValue() >= this.getDay().getValue()){
                    return true;
                }
                return false;
            }
            return false;
        }
        return false;
    }
    public boolean equalTwoDates(DateUtil date){//判断两个日期是否相等
        if((this.getYear().getValue() == date.getYear().getValue())
                && (this.getMonth().getValue() == date.getMonth().getValue()) && (this.getDay().getValue() == date.getDay().getValue())){
            return true;
        }
        return false;
    }
    public int getDaysofDates(DateUtil date){

        int sum1 = 0,sum2 = 0;
        //寻找两个日期中较小的年份
        int year = Math.min(date.getYear().getValue(), this.getYear().getValue());
        int month = 1;
        int day = 1;

        //构造日期类
        DateUtil dateUtil = new DateUtil(day,month,year);

        if(this.equalTwoDates(date)) {//如果两个日期相等
            return sum2 - sum1;
        } else {
            //逐年计算date到dateUtil的天数
            while (dateUtil.getYear().getValue() < date.getYear().getValue()) {
                if (dateUtil.getYear().isLeapYear()) {
                    sum1 += 366;
                }
                else {
                    sum1 += 365;
                }
                dateUtil.getYear().yearIncrement();
            }

            if(date.getYear().isLeapYear()){
                date.mon_maxnum[2] = 29;//把2月设置成29天
            }
            else {
                date.mon_maxnum[2] = 28;//把2月设置成28天
            }
            //逐月计算date到dateUtil的天数
            for(int i = 1;i < date.getMonth().getValue();i++) {
                sum1 += date.mon_maxnum[i];
            }
            sum1 += date.getDay().getValue() - 1;//加上天数

            //将dateUtil重新初始化
            dateUtil.getYear().setValue(year);
            dateUtil.getMonth().setValue(month);
            dateUtil.getDay().setValue(day);

            //逐年计算this到dateUtil的天数
            while (dateUtil.getYear().getValue() < this.getYear().getValue()) {
                if (dateUtil.getYear().isLeapYear()) {
                    sum2 += 366;
                }
                else {
                    sum2 += 365;
                }
                dateUtil.getYear().yearIncrement();
            }
            //逐月计算this到dateUtil的天数
            if(this.getYear().isLeapYear()){
                this.mon_maxnum[2] = 29;//把2月设置成29天
            }
            else {
                this.mon_maxnum[2] = 28;//把2月设置成28天
            }

            for (int i = month; i < this.getMonth().getValue(); i++) {
                sum2 += this.mon_maxnum[i];
            }

            sum2 += this.getDay().getValue() - 1;//加上天数

            return Math.abs(sum2 - sum1);//求两者的差
        }
    }
    public String showDate(){//输出格式控制
        return this.getYear().getValue() + "-" + this.getMonth().getValue() + "-" + this.getDay().getValue();
    }
}
class Day{
    private int value;
    //无参构造
    public Day(){

    }
    //有参构造
    public Day(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    public void setValue(int value) {
        this.value = value;
    }
    public void dayIncrement(){//天数加1
        this.value ++;
    }
    public void dayReduction(){//天数减1
        this.value --;
    }
}
class Month{
    private int value;

    //无参构造
    public Month(){

    }
    //有参构造
    public Month(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public void resetMin(){//月份归1
        this.value = 1;
    }
    public void resetMax(){//月份最大
        this.value = 12;
    }
    public boolean validate(){//判断月份是否非法
        if(this.value < 1 || this.value > 12){
            return false;
        }
        return true;
    }
    public void monthIncrement(){//月份加1
        this.value ++;
    }
    public void monthReduction(){//月份减1
        this.value --;
    }
}
class Year{
    private int value;
    //无参构造
    public Year() {

    }
    //有参构造
    public Year(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
    public boolean isLeapYear(){//判断是否是闰年
        if((this.value % 4 == 0 && this.value % 100 != 0) || this.value % 400 == 0){
            return true;
        }
        return false;
    }
    public boolean validate(){//判断年份是否非法
        if(this.value < 1820 || this.value > 2020){
            return false;
        }
        return true;
    }
    public void yearIncrement(){//年份加1
        this.value ++;
    }
    public void yearReduction(){//年份减1
        this.value --;
    }
}

类图

老师给的类图

我的代码生成的类图

代码分析



从上面的图可以看出:不但最大复杂度超标,我的最大深度和平均深度也超标了。复杂度超标的原因同上,最大深度是在判断闰年的地方达到最大,因为相较与上一个代码,因为Year类和Day类之间没有关系,所以我不能像上一段代码一样直接再判断后,对数组进行赋值,而是要将boolean的结果返回到DateUtil,再在DateUtil里面调用Day的方法,修改数组,导致了深度的增加。

踩坑心得

第四次作业

7-2

问题

一开始我发现这个题目跟之前的一样,以为是老师出重复了,按之前的写法交了一版,发现不是这样的,题面是一样的,但是数据变大了。也是因为数据太多,存储的时候花了大量的空间,导致内存超出限制。

import java.util.Scanner;
import java.util.Arrays;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        int [] arr = new int[n];
        int flag = 0;
        for(int i = 0;i < n;i++) {
            arr[i] = input.nextInt();
        }
        Arrays.sort(arr);
        for(int i = 1;i < n;i++){
            if(arr[i] == arr[i - 1]){
                System.out.println("YES");
                flag = 1;
            }
        }
        if(flag == 0)
        System.out.println("NO");
    }
}

然后我改成每次输入都进行排序,再筛选有没有一样的。一旦发现重复数据,就输出,并且结束程序。我一开始这样写的时候其实不觉得会对,因为Array.sort()是快排,而快排在比较有序的情况下,时间复杂度达到O(n^2),有比较大的可能会TLE。但是情况是这样的

代码如下

import java.util.Scanner;
import java.util.Arrays;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        int [] arr = new int[n];
        int flag = 0;
        for(int i = 0;i < n;i++) {
            arr[i] = input.nextInt();
            Arrays.sort(arr);
            for(int j = 0;j < i;j++){
                if(arr[i] == arr[j]){
                    System.out.println("YES");
                    return ;
                }
            }
        }
        System.out.println("NO");
    }
}

调试的时候发现,因为Java中的数组是默认初始化的,导致排序之后,数组中的前面的部分全部被0占位,出现多个重复的0,让程序输出了"YES"。
而后,突然想到Set多用于去重和排序,就有了下面的AC代码

import java.util.Scanner;
import java.util.Set;
import java.util.HashSet;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        Set<String> arr = new HashSet<String>();//构造一个HashSet用来去重
        int t = 0;
        for(int i = 0;i < n;i++) {
            String a = input.next();
            t++;
            arr.add(a);
            if(t > arr.size()){//根据Set的性质可知,不会记录重复数据,当t > arr.size()时,代表有重复数据
                System.out.println("YES");
                return ;
            }
        }
        System.out.println("NO");
    }
}

解释和心得

1、我后面有问别的同学,有人确实是没有用容器直接用之前的代码就直接AC了,不是太懂
2、容器的分类如图,用法跟C++的STL还是有比较大的区别,底层结构什么的还是一样的。

注:1、容器是数据结构,而且是Java以类库的形式供用户开发程序时可直接使用,不需要自己手写
2、这些容器的用法都是相似的,一通百通
3、7-3和7-2差不多,只是需要换一种无序去重的容器来存储数据

7-4

问题

上面我也提到了,我重构了TreeSet的排序算法,代码如下,TreeSet底层原理是TreeMap,而TreeMap的底层原理是一颗红黑树,所以就有了我注释里面写的存入左树和存入右树,是不是有点分治那味了。就是要注意什么时候存入左树,什么时候存入右树,我第一版的代码就有一部分写反了QAQ。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String s = input.nextLine();
        StringBuffer t = new StringBuffer();
        int flag = 0;
        Set<String> arr = new TreeSet<String>(new Comparator<String>() {
            @Override
            public int compare(String s, String t1) {//自定义排序
                if(s.equals(t1))//认为当前要存入的元素已经存在,不存入
                    return 0;
                if (s.length() > t1.length())
                    return -1;//认为当前要存入的元素比较小,存黑红树左边
                else if (t1.length() > s.length())
                    return 1;//认为当前要存入的元素比较大,存黑红树右边
                else {
                    for (int i = 0; i < s.length(); i++) {//依次比较单词的字母
                        int temp1 = s.charAt(i);
                        int temp2 = t1.charAt(i);
                        if (temp1 < 'a') {
                            temp1 += 'a' - 'A';
                        }
                        if (temp2 < 'a') {
                            temp2 += 'a' - 'A';
                        }
                        if (temp1 > temp2)
                            return 1;
                        else if (temp1 < temp2)
                            return -1;
                    }
                    return 0;//认为当前要存入的元素已经存在,不存入
                }
            }
        });//构造一个HashSet用来去重


        for(int i = 0;i < s.length();i++){
            if((s.charAt(i) != ' ') && (s.charAt(i) != '.') && s.charAt(i) != ',')
                t.append(s.charAt(i));//分割字符串,将子串暂时存储在t中
            else {
                arr.add(String.valueOf(t));//将子串放到arr中
                t.delete(0,t.length());//将t清空
            }
        }
        Iterator it = arr.iterator();//定义一个迭代器,用来遍历arr

        while (it.hasNext()){
            if(flag == 0){
                System.out.print(it.next());
                flag = 1;
            }
            System.out.printf("\n%s",it.next());
        }
    }
}

解释和心得

1、我后面跟同学交流了一下,然后知道了有一个能够忽略大小写对String进行排序的方法Arrays.sort(str, String.CASE_INSENSITIVE_ORDER)
2、TreeSet自定义比较器
我主要是看到了两种写法,一种是我这样的直接把Comparator直接覆写;另外一种是继承Comparator,构造一个新的类,如这位同学的代码(已争得同意,“同学”俩字附有超链接,可直接看原文)

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        String sentence = input.nextLine();
        String[] word = sentence.split(",| |\\.");
        TreeSet<String> sortedWord = new TreeSet<>(new newComparator());
        int i;
        for (i = 0;i < word.length;i++){
            if (!word[i].equals("")) {
                sortedWord.add(word[i]);
            }
        }
        Iterator<String> iterator = sortedWord.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}
class newComparator implements Comparator<String>{//重写排序方法
    @Override
    public int compare(String str1,String str2){
        if (str1.length() > str2.length()){
            return -1;
        }else if (str1.length() == str2.length()){
            return str1.compareToIgnoreCase(str2);//无视大小写进行比较
        }else{
            return 1;
        }
    }
}

写到这里,我突然想到,如果我在覆写了TreeSet的排序算法之后,我再构造一个TreeSet,默认的排序算法是什么样的呢?

结果很明显,至于前前后后的原理,跟同学讨论了一下,得出了初步结论,还要再分析一下,后期补充。
3、这里我分割字符串的操作,可以用String temp[] = s.split(",| |\.");来代替,更简洁,不容易出错。

7-6

问题

解释和心得

第五次作业

7-4

解释和心得

前面有提到一开始我写的正则写得很复杂,也做了展示,我这里主要是想把简化的代码也放一下。还有就是,我一开始自作聪明,在|的两边打了空格,导致字符串一直匹配不上,因为把" "也放在了匹配里面,但是数字之间是没有空格的。

import java.util.Scanner;

public class Main {
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        String s = input.nextLine();//读入字符串

        if(s.matches("^2020((1[1-7])|(61)|(7[1-3])|(8[1-2]))(([1-3][0-9])|(40)|(0[1-9]))$")){//判断字符串(千万不要在|两边打空格QAQ)
            // 注意61班和学号从01-09号以及40号
            System.out.println("正确");
        }
        else {//无法匹配
            System.out.println("错误");
        }
    }
}

第六次作业

7-1

问题

问题很多,最大的问题还是花的时候不够多,由于身体原因,写这个题目的时候没有熬大夜,我室友在狂写的时候我在睡觉。其次就是思路不够清晰,我在结束之后,要来了AC的代码,对比了一下,发现我的主方法不符合单一职责原则,要做的事情太多了,导致逻辑很混乱,我试过把判断的部分,封装成方法,但是那个时候已经有点拆不开的感觉了,我只能又疯狂加条件。还是放一下,我失败的且丑陋的代码

想看一下的可点,建议不点,眼不见为净QAQ
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int flagMenu = 0;//标记菜单是否已经输入完
        String s;
        boolean tableExist = false;//某桌是否存在
        boolean tableRight = true;
        int maxNow = 0;
        Order order = new Order();
        Menu menu = new Menu();
        Record record;
        Dish dish;
        Table table = new Table();
        Date date = null;
        ArrayList<Table> allTable = new ArrayList<>();
        ArrayList<Integer> deleteRecord = new ArrayList<Integer>();
        while (input.hasNext()) {
            s = input.nextLine();
            String[] arr = s.split(" ");
            if (s.equals("end")) {
                for (Table value : allTable) {
                    value.updateTotalPrice();
                    if(value.judge() == 0){
                        System.out.println("table " + value.getTableNum() + " out of opening hours");
                    }else {
                        System.out.println("table " + value.getTableNum() + ": " + value.getTotalPrice() + " " + table.afterDiscount());
                    }
                }
                return;
            }else if (arr.length == 2 || arr.length == 3) {
                if (arr[1].equals("delete")) {
                    if(!tableRight){
                        continue;
                    }
                    int compete = 0;
                    for(int i = 0;i < deleteRecord.size() ;i ++){
                        if(deleteRecord.get(i) == Integer.parseInt(arr[0])){
                            compete = 1;
                            System.out.println("deduplication " + arr[0]);
                            break;
                        }
                    }
                    deleteRecord.add(Integer.parseInt(arr[0]));
                    if(compete == 0){
                        if(order.findRecordByNum(Integer.parseInt(arr[0]))){
                            order.delARecordByRecord(Integer.parseInt(arr[0]));
                        }else {
                            System.out.println("delete error");
                        }
                    }
                } else{//菜单输入
                    if(!tableRight){
                        continue;
                    }
                    int sum = 0;
                    if(flagMenu == 0){
                        if(arr[1].indexOf(".") != -1){
                            System.out.println("wrong format");
                            continue;
                        }
                        for(int i = 0;i < arr[1].length();i ++){
                            if(arr[1].charAt(0) == '0' && arr[i].length() > 1){
                                System.out.println("wrong format");
                                continue;
                            }
                            if (arr[1].charAt(i) < '0' || arr[1].charAt(i) > '9') {
                                System.out.println("wrong format");
                                continue;
                            }
                            sum += Math.pow(10, arr[1].length() - 1 - i) * (arr[1].charAt(i) - '0');
                        }
                        if(sum > 300){
                            System.out.println(arr[0] + " price out of range");
                        } else{
                                if(arr.length == 2){
                                    if(menu.searthDish(arr[0]) == null){
                                        menu.addDish(arr[0], Integer.parseInt(arr[1]),false);
                                    }else {
                                        menu.updateDish(arr[0],Integer.parseInt(arr[1]),false);
                                    }
                                }else {
                                    if(menu.searthDish(arr[0]) == null){
                                        menu.addDish(arr[0], Integer.parseInt(arr[1]),true);
                                    }else {
                                        menu.updateDish(arr[0],Integer.parseInt(arr[1]),true);
                                    }
                                }
                            }
                        } else {
                             System.out.println("invalid dish");
                        }
                }
            } else if (!arr[0].equals("table") && arr[0].matches("\\d")) {//点菜
                if(!tableRight){
                    continue;
                }
                if(arr.length == 4) {//给自己点
                    if (maxNow < Integer.parseInt(arr[0])) {
                        maxNow = Integer.parseInt(arr[0]);
                        if (menu.searthDish(arr[1]) != null) {//查找菜单是否有该菜
                            if (!arr[2].matches("[123]") && !menu.searthDish(arr[1]).getSpecial()) {
                                System.out.println(arr[0] + " portion out of range " + arr[2]);
                            } else if (!arr[2].matches("[123]") && menu.searthDish(arr[1]).getSpecial()) {
                                System.out.println(arr[0] + " portion out of range " + arr[2]);
                            } else {
                                if (Integer.parseInt(arr[3]) > 15) {
                                    System.out.println(arr[0] + " num out of range " + Integer.parseInt(arr[3]));
                                } else {
                                    dish = menu.searthDish(arr[1]);
                                    record = table.getOrder().addARecord(Integer.parseInt(arr[0]), arr[1], Integer.parseInt(arr[2]), Integer.parseInt(arr[3]));
                                    record.setDish(dish);
                                    System.out.println(record.getOrderNum() + " " + record.getDish().getName() + " " + record.getPrice());
                                }
                            }

                        } else {
                            System.out.println(arr[1] + " does not exist");
                        }
                    }else {
                        System.out.println("record serial number sequence error");
                    }
                }else {//代点菜
                        if(!tableRight){
                            continue;
                        }
                        if(maxNow < Integer.parseInt(arr[1])) {
                            maxNow = Integer.parseInt(arr[1]);
                            for (Table value : allTable) {
                                if (value.getTableNum() == Integer.parseInt(arr[0])) {
                                    tableExist = true;
                                    if (menu.searthDish(arr[2]) != null) {//查找菜单是否有该菜
                                        if (!arr[3].matches("[1-3]")) {
                                            System.out.println(arr[0] + " portion out of range " + arr[3]);
                                        } else {
                                            if (Integer.parseInt(arr[4]) > 15) {
                                                System.out.println(arr[0] + " num out of range " + Integer.parseInt(arr[4]));
                                            } else {
                                                dish = menu.searthDish(arr[2]);
                                                record = order.addARecord(Integer.parseInt(arr[1]), arr[2], Integer.parseInt(arr[3]), Integer.parseInt(arr[4]));
                                                record.setDish(dish);
                                                System.out.println(record.getOrderNum() + " table" + table.getTableNum() + " pay for table " + arr[0] + " " + record.getPrice());
                                            }
                                        }

                                    } else {
                                        System.out.println(arr[1] + " does not exist");
                                    }
                                }
                            }
                            if (!tableExist) {
                                System.out.println("Table number :"+ arr[0] +" does not exist");
                            }
                        }else {
                            System.out.println("record serial number sequence error");
                        }
                    }
                } else if(arr[0].equals("table")){//输入新的table
                tableRight = true;
                deleteRecord.clear();
                flagMenu = 1;
                int sum = 0;
                int flag1 = 0;//桌号格式
                int flag2 = 0;//桌号范围
                maxNow = 0;
                //判断桌号是否合法
                for(int i = 0;i < arr[1].length();i ++) {
                    if(arr[1].charAt(0) == '0'){
                        flag1 = 1;
                        break;
                    }
                    if (arr[1].charAt(i) < '0' || arr[1].charAt(i) > '9') {
                        flag1 = 1;
                        break;
                    } else {
                        sum += Math.pow(10, arr[1].length() - 1 - i) * (arr[1].charAt(i) - '0');
                    }
                    if (sum > 55) {
                        flag2 = 1;
                        break;
                    }
                }
                if(flag1 == 0 && flag2 == 0){
                    boolean flagTime = false;//格式是否正确
                    boolean timeRight = true;//时间合法
                    String[] arr1 = arr[2].split("/");//将时间拆分
                    String[] arr2 = arr[3].split("/");//hh,mm,ss
                    //判断日期格式正确
                    if(arr1[0].matches("\\d{4}") && arr1[1].matches("\\d{1,2}") && arr1[2].matches("\\d{1,2}")
                            && arr2[0].matches("\\d{1,2}") && arr2[1].matches("\\d{1,2}") && arr2[2].matches("\\d{1,2}")){
                        if(arr1[0].charAt(0) != '0' && arr1[1].charAt(0) != '0' && arr1[2].charAt(0) != '0' &&
                                arr2[0].charAt(0) != '0'){
                            flagTime = true;
                        }
                    }
                    //判断日期是否合法
                    if(flagTime) {
                        int[] max_mon = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
                        int year = Integer.parseInt(arr1[0]);
                        int month = Integer.parseInt(arr1[1]);
                        int day = Integer.parseInt(arr1[2]);
                        int hh = Integer.parseInt(arr2[0]);
                        int mm = Integer.parseInt(arr2[1]);
                        int ss = Integer.parseInt(arr2[2]);
                        //判断闰年
                        if(year % 400 == 0 ||(year % 4 == 0 && year % 100 != 0)){
                            max_mon[2] = 29;
                        }else {
                            max_mon[2] = 28;
                        }

                        if(month < 1 || month > 12){
                            timeRight = false;
                        }else if(day < 1 || day > max_mon[month]){
                            timeRight = false;
                        }else if(hh > 24 || hh < 1){
                            timeRight = false;
                        } else if(mm > 59 || mm < 0){
                            timeRight = false;
                        } else if(ss > 59 || ss < 0){
                            timeRight = false;
                        }

                    }else {
                        System.out.println("wrong format");
                        tableRight = false;
                        continue;
                    }
                    //如果日期合法
                    if(flagTime && timeRight){
                        int year = Integer.parseInt(arr1[0]);
                        int month = Integer.parseInt(arr1[1]);
                        int day = Integer.parseInt(arr1[2]);
                        int hh = Integer.parseInt(arr2[0]);
                        int mm = Integer.parseInt(arr2[1]);
                        int ss = Integer.parseInt(arr2[2]);
                        if(year < 2022 || year > 2023){
                            System.out.println("not a valid time period");
                            tableRight = false;
                            continue;
                        }
                        date = new Date();
                        date.setDate(year,month,day,hh,mm,ss);
                        order = new Order();
                        table = new Table(Integer.parseInt(arr[1]), order);
                        table.setDate(date);
                        allTable.add(table);
                        System.out.println("table " + arr[1] + ": ");
                    }else {
                        System.out.println(arr[1] + " date error");
                        tableRight = false;
                        continue;
                    }
                }else if(flag1 == 0 && flag2 == 1){
                    System.out.println(arr[1] + " table num out of range");
                    tableRight = false;
                    continue;
                }else if(flag1 == 1){
                    System.out.println("wrong format");
                    tableRight = false;
                    continue;
                }
            }
            else {
                System.out.println("wrong format");
                continue;
            }
        }
    }
}

class Dish {
    private String name;//菜品名称
    private int unit_price;//单价
    private boolean special = false;

    public boolean getSpecial() {
        return special;
    }

    public void setSpecial(boolean special) {
        this.special = special;
    }

    public int getPrice(int portion){//计算价格
        double price = 0.0;
        if(portion == 1){//小
            price = unit_price;
        }
        else if(portion == 2){//中
            price = unit_price * 1.5;
        }
        else if(portion == 3){//大
            price = unit_price * 2;
        }
        return (int)(price + 0.5);
    }
    public String getName(){
        return this.name;
    }

    public int getUnit_price(){
        return this.unit_price;
    }

    public void setName(String name){
        this.name = name;
    }

    public void setUnit_price(int unit_price){
        this.unit_price = unit_price;
    }
}

class Menu {
    private final ArrayList<Dish> list = new ArrayList<>();//菜品数组,保存所有菜品信息
    public Dish searthDish(String dishName){//根据菜名查找
        for (Dish dish : list) {
            if (dishName.equals(dish.getName())) {
                return dish;
            }
        }
        return null;//没有找到
    }

    public Dish addDish(String dishName,int unit_price,boolean special){//增加一个菜品到list里面
        Dish newDish = new Dish();
        newDish.setName(dishName);
        newDish.setUnit_price(unit_price);
        newDish.setSpecial(special);
        list.add(newDish);
        return newDish;
    }

    public void updateDish(String dishName,int unit_price,boolean special){//重复时更新
        for (Dish dish : list) {
            if (dish.getName().equals(dishName)) {
                dish.setSpecial(special);
                dish.setUnit_price(unit_price);
            }
        }
    }

}

class Record{
    private int orderNum;//序号
    private Dish dish = new Dish();//菜品
    private int portion;//份额

    private int num;

    public Record(){

    }

    //有参构造
    public Record(int orderNum,String dishName,int portion,int num){
        this.orderNum = orderNum;
        dish.setName(dishName);
        this.portion = portion;
        this.num = num;
    }
    public int getPrice(){//计算价格
        int price = num * this.dish.getPrice((this.portion));
        return price;
    }

    public int getOrderNum() {
        return orderNum;
    }

    public void setOrderNum(int orderNum) {
        this.orderNum = orderNum;
    }

    public Dish getDish(){
        return dish;
    }
    public void setDish(Dish dish) {
        this.dish = dish;
    }
}
class Order{


    private final ArrayList<Record> list = new ArrayList<>();//保存订单上每一道记录
    public ArrayList<Record> getList() {
        return list;
    }
    public int getTotalPrice(){//计算总价
        int total = 0;
        for (Record record : list) {
            total += record.getPrice();
        }
        return total;
    }
    public Record addARecord(int orderNum,String dishName,int portion,int num){//添加菜品
        Record newRecord = new Record(orderNum,dishName,portion,num);
        list.add(newRecord);
        return newRecord;
    }
    public boolean delARecordByRecord(int orderNum){
        for(int i = 0;i < list.size();i++)
        {
            if(list.get(i).getOrderNum() == orderNum){
                list.remove(i);
                return true;
            }
        }
        return false;
    }
    public boolean findRecordByNum(int orderNum){
        for (Record record : list) {
            if (orderNum == record.getOrderNum()) {
                return true;
            }
        }
        return false;
    }


}

class Date{
    private LocalDateTime date;

    public Date() {
    }

    public Date(LocalDateTime date) {
        this.date = date;
    }

    public LocalDateTime getDate(){
        return date;
    }
    public void setDate(int year, int month, int day,int hh,int mm,int ss) {
        this.date = LocalDateTime.of(year, month, day,hh,mm,ss);
    }
    public int getWeek(){
        int week = this.date.getDayOfWeek().getValue();
        return week;
    }

}
class Table{
    private int tableNum;
    private Order order = new Order();
    private int totalPrice;
    private Date date = new Date();

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public Table() {

    }

    public Table(int tableNum, Order order) {
        this.tableNum = tableNum;
        this.order = order;
    }

    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 int getTotalPrice() {
        return totalPrice;
    }

    public void updateTotalPrice() {
        this.totalPrice = order.getTotalPrice();

    }
    public int judge(){
        if(date.getWeek() <= 5 && date.getWeek() >= 1){
            if(date.getDate().getHour() >= 11 && date.getDate().getHour() <= 14){
                return 7;
            }else if(date.getDate().getHour() >= 17 && date.getDate().getHour() <= 20){
                return 7;
            }else if(date.getDate().getHour() == 10 && date.getDate().getMinute() >= 30){
                return 7;
            }else if(date.getDate().getHour() == 20 && date.getDate().getMinute() <= 30){
                return 7;
            }else if(date.getDate().getHour() == 14 && date.getDate().getMinute() <= 30){
                return 7;
            } else{
                return  0;
            }
        }
        else {
            if(date.getDate().getHour() < 9){
                return 0;
            }else if(date.getDate().getHour() >= 22){
                return 0;
            } else if(date.getDate().getHour() == 9 && date.getDate().getMinute() < 30){
                return 0;
            }else if(date.getDate().getHour() == 21 && date.getDate().getMinute() > 30){
                return 0;
            } else{
                return 10;
            }
        }
    }
    public int falseJudge(){
        if(date.getWeek() <= 5 && date.getWeek() >= 1){
            if(date.getDate().getHour() >= 11 && date.getDate().getHour() <= 14){
                return 6;
            }else if(date.getDate().getHour() >= 17 && date.getDate().getHour() <= 20){
                return 8;
            }else if(date.getDate().getHour() == 10 && date.getDate().getMinute() >= 30){
                return 6;
            }else if(date.getDate().getHour() == 20 && date.getDate().getMinute() <= 30){
                return 8;
            }else if(date.getDate().getHour() == 14 && date.getDate().getMinute() <= 30){
                return 8;
            } else{
                return  0;
            }
        }
        else {
            if(date.getDate().getHour() < 9){
                return 0;
            }else if(date.getDate().getHour() >= 22){
                return 0;
            } else if(date.getDate().getHour() == 9 && date.getDate().getMinute() < 30){
                return 0;
            }else if(date.getDate().getHour() == 21 && date.getDate().getMinute() > 30){
                return 0;
            } else{
                return 10;
            }
        }
    }
    public int trueJudge(){
        if(date.getWeek() <= 5 && date.getWeek() >= 1){
            if(date.getDate().getHour() >= 11 && date.getDate().getHour() <= 14){
                return 7;
            }else if(date.getDate().getHour() >= 17 && date.getDate().getHour() <= 20){
                return 7;
            }else if(date.getDate().getHour() == 10 && date.getDate().getMinute() >= 30){
                return 7;
            }else if(date.getDate().getHour() == 20 && date.getDate().getMinute() <= 30){
                return 7;
            }else if(date.getDate().getHour() == 14 && date.getDate().getMinute() <= 30){
                return 7;
            } else{
                return  0;
            }
        }
        else {
            if(date.getDate().getHour() < 9){
                return 0;
            }else if(date.getDate().getHour() >= 22){
                return 0;
            } else if(date.getDate().getHour() == 9 && date.getDate().getMinute() < 30){
                return 0;
            }else if(date.getDate().getHour() == 21 && date.getDate().getMinute() > 30){
                return 0;
            } else{
                return 10;
            }
        }
    }
    public int afterDiscount(){
        int discountSpecial = trueJudge();
        int discountNormal = falseJudge();
        double total = 0.0;
        for(int i = 0;i < this.getOrder().getList().size();i ++){
            if(this.getOrder().getList().get(i).getDish().getSpecial() == true){
                total += this.getOrder().getList().get(i).getPrice() * 1.0 * discountSpecial / 10.0;
            }else {
                total += this.getOrder().getList().get(i).getPrice() * 1.0 * discountNormal / 10.0;
            }
        }
        return (int)(total + 0.5);
    }
}

已经做了的部分

1、一开始我是按第一次作业的题目先写了一个代码,包含了第一次作业的所有功能,提交之后发现,这次作业只有很少是正常测试,但是我正常测试都没过。又看了一遍题目,发现是我忘记打折了,只判断了是否在开放时间
2、打折的部分我改了好几版,最后还是决定返回一个整型来获得打几折,然后再在输出前进行计算;再加了对份额和份数的判断,这里有点表达不是很明确,试了几发才知道题目到底什么意思;根据输出发现,每一桌菜的总价是在最后统一输出,所以我用了一个ArrayList把每一桌的所有信息存储下来
3、用正则表达式判断了桌号是否符合范围
4、因为题目要求菜品的价格是整数,且在范围之内,所以我直接去分割后字符串中匹配是否有".",后面觉得不太对,改成了遍历分割后的字符串,看是否有数字外的字符,第一个字符是否为0,计算菜品价格是否超出范围
5、因为日期存在非法情况,先判断了每一个字符串对应的长度,然后看是否有前导0,再判断月和日是否合法,如果把不合法的数据用于构造一个LocalDateTime类型的属性会抛出异常。
6、因为增加了特色菜,所以菜单输入时,字符串长度有两种可能性,要分别讨论,但总体是相似的,先判断是否符合条件,再看数据范围,然后存储;在点菜时输入菜单应该忽略,并且输出错误,所以需要打标记,一旦开始点菜,就意味着菜单输入结束
7、特色菜和非特色菜的折扣存在差异,所以需要细化折扣的情况,分成特色菜折扣和非特色菜折扣两类
8、删除存在两种异常,一种是要删除的菜品不存在,一种是重复删除,所以需要记录删除过的菜品,
9、点菜分两种,一个是给自己点,一个是代点菜。两种都需要判断序号是否异常,可以用一个属性来记录当前最大的序号,每次点菜时判断,若序号 > Max说明可以点,更新Max否则输出错误。代点菜时,需要先判断桌号是否存在
10、因为桌面信息可能出现错误,如果该桌是第一桌的话,操作忽略,直到第二桌;若不是第一桌,将这桌信息和并到上一桌

还没完成的部分

1、重复的桌号
2、多次点同一道菜合并输出(我现在的算法是,点一道菜输出一道,要实现这个功能,就需要将所有点菜记录下来,最后统一输出)

改进建议

1、其实代码的规范问题还是存在,注释比较少,可读性比较差,没有边写代码边注释的习惯,几乎每次都是突然想起来,然后再看一遍代码回忆一下自己想表达什么,再统一补代码,这个习惯需要更正🥀。
2、还是没能做到先设计再写代码,菜单类的题目思路太混乱
3、写代码的时候还是没能比较好的遵守设计原则,尤其是菜单类的主方法
4、代码健壮性问题还是存在,自己做测试的时候考虑的角度还不够***钻。

总结

浅浅获得的一些知识

1、学到了一些容器的知识
2、类与类之间组合关系有了一点点感觉
3、练习了正则表达式,能初步运用

需要进一步学习的知识

1、正则表达式的运用还是不够熟练,用的时候还要翻表格来对应
2、其实感觉知识点上的学习显得没那么重要了,更多的还是要在思维和习惯上做出改变

一点小小的建议

1、有没有可能,出补题的题目集,就比如说这两个菜单问题,可以开放补题,让愿意继续完善程序的同学,能检测一下自己的代码,能够有一个比较直观的反馈(◐‿◑)。
2、有没有可能,推荐比较好的有关设计模式的文章来看一下,课上感觉(我还记得老师说:你感觉的都是错的QAQ)是理解为什么要用设计模式,它为什么好,但是课下回忆的时候,感觉还是什么都不会,我也有在网上找文章来读,最后的结果是更迷茫了🥀。
3、未完,可能再续……

一些阿巴阿巴

第一次没有满分的时候其实蛮不好受的,第一次不及格的时候就更难受了,不过责任还是在自己,没有足够强的实力,又没有花更多的时间去弥补,还是要加油叻💪💪💪。(题外话,怎么发blog还有时间限制的啊,居然不让我发首页😯)

posted @ 2023-04-29 01:25  clear_tea  阅读(83)  评论(4)    收藏  举报