Blog1

前言

对于第一次接触面向对象语言

关于第一次接触面向对象的编程语言有些切身的感受,虽然上个学期是通过面向过程的C语言初识编程,但是上个学期的基础也让我快速的上手了Java的基本语法和一些功能的实现,更多转变的是对于问题的分析角度和方法思维,从单一的以函数解决问题转变为对事物所涉及到的问题,个体,特性进行包装,转变为类与对象的思维模式,这种思维模式以及解决问题的方法要比面向过程更加容易理解,景尽管多了很多概念和新的语法,但学的越多,我解决问题的能力也就越强,这在PTA前三次作业中也有所体现(这些题要放在C语言作业里写起来真的有点难)。

 

对于前三次作业的大致反馈

首先第一次作业吧,题量挺多的,但是大部分都没有涉及到类的思想,所以凭借上个学期C语言的思维方法都是可以完成的(这也是我唯一AC的一次作业),需要的只是在网上多看网课,熟悉Java的基本语法啊,对于此次题目集认为困难的估计是没有在网上看课程。

第二次作业围绕我一个学期的菜单计价程序开始了,不出意外的我出意外了本次作业两个菜单程序让我失去了AC的可能,遇到的问题会在接下来的内容中详细展开。知识主要就是围绕考察类和对象的创建,以及各个对象之间的关系,以及不同的对象应该具备什么样的特性。难度适中因为还是有很多人AC的,题目量也可以接受。

第三次作业肯定还是菜单作为作业难点,但也是最能提升能力的一道题,从这次开始我就可以感受到出题人的目的,基本上就是刚学完的东西立马就会使用到,并且一步步引领学生不断优化自己的代码,是个非常不错的系列(虽然很难),并且每解决 一个测试点,看着分一点点加上,也很有成就感,这确实是我在别的作业完成上感受不到的。本次作业的其他题目在后续也会发现都是对后面作业的铺垫,所以对于作业代码的保存和分类也很重要,题目量适中,就是节奏比较快。

对于三次作业我觉的有一点可以更加优化,在答题期间内可以隐藏所有的测试点数据,但是在答题时间过后,公开所有测试点的具体数据,这样既可以在锻炼大家在答题时的思维能力,看待问题的全面性,还可以有助于同学们在之后回顾问题,总结经验不断改进。最好是还可以实行补题的方案,及时的纠错和改正更有利于同学不断完善自己的能力。

 

设计与分析

PTA-2

7-1

设计思路

Dish类用于储存单一菜品名称与单价,并且具备接收份额输出具体价格的方法

Menu类使用数组储存各类菜品组成菜单,具备添加菜品、根据菜名返回菜品对象的方法

Record类用于记录客户单条点餐信息,包含菜品以及份额,具备返回单条点餐价格的方法

Order类用于保存用户点的所有点餐信息、通过数组储存Record对象,具备返回订单总价、增加单条订单的方法

Main类用于接收用户输入并启动程序

类图如下:

Source Monitor代码分析

 

由分析图以及报表的内容可以清晰的看到,对于本次作业,代码风格比较轻便,主要由于内容不多,功能较少,注释语句占总语句的百分比较高,是一种良好的习惯,也为后续的代码优化带来了便利。

 

 

如图是源代码中的Main类,main函数的内部语句过多,作为启动函数,内置语句应该尽量少,本次代码优化可以将main方法的内部语句以方法的形式剥离出来。

 

源码如下:

package menu1;

import java.util.Scanner;

class Dish{
    String name;//菜品名称
    int unit_price;//单价
    
    Dish(String name,int price) {
        this.name = name;
        this.unit_price = price;
    }
    
    /*计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,
      代表小/中/大份)*/
    public int getPrice(int portion) {
        float price =0;
        switch(portion) {
        case 1:
            price = unit_price;
            break;
        case 2:
            price = unit_price*1.5f;
            break;
        case 3:
            price = unit_price*2;
            break;
        }
        return Math.round(price);
    }
}
//对应菜谱,包含饭店提供的所有菜的信息
class Menu{
    public Dish[] dishs;//菜品数组,保存所有菜品信息
    
    public void add(Dish dish) {
        int len=0;
        if(dishs!=null)
            len = dishs.length;
        Dish[] tmp = new Dish[len+1];
        if(len>0)
            System.arraycopy(dishs,0,tmp,0,len);
        tmp[len]=dish;
        dishs=tmp;
    }
    
    //根据菜名在菜谱中查找菜品信息,返回Dish对象。
    public Dish searthDish(String dishName) {
        if(dishs==null) {
            return null;
        }
        for(int i=0;i<dishs.length;i++){
            if(dishs[i].name.equals(dishName))
                return dishs[i];
        }
        System.out.println(dishName+" does not exist");
        return null;
    }
}
//保存订单上的一道菜品记录
class Record{
    Dish d;//菜品
    int portion;//份额(1/2/3代表小/中/大份)
    //计价,计算本条记录的价格
    
