PTA题目集4、5、6以及期中考试的总结性Blog
一.前言
大三上学期开始,我们开始接触java这门语言,Java具有大部分编程语言所共有的一些特征,被特意设计用于互联网的分布式环境。Java具有类似于C++语言的形式和感觉,但它要比C++语言更易于使用,而且在编程时彻底采用了一种以对象为导向的方式。
pta已经写了六次了,除了第一次题目难度比较简单,后面的数次难度激增。总体来说,最近pta的主要知识点还是在设计类和学习java语言,以及用面向对象的思维方式。对只接触过一点java语言的我来说还是很有挑战的。这三次pta题目相像,但是难度很大,每次都有菜单的设计,也有很多类的调用,十分复杂,还需要使用很多函数,要有继承和传参,这确实十分困难。
二.设计与分析:
第四次题目集:
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"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)//根据序号查找一条记录
}
### 输入格式:
桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
输入格式:
桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
注意:由于此次pta较难的题目还是菜单计价3,所以只讨论该题,且该题代码在之后并没有沿用下来,所以也不做过多讨论,这里只展示代码
import java.util.*; public class Main { private static final double DISCOUNT_WEEKDAY_EVENING = 0.8; private static final double DISCOUNT_WEEKDAY_NOON = 0.6; private static final double DISCOUNT_WEEKEND = 1.0; static Map<String, Double> prices = new HashMap<>(); public static void main(String[] args) { Scanner scanner = new Scanner(System.in); Map<String, List<OrderItem>> orders = new HashMap<>(); String line; while (!(line = scanner.nextLine().trim()).equals("end")) { if (line.isEmpty()) { continue; } String[] fields = line.split("\\s+"); if (fields.length < 2) { continue; } String type = fields[0]; if (type.equals("菜单")) { // 处理菜单 String name = fields[1]; double price = Double.parseDouble(fields[2]); prices.put(name, price); } else if (type.equals("桌号")) { // 处理订单 String tableNum = fields[1]; String time = fields[2]; List<OrderItem> orderItems = new ArrayList<>(); orders.put(tableNum, orderItems); double discount = getDiscount(time); while (!(line = scanner.nextLine().trim()).equals("")) { fields = line.split("\\s+"); if (fields.length < 2) { continue; } String cmd = fields[1]; if (cmd.equals("delete")) { // 处理删除指令 int index = Integer.parseInt(fields[0]) - 1; if (index < 0 || index >= orderItems.size()) { System.out.println("delete error"); } else { orderItems.remove(index); } } else { // 处理点菜记录 String name = fields[1]; int portion = Integer.parseInt(fields[2]); int count = Integer.parseInt(fields[3]); OrderItem item = new OrderItem(name, portion, count); orderItems.add(item); } } // 处理代点菜信息 while (!(line = scanner.nextLine().trim()).equals("")) { fields = line.split("\\s+"); if (fields.length < 5) { continue; } String otherTableNum = fields[0]; int index = Integer.parseInt(fields[1]) - 1; String name = fields[2]; int portion = Integer.parseInt(fields[3]); int count = Integer.parseInt(fields[4]); double price = prices.get(name) * getPortionRate(portion); OrderItem item = new OrderItem(name, portion, count, price); orders.get(tableNum).add(item); } // 输出该桌总价 double totalPrice = 0; for (OrderItem item : orderItems) { totalPrice += item.getPrice() * item.getCount(); } totalPrice *= discount; System.out.println("桌号 " + tableNum + " 总价:" + Math.round(totalPrice)); } } } private static double getPortionRate(int portion) { switch (portion) { case 1: return 1.0; case 2: return 1.5; case 3: return 2.0; default: return 1.0; } } private static double getDiscount(String time) { Scanner scanner = new Scanner(time); scanner.useDelimiter(":"); int hour = scanner.nextInt(); int minute = scanner.nextInt(); scanner.close(); boolean isWeekend = isWeekend(time); if (!isWeekend && hour >= 10 && hour <= 14 && minute >= 30 && minute <= 59) { return DISCOUNT_WEEKDAY_NOON; } else if (!isWeekend && hour >= 17 && hour <= 20 && minute >= 0 && minute <= 59) { return DISCOUNT_WEEKDAY_EVENING; } else if (isWeekend && hour >= 9 && hour <= 21 && minute >= 30 && minute <= 59) { return DISCOUNT_WEEKEND; } else { return 0; } } private static boolean isWeekend(String time) { Scanner scanner = new Scanner(time); scanner.useDelimiter(" "); String weekday = scanner.next(); scanner.close(); return weekday.equals("星期六") || weekday.equals("星期日"); } private static class OrderItem { private String name; private int portion; private int count; private double price; public OrderItem(String name, int portion, int count) { this(name, portion, count, 0); } public OrderItem(String name, int portion, int count, double price) { this.name = name; this.portion = portion; this.count = count; this.price = price; } public String getName() { return name; } public int getPortion() { return portion; } public int getCount() { return count; } public double getPrice() { return price == 0 ? prices.get(name) * getPortionRate(portion) : price; } } }
这个 Java 题目的难度属于中等级别。它涉及到输入输出的处理、字符串的分割和转换、Map 和 List 的使用等基本的编程技巧。
在技术方面,这个题目使用了以下技巧:
1. 使用 Scanner 类来读取用户的输入。
2. 使用 HashMap 来存储菜单的价格信息。
3. 使用 ArrayList 来存储每个桌号的点菜记录。
4. 使用字符串的 split() 方法和 trim() 方法来分割和处理输入的字段。
5. 使用条件语句和循环来判断和处理不同的命令和指令。
6. 使用 Math 类的 round() 方法对总价进行四舍五入。
此外,这个题目也涉及到了一些简单的逻辑判断和数据计算。
总体而言,这个题目可以帮助练习者巩固和应用基本的编程技巧,包括字符串处理、集合的使用和基本的算术运算
第五次题目集:
本次作业比菜单计价系列-3增加的功能:
菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+基础价格+"T"
例如:麻婆豆腐 9 T
菜价的计算方法:
周一至周五 7折, 周末全价。
注意:不同的四舍五入顺序可能会造成误差,请按以下步骤累计一桌菜的菜价:
计算每条记录的菜价:将每份菜的单价按份额进行四舍五入运算后,乘以份数计算多份的价格,然后乘以折扣,再进行四舍五入,得到本条记录的最终支付价格。
最后将所有记录的菜价累加得到整桌菜的价格。
代码如下:
Dish类:
Menu类:
Record类:
Order类:
Table类:
Main类:
类图如下:
圈复杂度:
题目分析:
此题是菜单类,包含菜品类,菜谱类,点菜记录类和订单类,菜品类主要是对应菜谱上一道菜的信息。菜谱类主要是对应菜谱,包含饭店提供的所有菜的信息。点菜记录类主要是保存订单上的一道菜品记录。订单类主要是保存用户点的所有菜的信息。一开始看到这个题目的时候,我是被吓了一跳的,因为这道题的文字量特别的大,而且在上次的pta上有加了许多别的功能,比如说删除和时间,还有特色菜,有这与普通菜不同的计算价格的方式和打折的方式。在得分上,得分点又被细化,导致不好拿到高分。
踩坑心得:
1,价格的算法出错,注意特色菜的价格算法以及打折的时间。
2,同一桌菜名、份额相同的点菜记录要合并成一条进行计算,否则可能会出现四舍五入的误差。
3,超出范围的返回值错误,导致返回date。
第六次题目集:
本次课题相比菜单计价系列-3新增要求如下:
1、菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+口味类型+英文空格+基础价格+"T"
菜价的计算方法:
周一至周五 7折, 周末全价。
特色菜的口味类型:川菜、晋菜、浙菜
川菜增加辣度值:辣度0-5级;对应辣度水平为:不辣、微辣、稍辣、辣、很辣、爆辣;
晋菜增加酸度值,酸度0-4级;对应酸度水平为:不酸、微酸、稍酸、酸、很酸;
浙菜增加甜度值,甜度0-3级;对应酸度水平为:不甜、微甜、稍甜、甜;
输出一桌的信息时,按辣、酸、甜度的顺序依次输出本桌菜各种口味的口味度水平,如果没有某个类型的菜,对应的口味(辣/酸/甜)度不输出,只输出已点的菜的口味度。口味度水平由口味度平均值确定,口味度平均值只综合对应口味菜系的菜计算,不做所有菜的平均。比如,某桌菜点了3份川菜,辣度分别是1、3、5;还有4份晋菜,酸度分别是,1、1、2、2,辣度平均值为3、酸度平均值四舍五入为2,甜度没有,不输出。
一桌信息的输出格式:table+英文空格+桌号+:+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格+"川菜"+数量+辣度+英文空格+"晋菜"+数量+酸度+英文空格+"浙菜"+数量+甜度。
2、考虑客户订多桌菜的情况,输入时桌号时,增加用户的信息:
格式:table+英文空格+桌号+英文空格+":"+英文空格+客户姓名+英文空格+手机号+日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
输出用户支付金额格式:
用户姓名+英文空格+手机号+英文空格+支付金额
代码如下:
Dish类:
Menu类:
people类:
Record类:
Order类:
table类:
main类:
类图如下:
圈复杂度:
题目分析:
此题是菜单类,包含菜品类,菜谱类,点菜记录类和订单类,菜品类主要是对应菜谱上一道菜的信息。菜谱类主要是对应菜谱,包含饭店提供的所有菜的信息。点菜记录类主要是保存订单上的一道菜品记录,订单类主要是保存用户点的所有菜的信息。这道题对比上次的pta,加入了手机号和排序,加入了口味值,加入了川菜,晋菜,浙菜。代码需要传参的地方更多,很容易传参错误导致输出错误,代码不能得分,在得分上,得分点又被细化,导致不好拿到高分。
踩坑心得:
1,数据类型转换错误,string类和int类转换和输出问题。
2,代码需要传参的地方更多,很容易传参错误导致输出错误。
3,不同的四舍五入顺序可能会造成误差。
4,本题要考虑代点菜的情况,当前桌点的菜要加上被其他桌代点的菜综合计算口味度平均值。
5,输出结果时,同一个客户的所有table金额一定要累加。
6,辣度值超标会返回date。
期中考试题目集:
第一题:
创建一个圆形类(Circle),私有属性为圆的半径,从控制台输入圆的半径,输出圆的面积
输入格式:
输入圆的半径,取值范围为(0,+∞)
,输入数据非法,则程序输出Wrong Format
,注意:只考虑从控制台输入数值的情况
输出格式:
输出圆的面积(保留两位小数,可以使用String.format(“%.2f”,输出数值)控制精度)
代码如下:
第二题:
设计一个矩形类,其属性由矩形左上角坐标点(x1,y1)及右下角坐标点(x2,y2)组成,其中,坐标点属性包括该坐标点的X轴及Y轴的坐标值(实型数),求得该矩形的面积。类设计如下图:
输入格式:
分别输入两个坐标点的坐标值x1,y1,x2,y2。
输出格式:
输出该矩形的面积值(保留两位小数)。
代码如下:
第三题:
将测验1与测验2的类设计进行合并设计,抽象出Shape父类(抽象类),Circle及Rectangle作为子类,类图如下所示:
代码如下:
踩坑心得:实际上自己刚遇到题目的时候并没有好好思考怎么去构造代码,而是一看到题目就写,导致总是频频报错,并且也不能跟后面的继承联系上。如果自己在看到题目后能够多加思考再去动笔,可能结果会更不一样。
总结: 在考试中我并没有写出第三题,自己不太会写是一个原因,不够熟练也是一个原因,如果前两题花的时间能够更少一些,也许自己就能够拥有更多的时间去思考第三题和尝试第三题。考试结束后也是经过一定的思考最后把这道题写了出来,所以平常的练习特别重要
三.改进建议:
1,pta部分题目运行时间超时,要优化代码的算法,很多时候不是你的方法不行,而是有优化的地方没有优化,导致程序运行的时间加长导致超时,现在争取把每个小步骤都优化,以后的大作业程序才能不断的节省时间。
2,pta部分题目非零返回,自己的代码有问题才会导致的,要检查自己的程序逻辑。
3,对继承的方法使用不熟练,对传参的方法也不太熟练,会用但是容易出错,要多使用,防止以后出错。
4,对类的设计要更细节和具体,每个类包含的属性和方法,以及不同类之间的关系。
四.总结:
这些题目总体来说难度大,题目量虽然也不多,但是有些题目还是需要静下心来思考才能做好。期中考试的难度不算很高,前三题还是比较好作对的,第四题的接口我还没有掌握,没能拿下分。通过这数次的PTA作业,我也基本能够掌握java语言中类的作用。这段时间的作业,也让我发现了自己最大的问题,那就是思维比较固化,写的很多程序的思路大多都是按部就班的那种,所以我的思维能力还是很需要培养的。这几次的作业,也基本帮助我们搭建了一个最基本的java语言的框架,让我学会了java的基本语法和类的分类,掌握了面向对象的语言的基本思路,学会了部分菜单的设计,学会了类的调用和部分函数,学会了传参和继承。虽然我还有很多不足和错误,java的语法不够熟练,对类的概念没有充分的掌握,传参也容易出错。希望老师可以更多的讲一下部分有用的java方法,毕竟自己查资料学习的不够系统,通过老师的讲解可以更加深入,系统的学习。