前三次作业总结blog
前言:
第4-6次作业题量不大,主要是四次菜单问题的迭代,难度比较大,第四次作业是菜单二和三,难度比较大主要是要分析到各种不同的情况,以满足题目要求,第五次作业和第六次作业都是在菜单三的基础上升级,其中第五次作业的菜单四相比于菜单三多了很多异常处理,会用到,try-catch语句。而菜单五相比于菜单四我觉得难度更小,它在菜单三的基础上增加了很多功能只要分析到位就可以很好解决。
设计与分析:
下面对个别具有代表性题目进行分析:
7-4 菜单计价程序-2
相关类图:
相关类代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// Dish[] dish = new Dish[10086];
// Record[] record = new Record[10086];
String[] d = new String[10086];//存放原始输入信息
//String[] e = new String[10086];//存放菜品记录
//String[] f = new String[10086];//存放点菜记录
//String[] g = new String[10086];//存放删除信息
Menu menu = new Menu();
Order order = new Order();
int i = 0,r=0,o=0;
Scanner input = new Scanner(System.in);
//将输入信息存入字符串数组
while (true) {
d[i] = input.nextLine();
if (d[i].equals("end")) {
break;
}
i++;
}
for(int j=0;j<i;j++)
{
String[] str = d[j].split(" ");
char lastchar=str[str.length-1].charAt(0);
if(str.length==2&&Character.isDigit(lastchar))
{
String name = str[0];
int unit_price = Integer.parseInt(str[1]);
menu.dishs[o]=new Dish();
menu.dishs[o]=menu.addDish(name, unit_price);
//System.out.println(menu.dishs[o].name+menu.dishs[o].unit_price);
o++;
}
else if(str.length==4)
{
int orderNum = Integer.parseInt(str[0]);
String dishname = str[1];
int portion = Integer.parseInt(str[2]);
int num = Integer.parseInt(str[3]);
// System.out.println(orderNum+" "+dishname+" "+portion+" "+num+"\n");
order.addARecord(orderNum, dishname, portion, num, menu);
r++;
}
else if(str.length==2&&Character.isLetter(lastchar))
{
int deletenumber = Integer.parseInt(str[0]);
// System.out.println(deletenumber+"\n");
order.delARecordByOrderNum(deletenumber,menu);//根据序号删除
}
}
/*
for (int m = 0; order.records[m]!=null; m++) {
Dish fdish=new Dish();
if(order.records[m].d==null)
{order.records[m].d=new Dish();}
fdish = menu.searthDish(order.records[m].d.name);
if (fdish == null) {
System.out.println(order.records[m].d.name + "does not exist");
} else {
System.out.println(order.records[m].orderNum+order.records[m].d.name+order.records[m].getPrice());
}
}*/
for (int y=0;y<r;y++)
{
// System.out.println(order.records[y].orderNum+" "+order.records[y].number+"\n");
}
System.out.print(order.getTotalPrice());
}
}
class Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion,int unit_price)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
{
int price = (int) Math.round((1 + (portion - 1) * 0.5) * unit_price);
return price;
}
}
class Menu {
Dish[] dishs = new Dish[100] ;//菜品数组,保存所有菜品信息
int i = 0;
/* public Menu() {
}
*/
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
{
for (int x=0;x<i;x++)
{
if( dishs[x]!=null)
{
if ( dishName.equals(dishs[x].name)) { // 判断 dish 是否为 null
return dishs[x];
}
}
}
return null;
}
int searthDish1(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
{
for (int x=0;x<i;x++)
{
if( dishs[x]!=null) {
if (dishName.equals(dishs[x].name)) { // 判断 dish 是否为 null
return x;
}
}
}
return -1;
}
Dish addDish(String dishName, int unit_price)//添加一道菜品信息
{
int x=-2;
x=searthDish1(dishName);
if(x==-1){
dishs[i].name = dishName;
dishs[i].unit_price = unit_price;
i++;}
else
{ dishs[x].name = dishName;
dishs[x].unit_price = unit_price;
}
return dishs[i-1];
}
}
class Record {
int orderNum;//序号\
Dish d=new Dish();//菜品\
int portion;//份额(1/2/3代表小/中/大份)\
int number;//份数;
int getPrice()//计价,计算本条记录的价格\
{
int price = number * d.getPrice(portion,d.unit_price);
return price;
}
}
class Order {
Record[] records=new Record[100];//保存订单上每一道的记录
int i = -1;
public Order() {
}
int getTotalPrice()//计算订单的总价
{
int price = 0;
for (int j=0;records[j]!=null;j++) {
price += records[j].getPrice();
}
return price;
}
Record addARecord(int orderNum, String dishName, int portion, int num, Menu menu)//添加一条菜品信息到订单中。
{
i++;
records[i] = new Record();// 创建 Record 对象
records[i].d=new Dish();
records[i].orderNum = orderNum;
records[i].portion = portion;
records[i].number = num;
if(menu.searthDish(dishName)==null)
{
System.out.print(dishName+" does not exist\n");
}
else
{
records[i].d= menu.searthDish(dishName);
System.out.print(orderNum+" "+dishName+" "+records[i].getPrice()+"\n");
}
return records[i];
}
void delARecordByOrderNum(int orderNum,Menu menu)//根据序号删除一条记录
{
int j;
for ( j = 0;records[j]!=null; j++) {
if (records[j].orderNum == orderNum)
{
if(records[j].d.name==null)
{
// System.out.print("delete error;\n");
}
else
{
/*
for (int k = j; records[k + 1] != null; k++) {
records[k] = records[k + 1];
records[k]
records[records.length - 1] = null;
}
*/
records[j].number=0;
}
}
}
if(j<orderNum){
System.out.print("delete error;\n");
}
}
Record findRecordByNum(int orderNum)//根据序号查找一条记录
{
for (int j = 0; j < records.length; j++) {
if (records[j].number == orderNum) {
return records[j];
}
}
records[10086].number = 10086;
return records[10086];
}
}
分析:从类图和时间空间复杂度分析可以看出它包含了四个类:Dish(菜品)、Menu(菜单)、Record(记录)和Order(订单)。
Dish类:
属性:name(菜品名称)、unit_price(单价)
方法:getPrice(),根据菜品的份额和单价计算价格
Menu类:
属性:dishs(菜品数组)
方法:searthDish(),根据菜名在菜谱中查找菜品信息;searthDish1(),根据菜名在菜谱中查找菜品信息并返回索引;addDish(),添加一道菜品信息到菜单中
Record类:
属性:orderNum(序号)、d(菜品对象)、portion(份额)、number(份数)
方法:getPrice(),计算本条记录的价格
Order类:
属性:records(记录数组)
方法:getTotalPrice(),计算订单的总价;addARecord(),向订单中添加一条菜品记录;delARecordByOrderNum(),根据序号删除一条记录;findRecordByNum(),根据序号查找一条记录
7-1 菜单计价程序-3
相关类图:
分析:通过类图可以看出此代码包括
Dish类:
该类表示菜品,包括菜品名称和单价,以及计算菜品价格的方法。但是在 getPrice 方法中只允许输入 1/2/3,代表小/中/大份,这种硬编码的方式不够灵活,可以考虑使用枚举类型来表示份额。
Menu类:
用于管理所有菜品信息,包括添加菜品和根据菜名查找菜品信息等功能。但是在添加菜品时,使用了数组来保存菜品信息,没有考虑到扩容的问题,如果菜品数量超过1000个会出现数组越界的问题。
Record类:
表示订单中的一条记录,包括菜品、序号、份额、份数等信息,可以计算本条记录的价格。但是属性命名不够清晰,不易理解每个属性的含义,推荐改进属性命名。
Order类:
表示一个订单,包括保存订单上每一道菜品的记录、计算订单的总价、添加菜品信息到订单中、根据序号删除一条记录等功能。在添加记录和计算订单总价的过程中,代码逻辑比较混乱,建议进行简化和优化。
Main类:
包含主程序入口,实现了具体的点餐逻辑和桌号管理。但是代码结构比较混乱,逻辑相对复杂,可以考虑将部分功能抽离成单独的方法或类来提高可读性和维护性。
table类:
表示一张餐桌,包括桌号、点菜时间、计算总价、判断时间是否在营业时间内等功能。在计算总价和判断营业时间的逻辑中,存在硬编码的问题,应该将这些逻辑提取成单独的方法或常量以提高可维护性。
菜单计价程序-4
相关类图:
分析:菜品类(Food)
属性:
name:菜品名称
price:菜品价格
菜谱类(Menu)
属性:
foods:菜谱中包含的菜品列表
方法:
addFood(Food food):将菜品添加到菜谱中
removeFood(Food food):从菜谱中移除指定的菜品
点菜记录类(OrderRecord)
属性:
food:被点的菜品
quantity:点菜的数量
订单类(Order)
属性:
orderRecords:订单中包含的点菜记录列表
方法:
addOrderRecord(OrderRecord record):将点菜记录添加到订单中
removeOrderRecord(OrderRecord record):从订单中移除指定的点菜记录
calculateTotalPrice():计算订单的总价格
属性:
tableNumber:桌号
orders:桌子上的订单列表
方法:
addOrder(Order order):将订单添加到桌子上
removeOrder(Order order):从桌子上移除指定的订单
错误判断类(ErrorChecking)
方法:
checkValidInput(String input):检查用户输入是否有效
这些类主要通过属性和方法的组合来实现餐厅点餐系统的功能。其中,菜品类表示一个具体的菜品,菜谱类管理菜谱信息,点菜记录类记录点菜信息,订单类表示一个具体的订单,桌子类表示一个具体的桌子,错误判断类用于检查用户输入的有效性。
通过这些类和方法的组合使用,可以实现点菜、加桌、删菜等功能。
7-1 菜单计价程序-5
相关类图
首先,我们看到了 Dish 类。这个类用于表示菜品,包括菜品名称、口味、单价等属性,以及计算菜品价格的方法。这个类的设计相对清晰,但是可能需要注意的是口味和等级的表示方式,可能需要进一步的说明或者使用枚举类型来表示。
接下来是 Menu 类,它用于管理菜单,包括菜品数组,保存所有菜品信息,并提供了添加菜品、查找菜品等方法。这个类的设计也比较合理,但在实际应用中可能需要考虑更高效的菜品查找方式。
然后是 Record 类,用于表示订单中的每一道菜品的记录,包括菜品、序号、口味、等级、份额等属性,并提供了计价的方法。这个类的设计也比较清晰,但可能需要注意口味和等级的表示方式,以及计价方法的实现逻辑。
接着是 Order 类,用于保存订单上每一道的记录,并提供了添加记录、删除记录、计算总价等方法。这个类的设计也比较合理,但可能需要注意记录的管理方式,以及计算总价的逻辑。
然后是 Table 类,表示餐桌,包括桌号、顾客信息、时间等属性,并提供了判断时间是否正确的方法。这个类的设计也比较清晰,但可能需要考虑更全面的餐桌状态管理。
最后是 Customer 类,表示顾客信息,包括姓名、电话、支付金额等属性。这个类的设计也比较简单清晰。
7-1 测验1-圆类设计
相关类代码import java.util.Scanner;
class Circle {
private double r;
private double s;
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
public double getS() {
return Math.PI*r*r;
}
public void setS(double s) {
this.s = s;
}
}
public class Main {
public static void main(String[] args) {
Circle c=new Circle();
Scanner sc = new Scanner(System.in);
double a=sc.nextDouble();
if(a<=0){
System.out.println("Wrong Format");
}
else {
c.setR(a);
double ss= c.getS();
System.out.println(String.format("%.2f",ss));
}
}
}
分析:此题比较简单:是对类的基本应用,只要设了类,对类进行运用就没有问题。
7-3 测验3-继承与多态
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int choice = input.nextInt();
switch (choice) {
case 1: // Circle
double radiums = input.nextDouble();
if (radiums <= 0) {
System.out.println("Wrong Format");
return;
}
Shape circle = new Circle(radiums);
printArea(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);
printArea(rectangle);
break;
}
}
public static void printArea(Shape shape) {
System.out.printf("%.2f", shape.getArea());
}
}
abstract class Shape {
public abstract double getArea();
}
class Circle extends Shape {
private double r;
public Circle(double r) {
this.r = r;
}
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
@Override
public double getArea() {
return Math.PI * r * r;
}
}
class Rectangle extends Shape {
private Point leftTopPoint;
private Point lowerRightPoint;
public Rectangle(Point leftTopPoint, Point lowerRightPoint) {
this.leftTopPoint = leftTopPoint;
this.lowerRightPoint = lowerRightPoint;
}
@Override
public double getArea() {
double width = Math.abs(lowerRightPoint.getX() - leftTopPoint.getX());
double height = Math.abs(lowerRightPoint.getY() - leftTopPoint.getY());
return width * height;
}
}
class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
此题主要考察了继承和多态的应用,考试给了类图,比较简单
7-4 测验4-抽象类与接口
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
ArrayList<Shape> list = new ArrayList<>();
int choice = input.nextInt();
while (choice != 0) {
switch (choice) {
case 1: // Circle
double radiums = input.nextDouble();
Shape circle = new Circle(radiums);
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();
}
//Collections.sort(list);
list.sort(Comparator.naturalOrder()); // 使用默认的升序排序
for (int i = 0; i < list.size(); i++) {
System.out.print(String.format("%.2f", list.get(i).getArea()) + " ");
}
}
}
abstract class Shape implements Comparable<Shape> {
public abstract double getArea();
@Override
public int compareTo(Shape o) {
return Double.compare(this.getArea(), o.getArea());
}
}
class Circle extends Shape {
private double radiums;
public Circle(double radiums) {
this.radiums = radiums;
}
@Override
public double getArea() {
return Math.PI * radiums * radiums;
}
}
class Rectangle extends Shape {
private Point leftTopPoint;
private Point lowerRightPoint;
public Rectangle(Point leftTopPoint, Point lowerRightPoint) {
this.leftTopPoint = leftTopPoint;
this.lowerRightPoint = lowerRightPoint;
}
@Override
public double getArea() {
double width = Math.abs(lowerRightPoint.getX() - leftTopPoint.getX());
double height = Math.abs(lowerRightPoint.getY() - leftTopPoint.getY());
return width * height;
}
}
class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
分析:此题是在第三题的基础的改进,主要加了接口部分知识,属于是老师上课讲的内容,没有难度
踩坑心得:
- 分清类和对象的区别,在调用对象前一定要初始化对象,否则就会出现对象为空的异常。比如这样
- 而且一定要保证数据存入对象
主要困难以及改进建议:
- 区分不清静态和动态的区别,不知道什么时候用什么类型的。最后通过查找资料明白了静态的内容,基于类而存在,非静态的内容基于对象而存在。也就是说静态内容是一类事物(即基于该类的所有对象)的共有特征,而非静态内容每个对象的独有特征。静态内容一旦修改,所有对象都会被影响,修改非静态内容,只会影响当前对象。
- 对于如何构造父类以及运用还不够熟练。
- 其次对于异常处理,try-catch语句的应用还需要多多练习。
总结:
- 经过这几次的pta以及期中考试,我对于Java有了更清晰的认知,已经不再是那么陌生,对于一个编程性问题我能很快想到如何运用Java思想来解决。
- 其次在这几次作业和考试中我也学习,掌握了多态的运用,以及异常处理问题。对于Java语言学习的深度更深了。
- 经过这几次的菜单问题,我对于一个问题的思考也更加全面,为以后得Java编程奠定了基础。