PTA4,5及期中总结

发布时间 2023-06-30 19:46:09作者: 鸣灏

1,前言

PTA4,5还是继续之前的菜单计价程序,只是在1,2,3的基础上加以完善,增加了更多的新的功能,期中考试则是在测试考核面向对象及接口,继承和多态以及抽象类等等知识点、

2,设计与分析

 菜单计价程序-4 类图

 

 

 第一次的课程成绩统计程序较为直观,题目要求中直接给了相关的类图,以及需要构造的相关类,在按照土题目的相关要求即可较为完整的实现成绩统计的功能,在本次课程统计的编写中运用ArrayList以及正则表达式即可克服相关难点,实现相关功能。

菜单计价程序-5 类图

 

 

期中考试类图 类图

 

 

 

3,踩坑心得

源码:

public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
ArrayList<Shape> list = new ArrayList<>();

int choice = input.nextInt();

while (choice != 0) {
switch (choice) {
case 1://Circle
double radium = input.nextDouble();
Shape circle = new Circle(radium);
list.add(circle);
break;
case 2://Rectangle
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double x2 = input.nextDouble();
double y2 = input.nextDouble();
Point leftTopPoint = new Point(x1, y1);
Point lowerRightPoint = new Point(x2, y2);
Rectangle rectangle = new Rectangle(leftTopPoint, lowerRightPoint);
list.add(rectangle);
break;
}
choice = input.nextInt();
}
list.sort(new Comparator<Shape>() {
public int compare(Shape o1, Shape o2) {
return (int) (o1.getArea() - o2.getArea());
}
});//正向排序

for (int i = 0; i < list.size(); i++) {
System.out.print(String.format("%.2f", list.get(i).getArea()) + " ");
}
}

public static void printArea(Shape shape) {
System.out.printf("%.2f", shape.getArea());
}
}

abstract class Shape {
public Shape() {
}

abstract double getArea();
}

class Point {
double x;
double y;

public Point() {
}

public Point(double x, double y) {
this.x = x;
this.y = y;
}

public double getX() {
return x;
}

public void setX(double x) {
this.x = x;
}

public double getY() {
return y;
}

public void setY(double y) {
this.y = y;
}
}


class Rectangle extends Shape {
private Point topLeftPoint;
private Point lowerRightPoint;

public Rectangle() {
}

public Rectangle(Point topLeftPoint, Point lowerRightPoint) {
this.topLeftPoint = topLeftPoint;
this.lowerRightPoint = lowerRightPoint;
}

public void setLeftPoint(Point topLeftPoint) {
this.topLeftPoint = topLeftPoint;
}

public Point getTopLeftPoint() {
return this.topLeftPoint;
}

public Point getLowerRightPoint() {
return this.lowerRightPoint;
}

public void setLowerRightPoint(Point lowerRightPoint) {
this.lowerRightPoint = lowerRightPoint;
}

public double getLength() {
return Math.abs(lowerRightPoint.x - topLeftPoint.x);
}

public double getHeight() {
return Math.abs(topLeftPoint.y - lowerRightPoint.y);
}

@Override
public double getArea() {
return getLength() * getHeight();
}
}

class Circle extends Shape {
double radium;

public Circle(double radium) {
this.radium = radium;
}

public double getRadium() {
return radium;
}

public void setRadium(double radium) {
this.radium = radium;
}

@Override
public double getArea() {
return radium * radium * Math.PI;
}
}

 

 

 

 

 

package PTA5;

