BLOG-2

一、前言

  ·对于菜单计价程序-4和菜单计价程序-5,是考验学生对于实际问题的代码化的能力,能不能设计出优秀的代码框架去实现这个点菜的功能是格外关键的

  ·其次,对于这几次的作业以及期中考试所考到的知识点,是非常适合我们正在学习的,期中考试对于接口的实现,对于类的构建,类与类之间的组合等等的考察是非常有利于我们学习Java这门语言的

  ·最后,希望我们大家都能在快乐的学习里面找到乐趣

二、设计与分析

PTA4:

  首先我们先对题意展开:

本体大部分内容与菜单计价程序-3相同,增加的部分用加粗文字进行了标注。

设计点菜计价程序,根据输入的信息,计算并输出总价格。

输入内容按先后顺序包括两部分:菜单、订单,最后以"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 {

String name;//菜品名称

int unit_price; //单价

int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }

菜谱类:对应菜谱,包含饭店提供的所有菜的信息。

Menu {

Dish[] dishs ;//菜品数组,保存所有菜品信息

Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。

Dish addDish(String dishName,int unit_price)//添加一道菜品信息

}

点菜记录类:保存订单上的一道菜品记录

Record {

int orderNum;//序号

Dish d;//菜品\\

int portion;//份额(1/2/3代表小/中/大份)

int getPrice()//计价,计算本条记录的价格

}

订单类:保存用户点的所有菜的信息。

Order {

Record[] records;//保存订单上每一道的记录

int getTotalPrice()//计算订单的总价

Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。

delARecordByOrderNum(int orderNum)//根据序号删除一条记录

findRecordByNum(int orderNum)//根据序号查找一条记录

}

本次课题比菜单计价系列-3增加的异常情况:

1、菜谱信息与订单信息混合,应忽略夹在订单信息中的菜谱信息。输出:"invalid dish"

2、桌号所带时间格式合法(格式见输入格式部分说明,其中年必须是4位数字,月、日、时、分、秒可以是1位或2位数),数据非法,比如:2023/15/16 ,输出桌号+" date error"

3、同一桌菜名、份额相同的点菜记录要合并成一条进行计算,否则可能会出现四舍五入的误差。

4、重复删除,重复的删除记录输出"deduplication :"+序号。

5、代点菜时,桌号不存在,输出"Table number :"+被点菜桌号+" does not exist";本次作业不考虑两桌记录时间不匹配的情况。

6、菜谱信息中出现重复的菜品名,以最后一条记录为准。

7、如果有重复的桌号信息,如果两条信息的时间不在同一时间段,(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒)以内算统一时段),此时输出结果按不同的记录分别计价。

8、重复的桌号信息如果两条信息的时间在同一时间段,此时输出结果时合并点菜记录统一计价。前提:两个的桌号信息的时间都在有效时间段以内。计算每一桌总价要先合并符合本条件的饭桌的点菜记录,统一计价输出。

9、份额超出范围(1、2、3)输出:序号+" portion out of range "+份额,份额不能超过1位,否则为非法格式,参照第13条输出。

10、份数超出范围,每桌不超过15份,超出范围输出:序号+" num out of range "+份数。份数必须为数值,最高位不能为0,否则按非法格式参照第16条输出。

11、桌号超出范围[1,55]。输出:桌号 +" table num out of range",桌号必须为1位或多位数值,最高位不能为0,否则按非法格式参照第16条输出。

12、菜谱信息中菜价超出范围(区间(0,300)),输出:菜品名+" price out of range "+价格,菜价必须为数值,最高位不能为0,否则按非法格式参照第16条输出。

13、时间输入有效但超出范围[2022.1.1-2023.12.31],输出:"not a valid time period"

14、一条点菜记录中若格式正确,但数据出现问题,如:菜名不存在、份额超出范围、份数超出范围,按记录中从左到右的次序优先级由高到低,输出时只提示优先级最高的那个错误。

15、每桌的点菜记录的序号必须按从小到大的顺序排列(可以不连续,也可以不从1开始),未按序排列序号的输出:"record serial number sequence error"。当前记录忽略。(代点菜信息的序号除外)

16、所有记录其它非法格式输入,统一输出"wrong format"

17、如果记录以“table”开头,对应记录的格式或者数据不符合桌号的要求,那一桌下面定义的所有信息无论正确或错误均忽略,不做处理。如果记录不是以“table”开头,比如“tab le 55 2023/3/2 12/00/00”,该条记录认为是错误记录,后面所有的信息并入上一桌一起计算。

本次作业比菜单计价系列-3增加的功能:

菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+基础价格+"T"

例如:麻婆豆腐 9 T

菜价的计算方法:

周一至周五 7折, 周末全价。

注意:不同的四舍五入顺序可能会造成误差,请按以下步骤累计一桌菜的菜价:

计算每条记录的菜价:将每份菜的单价按份额进行四舍五入运算后,乘以份数计算多份的价格,然后乘以折扣,再进行四舍五入,得到本条记录的最终支付价格。

最后将所有记录的菜价累加得到整桌菜的价格。

输入格式:

桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)

菜品记录格式:

菜名+英文空格+基础价格

如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。

点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。

删除记录格式:序号 +英文空格+delete

代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数

最后一条记录以“end”结束。

输出格式:

按输入顺序输出每一桌的订单记录处理信息,包括:

1、桌号,格式:table+英文空格+桌号+”:”+英文空格

2、按顺序输出当前这一桌每条订单记录的处理信息,

每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“** does not exist”,**是不能识别的菜名

如果删除记录的序号不存在,则输出“delete error”

最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价

在这里我们首先是去提取题目中给出的关键的类去构建相应的具体类,下面是我构建的类

class Dish
{
    String name="";//菜品名称
    int unit_price;
    boolean special=false;//特色菜,true为是
    //单价
    int getPrice(int portion)
    {
        int 菜价=0;
        //单菜价格
        switch(portion)
        {
            case 1: 菜价=unit_price;break;
            case 2: 菜价=(int)Math.ceil(1.0*unit_price*3/2);break;
            case 3: 菜价=unit_price*2;break;
        }
        return 菜价;
    }
}

  上述的是菜类

class Menu
{
     Dish[] dishs =new Dish[20];
     int i=0;//用于记录菜品总数
     void addDish(String dishName,int unit_price,Boolean ts)
     {
         
        // Dish dish1=new Dish();
         dishs[i]=new Dish();
         dishs[i].name=dishName;
         dishs[i].unit_price=unit_price;
         dishs[i].special=ts;
         i++;
         //return dish1;
     }
    //菜品数组,保存所有菜品信息
    Dish searthDish(String dishName) //根据菜名在菜谱中查找菜品信息,返回Dish对象。
    {
        int j=0;
        int flag=0;
        for(j=i-1;j>=0;j--)//从未末端开始查找比对
        {
            if(dishName.compareTo(dishs[j].name)==0)
            {
                flag=1;
                break;
            }
        }
        if(flag==1)
        return dishs[j];
        else
        {
            //麻辣鸡丝 does not exist
            System.out.println(dishName+" does not exist");
            return null;
        }
    }
}

  上述的是菜谱类

class Record 
{
    Dish d=new Dish();//菜品
    int orderNum=0;//序号\
    int portion=0;
    int num=0;//份数
    int tablenum=0;//桌号//没什么用
    boolean self=true;
    //份额(1/2/3代表小/中/大份)
    int getPrice()
    {
        int n=0;
        n=num*d.getPrice(portion);
        //2 油淋生菜 27
       // System.out.println(n);
        return n;
    }//计价,计算本条记录的价格
}

  上述的是点菜订单类

class Order 
{
    Record[] records=new Record[20];
    int j=0;
    int[] deletenum=new int[50];
    //添加一条菜品信息到订单中。
    void addARecord(int tablenum,int orderNum,String dishName,int portion,int num,boolean self)//添加一条菜品信息到订单中。
    {
        //1 麻婆豆腐 2 2
        records[j]=new Record();
        records[j].tablenum=tablenum;
        records[j].orderNum=orderNum;
        records[j].d.name=dishName;
        records[j].portion=portion;
        records[j].num=num;
        records[j].self=self;
        //System.out.println(num);
        j++;
    }

