一、前言

题目集7~9,总的来说,题目难度肯定是逐渐增加的,毕竟也是最后几次PTA作业了,相较于之前的题目难度也要大一些,题量也下降了,只有1~2个题目。对于题目集7而言,是两个图形卡片游戏,这两个题目相对而言比较简单,继承、多态、ArrayList等的使用算是复习巩固之前学习的东西。对于题目集8和题目9而言,题目是让我们设计一个ATM机仿真系统,题目集8刚开始做是非常困难的,出于初次接触,耗费了大量时间还请教了别人写这个题目的思路,题目集9在题目集8的基础上加入跨行业务,以及手续费和透支费用,看上去相对复杂了些,但有了题目集8的铺垫,反而比较容易写出来。

二、设计与分析

1.题目集7(7-1)

这个题目是一个图形卡片排序游戏,在前面我们已经写过一个图形继承与多态的题目,在此基础上去写相对要容易些。

题目7-1类图:

从类图来看,很明显能看出来各个类之间的关系。圆形(Circle)类、矩形(Rectangle)类、三角形(Triangle)类及梯形(Trapezoid)类都继承自Shape类,根据类与类之间的关系很容易就可以写出来各个类里的属性和方法,这是一个卡片排序游戏,肯定就得解决排序问题,在写完基本框架后,根据类图的指示,要在卡片(Card)类中设计一个接口,让卡片进行排序,然后还要有DealCardList类来进行卡片的存储。

依据这个思路,我先创建抽象父类Shape,其中的方法只有声明,再写Shape类的各个子类,重写父类方法,这部分比较简单,写完这部分后就开始写卡片(Card)类,这里主要就是实现一个接口让卡片进行排序,最后就是写DealCardList类了,首先创建一个数组链表来储存图形对象,用于后面的图形面积排序和图形面积的求和。根据主方法的源码,用list.get()进行选择创建的图形对象并给它添加名字属性,再用.add()方法将图形对象加到List链表中。然后就是写出判断数据合法性的方法和数据求和的方法以及数据输出的方法。

将输入的数据进行选择创建相应的卡片图形对象(1代表圆形卡片,2代表矩形卡片,3代表三角形卡片,4代表梯形卡片。):