import java.time.DateTimeException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Objects;
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Menu menu = new Menu();
ArrayList<Table> tables = new ArrayList<>();
ArrayList<User> users = new ArrayList<>();
Scanner in = new Scanner(System.in);
String str;
int i;
while (true) {// 输入菜单
Dish temp = new Dish();
int isRepeat;
str = in.nextLine();
if (str.matches("[\\S]* [\\S]* [\\d]* T")) {
String[] information = str.split(" ");
temp.name = information[0];
temp.unit_price = Integer.parseInt(information[2]);
if (temp.unit_price > 300) {
System.out.println(temp.name + " price out of range " + temp.unit_price);
continue;
}
temp.isT = true;
switch (information[1]) {
case "川菜":
temp.DishRange = "spicy";
temp.MaxFlavor = 5;
break;
case "晋菜":
temp.DishRange = "acidity";
temp.MaxFlavor = 4;
break;
case "浙菜":
temp.DishRange = "sweetness";
temp.MaxFlavor = 3;
break;
}
isRepeat = menu.searchDish(temp.name);
if (isRepeat != -1) {
menu.dishes.remove(isRepeat);
}
menu.dishes.add(temp);
} else if (str.matches("[\\S]* [1-9][\\d]*")) {
String[] information = str.split(" ");
temp.name = information[0];
temp.unit_price = Integer.parseInt(information[1]);
if (temp.unit_price > 300) {
System.out.println(temp.name + " price out of range " + temp.unit_price);
continue;
}
temp.isT = false;
isRepeat = menu.searchDish(temp.name);
if (isRepeat != -1) {
menu.dishes.remove(isRepeat);
}
menu.dishes.add(temp);
} else if (str.equals("end")) {
break;
} else if (str.matches("tab.*")) {
break;
} else {
System.out.println("wrong format");
}
}
while (!str.equals("end")) {
Table temp = new Table();
boolean isRepeat = false;
int repeatNum = 0;
if (str.matches(".*t.*a.*")) {
if (str.matches("table [1-9][\\d]* : [\\S]* [\\d]* [\\d]*/[\\d][\\d]?/[\\d][\\d]? [\\d][\\d]?/[\\d][\\d]?/[\\d][\\d]?")) {
String[] information = str.split(" ");
temp.userName = information[3];
if (information[3].length() > 10) {
str = in.nextLine();//读入order信息但不处理,直到读入table信息
System.out.println("wrong format");
continue;
}
temp.callNum = information[4];
if (information[4].length() != 11) {
str = in.nextLine();
System.out.println("wrong format");
continue;
}
String head = information[4].substring(0, 3);
if (!head.equals("180") && !head.equals("181") && !head.equals("189") && !head.equals("133") && !head.equals("135") && !head.equals("136")) {
str = in.nextLine();
System.out.println("wrong format");
continue;
}
String[] Date = information[5].split("/");
String[] Time = information[6].split("/");
int[] intDate = new int[5];
int[] intTime = new int[6];
for (i = 0; i < 3; i++) {
intDate[i] = Integer.parseInt(Date[i]);
intTime[i] = Integer.parseInt(Time[i]);
}
temp.num = Integer.parseInt(information[1]);
if (temp.num > 55) {
System.out.println(temp.num + " table num out of range");
str = in.nextLine();
continue;
}
try {
temp.time = LocalDateTime.of(intDate[0], intDate[1], intDate[2], intTime[0], intTime[1],
intTime[2]);
temp.getWeekDay();
} catch (DateTimeException e) {
System.out.println(temp.num + " date error");
str = in.nextLine();
continue;
}
if (!temp.isOpen()) {
System.out.println("table " + temp.num + " out of opening hours");
str = in.nextLine();
continue;
}
if (!(temp.time.isAfter(LocalDateTime.of(2022, 1, 1, 0, 0, 0)) && temp.time.isBefore(LocalDateTime.of(2024, 1, 1, 0, 0, 0)))) {
System.out.println("not a valid time period");
str = in.nextLine();
continue;
}
// 判断桌号是否重复
if (temp.isOpen()) {
for (i = 0; i < tables.size(); i++) {
// 有重复的桌号
if (temp.num == tables.get(i).num && tables.get(i).isOpen()) {
Duration duration = Duration.between(temp.time, tables.get(i).time);
// 同一天
if (duration.toDays() == 0) {
// 在周一到周五
if (temp.weekday > 0 && temp.weekday < 6) {
// 在同一时间段
if (temp.time.getHour() < 15 && tables.get(i).time.getHour() < 15) {
isRepeat = true;
repeatNum = i;
break;
}
}
// 在周末
else {
// 时间相差小于一小时
if (duration.toHours() < 3600) {
repeatNum = i;
isRepeat = true;
break;
}
}
}
}
}
}
System.out.println("table " + temp.num + ": ");

} else {
System.out.println("wrong format");
str = in.nextLine();
continue;
}

int portion, quotation;
// 本桌开始点菜
while (true) {
str = in.nextLine();
//判断是否为非特色菜
if (str.matches("[1-9][\\d]* [\\S]* [\\d] [1-9][\\d]*")) {
String[] information = str.split(" ");
portion = Integer.parseInt(information[2]);
quotation = Integer.parseInt(information[3]);
if (menu.searchDish(information[1]) == -1) {
System.out.println(information[1] + " does not exist");
continue;
}
Record tempRecord = new Record();
tempRecord.dishes = menu.dishes.get(menu.searchDish(information[1]));
tempRecord.orderNum = Integer.parseInt(information[0]);
tempRecord.portion = portion;
tempRecord.quota = quotation;
temp.records.add(tempRecord);
System.out.println(tempRecord.orderNum + " " + information[1] + " " + tempRecord.getPrice());
}
//判断是否为特色菜
else if (str.matches("[1-9][\\d]* [\\S]* [\\d] [\\d] [1-9][\\d]*")) {
String[] information = str.split(" ");
int FlavorNum = Integer.parseInt(information[2]);
if (FlavorNum < 0 || FlavorNum > menu.dishes.get(menu.searchDish(information[1])).MaxFlavor) {
System.out.println(menu.dishes.get(menu.searchDish(information[1])).DishRange + " num out of range :" + FlavorNum);
continue;
}
portion = Integer.parseInt(information[3]);
quotation = Integer.parseInt(information[4]);
if (menu.searchDish(information[1]) == -1) {
System.out.println(information[1] + " does not exist");
continue;
}
Record tempRecord = new Record();
tempRecord.dishes = menu.dishes.get(menu.searchDish(information[1]));
tempRecord.FlavorNum = FlavorNum;
tempRecord.orderNum = Integer.parseInt(information[0]);
tempRecord.portion = portion;
tempRecord.quota = quotation;
temp.records.add(tempRecord);
System.out.println(tempRecord.orderNum + " " + information[1] + " " + tempRecord.getPrice());
}
// 判断是否为删除订单
else if (str.matches("[1-9][\\d]* delete")) {
String[] information = str.split(" ");
int delNum = Integer.parseInt(information[0]);
for (i = 0; i < temp.records.size(); i++) {
if (temp.records.get(i).orderNum == delNum) {
if (!temp.records.get(delNum).isDeleted) {
temp.records.get(delNum).isDeleted = true;
} else System.out.println("deduplication :" + delNum);
break;
}
if (i == temp.records.size() - 1) System.out.println("delete error");
}

}
// 判断是否为夹杂菜单
else if (str.matches("[\\S]* [\\d]*")) {
System.out.println("invalid dish");
} else if (str.matches("[\\S]* [\\S]* [\\d]* T")) {
System.out.println("invalid dish");
}
// 判断是否为代点
else if (str.matches("[\\d]* [\\d]* [\\S].*")) {
String[] information = str.split(" ");
// 判断代点桌号是否存在
boolean exist = false;
int j;
for (j = 0; j < tables.size(); j++) {
if (tables.get(j).num == Integer.parseInt(information[0])) {
exist = true;
break;
}
}
if (exist) {
System.out.print(Integer.parseInt(information[1]) + " table " + temp.num + " pay for table " + Integer.parseInt(information[0]) + " ");
Record treat = new Record();
treat.dishes = menu.dishes.get(menu.searchDish(information[2]));
if (treat.dishes.isT) {
treat.FlavorNum = Integer.parseInt(information[3]);
treat.portion = Integer.parseInt(information[4]);
treat.quota = Integer.parseInt(information[5]);
if (treat.dishes.DishRange.equals("spicy")) {
tables.get(j).ChuanNum += treat.quota;
tables.get(j).spicyType += treat.FlavorNum * treat.quota;
}
if (treat.dishes.DishRange.equals("acidity")) {
tables.get(j).JinNum += treat.quota;
tables.get(j).spicyType += treat.FlavorNum * treat.quota;
}
if (treat.dishes.DishRange.equals("sweetness")) {
tables.get(j).ZheNum += treat.quota;
tables.get(j).spicyType += treat.FlavorNum * treat.quota;
}
} else {
treat.portion = Integer.parseInt(information[3]);
treat.quota = Integer.parseInt(information[4]);
}
System.out.print(treat.getPrice() + "\n");
treat.isTreat = true;
temp.records.add(treat);
}
// 若不存在则输出内容
else {
System.out.println("Table number :" + Integer.parseInt(information[0]) + " does not exist");
}

} else if (str.equals("end")) {
break;
} else if (str.matches("table.*")) {
break;
} else {
System.out.println("wrong format");
}
}
// 本桌点菜结束,进入下一桌
if (isRepeat) {
for (i = 0; i < tables.get(repeatNum).records.size(); i++) {
for (int j = 0; j < temp.records.size(); j++) {
if (Objects.equals(tables.get(repeatNum).records.get(i).dishes.name, temp.records.get(j).dishes.name)) {
if (tables.get(repeatNum).records.get(i).portion == temp.records.get(j).portion) {
tables.get(repeatNum).records.get(i).quota += temp.records.get(j).quota;
temp.records.remove(j);
}
}
}
}
tables.get(repeatNum).records.addAll(temp.records);
continue;
}
tables.add(temp);
} else {
str = in.nextLine();
}
}