    boolean srarchdelete(int orderNum)//找到返回true
    {
        int i=0;
        for(i=0;i<50;i++)
        {
            if(deletenum[i]!=0)
            {
                if(orderNum==deletenum[i])
                {
                    return true;
                }
            }
            else break;
        }
        deletenum[i]=orderNum;
        if(i==0)
        {
            return false;
        }
        return false;
    }
    void delARecordByOrderNum(int orderNum,table t)//根据序号删除一条记录
    //试试直接总价减去删除菜
    {
        if(srarchdelete(orderNum)==false)
        {
            for(int i=0;i<j;i++)
            {
                if(t.selforder.records[i].orderNum==orderNum)
                {
                    t.selforder.records[i].num=0;
                }
                //records[orderNum-1].getPrice();
            }
        }
        else//情况4 
        {
            
            System.out.println("deduplication "+orderNum);
            
        }
    }
    void srarchrecord(Record g,int k)
    {
        for(int i=0;i<k;i++)
        {
            if(g.d.name.equals(records[i].d.name)&&g.portion==records[i].portion&&records[i].self==true)
            {
                records[i].num+=g.num;
                g.num=0;
                break;
            }
        }
        
    }
}

  上述的是订单记录类

class table
{
    int tablenum;//桌号
    String time;//点菜时间//2023/3/22 12/2/3
    int year=0,month=0,day=0,ww=0,hh=0,mm=0,ss=0; 
    boolean flag=false;//判断时间是否正确
    double count=0;//普通菜折扣
    double specialcount=1;
    Order selforder=new Order();//本桌订单
    int sum=0;//计算总价
    int truesum=0;//未打折价
    int k=0;//点菜次数
    int sumdish=0;//菜总数  
    void input(String time,int b)//预处理
    {
        String[] arr1=time.split(" ");
        int blank=0;
                for(int bk=0;bk<time.length();bk++)
                {
                    if(time.charAt(bk)==' ')
                    {
                        blank++;
                    }
                }
        //桌号
        if(blank!=3||!arr1[1].matches("^[1-9][0-9]{0,}$")||arr1.length!=4)
        {
             System.out.println("wrong format");
        }
        
        //System.out.println();
        else
        {
            this.time=arr1[2]+" "+arr1[3];
           // System.out.println();
            tablenum=Integer.parseInt(arr1[1]);
            if(tablenum<=55&&tablenum>=1)
            {
                if(this.time.matches("^([0-9]{4}/[0-9]{1,2}/[0-9]{1,2}) ([0-9]{1,2}/[0-9]{1,2}/[0-9]{1,2})$"))
                {
                    if(arr1[2].matches("^(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})/((([0]{0,1}[13578]|1[02])/([0]{0,1}[1-9]|[12][0-9]|3[01]))|(([0]{0,1}[469]|11)/([0]{0,1}[1-9]|[12][0-9]|30))|([0]{0,1}2/([1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})([48]|[0]{0,1}[2468][048]|[0]{0,1}[13579][26])|(([48]|[2468][048]|[3579][26])00))/[0]{0,1}2/29)$")&&arr1[3].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$"))
                    {
               
                        boolean flag1=judgetime1();
                        if(flag1==true)//时间有效
                        {
                            timechange();
                            jscount();
                            pdflag();
                            if(b==1)
                                System.out.println("wrong format");
                        }
                        else
                        {
                            System.out.println("not a valid time period");
                        }
                    }
                    else
                    System.out.println(tablenum+" date error");
                }
                else
                    System.out.println("wrong format");
        
            }
            
        
            else
             {
                System.out.println(arr1[1] +" table num out of range");
             }
    }
    }

    boolean judgetime1()//是否有效//使用正则表达式
    {
        String[] arr=time.split(" ");
        boolean flag=arr[0].matches("^(2022|2023)/(([13578]|0[13578]|10|12)/(([1-9]|0[1-9])|([12][0-9])|3[01])|([469]|0[469]|11)/(([1-9]|0[1-9])|([12][0-9])|30)|(2|02)/(([1-9]|0[1-9])|(1[0-9])|(2[0-8])))$");
        boolean flag1=arr[1].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$");
        return (flag&&flag1);
        
    }
    void getTotalPrice()//计算桌总价
    {
        if(flag)
        {
    
            int j=selforder.j;
            for(int i=j-1;i>=0;i--)
            {
                selforder.srarchrecord(selforder.records[i],i);
            }
            for(int i=0;i<j;i++)
            {
                int x=0;
                x=selforder.records[i].getPrice();
                    truesum+=x;
                if(selforder.records[i].d.special==true)//特色菜
                {
                    sum+=(int)(x*specialcount+0.5);
                }
                else
                    sum+=(int)(x*count+0.5);
            }
            
            System.out.println("table "+tablenum+": "+truesum+" "+sum);
            //table 1: 63
        }
        
    }
    void jscount()//运用时间计算折扣
    {
        if(ww>=1&&ww<=5)
        {
            specialcount=0.7;
            if(hh>=17&&hh<20)
                count=0.8;
               else if(hh==20&&mm<30)
                count=0.8;
            else if(hh==20&&mm==30&&ss==0)
                count=0.8;
            else if(hh>=11&&hh<=13||hh==10&&mm>=30)
                count=0.6;
            else if(hh==14&&mm<30)
                count=0.6;
            else if(hh==14&&mm==30&&ss==0)
                count=0.6;
        }
        else 
        {
            specialcount=1;
            if(hh>=10&&hh<=20)
                count=1.0;
            else if(hh==9&&mm>=30)
                count=1.0;
            else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0)
                count=1.0;
        }
    }
    void pdflag()//判断时间是否正确
    {
        if(count==0)
        {
            System.out.println("table "+tablenum+" out of opening hours");
            flag=false;
        }
        else
            flag=true;
    }
    void timechange()//时间转换
    {
        //2023/3/22 12/2/3
         String[] arr=time.split(" ");
         String[] arr1=arr[0].split("/");
         String[] arr2=arr[1].split("/");
         year=Integer.parseInt(arr1[0]);//时间
         month=Integer.parseInt(arr1[1]);
         day=Integer.parseInt(arr1[2]);
         Calendar c = Calendar.getInstance();
         c.set(year,month-1,day);//设置时间
          ww=c.get(Calendar.DAY_OF_WEEK);
          hh=Integer.parseInt(arr2[0]);//时间
          mm=Integer.parseInt(arr2[1]);
          ss=Integer.parseInt(arr2[2]);
        if(ww==1)
            ww=7;
        else
            ww--;
    }
    boolean searthtable(table[]t,int num,int p)
    {
        for(int i=0;i<50;i++)
        {
            if(t[i]!=null&&i!=p)
            {
                if(t[i].tablenum==num&&t[i].flag)
                    return true;
            }
            else
                break;
        }
        //"Table number :"+被点菜桌号+" does not exist"
        System.out.println("Table number :"+num+" does not exist");
        return  false;
    }
    int searchtime(table[]t,table a,int sumtable)//若找到返回对应桌,找不到返回下一个空桌
    {
        //(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒)
        for(int i=0;i<sumtable;i++)
        {
            if(a.tablenum==t[i].tablenum)
            if(a.year==t[i].year)
            {
                if(a.day==t[i].day)
                {
                    if(a.ww>=1&&a.ww<=5)//周1~5
                    {
                        if(a.hh<=14&&t[i].hh<=14||a.hh>14&&t[i].hh>14)//在同一时段
                        {
                            
                            return i;
                            
                        }
                    }
                    else//周末
                    {
                        if(Math.abs((a.hh-t[i].hh)*60*60+(a.mm-t[i].mm)*60)+(a.ss-t[i].ss)<60*60)//在同一时段
                        {
                            
                            return i;
                        }
                        
                    }
                }
            }
        }
        //System.out.println(sumtable);
        return sumtable;
    }

}

  上述的是桌子类