    public Record(Dish d,int portion) {
        
        this.d = d;
        this.portion = portion;
        
    }
    
    public int getPrice() {
        return d.getPrice(portion);
    }
}
//保存用户点的所有菜的信息
class Order{
    Record[] records;//保存订单上每一道的记录
    Menu menu;
    //计算订单的总价
    
    public int getToalPrice() {
        int total = 0;
        if(records == null) {
            return 0;
        }
        for(int i=0;i<records.length;i++) {
            total+=records[i].getPrice();
        }
        return total;
    }
    
    public Order(Menu menu) {
        this.menu = menu;
    }
    
    //添加一条菜品信息到订单中
    public Record addARecord(String dishName,int portion) {
        Dish dish = menu.searthDish(dishName);
        Record record = null;
        if(dish!=null) {
            record = new Record(dish,portion);
            int len=0;
            if(records!=null) {
                len = records.length;
            }
            Record tmp[] = new Record[len+1];
            if(len>0)
                System.arraycopy(records,0,tmp,0,len);
            tmp[len]=record;
            records=tmp;
        }
        return record;
    }
}

public class Main {
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner in = new Scanner(System.in);
        Menu menu = new Menu();
        Dish d = new Dish("西红柿炒蛋",15);
        menu.add(d);
        d = new Dish("清炒土豆丝",12);
        menu.add(d);
        d = new Dish("麻婆豆腐",12);
        menu.add(d);
        d = new Dish("油淋生菜",9);
        menu.add(d);
        Order order = new Order(menu);
        String dishName;
        int portion;
        dishName = in.next();
        while(dishName.equals("end")==false){
            portion = in.nextInt();
            order.addARecord(dishName, portion);
            dishName = in.next();
        }
        if(order.getToalPrice()!=0) {
        System.out.println(order.getToalPrice());
        }
        
    }

}

 

7-2

设计思路

Dish类用于储存单一菜品名称与单价,并且具备接收份额输出具体价格的方法

Menu类使用ArrayList储存各类菜品组成菜单,具备添加菜品、根据菜名返回菜品对象、判别是否属于重命名菜品、重命名菜品的方法

Record类用于记录客户单条点餐信息,包含点餐序号,菜品以及份额,具备返回单条点餐价格的方法

Order类用于保存用户点的所有点餐信息、通过ArrayList储存Record对象,具备返回订单总价、增加单条订单,通过点餐序号删除单条订单、重新点餐。通过订单序号查找单条订单的方法

Main类用于接收用户输入并启动程序

类图如下:

 

 

 

Source Monitor代码分析

 

由分析图以及报表内容可知,本次代码没有注释,可读性差,不利于后期优化,如果时间过长难以快速上手修改代码。另外本次代码的复杂度相比较上次作业增大很多,单类中深度以及平均深度也更大,代码冗杂,可能是因为本次新增了更多需要判别输入格式以及储存数据的功能和需求。

 源码如下:

package menu2;

import java.util.*;


import java.util.Scanner;


class Dish{
    String name;
    int unit_price;
    
    Dish(String name,int unit_price){
        this.name = name;
        this.unit_price = unit_price;
    }
    
    int getPrcie(int portion) {
        float a[] = {1,1.5f,2};
        return (int) Math.round(unit_price*a[portion-1]);
    }
}

class Menu{
    List<Dish> dishs;
    Menu(){
        this.dishs = new ArrayList<>();
    }
    Dish searthDish(String dishName) {
        for(Dish dish:dishs) {
            if(dish.name.equals(dishName))
                return dish;
        }
        return null;
    }
    Dish addDish(String dishName,int unit_price) {
        Dish dish = new Dish(dishName,unit_price);
        dishs.add(dish);
        return dish;
    }
    
    boolean isredish(String dishName) {
        boolean isfind = false;
        for(Dish dish:dishs) {
            if(dish.name.equals(dishName)){
                isfind = true;
            }
        }
        return isfind;
    }
    
    void redish(String dishName,int unit_price) {
        for(Dish dish:dishs) {
            if(dish.name.equals(dishName)){
                dish.unit_price = unit_price;
            }
        }
    }
}

class Record{
    int orderNum;
    Dish dish;
    int portion;
    int number;
    Record(int orderNum,Dish dish,int portion,int number){
        this.orderNum = orderNum;
        this.dish = dish;
        this.portion = portion;
        this.number = number;
        
    }
    
    int getprice(){
        return dish.getPrcie(portion)*number;
    }
    
}