// 最终输出桌号订单信息
for (i = 0; i < tables.size(); i++) {
if (tables.get(i).isOpen()) {
tables.get(i).getSum();
tables.get(i).getFlavorNum();
if (i != 0) System.out.print("\n");
tables.get(i).showEnd();
boolean isRepeat = false;
for (int j = 0; j < users.size(); j++) {
if (tables.get(i).userName.equals(users.get(j).userName)) {
users.get(j).paidMoney += tables.get(i).sum;
isRepeat = true;
break;
}
}
if (!isRepeat) {
User tempUser = new User();
tempUser.userName = tables.get(i).userName;
tempUser.callNum = tables.get(i).callNum;
tempUser.paidMoney = tables.get(i).sum;
users.add(tempUser);
}
}
}
users.sort(Comparator.comparing(a -> a.userName));
for (i = 0; i < users.size(); i++) {
if (users.get(i).paidMoney == 0)
System.out.print("\n0");
else
System.out.print("\n" + users.get(i).userName + " " + users.get(i).callNum + " " + users.get(i).paidMoney);
}
}

static class Dish {
String name;
String DishRange;
int MaxFlavor;
int unit_price;
boolean isT = false;
}

static class Record {
int orderNum;
Dish dishes;
int FlavorNum;
int portion;
int quota;
boolean isDeleted = false;
boolean isTreat = false;

int getPrice() {
if (portion == 2)
return (int) Math.round(1.5 * dishes.unit_price) * quota;
else if (portion == 3)
return 2 * dishes.unit_price * quota;
else
return dishes.unit_price * quota;
}
}