class Worn//错误判断,错误b[i]==1
{
    void worninput(String[]a,int num,int[]b) 
    {
        //boolean flag1=true;
        
        for(int i=0;i<num;i++)
        {
            String[] arr=a[i].split(" ");
            boolean flag=false;
            //麻婆豆腐 12
            if(arr.length>5)
            {
                b[i]=1;
            }
            if(a[i].matches("^[\u4e00-\u9fa5]{1,} ([1-9][0-9]{0,2})$")==true)//普通菜存入
            {    
                flag=true;
            }
            //油淋生菜 9 T
            else if(a[i].matches("^[\u4e00-\u9fa5]{1,4} ([1-9][0-9]{0,2}) [T]$")==true)//特色菜存入
            {
                flag=true;
            }
            //table 31 2023/2/1 14/20/00
            else if(arr[0].equals("table")==true)//
            {
                int blank=0;
                for(int bk=0;bk<a[i].length();bk++)
                {
                    if(a[i].charAt(bk)==' ')
                    {
                        blank++;
                    }
                }
                if(arr[1].matches("^([1-9][0-9]{0,})$")&&blank==3)
                flag=true;
                //int blank=0;
                
            }
            //1 麻婆豆腐 1 16
            else if(a[i].matches("^[1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//自己点菜
            {
                flag=true;
            }
            //1 1 麻婆豆腐 1 16
            else if(a[i].matches("^([1-9][0-9]{0,1}) [1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//待点菜
            {
                flag=true;
            }
            //2 delete
            else if(a[i].matches("^([1-9][0-9]{0,1}) delete$")==true)//删菜
            {
                flag=true;
            }
            else if(a[i].matches("^end$")==true)//结尾
            {
                flag=true;
            }
            if(flag==false)
            {
                b[i]=1;
            }
        }
    }
}

  上述的是错误信息判断类

  结合上述的各类,组合最后的结果如下:

import java.util.*;
public class Main {
    public static void main(String[] args) {
    try (Scanner in = new Scanner(System.in)) {
        String[] a=new String[50];
        int[]b=new int[50];
        Menu c=new Menu();
        table[] t=new table[50];
        Dish g=new Dish();
        int i=0;//桌号
        int j=0;//菜数
        int p=0;//当前处理桌号
        int lastdish=0;
        int dc1=0,dc2=0,dc3=0,dd1=0,dd2=0,dd3=0,dd4=0;
        int inputnum=0,h;
        a[0]=in.nextLine();
        b[0]=0;
        while(!a[inputnum].equals("end"))
        {
            inputnum++;
            a[inputnum]=in.nextLine();
            b[inputnum]=0;
        }
        Worn w=new Worn();
        w.worninput(a,inputnum,b);
        for(h=0;h<inputnum;h++)
        { 
            boolean flagerror=false;
            //分割字符
            String[] arr = a[h].split(" ");
            if(arr.length==4||arr[0].charAt(0)=='t')
            {
                
                if(arr[0].equals("table"))//加桌
                {
                    flagerror=true;
                    lastdish=0;
                    table x=new table();
                    x.input(a[h],b[h]);
                        if(i!=0)
                        p=t[i-1].searchtime(t,x,i);
                        if(p==i)//加新桌
                        {
                            t[i]=new table();
                            t[p]=x;
                            i++;
                            lastdish=0;//初始化
                            if(t[p].flag)
                            System.out.println("table "+t[p].tablenum+": ");
                        }    
                        else
                        {
                            if(t[p].flag)
                            System.out.println("table "+t[p].tablenum+": ");
                            lastdish=0;
                        }
                        
                    }
                else if(arr[0].matches("^[1-9][0-9]{0,1}$"))//自己点菜
                {
                    if(b[h]==1)
                    {
                        flagerror=true;
                        if(i!=0&&t[p].flag)
                        {
                            System.out.println("wrong format");
                        }
                        continue;
                    }
                    dc1=Integer.parseInt(arr[0]);
                    dc2=Integer.parseInt(arr[2]);
                    dc3=Integer.parseInt(arr[3]);
                    if(i!=0&&t[p].flag)
                    {
                        
                            if(i!=0)
                            {                        
                                if(dc1<=lastdish)
                                {
                                    System.out.println("record serial number sequence error");
                                }
                                else
                                {    
                                    t[p].selforder.addARecord(0,dc1,arr[1],dc2,dc3,true);
                                    g=c.searthDish(arr[1]);
                                
                                    if(g!=null&&t[p].flag)
                                    {
                                        
                                        if(dc2>3&&dc2<10||dc2<=0&&dc2>-10)//情况9
                                        {
                                            //序号+" portion out of range "+份额
                                            System.out.println(dc1+" portion out of range "+dc2);
                                        }
                                        else if(dc3>15)
                                        {
                                            System.out.println(dc1+" num out of range "+dc3);
                                        }
                                        else
                                        {
                                            t[p].selforder.records[t[p].k].d=g;
                                            //System.out.println(t[p].selforder.records[]);
                                            int x=t[p].selforder.records[t[p].k].getPrice();
                                            //2 油淋生菜 27
                                            lastdish=dc1;
                                            System.out.println(dc1+" "+arr[1]+" "+x);
                                        }
                                        
                                    }
                                    t[p].k++;
                            
                        }
                    }
                    
                }
                }
                else 
                {
                    System.out.println("wrong format");
                    flagerror=true;
                }
                
            }
        
            else if(arr.length==5)//代点
            {
            //  1 4 麻婆豆腐 1 1
                if(b[h]==1)
                {
                    flagerror=true;
                    if(i!=0&&t[p].flag)
                    {
                        System.out.println("wrong format");
                    }
                    continue;
                }
                dd1=Integer.parseInt(arr[0]);
                dd2=Integer.parseInt(arr[1]);
                dd3=Integer.parseInt(arr[3]);
                dd4=Integer.parseInt(arr[4]);
                if(t[p].searthtable(t,dd1,p)==true)
                {
                    t[p].selforder.addARecord(dd2, dd1, arr[2], dd3,dd4,false);
                    g=c.searthDish(arr[2]);
                    if(g!=null)
                    {
                        t[p].selforder.records[t[p].k].d=g;
                        int x=t[p].selforder.records[t[p].k].getPrice();
                        System.out.println(dd2+" table "+t[p].tablenum+" pay for table "+dd1+" "+x);
                    }
                    //k++;
                    t[p].k++;
                }    
            }
            else if(arr.length==2)
            {
                if(arr[1].equals("delete"))//删菜
                {
                    
                    if(i!=0)
                    {
                    if(b[h]==1)
                    {
                        flagerror=true;
                        if(i!=0)
                        {
                            System.out.println("wrong format");
                        }
                        continue;
                    }
                    if(t[p].flag)
                        t[p].selforder.delARecordByOrderNum(Integer.parseInt(arr[0]),t[p]);
                    }
                }
                else//加菜
                {
                    if(b[h]==1)
                    {
                        flagerror=true;
                        System.out.println("wrong format");
                        continue;
                    }
                    if(i!=0&&t[p].flag)//情况1
                    {
                        System.out.println("invalid dish");
                    }
                    else
                    {
                        if(Integer.parseInt(arr[1])>0&&Integer.parseInt(arr[1])<300)
                        {
                            c.addDish(arr[0], Integer.parseInt(arr[1]),false);
                            j++;
                        }
                        else
                        {
                            System.out.println(arr[0]+" price out of range "+arr[1]);
                        }
                    }
                }
            }
            else if(arr.length==3)//特色菜
            {
                if(b[h]==1)
                {
                    flagerror=true;
                    System.out.println("wrong format");
                    continue;
                }
                if(i!=0&&t[p].flag)
                {
                    System.out.println("invalid dish");
                }
                else 
                {
                    if(arr[2].equals("T"))
                    {
                        if(Integer.parseInt(arr[1])>0&&Integer.parseInt(arr[1])<300)
                        {
                            c.addDish(arr[0], Integer.parseInt(arr[1]),true);
                            j++;
                        }
                        else
                        {
                            System.out.println(arr[0]+" price out of range "+arr[1]);
                        }
                    }
                }
            }     
        }
        for(int l=0;l<i;l++)
        {
            t[l].getTotalPrice();
        }
    } catch (NumberFormatException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }

}
class Dish
{
    String name="";//菜品名称
    int unit_price;
    boolean special=false;//特色菜,true为是
    //单价
    int getPrice(int portion)
    {
        int 菜价=0;
        //单菜价格
        switch(portion)
        {
            case 1: 菜价=unit_price;break;
            case 2: 菜价=(int)Math.ceil(1.0*unit_price*3/2);break;
            case 3: 菜价=unit_price*2;break;
        }
        return 菜价;
    }
}
class Menu
{
     Dish[] dishs =new Dish[20];
     int i=0;//用于记录菜品总数
     void addDish(String dishName,int unit_price,Boolean ts)
     {
         
        // Dish dish1=new Dish();
         dishs[i]=new Dish();
         dishs[i].name=dishName;
         dishs[i].unit_price=unit_price;
         dishs[i].special=ts;
         i++;
         //return dish1;
     }
    //菜品数组,保存所有菜品信息
    Dish searthDish(String dishName) //根据菜名在菜谱中查找菜品信息,返回Dish对象。
    {
        int j=0;
        int flag=0;
        for(j=i-1;j>=0;j--)//从未末端开始查找比对
        {
            if(dishName.compareTo(dishs[j].name)==0)
            {
                flag=1;
                break;
            }
        }
        if(flag==1)
        return dishs[j];
        else
        {
            //麻辣鸡丝 does not exist
            System.out.println(dishName+" does not exist");
            return null;
        }
    }
}
class Record 
{
    Dish d=new Dish();//菜品
    int orderNum=0;//序号\
    int portion=0;
    int num=0;//份数
    int tablenum=0;//桌号//没什么用
    boolean self=true;
    //份额(1/2/3代表小/中/大份)
    int getPrice()
    {
        int n=0;
        n=num*d.getPrice(portion);
        //2 油淋生菜 27
       // System.out.println(n);
        return n;
    }//计价,计算本条记录的价格
}

class Order 
{
    Record[] records=new Record[20];
    int j=0;
    int[] deletenum=new int[50];
    //添加一条菜品信息到订单中。
    void addARecord(int tablenum,int orderNum,String dishName,int portion,int num,boolean self)//添加一条菜品信息到订单中。
    {
        //1 麻婆豆腐 2 2
        records[j]=new Record();
        records[j].tablenum=tablenum;
        records[j].orderNum=orderNum;
        records[j].d.name=dishName;
        records[j].portion=portion;
        records[j].num=num;
        records[j].self=self;
        //System.out.println(num);
        j++;
    }

    boolean srarchdelete(int orderNum)//找到返回true
    {
        int i=0;
        for(i=0;i<50;i++)
        {
            if(deletenum[i]!=0)
            {
                if(orderNum==deletenum[i])
                {
                    return true;
                }
            }
            else break;
        }
        deletenum[i]=orderNum;
        if(i==0)
        {
            return false;
        }
        return false;
    }
    void delARecordByOrderNum(int orderNum,table t)//根据序号删除一条记录
    //试试直接总价减去删除菜
    {
        if(srarchdelete(orderNum)==false)
        {
            for(int i=0;i<j;i++)
            {
                if(t.selforder.records[i].orderNum==orderNum)
                {
                    t.selforder.records[i].num=0;
                }
                //records[orderNum-1].getPrice();
            }
        }
        else//情况4 
        {
            
            System.out.println("deduplication "+orderNum);
            
        }
    }
    void srarchrecord(Record g,int k)
    {
        for(int i=0;i<k;i++)
        {
            if(g.d.name.equals(records[i].d.name)&&g.portion==records[i].portion&&records[i].self==true)
            {
                records[i].num+=g.num;
                g.num=0;
                break;
            }
        }
        
    }
}
class table
{
    int tablenum;//桌号
    String time;//点菜时间//2023/3/22 12/2/3
    int year=0,month=0,day=0,ww=0,hh=0,mm=0,ss=0; 
    boolean flag=false;//判断时间是否正确
    double count=0;//普通菜折扣
    double specialcount=1;
    Order selforder=new Order();//本桌订单
    int sum=0;//计算总价
    int truesum=0;//未打折价
    int k=0;//点菜次数
    int sumdish=0;//菜总数  
    void input(String time,int b)//预处理
    {
        String[] arr1=time.split(" ");
        int blank=0;
                for(int bk=0;bk<time.length();bk++)
                {
                    if(time.charAt(bk)==' ')
                    {
                        blank++;
                    }
                }
        //桌号
        if(blank!=3||!arr1[1].matches("^[1-9][0-9]{0,}$")||arr1.length!=4)
        {
             System.out.println("wrong format");
        }
        
        //System.out.println();
        else
        {
            this.time=arr1[2]+" "+arr1[3];
           // System.out.println();
            tablenum=Integer.parseInt(arr1[1]);
            if(tablenum<=55&&tablenum>=1)
            {
                if(this.time.matches("^([0-9]{4}/[0-9]{1,2}/[0-9]{1,2}) ([0-9]{1,2}/[0-9]{1,2}/[0-9]{1,2})$"))
                {
                    if(arr1[2].matches("^(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})/((([0]{0,1}[13578]|1[02])/([0]{0,1}[1-9]|[12][0-9]|3[01]))|(([0]{0,1}[469]|11)/([0]{0,1}[1-9]|[12][0-9]|30))|([0]{0,1}2/([1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})([48]|[0]{0,1}[2468][048]|[0]{0,1}[13579][26])|(([48]|[2468][048]|[3579][26])00))/[0]{0,1}2/29)$")&&arr1[3].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$"))
                    {
               
                        boolean flag1=judgetime1();
                        if(flag1==true)//时间有效
                        {
                            timechange();
                            jscount();
                            pdflag();
                            if(b==1)
                                System.out.println("wrong format");
                        }
                        else
                        {
                            System.out.println("not a valid time period");
                        }
                    }
                    else
                    System.out.println(tablenum+" date error");
                }
                else
                    System.out.println("wrong format");
        
            }
            
        
            else
             {
                System.out.println(arr1[1] +" table num out of range");
             }
    }
    }

    boolean judgetime1()//是否有效//使用正则表达式
    {
        String[] arr=time.split(" ");
        boolean flag=arr[0].matches("^(2022|2023)/(([13578]|0[13578]|10|12)/(([1-9]|0[1-9])|([12][0-9])|3[01])|([469]|0[469]|11)/(([1-9]|0[1-9])|([12][0-9])|30)|(2|02)/(([1-9]|0[1-9])|(1[0-9])|(2[0-8])))$");
        boolean flag1=arr[1].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$");
        return (flag&&flag1);
        
    }
    void getTotalPrice()//计算桌总价
    {
        if(flag)
        {
    
            int j=selforder.j;
            for(int i=j-1;i>=0;i--)
            {
                selforder.srarchrecord(selforder.records[i],i);
            }
            for(int i=0;i<j;i++)
            {
                int x=0;
                x=selforder.records[i].getPrice();
                    truesum+=x;
                if(selforder.records[i].d.special==true)//特色菜
                {
                    sum+=(int)(x*specialcount+0.5);
                }
                else
                    sum+=(int)(x*count+0.5);
            }
            
            System.out.println("table "+tablenum+": "+truesum+" "+sum);
            //table 1: 63
        }
        
    }
    void jscount()//运用时间计算折扣
    {
        if(ww>=1&&ww<=5)
        {
            specialcount=0.7;
            if(hh>=17&&hh<20)
                count=0.8;
               else if(hh==20&&mm<30)
                count=0.8;
            else if(hh==20&&mm==30&&ss==0)
                count=0.8;
            else if(hh>=11&&hh<=13||hh==10&&mm>=30)
                count=0.6;
            else if(hh==14&&mm<30)
                count=0.6;
            else if(hh==14&&mm==30&&ss==0)
                count=0.6;
        }
        else 
        {
            specialcount=1;
            if(hh>=10&&hh<=20)
                count=1.0;
            else if(hh==9&&mm>=30)
                count=1.0;
            else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0)
                count=1.0;
        }
    }
    void pdflag()//判断时间是否正确
    {
        if(count==0)
        {
            System.out.println("table "+tablenum+" out of opening hours");
            flag=false;
        }
        else
            flag=true;
    }
    void timechange()//时间转换
    {
        //2023/3/22 12/2/3
         String[] arr=time.split(" ");
         String[] arr1=arr[0].split("/");
         String[] arr2=arr[1].split("/");
         year=Integer.parseInt(arr1[0]);//时间
         month=Integer.parseInt(arr1[1]);
         day=Integer.parseInt(arr1[2]);
         Calendar c = Calendar.getInstance();
         c.set(year,month-1,day);//设置时间
          ww=c.get(Calendar.DAY_OF_WEEK);
          hh=Integer.parseInt(arr2[0]);//时间
          mm=Integer.parseInt(arr2[1]);
          ss=Integer.parseInt(arr2[2]);
        if(ww==1)
            ww=7;
        else
            ww--;
    }
    boolean searthtable(table[]t,int num,int p)
    {
        for(int i=0;i<50;i++)
        {
            if(t[i]!=null&&i!=p)
            {
                if(t[i].tablenum==num&&t[i].flag)
                    return true;
            }
            else
                break;
        }
        //"Table number :"+被点菜桌号+" does not exist"
        System.out.println("Table number :"+num+" does not exist");
        return  false;
    }
    int searchtime(table[]t,table a,int sumtable)//若找到返回对应桌,找不到返回下一个空桌
    {
        //(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒)
        for(int i=0;i<sumtable;i++)
        {
            if(a.tablenum==t[i].tablenum)
            if(a.year==t[i].year)
            {
                if(a.day==t[i].day)
                {
                    if(a.ww>=1&&a.ww<=5)//周1~5
                    {
                        if(a.hh<=14&&t[i].hh<=14||a.hh>14&&t[i].hh>14)//在同一时段
                        {
                            
                            return i;
                            
                        }
                    }
                    else//周末
                    {
                        if(Math.abs((a.hh-t[i].hh)*60*60+(a.mm-t[i].mm)*60)+(a.ss-t[i].ss)<60*60)//在同一时段
                        {
                            
                            return i;
                        }
                        
                    }
                }
            }
        }
        //System.out.println(sumtable);
        return sumtable;
    }

}
class Worn//错误判断,错误b[i]==1
{
    void worninput(String[]a,int num,int[]b) 
    {
        //boolean flag1=true;
        
        for(int i=0;i<num;i++)
        {
            String[] arr=a[i].split(" ");
            boolean flag=false;
            //麻婆豆腐 12
            if(arr.length>5)
            {
                b[i]=1;
            }
            if(a[i].matches("^[\u4e00-\u9fa5]{1,} ([1-9][0-9]{0,2})$")==true)//普通菜存入
            {    
                flag=true;
            }
            //油淋生菜 9 T
            else if(a[i].matches("^[\u4e00-\u9fa5]{1,4} ([1-9][0-9]{0,2}) [T]$")==true)//特色菜存入
            {
                flag=true;
            }
            //table 31 2023/2/1 14/20/00
            else if(arr[0].equals("table")==true)//
            {
                int blank=0;
                for(int bk=0;bk<a[i].length();bk++)
                {
                    if(a[i].charAt(bk)==' ')
                    {
                        blank++;
                    }
                }
                if(arr[1].matches("^([1-9][0-9]{0,})$")&&blank==3)
                flag=true;
                //int blank=0;
                
            }
            //1 麻婆豆腐 1 16
            else if(a[i].matches("^[1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//自己点菜
            {
                flag=true;
            }
            //1 1 麻婆豆腐 1 16
            else if(a[i].matches("^([1-9][0-9]{0,1}) [1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//待点菜
            {
                flag=true;
            }
            //2 delete
            else if(a[i].matches("^([1-9][0-9]{0,1}) delete$")==true)//删菜
            {
                flag=true;
            }
            else if(a[i].matches("^end$")==true)//结尾
            {
                flag=true;
            }
            if(flag==false)
            {
                b[i]=1;
            }
        }
    }
}

  实现的效果如下:

 PTA5:

  对于本次的题目集只有一道题目,那就是菜单计价程序-5,这也是菜单计价程序的收官之作,个人认为难度很大,以至于最初的思路改了很多遍但是还是只能过一些的点

  第一步是和菜单计价程序-4一样的,构建好相应的类,组合相应的类,下面我将给出相应的类以及对应类的功能介绍

//菜品类:对应菜谱上一道菜的信息。
class Dish {
    String name;// 菜品名称
    int unit_price; // 单价
    String kowei=null;//这个是特色菜的口味
    int dudu;//这个是记录点的这个菜的度
    float acc=0.7f;//这个是特色菜在周一到周五的折扣
    String isT=null;//特色菜的标记
    Dish(String name,int price)
    {
        this.name = name;
        this.unit_price = price;
    }
    Dish(String name,String kowei,String isT,String price)
    {
        this.name = name;
        this.kowei = kowei;
        this.isT = isT;
        this.unit_price = Integer.parseInt(price);
    }
    int getPrice(int portion)
    {
// 计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
        float bl[]= {1,1.5f,2};
        return Math.round(unit_price*bl[portion-1]);
    }
}
//菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
class Menu {
    ArrayList<Dish> dishs = new ArrayList<Dish>();// 菜品数组,保存所有菜品信息
    public void add(Dish dish)
    {
        //菜单加一道菜
        for(int i=0;i<dishs.size();i++) 
        {
            if(dish.name.equals(dishs.get(i).name)) 
            {
                //找到了相同菜名,就替换
                dishs.set(i, dish);//这里是重新的覆盖
                return ;
            }
        }
        //未找到相同菜名,就增加
        dishs.add(dish);
    }
    Dish searthDish(String dishName)
    {
        // 根据菜名在菜谱中查找菜品信息,返回Dish对象。
        for(int i=0;i<dishs.size();i++) 
        {
            if(dishs.get(i).name.equals(dishName))
                return dishs.get(i);
        }
        return null;
    }
}
//点菜记录类:保存订单上的一道菜品记录
class Record {
    int orderNum;//序号
    Dish d;// 菜品
    int portion;// 份额(1/2/3代表小/中/大份)
    int num;//份数1,2,3,4,5
    public Record(int orderNum,Dish d,int portion,int num)
    {
        this.orderNum=orderNum;
        this.d=d;
        this.portion=portion;
        this.num=num;
    }
    public Record(int orderNum,Dish d,int dudu,int portion,int num)
    {
        this.orderNum=orderNum;
        this.d=d;
        this.d.dudu=dudu;
        this.portion=portion;
        this.num=num;
    }
    int getPrice()
    {
        // 计价,计算本条记录的价格
        return d.getPrice(portion)*num;
    }
}
//订单类:保存用户点的所有菜的信息
class Order
{
    ArrayList<Record> records = new ArrayList<Record>();// 保存订单上每一道的记录
    Menu menu;
    int table;
    int yuanjia=0;//记录不打折的原价
    int zhehoujia=0;//这个是打折后的价格
    float acc=0;
    String orderP;//用来记录点菜的人的名字 规定是不能超过10个字符
    String dianhua;//用来记录点菜人的电话 规定是11位的
    int chuancai=0;//川菜
    float chuanla=0;//川菜的辣度值
    int chuanla1=0;
    int jicai=0;//晋菜
    float jila=0;
    int jila1=0;
    int zhecai=0;//浙菜
    float zhela=0;
    int zhela1=0;
    void chuancaide()
    {
        for(int i=0;i<records.size();i++)
        {
            if(records.get(i)!=null)
            {
                if(records.get(i).d.isT!=null)
                {
                    if(records.get(i).d.kowei.equals("川菜"))
                    {
                        this.chuancai+=records.get(i).num;
                        this.chuanla+=records.get(i).num*records.get(i).d.dudu;
                    }
                }
            }
        }
        if(this.chuancai!=0) 
        {
            this.chuanla1=Math.round(this.chuanla*1.0f/this.chuancai);
        }
    }
    void jicaide()
    {
        for(int i=0;i<records.size();i++)
        {
            if(records.get(i)!=null)
            {
                if(records.get(i).d.isT!=null)
                {
                    if(records.get(i).d.kowei.equals("晋菜"))
                    {
                        this.jicai+=records.get(i).num;
                        this.jila+=records.get(i).num*records.get(i).d.dudu;
                    }
                }
            }
        }
        if(this.jicai!=0) 
        {
            this.jila1=Math.round(this.jila*1.0f/this.jicai*1.0f);
        }
    }
    void zhecaide()
    {
        for(int i=0;i<records.size();i++)
        {
            if(records.get(i)!=null)
            {
                if(records.get(i).d.isT!=null)
                {
                    if(records.get(i).d.kowei.equals("浙菜"))
                    {
                        this.zhecai+=records.get(i).num;
                        this.zhela+=records.get(i).num*records.get(i).d.dudu;
                    }
                }
            }
        }
        if(this.zhecai!=0) 
        {
            this.zhela1=Math.round(this.zhela*1.0f/this.zhecai*1.0f);
        }
    }
    void account(String a,String b) 
    {//a接收日期,b接收时间
        //计算星期几w
        String[] s = a.split("/");
        if(s[1].length()==1)
            s[1]="0"+s[1];
        if(s[2].length()==1)
            s[2]="0"+s[2];
        a = s[0]+"-"+s[1]+"-"+s[2];
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal=Calendar.getInstance();
        Date date=null;
        try 
        {
            date = format.parse(a);
        } catch (ParseException e) 
        {
            e.printStackTrace();
        }
        cal.setTime(date);
        int w=cal.get(Calendar.DAY_OF_WEEK)-1;
        if(w<=0)
            w=7;
        //处理时间
        String[] time = b.split("/");
        int h=Integer.parseInt(time[0]);
        int m=Integer.parseInt(time[1]);
        int sc=Integer.parseInt(time[2]);
        if(w>=1&&w<=5) 
        {
            if(h>=17&&(h<20||(h==20&&m<30)||(h==20&&m==30&&sc==0)))
                acc=0.8f;
            else if((h>10||(h==10&&m>=30))&&(h<14||(h==14&&m<30)||(h==14&&m==30&&sc==0)))
                acc=0.6f;
        }
        else if((h>9||(h==9&&m>=30))&&(h<21||(h==21&&m<30)||(h==21&&m==30&&sc==0)))
                acc=1;
    }
    int getTotalPrice()//这个函数只调用一次
    {
    // 计算订单的总价
        int total=0;
        if(records==null)
        {
            return 0;
        }
        else
        {
        for(int i=0;i<records.size();i++)
            total+=records.get(i).getPrice();
        return total;
        }
    }
    int getZhegoujia()
    {
        //System.out.println("1");
        if(records==null)
        {
            return 0;
        }
        else
        {
            int zhehoujia=0;
        for(int i=0;i<records.size();i++)
        {
            if(acc!=1.0f)//这就判断出来这个日子是在周一到周五的
            {
                if(records.get(i).d.isT!=null)//说明是特色菜 这个的折扣是0.7
                {
                    zhehoujia+=Math.round(records.get(i).getPrice()*0.7f);
                }
                else
                {
                    zhehoujia+=Math.round(records.get(i).getPrice()*0.8f);
                }
            }
            else
            {
                zhehoujia+=records.get(i).getPrice();
            }
        }
        return zhehoujia;
        }
    }
    public Order(Menu menu,int table)
    {
        this.menu = menu;
        this.table = table;
    }
    Order()
    {

    }
    //根据菜名点菜
    Record addARecord(int orderNum,String dishName,int portion,int num) 
    {
        //不用判断菜品是否存在,main里会判断,在这里一定会存在
        Record r = new Record(orderNum,menu.searthDish(dishName),portion,num);
        records.add(r);
        return r;
    }
    Record addARecord(int orderNum,String dishName,int dudu,int portion,int num)
     {
        //不用判断菜品是否存在,main里会判断,在这里一定会存在
        Record r = new Record(orderNum,menu.searthDish(dishName),dudu,portion,num);
        records.add(r);
        return r;
    }
    void delARecordByOrderNum(int orderNum)
    {
        //根据序号删除一条记录
        for(int i=0;i<records.size();i++) 
        {
            if(records.get(i).orderNum==orderNum) 
            {
                records.remove(i);
                return ;//删除成功
            }
        }
        System.out.println("delete error;");//删除失败
    }
}

  以上的代码是我所构建的类以及相应的功能介绍,接下来我将给出完整的实现代码以及实现的效果

  完整的代码如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
//table 1: 113 113 川菜 1 2 稍辣 晋菜 4 2 稍酸 浙菜 1 3 甜
//table 1: 113 113 川菜 1 2 稍辣 晋菜 4 2 稍酸 浙菜 1 3 甜
//table 1: 113 113 川菜 1 稍辣 晋菜 6 微酸 浙菜 1 甜
//麻婆豆腐 川菜 12 T
//油淋生菜 9
//麻辣鸡丝 10
//table 1 : tom 13605054400 2023/5/1 18/30/00
//1 麻婆豆腐 1 1 2
//2 油淋生菜 1 1
//3 麻婆豆腐 2 2 2
//table 2 : tom 13605054400 2023/5/6 18/30/00
//1 麻婆豆腐 2 1 2
//2 麻辣鸡丝 2 2
//3 麻婆豆腐 2 1 1
//end
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Menu menu=new Menu();
        Dish d;
        String a ;//接受内容
        a = in.next();
        //in.nextLine();
    //创建菜单
        while(!a.equals("end")) 
        {
            if(a.charAt(0)!='t')
            {
                String buff;
                buff=in.nextLine();
                String [] buffer = buff.split(" ");
                if(buffer.length==2)//这个是普通的菜
                {
                    int price=Integer.parseInt(buffer[1]);
                    d=new Dish(a,price);
                    menu.add(d);
                }
                if(buffer.length==4)//这个是特色菜
                {
                    d=new Dish(a,buffer[1],buffer[3],buffer[2]);
                    menu.add(d);
                }
                // int price;
                // price=in.nextInt();
                // d=new Dish(a,price);
                // menu.add(d);
            }
            else
                break;
            a=in.next();
           // in.nextLine();
        }
    //订单,此时的a="table"
        ArrayList<Order> orders = new ArrayList<Order>();
        while(!a.equals("end")) 
        {
            int table=in.nextInt();        //接收第几桌
            //接受订单信息
            Order order = new Order(menu,table);
            orders.add(order);
            a=in.next();    //接受分号
            a=in.next();    //用来记录点菜人的名字
            order.orderP=a;
            a=in.next();    //用来记录点菜人的电话
            order.dianhua=a;
            a=in.next();    //接收日期
            String b = in.next();    //接收时间
            order.account(a,b);
            if(order.acc==0)
            {
                System.out.println("table "+table+" out of opening hours");
                a=in.next();
                //in.nextLine();
                continue;//不进行下面的操作直接对下一组进行操作
            }
            if(order.orderP.length()<=10&&order.dianhua.length()==11)//检验点菜的格式是不是正确的
            {
                String qiansan=order.dianhua.substring(0,3);
                if(qiansan.equals("180")||qiansan.equals("181")||qiansan.equals("189")||qiansan.equals("133")||qiansan.equals("135")||qiansan.equals("136"))//检查电话的格式
                {
                    System.out.println("table "+table+": ");
                }
                else
                {
                    System.out.println("wrong format");
                }
            }
            else
            {
                System.out.println("wrong format");
            }
            while(true)
            {
                a=in.next();
                //in.nextLine();
                if(a.equals("end")||a.equals("table"))
                    break;
                String m=in.nextLine();
                String[] p = m.split(" ");
                if(p.length==4||p.length==5) 
                {
                    if(p.length==5)//这个点的菜是包含特色菜的
                    {
                        int orderNum = Integer.parseInt(a);
                        String dishName = p[1];//这个是菜名
                        int dudu = Integer.parseInt(p[2]);//这个是度
                        int portion = Integer.parseInt(p[3]);//这个是份额
                        int num = Integer.parseInt(p[4]);//这个是份数
                        d = menu.searthDish(dishName);
                        if(d==null)//菜单没有这道菜
                        {
                            System.out.println(dishName+" does not exist");
                        }
                        else
                        {
                            if(d.kowei.equals("川菜"))//辣度0-5级;对应辣度水平为:不辣、微辣、稍辣、辣、很辣、爆辣;
                            {
                                if(dudu>5)
                                {
                                    System.out.println("spicy num out of range "+":"+dudu);
                                    continue;
                                }
                            }
                            if(d.kowei.equals("晋菜"))//酸度0-4级;对应酸度水平为:不酸、微酸、稍酸、酸、很酸;
                            {
                                if(dudu>4)
                                {
                                    System.out.println("acidity num out of range "+":"+dudu);
                                    continue;
                                }
                            }
                            if(d.kowei.equals("浙菜"))//甜度0-3级;对应酸度水平为:不甜、微甜、稍甜、甜;
                            {
                                if(dudu>3)
                                {
                                    System.out.println("sweetness num out of range "+":"+dudu);
                                    continue;
                                }
                            }
                            Record r = order.addARecord(orderNum, dishName,dudu,portion, num);
                            System.out.println(orderNum+" "+dishName+" "+r.getPrice());
                        }
                    }
                    else
                    {
                    //给本桌点餐
                    int orderNum = Integer.parseInt(a);
                    String dishName = p[1];
                    int portion = Integer.parseInt(p[2]);
                    int num = Integer.parseInt(p[3]);
                    //查找是否有此菜名
                    d = menu.searthDish(dishName);//接受菜品
                    if(d==null)//未找到,说明没有该菜品
                        System.out.println(dishName+" does not exist");
                    else 
                    {//找到了,添加订单
                        Record r = order.addARecord(orderNum, dishName, portion, num);
                        System.out.println(orderNum+" "+dishName+" "+r.getPrice());
                    }
                    }
                }
                if(p.length==6)//给别的桌子点的菜一定是特色菜 
                {
                    //为别桌点菜
                    int orderNum = Integer.parseInt(p[1]);//这个是点菜的序号
                    String dishName = p[2];
                    int dudu = Integer.parseInt(p[3]);
                    int portion = Integer.parseInt(p[4]);
                    int num = Integer.parseInt(p[5]);
                    //查找是否有此菜名
                    d = menu.searthDish(dishName);//接受菜品
                    if(d==null)//未找到,说明没有该菜品
                        System.out.println(dishName+" does not exist");
                    else
                     {//找到了,添加订单
                             if(d.kowei.equals("川菜"))//辣度0-5级;对应辣度水平为:不辣、微辣、稍辣、辣、很辣、爆辣;
                            {
                                if(dudu>5)
                                {
                                    System.out.println("spicy num out of range "+": "+dudu);
                                    continue;
                                }
                            }
                            if(d.kowei.equals("晋菜"))//酸度0-4级;对应酸度水平为:不酸、微酸、稍酸、酸、很酸;
                            {
                                if(dudu>4)
                                {
                                    System.out.println("acidity num out of range "+": "+dudu);
                                    continue;
                                }
                            }
                            if(d.kowei.equals("浙菜"))//甜度0-3级;对应酸度水平为:不甜、微甜、稍甜、甜;
                            {
                                if(dudu>3)
                                {
                                    System.out.println("sweetness num out of range "+": "+dudu);
                                    continue;
                                }
                            }
                        Record r = order.addARecord(orderNum, dishName,dudu, portion, num);
                        System.out.println(orderNum+" table "+table
                                +" pay for table "+a+" "+r.getPrice());//这里的a是给别的桌子点菜的桌位号
                    }
                }
                if(p.length==2) 
                {//删除
                    order.delARecordByOrderNum(Integer.parseInt(a));
                }
            }
        }
        Order [] dingdan = new Order[100];
        int iiop=0;
           for(int i=0;i<orders.size();i++)
         {
                dingdan[iiop]=new Order();
                dingdan[iiop]=orders.get(i);
                iiop++;
                orders.get(i).yuanjia=orders.get(i).getTotalPrice();
                orders.get(i).zhehoujia=orders.get(i).getZhegoujia();
                System.out.print("table "+orders.get(i).table+": "+orders.get(i).yuanjia+" "+orders.get(i).zhehoujia+" ");
                //orders.get(i).tongjicai();
                orders.get(i).chuancaide();
                if(orders.get(i).chuancai!=0)
                {
                    // orders.get(i).chuancaide();
                    System.out.print("川菜 "+orders.get(i).chuancai);//不辣、微辣、稍辣、辣、很辣、爆辣;
                    //System.out.print(" "+orders.get(i).chuanla1);
                    switch(orders.get(i).chuanla1)
                    {
                        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;
                    }
                    //orders.get(i).chuanla1=0;
                }
                orders.get(i).jicaide();
                if(orders.get(i).jicai!=0)
                {
                    // orders.get(i).tongjicai();
                    System.out.print(" 晋菜 "+orders.get(i).jicai);//不酸、微酸、稍酸、酸、很酸;
                    //System.out.print(" "+orders.get(i).jila1);
                    switch(orders.get(i).jila1)
                    {
                        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;
                    }
                   //orders.get(i).jicai=0;
                }
                orders.get(i).zhecaide();
                if(orders.get(i).zhecai!=0)
                {
                    System.out.print(" 浙菜 "+orders.get(i).zhecai);//不甜、微甜、稍甜、甜
                    //System.out.print(" "+orders.get(i).zhela1);
                    switch(orders.get(i).zhela1)
                    {
                        case 0 :
                            System.out.print(" 不甜");
                            break;
                        case 1 :
                            System.out.print(" 微甜");
                            break;
                        case 2 :
                            System.out.print(" 稍甜");
                            break;
                        case 3 :
                            System.out.print(" 甜");
                            break;
                    }
                   // orders.get(i).zhela1=0;
                }
                System.out.print("\n");
        }
        Order temp = new Order();
        for(int j=0;j<iiop-1;j++)
        {
            for(int k=0;k<iiop-1-j;k++)
            {
                if(((dingdan[k].orderP).compareTo(dingdan[k+1].orderP))>0)
                {
                    temp=dingdan[k+1];
                    dingdan[k+1]=dingdan[k];
                    dingdan[k]=temp;
                }
            }
        }//已经按名字的次序拍好了
        for(int i=0;i<orders.size()&&dingdan[i]!=null;i++)
        {
            for(int j=i+1;j<orders.size()&&dingdan[j]!=null;j++)
            {
                if(dingdan[i].orderP.equals(dingdan[j].orderP))
                {
                    dingdan[i].zhehoujia+=dingdan[j].zhehoujia;
                    dingdan[j]=null;
                }
            }
        }
        for(int i=0;i<orders.size()&&dingdan[i]!=null;i++)
        {
            System.out.println(dingdan[i].orderP+" "+dingdan[i].dianhua+" "+dingdan[i].zhehoujia);
        }
        in.close();
    }
}
//菜品类:对应菜谱上一道菜的信息。
class Dish {
    String name;// 菜品名称
    int unit_price; // 单价
    String kowei=null;//这个是特色菜的口味
    int dudu;//这个是记录点的这个菜的度
    float acc=0.7f;//这个是特色菜在周一到周五的折扣
    String isT=null;//特色菜的标记
    Dish(String name,int price)
    {
        this.name = name;
        this.unit_price = price;
    }
    Dish(String name,String kowei,String isT,String price)
    {
        this.name = name;
        this.kowei = kowei;
        this.isT = isT;
        this.unit_price = Integer.parseInt(price);
    }
    int getPrice(int portion)
    {
// 计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
        float bl[]= {1,1.5f,2};
        return Math.round(unit_price*bl[portion-1]);
    }
}
//菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
class Menu {
    ArrayList<Dish> dishs = new ArrayList<Dish>();// 菜品数组,保存所有菜品信息
    public void add(Dish dish)
    {
        //菜单加一道菜
        for(int i=0;i<dishs.size();i++) 
        {
            if(dish.name.equals(dishs.get(i).name)) 
            {
                //找到了相同菜名,就替换
                dishs.set(i, dish);//这里是重新的覆盖
                return ;
            }
        }
        //未找到相同菜名,就增加
        dishs.add(dish);
    }
    Dish searthDish(String dishName)
    {
        // 根据菜名在菜谱中查找菜品信息,返回Dish对象。
        for(int i=0;i<dishs.size();i++) 
        {
            if(dishs.get(i).name.equals(dishName))
                return dishs.get(i);
        }
        return null;
    }
}
//点菜记录类:保存订单上的一道菜品记录
class Record {
    int orderNum;//序号
    Dish d;// 菜品
    int portion;// 份额(1/2/3代表小/中/大份)
    int num;//份数1,2,3,4,5
    public Record(int orderNum,Dish d,int portion,int num)
    {
        this.orderNum=orderNum;
        this.d=d;
        this.portion=portion;
        this.num=num;
    }
    public Record(int orderNum,Dish d,int dudu,int portion,int num)
    {
        this.orderNum=orderNum;
        this.d=d;
        this.d.dudu=dudu;
        this.portion=portion;
        this.num=num;
    }
    int getPrice()
    {
        // 计价,计算本条记录的价格
        return d.getPrice(portion)*num;
    }
}
//订单类:保存用户点的所有菜的信息
class Order
{
    ArrayList<Record> records = new ArrayList<Record>();// 保存订单上每一道的记录
    Menu menu;
    int table;
    int yuanjia=0;//记录不打折的原价
    int zhehoujia=0;//这个是打折后的价格
    float acc=0;
    String orderP;//用来记录点菜的人的名字 规定是不能超过10个字符
    String dianhua;//用来记录点菜人的电话 规定是11位的
    int chuancai=0;//川菜
    float chuanla=0;//川菜的辣度值
    int chuanla1=0;
    int jicai=0;//晋菜
    float jila=0;
    int jila1=0;
    int zhecai=0;//浙菜
    float zhela=0;
    int zhela1=0;
    void chuancaide()
    {
        for(int i=0;i<records.size();i++)
        {
            if(records.get(i)!=null)
            {
                if(records.get(i).d.isT!=null)
                {
                    if(records.get(i).d.kowei.equals("川菜"))
                    {
                        this.chuancai+=records.get(i).num;
                        this.chuanla+=records.get(i).num*records.get(i).d.dudu;
                    }
                }
            }
        }
        if(this.chuancai!=0) 
        {
            this.chuanla1=Math.round(this.chuanla*1.0f/this.chuancai);
        }
    }
    void jicaide()
    {
        for(int i=0;i<records.size();i++)
        {
            if(records.get(i)!=null)
            {
                if(records.get(i).d.isT!=null)
                {
                    if(records.get(i).d.kowei.equals("晋菜"))
                    {
                        this.jicai+=records.get(i).num;
                        this.jila+=records.get(i).num*records.get(i).d.dudu;
                    }
                }
            }
        }
        if(this.jicai!=0) 
        {
            this.jila1=Math.round(this.jila*1.0f/this.jicai*1.0f);
        }
    }
    void zhecaide()
    {
        for(int i=0;i<records.size();i++)
        {
            if(records.get(i)!=null)
            {
                if(records.get(i).d.isT!=null)
                {
                    if(records.get(i).d.kowei.equals("浙菜"))
                    {
                        this.zhecai+=records.get(i).num;
                        this.zhela+=records.get(i).num*records.get(i).d.dudu;
                    }
                }
            }
        }
        if(this.zhecai!=0) 
        {
            this.zhela1=Math.round(this.zhela*1.0f/this.zhecai*1.0f);
        }
    }
    void account(String a,String b) 
    {//a接收日期,b接收时间
        //计算星期几w
        String[] s = a.split("/");
        if(s[1].length()==1)
            s[1]="0"+s[1];
        if(s[2].length()==1)
            s[2]="0"+s[2];
        a = s[0]+"-"+s[1]+"-"+s[2];
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal=Calendar.getInstance();
        Date date=null;
        try 
        {
            date = format.parse(a);
        } catch (ParseException e) 
        {
            e.printStackTrace();
        }
        cal.setTime(date);
        int w=cal.get(Calendar.DAY_OF_WEEK)-1;
        if(w<=0)
            w=7;
        //处理时间
        String[] time = b.split("/");
        int h=Integer.parseInt(time[0]);
        int m=Integer.parseInt(time[1]);
        int sc=Integer.parseInt(time[2]);
        if(w>=1&&w<=5) 
        {
            if(h>=17&&(h<20||(h==20&&m<30)||(h==20&&m==30&&sc==0)))
                acc=0.8f;
            else if((h>10||(h==10&&m>=30))&&(h<14||(h==14&&m<30)||(h==14&&m==30&&sc==0)))
                acc=0.6f;
        }
        else if((h>9||(h==9&&m>=30))&&(h<21||(h==21&&m<30)||(h==21&&m==30&&sc==0)))
                acc=1;
    }
    int getTotalPrice()//这个函数只调用一次
    {
    // 计算订单的总价
        int total=0;
        if(records==null)
        {
            return 0;
        }
        else
        {
        for(int i=0;i<records.size();i++)
            total+=records.get(i).getPrice();
        return total;
        }
    }
    int getZhegoujia()
    {
        //System.out.println("1");
        if(records==null)
        {
            return 0;
        }
        else
        {
            int zhehoujia=0;
        for(int i=0;i<records.size();i++)
        {
            if(acc!=1.0f)//这就判断出来这个日子是在周一到周五的
            {
                if(records.get(i).d.isT!=null)//说明是特色菜 这个的折扣是0.7
                {
                    zhehoujia+=Math.round(records.get(i).getPrice()*0.7f);
                }
                else
                {
                    zhehoujia+=Math.round(records.get(i).getPrice()*0.8f);
                }
            }
            else
            {
                zhehoujia+=records.get(i).getPrice();
            }
        }
        return zhehoujia;
        }
    }
    public Order(Menu menu,int table)
    {
        this.menu = menu;
        this.table = table;
    }
    Order()
    {

    }
    //根据菜名点菜
    Record addARecord(int orderNum,String dishName,int portion,int num) 
    {
        //不用判断菜品是否存在,main里会判断,在这里一定会存在
        Record r = new Record(orderNum,menu.searthDish(dishName),portion,num);
        records.add(r);
        return r;
    }
    Record addARecord(int orderNum,String dishName,int dudu,int portion,int num)
     {
        //不用判断菜品是否存在,main里会判断,在这里一定会存在
        Record r = new Record(orderNum,menu.searthDish(dishName),dudu,portion,num);
        records.add(r);
        return r;
    }
    void delARecordByOrderNum(int orderNum)
    {
        //根据序号删除一条记录
        for(int i=0;i<records.size();i++) 
        {
            if(records.get(i).orderNum==orderNum) 
            {
                records.remove(i);
                return ;//删除成功
            }
        }
        System.out.println("delete error;");//删除失败
    }
}

  接下来的是实现的效果

 期中考试

  期中考试的题目是有关于7-1 测验1-圆类设计和7-2 测验2-类结构设计和7-3 测验3-继承与多态和7-4 测验4-抽象类与接口,由于题目都较为简单,在这里我就对于整体题目感觉进行概述,在我看来,期中考试的大多数题目其实没什么好说的,因为前三题我觉得很简单,完全就是按照题目所说的对类进行构建然后就可以获得满分,但是最后一题的一些细节还有有点意思的,在最后一题中,我们需要对一个对象进行判断,判断其到底来自与哪个接口的处理,下面是我思考后的处理方式:

static void printArea(Shape shape) {
        double f = shape.getArea();
        if (shape instanceof Circle) {
            if (f <= 0)
                System.out.print("Wrong Format");
            else {
                String tmp = String.format("%.2f", f);
                System.out.print(tmp);
            }
        } else {
            String tmp = String.format("%.2f", f);
            System.out.print(tmp);
        }
    }

这是一个名为printArea的静态方法,接受一个Shape类型的参数shape,该方法用于计算并打印出给定形状的面积,首先,方法中声明了一个双精度类型的变量f,用于存储调用shape对象的getArea方法所返回的面积值,接下来使用了一个条件语句if,判断shape对象是否属于Circle类。如果属于Circle类,则进入if块,在if块中,首先检查面积值f是否小于等于0,如果是,则打印出"Wrong Format",表示格式错误,如果面积值大于0,则使用String.format("%.2f", f)将面积值格式化为保留两位小数的字符串tmp,并将tmp打印出来。如果shape对象不属于Circle类,那么直接进入else块,在else块中,同样使String.format("%.2f", f)将面积值格式化为保留两位小数的字符串tmp,并将tmp打印出来,因此,该方法根据给定形状的类型和面积值进行不同的处理,并将结果打印出来,其他我觉得没有什么好说的

三、踩坑心得

  1、注意检查价格算法,特别是特色菜的定价算法和打折时间。确保算法正确并准确反映实际情况

  2、记得在编写代码时,所有的大括号“{}”都需要成对出现。有时候我们只记得输入左括号“{”,却忘记输入与之对应的右括号“}”

  3、在使用Java语言时,要注意大小写。Java对于输入的语法要求非常严格,很多报错是因为方法名称没有正确的大写首字母

  4、在调用方法类函数时,请确保在方法名后加上括号()来进行调用,以避免报错

四、主要困难以及改进建议

  1.个人代码思路感觉没有问题,但是就是有些测试点过不去,有些测试点感觉就是没必要那么设计

  2.个人的编码属于C语言的块式风格的,对于java的格式控制不怎么熟悉  

五、总结

  个人总结:个人感觉做完这2次大的PTA的作业和期中考试,收获是有的,从一开始的点菜4到现在的点菜5,我一路走来,虽然说自己不能把这两道题都AC把,但是个人感觉,这一系列的题目考察了我们学生的思维能力,对流程的控制,对大型设计程序框架的设计,在锻炼我们编码的能力,也悄悄为我们叩开了写出优美的大型框架之门。其次通过期中考试之后,让我对于类的理解有了更加深刻的了解,对于类与类之间的联系,对于接口的实现的掌握有了很大的帮助,通过点菜系列题目的磨练,我感觉到我的心态的变化,我的心态变得更加的稳定,我的情绪波动不再会那么大。最后,通过了点菜系列题目和期中考试,巩固了我对于类和对象的知识,点菜系列的题目是金典的,我很赞赏。

  个人意见:老师可以在课堂上对于点菜系列的题目进行相应的讲解,去帮助班上编程能力水平较低的学生,他们懂得可能没有那么快,其次吧,个人对该类型的题目的建议是可以适当降低难度,转向去将题目与实时所学建立联系,做到现学现用。

  

  

 
posted @ 2023-06-29 00:53  铭记巅峰1427  阅读(53)  评论(0)    收藏  举报