class Order{
    List<Record> records;
    Menu menu;
    Order(Menu menu){
        this.records = new ArrayList<>();
        this.menu = menu;
    }
    int getTotalPrice() {
        int total = 0;
        for(Record record:records) {
            total+=record.getprice();
        }
        return total;
    }
    
    Record addARecord(int orderNum,String dishName,int portion,int number) {
        Dish dish = menu.searthDish(dishName);
        if(dish==null) {
            System.out.println(dishName+" does not exist");
            return null;
        }
        Record record = new Record(orderNum,dish,portion,number);
        if(record.number>0)
            System.out.println(record.orderNum+" "+record.dish.name+" "+record.getprice());
        records.add(record);
        return record;
    }
    
    void delARecordByOrderNum(int orderNum) {
        boolean isfind = true;
        for(Record record:records) {
            if(orderNum==record.orderNum) {
                record.dish.unit_price = 0;
                isfind = false;
                break;
            }
        }
        if(isfind) {
            System.out.println("delete error;");
        }

    }
    
    void reRecord(int orderNum,int portion,int number) {
        Record record;
        record = records.get(orderNum);
        record.portion = portion;
        record.number = number;
    }
    
    int findRecordByNum(int orderNum) {
        int i = 0;
        for(Record record:records) {
            if(orderNum == record.orderNum) {
                return i;
            }
            i++;
        }
        return -1;
    }
    
}

public class Main{
    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        
        Menu menu = new Menu();
        Order order = new Order(menu);
        String fline;
        while(true) {
            String line = in.nextLine();
            fline = line;
            String[] parts = line.split(" ");
            if(parts[0].equals("1")||line.equals("end")) {
                break;
            }
            String dishName = parts[0];
            int unit_price = Integer.parseInt(parts[1]);
            Dish dish = new Dish(dishName,unit_price);
            if(menu.isredish(dishName)) {
                menu.redish(dishName,unit_price);
            }else {
            menu.addDish(dishName,unit_price);
            }
            
        }
        while(true) {
            String[] parts = fline.split(" ");
            if(fline.equals("end")) {
                break;
            }
            if(parts[1].equals("delete")) {
                int reorderNum = Integer.parseInt(parts[0]);
                order.delARecordByOrderNum(reorderNum);
                fline = in.nextLine();
                continue;
            }
            else
            {
                int orderNum = Integer.parseInt(parts[0]);
                String dishName = parts[1];
                int portion = Integer.parseInt(parts[2]);
                int number = Integer.parseInt(parts[3]);
                if(order.findRecordByNum(orderNum)==-1) {
                    order.addARecord(orderNum,dishName,portion,number);
                }
                else {
                    int reorderNum = order.findRecordByNum(orderNum);
                    order.reRecord(reorderNum,portion,number);
                }
                        
            }
            fline = in.nextLine();
        }
        System.out.print(order.getTotalPrice());
    }
}
 
7-3
设计思路

只需要对输入格式以及输入的日期合法性进行判断即可

格式要求:

第一行输入一个日期字符串,格式为"YYYY-MM-dd"
第二行输入两个日期字符串,中间使用空格隔开。分别代表开始日期与结束日期。

*日子要用两位表示

合法性:

格式合法

日期符合常理(闰年一年366天,非闰年一天365天,二月闰年29天,非闰年二月28天)

“早于”之前的日期要比之后的早

Source Monitor代码分析

 

本题目旨在为后PTA3-7-1通过日期判断折扣奠定基础。

 

源码如下:

 

package clander;

import java.util.Scanner;

import java.util.Calendar;

import java.util.GregorianCalendar;

public class Main {
    
    public static boolean stringTrue(String s) {
        int location = s.lastIndexOf('-');
        int len = s.length();
        if(len-location-1==2)
            return true;
        else
            return false;
    }
    
    public static boolean isTrue(String s1,String s2,int year_1,int month_1,int day_1,int year_2,int month_2,int day_2) {
        if(stringTrue(s1)&&stringTrue(s2)) {
            if(year_1==year_2) {
                if(month_1==month_2) {
                    if(day_1<day_2) {
                        return true;
                    }
                    else if(day_1==day_2){
                        return true;
                    }
                    else {
                        return false;
                    }
                }
                else if(month_1<month_2) {
                    return true;
                    }
                else {
                    return false;
                }
                }
            else if(year_1<year_2) {
                return true;
            }
            else {
                return false;
                
            }
        }
        else {
            return false;
        }
    }
    