static class Menu {
ArrayList<Dish> dishes = new ArrayList<>();

int searchDish(String dishName) {
for (int i = 0; i < dishes.size(); i++) {
if (dishName.equals(dishes.get(i).name)) {
return i;
}
}
return -1;
}

}

static class User {
String userName;
String callNum;
long paidMoney;
}

static class Table {
ArrayList<Record> records = new ArrayList<>();
int num;
String userName;
String callNum;
LocalDateTime time;
int weekday;
int ChuanNum = 0;
float spicyType = 0;
int JinNum = 0;
float acidType = 0;
int ZheNum = 0;
float sweetType = 0;
long sum = 0;
long origSum = 0;

void getWeekDay() {
weekday = time.getDayOfWeek().getValue();
}

void getFlavorNum() {
for (int i = 0; i < records.size(); i++) {
if (records.get(i).dishes.isT && !records.get(i).isDeleted && !records.get(i).isTreat) {
if (records.get(i).dishes.DishRange.equals("spicy")) {
ChuanNum += records.get(i).quota;
spicyType += records.get(i).FlavorNum * records.get(i).quota;
}
if (records.get(i).dishes.DishRange.equals("acidity")) {
JinNum += records.get(i).quota;
acidType += records.get(i).FlavorNum * records.get(i).quota;
}
if (records.get(i).dishes.DishRange.equals("sweetness")) {
ZheNum += records.get(i).quota;
sweetType += records.get(i).FlavorNum * records.get(i).quota;
}
}
}
if (ChuanNum != 0) spicyType = Math.round(spicyType / ChuanNum * 1.0);
if (JinNum != 0) acidType = Math.round(acidType / JinNum * 1.0);
if (ZheNum != 0) sweetType = Math.round(sweetType / ZheNum * 1.0);
}

void showEnd() {
System.out.print("table " + num + ": " + origSum + " " + sum);
//输出川菜
if (ChuanNum != 0) {
System.out.print(" 川菜 " + ChuanNum);
switch ((int) spicyType) {
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;
}
}
//输出晋菜
if (JinNum != 0) {
System.out.print(" 晋菜 " + JinNum);
switch ((int) acidType) {
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;
}
}
//输出浙菜
if (ZheNum != 0) {
System.out.print(" 浙菜 " + ZheNum);
switch ((int) sweetType) {
case 0:
System.out.print(" 不甜");
break;
case 1:
System.out.print(" 微甜");
break;
case 2:
System.out.print(" 稍甜");
break;
case 3:
System.out.print(" 甜");
break;
}
}

}

void getSum() {
for (int i = 0; i < records.size(); i++) {
if (!records.get(i).isDeleted) {
origSum += records.get(i).getPrice();
if (records.get(i).dishes.isT) {
if (weekday > 0 && weekday < 6) {
sum += Math.round(records.get(i).getPrice() * 0.7);
} else {
sum += records.get(i).getPrice();
}
} else {
if (weekday > 0 && weekday < 6) {
if (time.getHour() >= 17 && time.getHour() < 20)
sum += Math.round(records.get(i).getPrice() * 0.8);
if (time.getHour() == 20) {
if (time.getMinute() <= 30)
sum += Math.round(records.get(i).getPrice() * 0.8);
}
if (time.getHour() >= 10 && time.getHour() < 14)
sum += Math.round(records.get(i).getPrice() * 0.6);
if (time.getHour() == 14) {
if (time.getMinute() <= 30)
sum += Math.round(records.get(i).getPrice() * 0.6);
}
} else
sum += records.get(i).getPrice();
}
}
}

}

boolean isOpen() {
if (weekday > 0 && weekday < 6) {
if (time.getHour() >= 17 && time.getHour() < 20)
return true;
if (time.getHour() == 20) {
if (time.getMinute() <= 30)
return true;
}
if (time.getHour() > 10 && time.getHour() < 14)
return true;
if (time.getHour() == 10) {
if (time.getMinute() >= 30)
return true;
}
if (time.getHour() == 14) {
return time.getMinute() <= 30;
}
} else {
if (time.getHour() > 9 && time.getHour() < 21)
return true;
if (time.getHour() == 9) {
if (time.getMinute() >= 30)
return true;
}
if (time.getHour() == 21) {
return time.getMinute() <= 30;
}
}
return false;

}
}
}
 
 
 

最先我尝试过对每个格式采取逐个相等的方法,过程相当麻烦,最后甚至超过了PTA的最大限度,测试点确实是能过,但是格式错误无法从根本上解决,在使用正则表达式后代码明显简洁了许多,并且解决了格式错误的问题;

我个人认为还是比较符合面向对象的思想,最后还是有些测试点解决不了,改进了几次,最后方案为,先进行格式判断,正确之后无论对错都添加进链表中,再经过一系列方法的筛选,最后打印出结果;

改进建议

测试点太多了,导致Main函数中的判断代码量太大,在deBug是大大增加了改进的难度性,同时复用性大大降低。

总结

本次作业,我个人进步最大的地方是学习了几个设计模式来辅助自己设计,这让我代码整体结构比较好,思路清晰,逻辑严谨。

本次实验中第一次接触了正则表达式,也体会到了正则表达式的强大,正则的效率挺高的,在很多情况下都能用到,对正则表达式更加熟练了;

但是,我还有许多地方有待进步,比如测试环节。设计模式也需要抓紧时间学习。