DealCardList(ArrayList<Integer>list){
for(int i=0;i<list.size();i++)
{
if(list.get(i)==1)
{
double radius = Main.input.nextDouble();
Circle circle = new Circle(radius);
Card card=new Card(circle);
card.getShape().setShapeName("Circle");
cardArrayList.add(card);
}
if(list.get(i)==2) {
double width = Main.input.nextDouble();
double length = Main.input.nextDouble();
Rectangle rectangle = new Rectangle(width,length);
Card card = new Card(rectangle);
card.getShape().setShapeName("Rectangle");
cardArrayList.add(card);
}
if(list.get(i)==3) {
double side1 = Main.input.nextDouble();
double side2 = Main.input.nextDouble();
double side3 = Main.input.nextDouble();
Triangle triangle = new Triangle(side1,side2,side3);
Card card = new Card(triangle);
card.getShape().setShapeName("Triangle");
cardArrayList.add(card);
}
if(list.get(i)==4) {
double topSide = Main.input.nextDouble();
double bottomSide = Main.input.nextDouble();
double height = Main.input.nextDouble();
Trapezoid trapezoid = new Trapezoid(topSide,bottomSide,height);
Card card = new Card(trapezoid);
card.getShape().setShapeName("Trapezoid");
cardArrayList.add(card);
}
}

2.题目集7(7-2)

这个题目是一个图形卡片分组游戏,算是题目7-1的进阶版,其中题目集7-1的代码大部分都能保留,在题目7-1的基础上根据题目要求稍加改进和添加一些新的东西即可。

因为这是一个图形分组游戏,首先要将不同类型的图形卡片进行分组,然后在将每一组的的图形卡片面积进行排序,还要求出每一组的图形卡片总面积,再将每一组的图形卡片的总面积进行排序输出,并给出图形卡片的总面积最大的一组的数据。

了解完题目的需求后,我首先创建了四个数组链表储存不同类型的图形对象:

ArrayList<Card>circleArrayList = new ArrayList<>();
ArrayList<Card>rectangleArrayList = new ArrayList<>();
ArrayList<Card>triangleArrayList = new ArrayList<>();
ArrayList<Card>trapezoidArrayList = new ArrayList<>();

我认为这样相对来说更方便些,省得到后面再去判断图形对象的类型,完成这一步后接下来就是对每一组的卡片对象进行排序了,由于已经分好了组,对每组卡片对象进行排序只需要调用cardSort()方法就好了,接下来就是对每组卡片的面积求和并且排序,排序和求和已经做过很多遍了,就不过多赘述了。

类图:

3.题目集8

这次题目集居然只有一个题目,要求我们写一个ATM机仿真系统,能够完成用户的存款、取款以及查询余额功能。

写完这个题目以后,我认为这里最重要的是各个类之间的关系以及不同对象的属性该怎么给。在一开始,我是毫无头绪的,硬着头皮上,首先我创建了银联(ChinaUnionPay)类、银行(Bank)类、用户(User)类、账户(Account)类、银行卡(Card)类、ATM类,主要在ATM类中进行判断数据合法性和进行输出,在Main方法里创建List链表储存相关信息,而且还在Main方法里根据卡号去判断这个卡是属于那个银行的。如:if (m[i].equals("6217000010041315709") || m[i].equals("6217000010041315715") || m[i].equals("6217000010041315718"))。每个银行都用这种方法去判断,非常繁琐和复杂。

这道题在当时确实难到我了,自己写的代码有许多不合理之处,而且非常复杂。

类图:

4.题目集9

这次题目还是ATM机仿真系统,在题目集8的基础上增加了可以透支的信用卡,透支取款也要收手续费,跨行取款手续费的内容,而且不同银行的手续费是不一样的。

数据初始化代码:

UnionPay unionPay = new UnionPay();

Bank ccb = new Bank("1001","中国建设银行");
Bank icbc = new Bank("1002","中国工商银行");
Bank abc = new Bank("1003","中国农业银行");
unionPay.addBank(ccb);
unionPay.addBank(icbc);
unionPay.addBank(abc);

ATM aTM1 = new ATM("01",ccb);
ATM aTM2 = new ATM("02",ccb);
ATM aTM3 = new ATM("03",ccb);
ATM aTM4 = new ATM("04",ccb);
ATM aTM5 = new ATM("05",icbc);
ATM aTM6 = new ATM("06",icbc);
ATM aTM7 = new ATM("07",abc);
ATM aTM8 = new ATM("08",abc);
ATM aTM9 = new ATM("09",abc);
ATM aTM10 = new ATM("10",abc);
ATM aTM11 = new ATM("11",abc);

ccb.addATM(aTM1);
ccb.addATM(aTM2);
ccb.addATM(aTM3);
ccb.addATM(aTM4);
icbc.addATM(aTM5);
icbc.addATM(aTM6);
abc.addATM(aTM7);
abc.addATM(aTM8);
abc.addATM(aTM9);
abc.addATM(aTM10);
abc.addATM(aTM11);

User Yangguo = new User("360101200102122324","杨过","13856223254");
User Guojing = new User("360101200012302552","郭靖","13800021124");
User Zhangwuji = new User("360502199805163221","张无忌","13952110011");
User Weixiaobao = new User("360201200513243326","韦小宝","13025996587");
User Zhangsanfeng = new User("360502199802122324","张三丰","13025990011");
User Linghuchong = new User("360101200013243326","令狐冲","13800023254");
User Qiaofeng = new User("360201200512302552","乔峰","13800026587");
User Hongqigong = new User("360502199805163221","洪七公","13956226587");

Account ccbAcc1 = new Account("3217000010041315709",10000.00,Yangguo,ccb);
Account ccbAcc2 = new Account("3217000010041315715",10000.00,Yangguo,ccb);
Account ccbAcc3 = new Account("3217000010051320007",10000.00,Guojing,ccb);
Account ccAcc4 = new Account("3640000010045442002",10000.00,Zhangsanfeng,ccb);
Account icbcAcc1 = new Account("3222081502001312389",10000.00,Zhangwuji,icbc);
Account icbcAcc2 = new Account("3222081502001312390",10000.00,Zhangwuji,icbc);
Account icbcAcc3 = new Account("3222081502001312399",10000.00,Zhangwuji,icbc);
Account icbcAcc4 = new Account("3222081502051320785",10000.00,Weixiaobao,icbc);
Account icbcAcc5 = new Account("3222081502051320786",10000.00,Weixiaobao,icbc);
Account icbcAcc6 = new Account("3640000010045441009 ",10000.00,Linghuchong,icbc);
Account abcAcc1 = new Account("3630000010033431001",10000.00,Qiaofeng,abc);
Account abcAcc2 = new Account("3630000010033431008 ",10000.00,Hongqigong,abc);

ccb.addAccount(ccbAcc1);
ccb.addAccount(ccbAcc2);
ccb.addAccount(ccbAcc3);
ccb.addAccount(ccAcc4);
icbc.addAccount(icbcAcc1);
icbc.addAccount(icbcAcc2);
icbc.addAccount(icbcAcc3);
icbc.addAccount(icbcAcc4);
icbc.addAccount(icbcAcc5);
icbc.addAccount(icbcAcc6);
abc.addAccount(abcAcc1);
abc.addAccount(abcAcc2);

Yangguo.addAccount(ccbAcc1);
Yangguo.addAccount(ccbAcc2);
Guojing.addAccount(ccbAcc3);
Zhangwuji.addAccount(icbcAcc1);
Zhangwuji.addAccount(icbcAcc2);
Zhangwuji.addAccount(icbcAcc3);
Weixiaobao.addAccount(icbcAcc4);
Weixiaobao.addAccount(icbcAcc5);
Zhangsanfeng.addAccount(ccAcc4);
Linghuchong.addAccount(icbcAcc6);
Qiaofeng.addAccount(abcAcc1);
Hongqigong.addAccount(abcAcc2);

Card ccbCard1 = new Card("6217000010041315709","88888888",ccbAcc1,0);
Card ccbCard2 = new Card("6217000010041315715","88888888",ccbAcc1,0);
Card ccbCard3 = new Card("6217000010041315718","88888888",ccbAcc2,0);
Card ccbCard4 = new Card("6217000010051320007","88888888",ccbAcc3,0);
Card icbcCard5 = new Card("6222081502001312389","88888888",icbcAcc1,0);
Card icbcCard6 = new Card("6222081502001312390","88888888",icbcAcc2,0);
Card icbcCard7 = new Card("6222081502001312399","88888888",icbcAcc3,0);
Card icbcCard8 = new Card("6222081502001312400","88888888",icbcAcc3,0);
Card icbcCard9 = new Card("6222081502051320785","88888888",icbcAcc4,0);
Card icbcCard10 = new Card("6222081502051320786","88888888",icbcAcc5,0);
Card ccCard11 = new Card("6640000010045442002","88888888",ccAcc4,1);
Card ccCard12 = new Card("6640000010045442003","88888888",ccAcc4,1);
Card icbcCard13 = new Card("6640000010045441009","88888888",icbcAcc6,1);
Card abcCard14 = new Card("6630000010033431001","88888888",abcAcc1,1);
Card abcCard15 = new Card("6630000010033431008","88888888",abcAcc2,1);

ccbAcc1.addCard(ccbCard1);
ccbAcc1.addCard(ccbCard2);
ccbAcc2.addCard(ccbCard3);
ccbAcc3.addCard(ccbCard4);
icbcAcc1.addCard(icbcCard5);
icbcAcc2.addCard(icbcCard6);
icbcAcc3.addCard(icbcCard7);
icbcAcc3.addCard(icbcCard8);
icbcAcc4.addCard(icbcCard9);
icbcAcc5.addCard(icbcCard10);
ccAcc4.addCard(ccCard11);
ccAcc4.addCard(ccCard12);
icbcAcc6.addCard(icbcCard13);
abcAcc1.addCard(abcCard14);
abcAcc2.addCard(abcCard15);

这里的数据初始化看起来很麻烦,但实际就是将数据存储起来而已,没有技术含量,但我在题目集8中我并没有初始化数据,这样直接导致我数据合法性判断特别麻烦。

计算贷跨行取款手续费的代码:

计算贷款手续费:

这里card.getCardType()==1,1指的是信用卡,只有信用卡才能透支。

类图:

三. 踩坑心得 

1.在题目集的7-2中刚开始只用了一个List链表去存储图形卡片对象,用instanceof去判断是哪种图形对象,但这样会使得代码过于复杂,重新思考后还是用4个会比较方便些。

2.在题目集8中,我发现存在的问题还是挺多的,在一开始老师还没有对题目进行讲解时,只能硬着头皮去写,创建了几个类,写了我认为对应的属性和方法,然后在Main方法中根据输入的银行卡号,ATM机号等对应各种情况去匹配,即使用if-else语句将各种情况罗列出来,起初存在一些输出格式的问题,但修改后还是能够达到题目给出的要求。但在老师给出相应的类图并进行了部分讲解后发现自己写的并没有运用到新的内容和知识,所以需要进行重新构建类图,因为题目集9也需要在题目集8的基础上改进才能得到更好的答案,改进后基本实现了上面对设计与分析中的分析点,但其实和老师给出的类图以及讲解还是存在差异的,对于我个人而言还是能够完全理解的,所以在题目集8中最大的问题就是不知道如何对程序的进行设计与分析。

3.在遍历链表的时候使用for each如果要删除链表内容的时候,会出问题。在Main类中定义一个静态Scanner对象,这样在其它类中如果想要使用该对象进行输入,则直接使用Main.input.next…即可(避免采坑)

在看到这句话之前我们会在每个需要输入数据的方法中写一句:Scanner input = new Scanner(System.in);这样的一句提示,对我以后写代码提供了方便,代码在封装性上也会更好。

4.在题目集9中,也存在许多问题,首先对于取款跨行并且是贷款取款的运算是要仔细去推算它是如何计算费用的,其次因为题目集9输出格式与题目集8存在差异,应该认真看题目的要求去避免,编程不单单考研自己的编程能力,也考验自身的数学水平,还要有细心、仔细,不然很容易就会出现了错误但却一头雾水不知道哪里出了错误,细节决定成败,一个小小的bug可能会影响很大。

四.改进建议

1.题目集7的第二题我创建了四个ArrayList来进行存储图形卡片对象,这样代码相对来说要好写一点,但复杂度可能会更高,可以创建两个ArrayList来存储图形卡片对象,一个保存所有的图形卡片对象,一个将所有的图形卡片对象分类。

 2.题目集8中我用if语句去判断输入的银行卡号是属于哪个银行的,这样代码非常难写而且复杂,不容易看懂,应该改成类似题目集9那样的会比较合适,初始化数据,给它相应的属性就能解决用if去判断输入的数据是属于哪个银行的问题了。还有关于泛型容器只知道ArrayList,ArrayList类中的一些API也不会,需要学习的东西还有很多。

五、总结

随着时间的前进,这门课程也要迎来了它的尾声,这应该是最后一次作业总结了。这门课程将告一段落了,但Java的学习还在继续。

随着课程的进行,题目集的难度逐渐攀升,总的来说,题目集9是这三次题目集里综合性最高的,也是最难的,都说Java的三大核心是继承、多态和封装,我真真切切感受到了很多时候都要用到他们。通过写这三次题目集,我初步学习了较复杂数据的数据处理方式,链表的使用。但对抽象类,接口的作用以及应用环境还需要继续加深理解。关于接口,接口相当于一个完全抽象的抽象类,其中有抽象方法,而接口和抽象类一个重要的区别就是接口中只有抽象方法和常量,但接口可以进行多继承,这是两者的区别,使用接口可以提高代码的可维护性和扩展性,且接口可以减少代码的书写,学会使用接口对我们专业的学习非常有帮助。我现在还只了解接口的大概,还需要进一步地去学习接口。我认为我还是需要多花时间去学习,把自己不懂和不了解的的地方尽量去搞懂,像正则表达式这一部分我就只是简单的了解一些常用的用法,一些较为复杂的用法我还不是特别熟悉和了解,这方面就还存在很大的提升空间,其他还有没学习到的就不用说了,同时我也要多去做一些题巩固提升自己的能力,good good study,day day up!

对于课程和老师教学我认为很好,感谢老师在这个学期里的付出的努力,线上和线下相结合的学习方式可行性和效果还不错。

希望以后能在Java的路上走得更高、更远!