    public static boolean isTrue(String s,int year,int month,int day) {
        if(stringTrue(s)) {
            if(year<0||month<=0||month>12||day<=0||day>31) {
                System.out.println(s+"无效!");
                return false;
            }
            else {
                if(month==4||month==6||month==9||month==11) {
                    if(day>30) {
                        System.out.println(s+"无效!");
                        return false;
                    }
                }
                else if(month==2) {
                    if(!isLeapYear(year)) {
                        if(day>28) {
                            System.out.println(s+"无效!");
                            return false;
                        }
                    }
                    else {
                        if(day>29) {
                            System.out.println(s+"无效!");
                            return false;
                        }
                    }
                }
                else {
                    return true;
                }
                return true;
            }
        }
        else {
            return false;
        }
    }
    
    public static boolean isLeapYear(int year) {
        return year%400==0||(year%4==0&&year%100!=0);
    }
    
    public static void printMessage(String s,int year,int month,int day) {
        if(isTrue(s,year,month,day)) {
            if(isLeapYear(year)) {
                System.out.printf(s);
                System.out.println("是闰年.");
            }
            System.out.printf(s);
            System.out.print("是当年第");
            printYear(year,month,day);
            printMonth(day);
            printWeek(year,month,day);
        }
        else {
            System.out.println(s+"无效!");
        }
        
    }
    
    public static void printYear(int year,int month,int day) {
        int sumday = 0;
        for(int i=1;i<month;i++) {
            sumday+=getNumberOfMonthDays(year,i);
        }
        sumday+=day;
        System.out.print(sumday+"天,当月第");
        
    }
    
    public static void printMonth(int day) {
        System.out.print(day+"天,当周第");
    }
    
    public static void printWeek(int year,int month,int day) {
        Calendar c = new GregorianCalendar(year,month-1,day);//因为一月为0
        int week= c.get(Calendar.DAY_OF_WEEK)-1;
        if(week==0)
            week=7;
        System.out.println(week+"天.");
    }
    
    public static int getTotalNumberOfDays(int year_1,int month_1,int day_1,int year_2,int month_2,int day_2) {
        int total = 0;
        int del = 0;
        for(int i=year_1;i<year_2;i++) {
            if(isLeapYear(i))
                total+=366;
            else
                total+=365;
        }
        for(int i=1;i<month_2;i++) {
            total+=getNumberOfMonthDays(year_2,i);
        }
        total+=day_2;
        for(int i=1;i<month_1;i++) {
            del+=getNumberOfMonthDays(year_1,i);
        }
        del+=day_1;
        total-=del;
        return total;
    }
    
    public static int getNumberOfMonthDays(int year,int month) {
        if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
            return 31;
        else if(month==2) {
            if(isLeapYear(year))
                return 29;
            else
                return 28;
        }
        else {
            return 30;
        }
    }
    
    public static void printMessage(String s1,String s2,int year_1,int month_1,int day_1,int year_2,int month_2,int day_2) {
        if(isTrue(s1,year_1,month_1,day_1)&&isTrue(s2,year_2,month_2,day_2)) {
            if(isTrue(s1,s2,year_1,month_1,day_1,year_2,month_2,day_2)) {
                System.out.printf(s2);
                System.out.print("与");
                System.out.printf(s1);
                System.out.print("之间相差");
                difDays(year_1,month_1,day_1,year_2,month_2,day_2);
                difMonths(year_1,month_1,day_1,year_2,month_2,day_2);
                difYears(year_1,month_1,day_1,year_2,month_2,day_2);
            }
            else {
                System.out.printf(s2);
                System.out.print("早于");
                System.out.printf(s1);
                System.out.print(",不合法!");
            }
        }
        else {
            System.out.printf(s1);
                    System.out.print("或");
                    System.out.printf(s2);
                    System.out.print("中有不合法的日期.");
        }
    }
    
    public static void difDays(int year_1,int month_1,int day_1,int year_2,int month_2,int day_2) {
        int difdays;
        difdays = getTotalNumberOfDays(year_1,month_1,day_1,year_2,month_2,day_2);
        System.out.print(difdays+"天,所在月份相差");
    }
    
    public static void difMonths(int year_1,int month_1,int day_1,int year_2,int month_2,int day_2) {
        int difmonth = month_2-month_1;
        System.out.print(difmonth+",所在年份相差");
    }
    
    public static void difYears(int year_1,int month_1,int day_1,int year_2,int month_2,int day_2) {
        int difyear = year_2-year_1;
        System.out.print(difyear+".");
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner in = new Scanner(System.in);
        String s = in.nextLine();
        String[] dates = s.split("-"); //此处以空格字符分割为例
        
        int[] date = new int[3];
        
        //遍历分割后的字符串数组并依次转型为整型
        
        for (int i = 0; i < dates.length; i++) {
        
            date[i] = Integer.parseInt(dates[i]);
        
        }
        int year = date[0];
        int month = date[1];
        int day = date[2];
        printMessage(s,year,month,day);
        String s1 = in.next();
        dates = s1.split("-");
        for (int i = 0; i < dates.length; i++) {
            
            date[i] = Integer.parseInt(dates[i]);
        
        }
        int year_1 = date[0];
        int month_1 = date[1];
        int day_1 = date[2];
        String s2 = in.next();
        dates = s2.split("-");
        for (int i = 0; i < dates.length; i++) {
            
            date[i] = Integer.parseInt(dates[i]);
        
        }
        int year_2 = date[0];
        int month_2 = date[1];
        int day_2 = date[2];
        printMessage(s1,s2,year_1,month_1,day_1,year_2,month_2,day_2);
        
    }

}

 

