blog-3
BLOG-3
前言:
7-8次PTA题目集(成绩计算系列)题量不大,但难度比较大,都是对前面成绩计算系列的迭代,但设计思想与菜单系列类似,没有很大的改动,只要理解透彻了菜单系列的设计思路,对于成绩计算类也就没有什么问题了。期末考试的题目提醒和期中考试类似,难度有了些许提升,题量较大。
设计与分析:
下面对个别具有代表性题目进行分析:
7-3 课程成绩统计程序-2
相关类图:
相关类代码:
class xuanke
{
Student student;
Course course;
Score score;
boolean flag=true;//记录本条信息是否有效
xuanke(Student student,Course course,Score score)//构造法
{
this.course=course;
this.score=score;
this.student=student;
}
void judge()//判断本条信息是否有效
{
if(course.coursekind!=null)
{
if(course.getClass().getSimpleName().equals("Requireed_course"))//必修
{
if(score.zong!=2)
{
flag=false;
}
}
else if(course.getClass().getSimpleName().equals("Elective_course"))//选修
{
if(course.kaocha.equals("考试"))
{
if(score.zong!=2)
{
flag=false;
}
}
if(course.kaocha.equals("考察"))
{
if(score.zong!=1)
{
flag=false;
}
}
}
else if(course.getClass().getSimpleName().equals("experimental_course"))//实验课
{
if(!course.kaocha.equals("实验"))
{
flag=false;
}
}
}
else
{
flag=false;
}
}
static boolean fsc(Course c,Student s)
{
for(xuanke it:Main.scs)
{
if(it.course.coursename.equals(c.coursename)&&it.student.id.equals(s.id))
return false;
}
return true;
}
}
class Student//学生
{
String name;//姓名
String id;//学号
int x=0;//记录该学生所选课程总数
int chengji=0;//成绩
//课程成绩,键为课程名,
void getScore()//计算总成绩
{
for(xuanke it:Main.scs){
if(it.student.name.equals(name)&&it.student.id.equals(id))
{
if(it.flag)
{
chengji+=it.score.zhong;
x++;
}
}
}
if(x!=0)
chengji/=x;
}
Student(String id,String name)//构造法
{
this.id=id;
this.name=name;
}
}
class Course//课程
{
String coursename;//课程名
String coursekind;//总类
String kaocha;//考察方式
Score Cscore=new Score();//成绩
int x=0;//记录选该课程的总人数
Course(String coursename,String coursekind,String kaocha)//构造方法
{
this.coursename=coursename;
this.coursekind=coursekind;
this.kaocha=kaocha;
}
void getzong(Score s)//计算成绩
{
double sum=0;
sum=0.3*s.ping+0.7*s.finaly;
s.zhong=(int)sum;
}
void getsum()//计算总成绩
{
for(xuanke it:Main.scs){
if(it.course.coursename.equals(coursename)&&it.course.coursekind.equals(coursekind))
{
if(it.flag)
{
Cscore.add(it.score);
x++;
}
}
}
if(x!=0)
{
Cscore.ping/=x;
Cscore.finaly/=x;
Cscore.zhong/=x;
}
}
}
class Grade//班级
{
String number;//班级号
Set<String> students=new HashSet<String>();
int x=0;//记录所有有成绩的学生
Score Gscore=new Score();
Grade(String number)//新构造方法
{
this.number=number;
}
void addstudent(String studentnumber)//加入新学生
{
students.add(studentnumber);
}
static void addgrade(String number)//添加新班级
{
if(!Main.grades.containsKey(number))
{
Main.grades.put(number, new Grade(number));
}
}
void getScore()//计算总成绩
{
Main.scs.forEach(t->{
if(students.contains(t.student.id))
{
if(t.flag) {
Gscore.add(t.score);
x++;
}
}
});
if(x!=0)
{
Gscore.ping/=x;
Gscore.finaly/=x;
Gscore.zhong/=x;
}
}
}
class Score//成绩
{
int ping=0;//平时
int finaly=0;//期末
int zhong=0;//最终
int zong=0;//记录成绩总数
Score(){
zong=3;
};
Score(int usual,int last)//考试课构造法
{
this.ping=usual;
this.finaly=last;
zong=2;
}
Score(int last)//考察课构造法
{
this.finaly=last;
zong=1;
}
Score(String arr[])//实验课课程构造方法
{
zong=Integer.parseInt(arr[3]);
for(int i=0;i<arr.length-4;i++)
{
zhong+=Integer.parseInt(arr[i+4]);
}
zhong/=zong;
}
void add(Score s)//成绩相加,用于计算班级,课程成绩
{
this.ping+=s.ping;
this.finaly+=s.finaly;
this.zhong+=s.zhong;
}
}
class bixiucourse extends Course//必修课
{
bixiucourse(String name, String kind, String e_way) {
super(name, kind, e_way);
}
}
class xuanxiucourse extends Course//选修课
{
xuanxiucourse(String name, String kind, String e_way) {
super(name, kind, e_way);
}
void getzong(Score s)//计算成绩
{
double sum=0;
sum=s.finaly;
s.zhong=(int)sum;
if(kaocha.equals("考试"))//考试课
super.getzong(s);
}
}
class shiyancourse extends Course//实验课
{
shiyancourse(String coursename, String coursekind, String kaocha) {
super(coursename, coursekind, kaocha);
}
void getzong(Score s)//计算成绩
{
s.zhong=s.zhong;
}
}
分析:
Main 类:
包含 main 方法,作为程序的入口。
通过控制台输入来管理学生选课、成绩计算等操作。
panduan 方法:
该方法用于判断输入的格式是否正确,主要用于对输入进行合法性检查。
xuanke 类:
该类表示学生选课情况,包含学生、课程和成绩等信息。
Student 类:
表示学生信息,包含学号、姓名、选课数和总成绩等信息。
Course 类:
表示课程信息,包含课程名、课程类型(必修、选修、实验)、考察方式(考试、考察、实验)和成绩等信息。
同时还有子类 bixiucourse、xuanxiucourse 和 shiyancourse 分别表示必修课、选修课和实验课。
Grade 类:
表示班级信息,包含班级号、学生列表和总成绩等信息。
Score 类:
表示成绩信息,包含平时成绩、期末成绩、总成绩等信息。
7-2 课程成绩统计程序-3
相关类图:
相关类代码
class xuanke
{
Student student;
Course course;
Score score;
boolean flag=true;//记录本条信息是否有效
xuanke(Student student,Course course,Score score)//构造法
{
this.course=course;
this.score=score;
this.student=student;
}
void panben()//判断本条信息是否有效
{
if(course.coursekind!=null)
{
if(course.getClass().getSimpleName().equals("Requireed_course"))//必修
{
if(score.sum!=2)
{
flag=false;
}
}
else if(course.getClass().getSimpleName().equals("Elective_course"))//选修
{
if(course.courseway.equals("考试"))
{
if(score.sum!=2)
{
flag=false;
}
}
if(course.courseway.equals("考察"))
{
if(score.sum!=1)
{
flag=false;
}
}
}
else if(course.getClass().getSimpleName().equals("experimental_course"))//实验课
{
if(!course.courseway.equals("实验"))
{
flag=false;
}
}
}
else
{
flag=false;
}
}
static boolean fstudentc(Course c,Student s)
{
for(xuanke it:Main.scs)
{
if(it.course.coursename.equals(c.coursename)&&it.student.number.equals(s.number))
return false;
}
return true;
}
}
class Student//学生
{
String name;//姓名
String number;//学号
int x=0;//记录该学生所选课程总数
int sum=0;//成绩
void getScore()//计算总成绩
{
for(xuanke it:Main.scs){
if(it.student.name.equals(name)&&it.student.number.equals(number))
{
if(it.flag)
{
sum+=it.score.last;
x++;
}
}
}
if(x!=0)
sum=(int)(sum/x);
}
Student(String number,String name)//构造法
{
this.number=number;
this.name=name;
}
}
class Course//课程
{
String coursename;//课程名
String coursekind;//总类
String courseway;//考察方式
Score Cscore=new Score();//成绩
int x=0;//记录选该课程的总人数
int n=0;//记录该课程成绩次数
float power[]=new float[20]; //权重
Course(String coursename,String coursekind,String courseway,int n,float []power)//构造方法
{
this.coursename=coursename;
this.coursekind=coursekind;
this.courseway=courseway;
if(courseway!=null&&courseway.equals("考试"))n=2;
else if(courseway!=null&&courseway.equals("考察"))n=1;
this.n=n;
this.power=power;
}
void getfinalScore(Score s)//计算成绩
{
double sum=0;
sum=power[0]*s.pinshi+power[1]*s.qimo;
s.last=(int)(sum);
}
void getScore()//计算总成绩
{
for(xuanke it:Main.scs){
if(it.course.coursename.equals(coursename)&&it.course.coursekind.equals(coursekind))
{
if(it.flag)
{
Cscore.add(it.score);
x++;
}
}
}
if(x!=0)
{
Cscore.pinshi=(int)(Cscore.pinshi/x+0.5);
Cscore.qimo=(int)(Cscore.qimo/x+0.5);
Cscore.last=(int)(Cscore.last/x+0.5);
}
}
}
class Grade//班级
{
String number;//班级号
Set<String> students=new HashSet<String>();
//添加学生学号
int x=0;//记录所有有成绩的学生
Score Gscore=new Score();
//计入成绩
Grade(String number)//新构造方法
{
this.number=number;
}
void addstudent(String studentnumber)//加入新学生
{
students.add(studentnumber);
}
static void addgrade(String number)//添加新班级
{
if(!Main.grades.containsKey(number))
{
Main.grades.put(number, new Grade(number));
}
}
void getScore()//计算总成绩
{
Main.scs.forEach(t->{
if(students.contains(t.student.number))
{
if(t.flag) {
Gscore.add(t.score);
x++;
}
}
});
if(x!=0)
{
Gscore.pinshi=(int)(Gscore.pinshi/x+0.5);
Gscore.qimo=(int)(Gscore.qimo/x+0.5);
Gscore.last=(int)(Gscore.last/x+0.5);
}
}
}
class Score//成绩
{
int pinshi=0;//平时
int qimo=0;//期末
int last=0;//最终
int sum=0;//记录成绩总数
Score(){
sum=3;
};
Score(String arr[])//构造方法
{
Course c=Main.findcourse(arr[2]);
if(c!=null)
{
sum=c.n;
if(sum==1&&arr.length==4)
{
qimo=Integer.parseInt(arr[3]);
}
else if(sum==2&&arr.length==5)
{
pinshi=Integer.parseInt(arr[3]);
qimo=Integer.parseInt(arr[4]);
}
if(c.n!=1&&c.n!=2)
{
float end1=0;
for(int i=0;i<arr.length-3&&i<sum;i++)
{
end1+=1.0*Integer.parseInt(arr[i+3])*c.power[i];
}
last=(int)(end1);
}
}
}
void add(Score s)//成绩相加,用于计算班级,课程成绩
{
this.pinshi+=s.pinshi;
this.qimo+=s.qimo;
this.last+=s.last;
}
}
class Requireed_course extends Course//必修课
{
Requireed_course(String name, String kind, String e_way,int n,float []power) {
super(name, kind, e_way,n,power);
}
}
class Elective_course extends Course//选修课
{
Elective_course(String name, String kind, String e_way,int n,float []power)
{
super(name, kind, e_way,n,power);
}
void getfinalScore(Score s)//计算成绩
{
double sum=0;
sum=s.qimo;
s.last=(int)sum;
if(courseway.equals("考试"))//考试课
super.getfinalScore(s);
}
}
class experimental_course extends Course//实验课
{
experimental_course(String coursename, String coursekind, String e_way,int n,float []power) {
super(coursename, coursekind, e_way,n,power);
}
void getfinalScore(Score s)//计算成绩
{
s.last=s.last;//表示一下
}
}
分析:通过类图可以看出此代码包括
主要功能
管理学生信息,包括学号、姓名和成绩。
管理课程信息,包括课程名称、类型(必修、选修、实验)、考察方式(考试、考察、实验)和成绩权重。
管理班级信息,包括班级号和学生信息。
代码结构
Main 类是程序的入口,包含 main 方法,用于接收用户输入、处理成绩数据和输出结果。
xuanke 类表示学生选课信息,包含学生、课程、成绩等相关信息。
Student 类表示学生信息,包含学号、姓名、总成绩等信息。
Course 类表示课程信息,包含课程名称、类型、考察方式、成绩等信息。
Grade 类表示班级信息,包含班级号、学生列表和成绩信息。
Score 类表示学生成绩信息,包含平时成绩、期末成绩、最终成绩等信息。
Requireed_course、Elective_course、experimental_course 类分别表示必修课、选修课和实验课,继承自 Course 类。
输入和处理
Main 类中的 main 方法接收用户输入,并根据输入内容判断是课程信息还是成绩信息,然后将其分发给相应的处理方法。
panduan 方法用于判断输入格式是否正确,并返回输入的类型(课程信息或成绩信息)。
数据存储
使用 Map 存储班级、学生和课程信息,其中键为班级号、学号和课程名称,保证了数据的唯一性和快速检索。
使用 List 存储学生选课信息,方便遍历和操作。
成绩计算
在 main 方法中使用了多个 forEach 循环来计算学生、班级和课程的最终成绩,最后输出结果。
错误处理
在 panduan 方法中进行了输入格式的错误判断,并输出提示信息。
由于代码篇幅较长,以上是对代码的整体概括和分析,具体细节可能需要在特定部分进行更详细的讨论。
7-1 立体图形问题
相关类图:
分析:
主要功能
定义了一个抽象类 Solid,其中包含了抽象方法 getArea() 和 getVolume(),分别用于计算固体的表面积和体积。
定义了两个实体类 Cube 和 RegularPyramid,分别表示立方体和正四面体,并实现了 Solid 类的抽象方法。
类的结构
Solid 抽象类:定义了抽象方法 getArea() 和 getVolume(),以及构造函数。
Cube 类:继承自 Solid 类,表示立方体,包含了边长属性和相关的计算方法。
RegularPyramid 类:继承自 Solid 类,表示正四面体,包含了底边边长属性和相关的计算方法。
Main 类:包含了 display 方法和 main 方法,用于展示结果和接收用户输入。
输入和处理
在 main 方法中,通过 Scanner 获取用户输入的边长 side。
然后分别创建了一个立方体对象和一个正四面体对象,并调用 display 方法展示它们的表面积和体积。
结果展示
display 方法根据传入的参数类型,分别计算并显示了立方体和正四面体的表面积和体积。
计算公式
立方体的表面积为 6 * side * side,体积为 side * side * side。
正四面体的表面积和体积的计算使用了对应的数学公式。
总结
这段代码通过面向对象的方式,利用抽象类和继承,实现了对立方体和正四面体的表面积和体积的计算。它展示了面向对象编程的特点,具有良好的可扩展性和可维护性。同时,通过输入获取用户数据,并将结果显示给用户,实现了一个简单但完整的功能。
7-2 魔方问题
相关类图
主要功能
定义了抽象类 Solid,其中包含了抽象方法 getArea() 和 getVolume(),分别用于计算固体的表面积和体积。
定义了两个实体类 Cube 和 RegularPyramid,分别表示立方体和正四面体,并实现了 Solid 类的抽象方法。
定义了抽象类 RubikCube,包含了颜色、层数和固体属性,以及计算魔方立方体表面积和体积的方法。
输入和处理
在 main 方法中,通过 Scanner 获取用户输入的颜色、层数和边长,并创建了两个魔方立方体对象 cube1 和 cube2。
然后调用 display 方法展示它们的颜色、表面积和体积。
结果展示
display 方法根据传入的参数类型,分别显示了魔方立方体的颜色、表面积和体积。
类的结构
Solid 抽象类:定义了抽象方法 getArea() 和 getVolume(),以及构造函数。
Cube 类:继承自 Solid 类,表示立方体,包含了边长属性和相关的计算方法。
RegularPyramid 类:继承自 Solid 类,表示正四面体,包含了底边边长属性和相关的计算方法。
RubikCube 抽象类:包含了颜色、层数和固体属性,以及计算魔方立方体表面积和体积的方法。
SquareCube 类和 RegularPyramidCube 类:分别表示魔方立方体和魔方正四面体,继承自 RubikCube 抽象类。
计算公式
立方体和正四面体的表面积和体积的计算使用了对应的数学公式。
总结
这段代码通过面向对象的方式,利用抽象类和继承,实现了对魔方立方体和魔方正四面体的表面积和体积的计算。它展示了面向对象编程的特点,具有良好的可扩展性和可维护性。同时,通过输入获取用户数据,并将结果显示给用户,实现了一个简单但完整的功能。
7-3 魔方排序问题
相关类图:
分析:主要功能
定义了抽象类 Solid,其中包含了抽象方法 getArea() 和 getVolume(),分别用于计算固体的表面积和体积。
定义了两个实体类 Cube 和 RegularPyramid,分别表示立方体和正四面体,并实现了 Solid 类的抽象方法。
定义了抽象类 RubikCube,包含了颜色、层数和固体属性,以及计算魔方立方体表面积和体积的方法。
定义了 SquareCube 和 RegularPyramidCube 类,它们分别表示魔方立方体和魔方正四面体,是 RubikCube 的子类。
输入和处理
在 main 方法中,通过 Scanner 获取用户输入的选择,颜色、层数和边长,并创建了魔方立方体对象。
根据用户的选择,将创建的对象添加到列表中。
结果展示
使用列表排序将所有的魔方立方体对象按照体积从小到大排序。
遍历列表,输出每个魔方立方体对象的颜色、表面积和体积。
类的结构
Solid 抽象类:定义了抽象方法 getArea() 和 getVolume(),以及构造函数。
Cube 类:继承自 Solid 类,表示立方体,包含了边长属性和相关的计算方法。
RegularPyramid 类:继承自 Solid 类,表示正四面体,包含了底边边长属性和相关的计算方法。
RubikCube 抽象类:包含了颜色、层数和固体属性,以及计算魔方立方体表面积和体积的方法,还实现了 Comparable 接口用于排序。
SquareCube 类和 RegularPyramidCube 类:分别表示魔方立方体和魔方正四面体,继承自 RubikCube 抽象类。
计算公式
立方体和正四面体的表面积和体积的计算使用了对应的数学公式。
总结
这段代码通过面向对象的方式,利用抽象类和继承,实现了对魔方立方体和魔方正四面体的表面积和体积的计算,并通过 Comparable 接口进行排序。同时,通过输入获取用户数据,并将结果显示给用户,实现了一个完整的功能。
7-4 销售步枪问题(附加题)
相关类图:
分析:GunPart 类
GunPart 类表示枪支的零部件,包括零部件名称、价格、月销售限额和已售数量等属性。
构造函数用于初始化零部件的名称、价格和月销售限额。
提供了获取零件名称、价格、月销售限额和已售数量的方法,以及设置已售数量的方法。
SalesOrder 类
SalesOrder 类表示销售订单,包含了枪锁、枪托和枪管三个零部件的信息。
构造函数用于初始化销售订单中的零部件信息。
提供了计算总销售额和佣金的方法。
calculateTotalSales 方法计算所有零部件的销售额之和。
calculateCommission 方法根据销售额计算佣金,采用不同销售额范围的不同佣金比例。
主函数 Main
主函数从控制台读取用户输入的枪锁、枪托和枪管的数量。
根据输入的数量,创建对应的 GunPart 对象,并设置已售出数量。
创建 SalesOrder 对象,计算销售额和佣金。
最后输出计算结果。
输入和处理
从控制台获取输入的数量,对输入进行合法性检查,如数量是否符合范围要求。
创建对应的零部件对象,并设置已售出数量。
结果展示
输出计算得到的总销售额和佣金。
总结
该程序利用面向对象的思想,将零部件和销售订单抽象为对象,并通过相应的方法进行销售额和佣金的计算。同时,通过用户输入和条件判断,实现了一个简单的零部件销售系统。
踩坑心得:
- 分清类和对象的区别,在调用对象前一定要初始化对象,否则就会出现对象为空的异常。比如这样
- 而且一定要保证数据存入对象
主要困难以及改进建议:
- 区分不清静态和动态的区别,不知道什么时候用什么类型的。最后通过查找资料明白了静态的内容,基于类而存在,非静态的内容基于对象而存在。也就是说静态内容是一类事物(即基于该类的所有对象)的共有特征,而非静态内容每个对象的独有特征。静态内容一旦修改,所有对象都会被影响,修改非静态内容,只会影响当前对象。
- 对于如何构造父类以及运用还不够熟练。
- 其次对于异常处理,try-catch语句的应用还需要多多练习。
总结:
- 经过这几次的pta以及期末考试,我对于Java有了更清晰的认知,已经不再是那么陌生,对于一个编程性问题我能很快想到如何运用Java思想来解决。
- 其次在这几次作业和考试中我也学习,掌握了多态的运用,以及异常处理问题。对于Java语言学习的深度更深了。
- 经过这几次的菜单问题,我对于一个问题的思考也更加全面,为以后得Java编程奠定了基础。
浙公网安备 33010602011771号