blog-3

BLOG-3

前言:

7-8次PTA题目集(成绩计算系列)题量不大,但难度比较大,都是对前面成绩计算系列的迭代,但设计思想与菜单系列类似,没有很大的改动,只要理解透彻了菜单系列的设计思路,对于成绩计算类也就没有什么问题了。期末考试的题目提醒和期中考试类似,难度有了些许提升,题量较大。

设计与分析:

下面对个别具有代表性题目进行分析:

7-3 课程成绩统计程序-2

相关类图:

IMG_256

IMG_256

相关类代码:

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 立体图形问题

相关类图:IMG_256IMG_256

IMG_256

分析:

主要功能

定义了一个抽象类 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 魔方问题

相关类图

IMG_256

主要功能

定义了抽象类 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 魔方排序问题

相关类图:

IMG_256

分析:主要功能

定义了抽象类 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 销售步枪问题(附加题)

相关类图:IMG_256

分析:GunPart 类

GunPart 类表示枪支的零部件,包括零部件名称、价格、月销售限额和已售数量等属性。

构造函数用于初始化零部件的名称、价格和月销售限额。

提供了获取零件名称、价格、月销售限额和已售数量的方法,以及设置已售数量的方法。

SalesOrder 类

SalesOrder 类表示销售订单,包含了枪锁、枪托和枪管三个零部件的信息。

构造函数用于初始化销售订单中的零部件信息。

提供了计算总销售额和佣金的方法。

calculateTotalSales 方法计算所有零部件的销售额之和。

calculateCommission 方法根据销售额计算佣金,采用不同销售额范围的不同佣金比例。

主函数 Main

主函数从控制台读取用户输入的枪锁、枪托和枪管的数量。

根据输入的数量,创建对应的 GunPart 对象,并设置已售出数量。

创建 SalesOrder 对象,计算销售额和佣金。

最后输出计算结果。

输入和处理

从控制台获取输入的数量,对输入进行合法性检查,如数量是否符合范围要求。

创建对应的零部件对象,并设置已售出数量。

结果展示

输出计算得到的总销售额和佣金。

总结

该程序利用面向对象的思想,将零部件和销售订单抽象为对象,并通过相应的方法进行销售额和佣金的计算。同时,通过用户输入和条件判断,实现了一个简单的零部件销售系统。

踩坑心得:

  1. 分清类和对象的区别,在调用对象前一定要初始化对象,否则就会出现对象为空的异常。比如这样

IMG_256

  1. 而且一定要保证数据存入对象

主要困难以及改进建议:

  1. 区分不清静态和动态的区别,不知道什么时候用什么类型的。最后通过查找资料明白了静态的内容,基于类而存在,非静态的内容基于对象而存在。也就是说静态内容是一类事物(即基于该类的所有对象)的共有特征,而非静态内容每个对象的独有特征。静态内容一旦修改,所有对象都会被影响,修改非静态内容,只会影响当前对象。
  2. 对于如何构造父类以及运用还不够熟练。
  3. 其次对于异常处理,try-catch语句的应用还需要多多练习。

总结:

  1. 经过这几次的pta以及期末考试,我对于Java有了更清晰的认知,已经不再是那么陌生,对于一个编程性问题我能很快想到如何运用Java思想来解决。
  2. 其次在这几次作业和考试中我也学习,掌握了多态的运用,以及异常处理问题。对于Java语言学习的深度更深了。
  3. 经过这几次的菜单问题,我对于一个问题的思考也更加全面,为以后得Java编程奠定了基础。
posted @ 2023-12-09 20:32  陈鹏祥  阅读(21)  评论(0)    收藏  举报