7-4

设计思路

这道题使用动态规划算法
其中b[i]表示有i个格子时的走法;
则状态转移方程为b[i]=b[i-1]+b[i-2]+b[i-3]+b[i-4];
优化可以得到b[i]=2*b[j-1]-b[j-5];

 

源码如下:

 

属于算法类中dfs模板题

PTA-3

7-1
设计思路

Dish类用于储存单一菜品名称与单价,并且具备接收份额输出具体价格的方法

 

Menu类使用ArrayList储存各类菜品组成菜单,具备添加菜品、根据菜名返回菜品对象、判别是否属于重命名菜品、重命名菜品的方法

Record类用于记录客户单条点餐信息,包含点餐序号,菜品以及份额,具备返回单条点餐价格的方法

Order类用于保存用户点的所有点餐信息,通过ArrayList储存Record对象,具备返回订单总价、增加单条订单,通过点餐序号删除单条订单、重新点餐。通过订单序号查找单条订单、代点餐的方法

Table类用于记录单卓信息,信息包括:桌号、订桌日期(年月日)、订桌时间(时分秒)通过ArrayList储存Order对象作为单桌点餐的全部订单。具备添加订单的方法

Tables类用于统计所有桌子的信息,通过ArrayList储存Table对象,具备输出每一桌信息的方法,信息包括:桌号、订单总价

Date类用于储存订桌日期(年月日),具备判别是否是工作日、判断某日星期的方法(采用上次PTA中对星期的判断)

Time类用于储存订桌时间(时分秒),具备通过调用日期是否是工作日返回折扣力度的方法

Main类用于接收用户输入并启动程序

类图如下:

 

 

Source Monitor代码分析

 

由分析图以及报表内容可知,代码风格就上次作业来讲,注释占比增大,但是复杂度还是没有下降,并且单类最大深度大幅增加,并且程序中最复杂的类是Main类,但是由于题目中有太多的对客户输入文本的判断所以在Main类中存在很多语句用于分析并且调用各个对象和方法,这个问题在后续的PTA作业中有所改进(单独分离出:新增菜单、新增订单、删除订单、重新编辑菜单、重新编辑订单、新增桌等方法来简便main方法;)。

 

源码如下:

 

package menu3;

import java.util.*;

class Dish{
    String name;
    int unit_price;
    
    Dish(String name,int unit_price){
        this.name = name;
        this.unit_price = unit_price;
    }
    
    int getPrcie(int portion) {            //得到单份菜品价格
        float a[] = {1,1.5f,2};
        return (int) Math.round(unit_price*a[portion-1]);
    }
}

class Menu{
    List<Dish> dishs;
    Menu(){
        this.dishs = new ArrayList<>();
    }
    Dish searthDish(String dishName) {        //通过菜名寻找菜品信息
        for(Dish dish:dishs) {
            if(dish.name.equals(dishName))
                return dish;
        }
        return null;
    }
    Dish addDish(String dishName,int unit_price) {    //新增菜品信息
        Dish dish = new Dish(dishName,unit_price);
        dishs.add(dish);
        return dish;
    }
    
    boolean isredish(String dishName) {        //判断是否重复添加一样的菜名
        boolean isfind = false;
        for(Dish dish:dishs) {
            if(dish.name.equals(dishName)){
                isfind = true;
            }
        }
        return isfind;
    }
    
    void redish(String dishName,int unit_price) {    //重新定义重复菜品的价格信息
        for(Dish dish:dishs) {
            if(dish.name.equals(dishName)){
                dish.unit_price = unit_price;
            }
        }
    }
}

class Record{        //单条订单信息
    int orderNum;    
    Dish dish;
    int portion;
    int number;
    Record(int orderNum,Dish dish,int portion,int number){
        this.orderNum = orderNum;
        this.dish = dish;
        this.portion = portion;
        this.number = number;
        
    }
    
    int getprice(){        //单条订单总价
        return dish.getPrcie(portion)*number;
    }
    
}

class Order{        //单桌总订单
    List<Record> records;
    Menu menu;
    Order(Menu menu){
        this.records = new ArrayList<>();
        this.menu = menu;
    }
    int getTotalPrice() {        //单桌订单总价
        int total = 0;
        for(Record record:records) {
            total+=record.getprice();
        }
        return total;
    }
    
    Record addARecord(int orderNum,String dishName,int portion,int number) {        //添加一条订单
        Dish dish = menu.searthDish(dishName);
        
        if(dish==null) {
            System.out.println(dishName+" does not exist");
            return null;
        }
        
        Record record = new Record(orderNum,dish,portion,number);
        if(record.number>0)
            System.out.println(record.orderNum+" "+record.dish.name+" "+record.getprice());
        records.add(record);
        return record;
    }
    
    Record addARecord(int orderNum,String dishName,int portion,int number,int paytablenum,int bepaytablenum) {
        Dish dish = menu.searthDish(dishName);
        
        if(dish==null) {
            System.out.println(dishName+" does not exist");
            return null;
        }
        
        Record record = new Record(orderNum,dish,portion,number);
        if(record.number>0)
            System.out.println(record.orderNum+" "+"table "+(paytablenum-1)+" pay for table "+bepaytablenum+" "+record.getprice());
        records.add(record);
        return record;
    }
    
    void delARecordByOrderNum(int orderNum) {        //通过订单序号删除某一条订单
        boolean isfind = true;
        for(Record record:records) {
            if(orderNum==record.orderNum) {
                record.dish.unit_price = 0;
                isfind = false;
                break;
            }
        }
        if(isfind) {
            System.out.println("delete error;");
        }
    }
    
    void reRecord(int orderNum,int portion,int number) {        //重复订单
        Record record;
        record = records.get(orderNum);
        record.portion = portion;
        record.number = number;
    }
    
    int findRecordByNum(int orderNum) {        //通过订单序号查找订单(返回订单初始序号)
        int i = 0;
        for(Record record:records) {
            if(orderNum == record.orderNum) {
                return i;
            }
            i++;
        }
        return -1;
    }
    
}

class Table{        //单桌信息
    int tablenum;
    Date date;
    Time time;
    List<Order> orders;
    
    Table(){
        this.orders = new ArrayList<>();
    }
    
     void getTable(int tablenum,Date date,Time time){        
        this.tablenum = tablenum;
        this.date = date;
        this.time = time;
    }
    
    void addOrders(Order order) {        //添加总订单
        orders.add(order);
    }
}

class Tables{        //总桌信息
    List<Table> tables;
    
    Tables(){
        this.tables = new ArrayList<>();
    }
    
    void getTables(Table table){
        tables.add(table);
    }
    
    void printTables() {        //最后输出每桌订单结果
        for(int i = 0;i<tables.size();i++) {
            double discount = tables.get(i).time.isWork(tables.get(i).date);
            if(discount==0) {
                System.out.println("table "+(i+1)+" out of opening hours");
            }
            else {
                long totalprice = Math.round(tables.get(i).orders.get(i).getTotalPrice()*discount);
                System.out.println("table "+(i+1)+": "+totalprice);
            }
        }
    }
}

class Date{        //日期
    int year;
    int month;
    int day;
    
    Date(int year,int month,int day){
        this.year = year;
        this.month = month;
        this.day = day;
    }
    boolean isWorkDay(){        //判断是否工作日
        int week = theWeekDay();
        if(week>=1&&week<=5) {
            return true;
        }
        else {
            return false;
        }
    }
    
    int theWeekDay() {        //判断星期几
        Calendar c = new GregorianCalendar(year,month-1,day);//因为一月为0
        int week= c.get(Calendar.DAY_OF_WEEK)-1;
        if(week==0)
            week=7;
        return week;
    }
}

class Time{        //时间
    int hour;
    int minute;
    int second;
    
    Time(int hour,int minute,int second){
        this.hour = hour;
        this.minute = minute;
        this.second = second;
    }
    
    double isWork(Date date) {        //判断最终折扣
        double discount;
            if(date.isWorkDay()) {
                if((hour*60+minute>=1020)&&(hour*60+minute<=1230)) {
                    discount = 0.8;
                }
                else if((hour*60+minute)>=630&&(hour*60+minute)<=870) {
                    discount = 0.6;
                }
                else {
                    discount = 0;
                }
            }
            else {
                if((hour*60+minute)>=570&&(hour*60+minute)<=1260) {
                    discount = 1;
                }
                else {
                    discount = 0;
                }
            }
            return discount;
        }
}

public class Main{
    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Menu menu = new Menu();
        Order order = new Order(menu);
        Tables tables = new Tables();
        String fline;
        while(true) {
            String line = in.nextLine();
            fline = line;
            String[] parts = line.split(" ");
            if(parts[0].equals("table")||line.equals("end")) {
                break;
            }
            String dishName = parts[0];
            int unit_price = Integer.parseInt(parts[1]);
            Dish dish = new Dish(dishName,unit_price);
            if(menu.isredish(dishName)) {
                menu.redish(dishName,unit_price);
            }else {
            menu.addDish(dishName,unit_price);
            }
            
        }
        int i = 1;
        Table table = new Table();
        while(true) {
            String[] parts = fline.split(" ");
            if(fline.equals("end")) {
                break;
            }
            else if(parts[0].equals("table")) {
                table = new Table();
                int tablenum = Integer.parseInt(parts[1]);
                String[] part = parts[2].split("/");
                int year = Integer.parseInt(part[0]);
                int month = Integer.parseInt(part[1]);
                int day = Integer.parseInt(part[2]);
                part = parts[3].split("/");
                int hour = Integer.parseInt(part[0]);
                int minute = Integer.parseInt(part[1]);
                int second = Integer.parseInt(part[2]);
                Date date = new Date(year,month,day);
                Time time = new Time(hour,minute,second);
                table.getTable(tablenum,date,time);
                tables.getTables(table);
                System.out.println("table "+i+": ");
                order = new Order(menu);
                if(i>1) {
                    while(true) {
                        String line = in.nextLine();
                        fline = line;
                        parts = line.split(" ");
                        if(parts[0].equals("1")) {
                            if(Character.isDigit((parts[1]).charAt(0))) {
                                int bepaytablenum = Integer.parseInt(parts[0]);
                                int orderNum = Integer.parseInt(parts[1]);
                                String dishName = parts[2];
                                int portion = Integer.parseInt(parts[3]);
                                int number = Integer.parseInt(parts[4]);
                                if(order.findRecordByNum(orderNum)==-1) {
                                    order.addARecord(orderNum,dishName,portion,number,i,bepaytablenum);
                                }
                                else {
                                    int reorderNum = order.findRecordByNum(orderNum);
                                    order.reRecord(reorderNum,portion,number);
                                }
                                table.addOrders(order);
                            }
                            else {
                                int orderNum = Integer.parseInt(parts[0]);
                                String dishName = parts[1];
                                int portion = Integer.parseInt(parts[2]);
                                int number = Integer.parseInt(parts[3]);
                                if(order.findRecordByNum(orderNum)==-1) {
                                    order.addARecord(orderNum,dishName,portion,number);
                                }
                                else {
                                    int reorderNum = order.findRecordByNum(orderNum);
                                    order.reRecord(reorderNum,portion,number);
                                }
                                table.addOrders(order);
                            }
                            break;
                        }
                            
                        String dishName = parts[0];
                        int unit_price = Integer.parseInt(parts[1]);
                        Dish dish = new Dish(dishName,unit_price);
                        if(menu.isredish(dishName)) {
                            menu.redish(dishName,unit_price);
                        }else {
                        menu.addDish(dishName,unit_price);
                        }
                        
                    }
                }
                i++;
            }
            else if(parts[1].equals("delete")) {
                int reorderNum = Integer.parseInt(parts[0]);
                order.delARecordByOrderNum(reorderNum);
                fline = in.nextLine();
                continue;
            }
            else
            {
                if(Character.isDigit((parts[1]).charAt(0))) {
                    int bepaytablenum = Integer.parseInt(parts[0]);
                    int orderNum = Integer.parseInt(parts[1]);
                    String dishName = parts[2];
                    int portion = Integer.parseInt(parts[3]);
                    int number = Integer.parseInt(parts[4]);
                    if(order.findRecordByNum(orderNum)==-1) {
                        order.addARecord(orderNum,dishName,portion,number,i,bepaytablenum);
                    }
                    else {
                        int reorderNum = order.findRecordByNum(orderNum);
                        order.reRecord(reorderNum,portion,number);
                    }
                    table.addOrders(order);
                }
                else {
                    int orderNum = Integer.parseInt(parts[0]);
                    String dishName = parts[1];
                    int portion = Integer.parseInt(parts[2]);
                    int number = Integer.parseInt(parts[3]);
                    if(order.findRecordByNum(orderNum)==-1) {
                        order.addARecord(orderNum,dishName,portion,number);
                    }
                    else {
                        int reorderNum = order.findRecordByNum(orderNum);
                        order.reRecord(reorderNum,portion,number);
                    }
                    table.addOrders(order);
                }
            }
            fline = in.nextLine();
        }
        tables.printTables();
    }
}

 

踩坑心得

PTA-2

7-1

对于输入订单份额后的计算,由于没有使用四舍五入的方式转换数据导致输出的结果有所偏差,初始代码如下:

 

 

经过查询后很容易找到了解决办法,调用Math类中的round()方法实现数据的四舍五入,这是修改后的代码:

7-2

1)由于此次作业要求自己输入菜单,以及订单,所以运用普通的数组进行储存,由于不清楚菜品数量或者订单数量导致出现运行时异常的情况发生,最后采用ArrayList(动态数组)的数据结构进行储存,方便快捷

2) 在对客户输入的数据进行处理分析时,很难判断什么时候菜单输入停止,什么时候订单输入停止,以及什么时候时进行删除订单操作,如果只是延续上次作业的方法会出现输入异常的情况。故对代码进行以下改进:

 

通过储存每一次输入的字符串,再用String类中的split()方法将整行用“ ”截断存在一个字符串数组parts中,从而解决了无法分析输入数据的问题

3) 对于重复出现的菜名,需要更改的只是单价所以用一个for-each的循环找到同名菜品更改单价即可

7-3

1)一开始没有注意格式的非法性导致最初提交的代码通过的测试点很少,后来经过不断地测试发现日期必须由两位表示但是月份不需要两位表示,如图:

最后采用从后往前遍历找到一个-”符号时记录“-”到最后一个字符的长度,如果小于2,说明日期是用个位数表示的,非法,更改后部分代码如图:

2)对于某日星期几的判断本来是按照书本上的内容进行判断但是每次都有误差,不具有普遍性所以经过上网浏览找到了一种不错的方法,是使用Calendar类中的方法判断,如下:

 

PTA-3

7-1

新增带点餐模式,要把订单记录在他桌但是钱还是要由本桌人记账,解决方式如下:

 

主要困难以及改进建议

1) 刚开始对给出的样例的数据处理起来有点困难,比如无法区别出到哪里是进行菜单的输入,哪里是进行订单的输入,后面通过String类中的split()方法解决了类似的问题;

2) 再者就是订单和总订单中之间的关系,以及单桌和总桌之间的联系会比较难以解决,并且在进行订单价格计算的时候会比较繁琐,而且一开始有一个很不好的习惯,就是上手直接进行编码,但是后面发现先画出类图,理清思路可以提升编码效率,也可以让代码的质量更高;

3) 对于一些细节上的错误,类似于没有关系到四舍五入的情况,以及在编码时一直出现有空指针应用的情况,后面发现是忘记了对声明的List结果进行初始化new,所以对于后期的改进想法就是在每一个类写出后,先把构造函数写出来,并在里面将需要用到的类实例化成对象之后在进行后续的编码;

4) 在所有我写的这一系列的菜单系统中,都存在一个很大的问题,通过Source Monitor代码分析也可以看出,在所有类中Main类是最复杂的,而在Main类中最复杂的也是main函数,但是在学习编程最开始就学过,main中是用来启动程序的,应该尽量少放功能性的方法,所以,为了使后续系统开发中Main方法更加便捷,要合理改善程序结构,让main方法轻量化。

总结

收获

从这三次题目集中,我收获了很多很多,其中令我印象深刻的还是菜单计价程序系列(毕竟都要陪伴我一个学期了),从这系列中的这三次中我经历了三个主要阶段:

第一阶段:我初识面向对象编程语言,菜单计价-1让我实际学会了应该如何从类与对象的角度去思考,去解决问题:

  1. 首先分析问题涉及到的类,如:菜品、菜单、订单、总订单等

  2. 分析各类所具有的特性,如:菜品具备名称、单价、各个份额对应的价格;菜单应该包含所有菜品信息;订单应该包含菜品类别以及用户需要的份数;总订单应该包含各个订单的信息以及具备输出总价的功能;

  3. 通过数组或者ArrayList结构将有包含关系的两个类联系到一起,比如菜单中包含菜品,所以在菜单中建立结构储存菜品,订单与总订单同理;

  4. 通过合适的方法对输入的数据处理然后对类实例化,合理调用各个类中的方法解决问题

第二阶段:我对面向对象编程的思想已经比较熟练,开始对第一次程序优化新增内容,从菜单计价-2以及日历我学会了一些类似ArrayListCalendar类,Math类等内部类的使用,带来了很大的方便

第三阶段:我又接触到String内部类中的方法如split()等,也知道了一些进阶的语法,例如重构函数等,也让我的代码更加简洁

改进建议与意见

对于三次作业我觉的有一点可以更加优化,在答题期间内可以隐藏所有的测试点数据,但是在答题时间过后,公开所有测试点的具体数据,这样既可以在锻炼大家在答题时的思维能力,看待问题的全面性,还可以有助于同学们在之后回顾问题,总结经验不断改进。最好是还可以实行补题的方案,及时的纠错和改正更有利于同学不断完善自己的能力。

 

posted @ 2023-05-23 23:53  啊呸930  阅读(12)  评论(0)    收藏  举报