第三次作业Blog总结

一、作业总结

这三次作业相对于之前两次作业,作业量并没有增加,但是难度系数相较之有所增加了。之前所考察的多态、继承、封装、接口等,本次作业均有所考察,并且大多放在同一次题目集进行考察,所以复杂度大大提高了,所需要耗时更多了。

但是对于题目集8,我写的代码类间设计存在一定的问题,并且,没有很好的理解ArrayList的用法,代码缺少扩展性和维护性。所以,该次作业虽然PTA的测试点都通过了,但是单独将代码拿出来还是很有问题的。

下面我就对这三次题目集做个简要分析。

  1. 图形卡片排序游戏(题目集7

作业指导中有给出完整的类图和主方法源码,这对我们做题有很大的指导。对于这道题,考察的就是类的继承、多态性使用方法以及接口的应用。题中要求设计圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid)四种卡片类型,四种卡片均继承于Shape类。另有要求对卡片排序时使用Comparable接口,即Card类需要实现Comparable接口中的CompareTo()方法。这是学习java以来第一次使用Comparable接口,所以开始学习的时候费了点时间,学习了以后发现使用起来非常方便。

SourceMonitor生成报表内容如下:

 

 

 

 

圈复杂度只有7,题目比较简单,所以代码也比较简单,复杂程度并不高,稍微在接口处学习下就能做好题。

 

PowerDesigner类图如下:

 

 

 

 

 

只有几处使用了数组遍历,提高了代码的复杂程度,例如:

public boolean validate(){
    for(Card card : cardList)
    {
        if(card.getShape().validate())
            return true;
        else
            return false;
    }
    return true;
}

此题还有的重点在于排序,排序代码如下:

public void cardSort(){
    for(int i = 0; i < cardList.size(); i++)
    {
        for(int j = i + 1; j < cardList.size(); j++)
        {
            if(cardList.get(i).getShape().getArea() < cardList.get(j).getShape().getArea())
                Collections.swap(cardList,i,j);
        }
    }
}

public double getAllArea(){
    double sumarea = 0;
    for(Card card : cardList)
    {
        sumarea += card.getShape().getArea();
    }
    return sumarea;
}

输出方法:

public void showResult(){
    System.out.println("The original list:");
    for(int i = 0; i < cardList.size(); i++)
    {
        System.out.print(cardList.get(i).getShape().getShapeName()+":"+String.format("%.2f",cardList.get(i).getShape().getArea())+" ");
    }
    System.out.println();
    System.out.println("The sorted list:");
    cardSort();
    for(int i = 0; i < cardList.size(); i++)
    {
        System.out.print(cardList.get(i).getShape().getShapeName()+":"+String.format("%.2f",cardList.get(i).getShape().getArea())+" ");
    }
    ;
    System.out.println();
    System.out.println("Sum of area:"+String.format("%.2f",getAllArea()));
}

2.图形卡片分组游戏(题目集7)

这道题与第一题类似,只是在7-1的基础上进一步改进和完善。

由如下SourceMonitor生成报表可以看到,圈复杂程度并没有较大提高,因为较之7-1,只是输出方式和排序方式有所改变,其他的并没有大的变化。

 

 

 

 

7-1是从小到大排序,而7-2是在每一个图形集合里进行排序。

排序算法如下:

public void cardSort(){
    Collections.sort(circles);
    Collections.sort(rectangles);
    Collections.sort(triangles);
    Collections.sort(trapezoids);
    String s1="",s2="",s3="",s4="";
    System.out.print("[");
    for(int i=circles.size()-1;i>=0;i--)
        s1=s1+circles.get(i).toString()+" ";
    System.out.print(s1);
    System.out.print("]");
    System.out.print("[");
    for(int i=rectangles.size()-1;i>=0;i--)
        s2=s2+rectangles.get(i).toString()+" ";
    System.out.print(s2);
    System.out.print("]");
    System.out.print("[");
    for(int i=triangles.size()-1;i>=0;i--)
        s3=s3+triangles.get(i).toString()+" ";
    System.out.print(s3);
    System.out.print("]");
    System.out.print("[");
    for(int i=trapezoids.size()-1;i>=0;i--)
        s4=s4+trapezoids.get(i).toString()+" ";
    System.out.print(s4);
    System.out.print("]");
}

输出代码如下:

public void showResult(){
    System.out.println("The original list:");
    System.out.print("[");
    double[] s=new double[4];
    for (Card card:cardArrayList){
        System.out.print(card.getShape()+" ");
    }
    System.out.print("]");
    System.out.println();
    System.out.println("The Separated List:");
    System.out.print("[");
    for(Circle circle:circles)
    { System.out.printf("Circle:%.2f ",circle.getArea());
        s[0]=s[0]+circle.getArea();}
    System.out.print("]");
    System.out.print("[");
    for(Rectangle rectangle:rectangles)
    { System.out.printf("Rectangle:%.2f ",rectangle.getArea());
        s[1]=s[1]+rectangle.getArea();}
    System.out.print("]");
    System.out.print("[");
    for(Triangle triangle:triangles)
    {System.out.printf("Triangle:%.2f ",triangle.getArea());
        s[2]=s[2]+triangle.getArea();}
    System.out.print("]");
    System.out.print("[");
    for(Trapezoid trapezoid:trapezoids)
    { System.out.printf("Trapezoid:%.2f ",trapezoid.getArea());
        s[3]=s[3]+trapezoid.getArea();}
    System.out.print("]");
    System.out.println();
    System.out.println("The Separated sorted List:");
    cardSort();
    System.out.println();
    double max=s[0];
    for(int i=0;i<4;i++){
        if(s[i]>=max)
            max=s[i];
    }
    System.out.printf("The max area:%.2f",max);
}

对比PowerDesigner生成的7-2类图和7-1类图并无太大的差别。

 

 

 

 

 

3.ATM机类结构设计(一)(题目集8)

说实话,刚做这道题的时候,根本没有思路,完全写不出来,题目有些晦涩难懂,可能是因为太多的类设计非常复杂,一环套一环,思路很乱,不知从何下手。题目给的信息还算比较全面的,但其实有一些在最后运行中可能用不上,但如果在实际生活中,是有必要的。例如账户,其实在输入输出中未曾出现过,但其实在类间套中还是发挥了很大的作用,在最初的代码中,由于发现很多类其实用不太到,所以没有在代码中并没有加入相应类。类间关系设计又问题,另外,ArrayList用得不对,未能很好的弄清楚ArrayList是做什么的,导致代码没有扩展性和维护性。主类写的过于复杂,非常不整洁。主类内用的都是for循环内的if-else语句,所以说代码没有扩展性和维护性,没有实现面向对象的思维。

主类如下:

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String sa="";
        double m0=10000;
        double m1=10000;double m2=10000;double m3=10000;
        sa=in.nextLine();
        String a[]=sa.split("\\s+");
        while(!sa.equals("#")){
            //System.out.println(a[0]);
            China china=new China();
            User user=new User();
            Bank bank=new Bank();
            bank.useradd();
            bank.useratm();
            user.addcard();
            int t=0;
            if(a.length==1)
            {
                for(int i=0;i<user.card0.size();i++)
                {
                    if(a[0].equals(user.card0.get(i).card))
                    {t=1;
                        System.out.println("¥"+String.format("%.2f",m0));
                        //System.exit(0);
                    }
                }
                for(int i=0;i<user.card1.size();i++)
                {
                    if(a[0].equals(user.card1.get(i).card))
                    {t=1;
                        System.out.println("¥"+String.format("%.2f",m1));
                    }
                }
                for(int i=0;i<user.card2.size();i++)
                {
                    if(a[0].equals(user.card2.get(i).card))
                    {t=1;
                        System.out.println("¥"+String.format("%.2f",m2));
                    }
                }
                for(int i=0;i<user.card3.size();i++)
                {
                    if(a[0].equals(user.card3.get(i).card))
                    {t=1;
                        System.out.println("¥"+String.format("%.2f",m3));
                    }
                }
                if(t==0) {
                    System.out.println("Sorry,this card does not exist.");
                    System.exit(0);
                }
            }
            t=0;
            int s=0;
            if(a.length==4)
            {for(int i=0;i<user.card0.size();i++)
            {
                if(!a[0].equals(user.card0.get(i).card))
                {
                    s++;
                }
            }
                for(int i=0;i<user.card1.size();i++)
                {
                    if(!a[0].equals(user.card1.get(i).card))
                    {
                        s++;
                    }
                }
                for(int i=0;i<user.card2.size();i++)
                {
                    if(!a[0].equals(user.card2.get(i).card))
                    {
                        s++;
                    }
                }
                for(int i=0;i<user.card3.size();i++)
                {
                    if(!a[0].equals(user.card3.get(i).card))
                    {
                        s++;
                    }
                }
                if(s==10)
                {
                    System.out.println("Sorry,this card does not exist.");
                    System.exit(0);
                }
                if(a[1].equals("88888888")) {
                    if(a[2].equals(bank.atm.get(0).name)||a[2].equals(bank.atm.get(1).name)||a[2].equals(bank.atm.get(2).name)||a[2].equals(bank.atm.get(3).name)||a[2].equals(bank.atm1.get(0).name)||a[2].equals(bank.atm1.get(1).name))
                    {
                        for(int i=0;i<user.card0.size();i++)
                        {t=1;
                            if(a[0].equals(user.card0.get(i).card)&&a[1].equals(user.card0.get(i).password)&&(a[2].equals(bank.atm.get(0).name)||a[2].equals(bank.atm.get(1).name)||a[2].equals(bank.atm.get(2).name)||a[2].equals(bank.atm.get(3).name)||a[2].equals(bank.atm1.get(0).name)||a[2].equals(bank.atm1.get(1).name)))
                            {
                                if(a[2].equals(bank.atm1.get(0).name)||a[2].equals(bank.atm1.get(1).name))
                                {
                                    System.out.println("Sorry,cross-bank withdrawal is not supported.");
                                    System.exit(0);
                                }
                                if(m0<Double.parseDouble(a[3]))
                                {
                                    System.out.println("Sorry,your account balance is insufficient.");
                                    System.exit(0);
                                }
                                if(Double.parseDouble(a[3])>0)
                                {
                                    System.out.println("杨过在中国建设银行的"+a[2]+"ATM机上取款¥"+String.format("%.2f",Double.parseDouble(a[3])));
                                    m0=m0-Double.parseDouble(a[3]);
                                    System.out.println("当前余额为¥"+String.format("%.2f",m0));
                                }
                                if(Double.parseDouble(a[3])<0)
                                {
                                    System.out.println("杨过在中国建设银行的"+a[2]+"ATM机上存款¥"+String.format("%.2f",-Double.parseDouble(a[3])));
                                    m0=m0-Double.parseDouble(a[3]);
                                    System.out.println("当前余额为¥"+String.format("%.2f",m0));
                                }
                            }
                        }
                        for(int i=0;i<user.card1.size();i++)
                        {
                            if(a[0].equals(user.card1.get(i).card)&&a[1].equals(user.card1.get(i).password)&&(a[2].equals(bank.atm.get(0).name)||a[2].equals(bank.atm.get(1).name)||a[2].equals(bank.atm.get(2).name)||a[2].equals(bank.atm.get(3).name)||a[2].equals(bank.atm1.get(0).name)||a[2].equals(bank.atm1.get(1).name)))
                            {if(a[2].equals(bank.atm1.get(0).name)||a[2].equals(bank.atm1.get(1).name))
                            {
                                System.out.println("Sorry,cross-bank withdrawal is not supported.");
                                System.exit(0);
                            }
                                if(m1<Double.parseDouble(a[3]))
                                {
                                    System.out.println("Sorry,your account balance is insufficient.");
                                    System.exit(0);
                                }
                                if(Double.parseDouble(a[3])>0)
                                {
                                    System.out.println("郭靖在中国建设银行的"+a[2]+"ATM机上取款¥"+String.format("%.2f",Double.parseDouble(a[3])));
                                    m1=m1-Double.parseDouble(a[3]);
                                    System.out.println("当前余额为¥"+String.format("%.2f",m1));
                                }
                                if(Double.parseDouble(a[3])<0)
                                {
                                    System.out.println("郭靖在中国建设银行的"+a[2]+"ATM机上存款¥"+String.format("%.2f",-Double.parseDouble(a[3])));
                                    m1=m1-Double.parseDouble(a[3]);
                                    System.out.println("当前余额为¥"+String.format("%.2f",m1));
                                }
                            }
                        }
                        for(int i=0;i<user.card2.size();i++)
                        {
                            if(a[0].equals(user.card2.get(i).card)&&a[1].equals(user.card2.get(i).password)&&(a[2].equals(bank.atm1.get(0).name)||a[2].equals(bank.atm1.get(1).name)||a[2].equals(bank.atm.get(0).name)||a[2].equals(bank.atm.get(1).name)||a[2].equals(bank.atm.get(2).name)||a[2].equals(bank.atm.get(3).name)))
                            {if(a[2].equals(bank.atm.get(0).name)||a[2].equals(bank.atm.get(1).name)||a[2].equals(bank.atm.get(2).name)||a[2].equals(bank.atm.get(3).name))
                            {
                                System.out.println("Sorry,cross-bank withdrawal is not supported.");
                                System.exit(0);
                            }
                                if(m2<Double.parseDouble(a[3]))
                                {
                                    System.out.println("Sorry,your account balance is insufficient.");
                                    System.exit(0);
                                }
                                if(Double.parseDouble(a[3])>0)
                                {
                                    System.out.println("张无忌在中国工商银行的"+a[2]+"ATM机上取款¥"+String.format("%.2f",Double.parseDouble(a[3])));
                                    m2=m2-Double.parseDouble(a[3]);
                                    System.out.println("当前余额为¥"+String.format("%.2f",m2));
                                }
                                if(Double.parseDouble(a[3])<0)
                                {
                                    System.out.println("张无忌在中国工商银行的"+a[2]+"ATM机上存款¥"+String.format("%.2f",-Double.parseDouble(a[3])));
                                    m2=m2-Double.parseDouble(a[3]);
                                    System.out.println("当前余额为¥"+String.format("%.2f",m2));
                                }
                            }
                        }
                        for(int i=0;i<user.card3.size();i++)
                        {
                            if(a[0].equals(user.card3.get(i).card)&&a[1].equals(user.card3.get(i).password)&&(a[2].equals(bank.atm.get(0).name)||a[2].equals(bank.atm.get(1).name)||a[2].equals(bank.atm.get(2).name)||a[2].equals(bank.atm.get(3).name)||a[2].equals(bank.atm1.get(0).name)||a[2].equals(bank.atm1.get(1).name)))
                            {if(a[2].equals(bank.atm.get(0).name)||a[2].equals(bank.atm.get(1).name)||a[2].equals(bank.atm.get(2).name)||a[2].equals(bank.atm.get(3).name))
                            {
                                System.out.println("Sorry,cross-bank withdrawal is not supported.");
                                System.exit(0);
                            }
                                if(m2<Double.parseDouble(a[3]))
                                {
                                    System.out.println("Sorry,your account balance is insufficient.");
                                    System.exit(0);
                                }
                                if(Double.parseDouble(a[3])>0)
                                {
                                    System.out.println("韦小宝在中国工商银行的"+a[2]+"ATM机上取款¥"+String.format("%.2f",Double.parseDouble(a[3])));
                                    m3=m3-Double.parseDouble(a[3]);
                                    System.out.println("当前余额为¥"+String.format("%.2f",m3));
                                }
                                if(Double.parseDouble(a[3])<0)
                                {
                                    System.out.println("韦小宝在中国工商银行的"+a[2]+"ATM机上存款¥"+String.format("%.2f",-Double.parseDouble(a[3])));
                                    m2=m2-Double.parseDouble(a[3]);
                                    System.out.println("当前余额为¥"+String.format("%.2f",m3));
                                }
                            }
                        }
                    }
                    else{
                        System.out.print("Sorry,the ATM's id is wrong.");
                        System.exit(0);
                    }
                }
                else {
                    System.out.print("Sorry,your password is wrong.");
                    System.exit(0);
                }
            }
            sa=in.nextLine();
            a=sa.split("\\s+");
        }
    }
}

可以看到代码写的很没有条理。

由SourceMonitor的生成报表和PowerDesigner生成的类图如下:

 

 

 

 

 

所以在下一次作业时,老师给了源码,在源码基础上进行改编,难度降低了很多。

4.ATM机类结构设计(二)

9-1是在8-1的基础上进行跨行取款操作,由于老师给了源码,增加的难点只是现在银行卡分为借记卡和信用卡,实现跨行取款的基础上,需要考虑手续费的大小,是否透支取款,并且是否超过透支的最大额度等等。考察的点比较多,需要考虑的细节也就比较多。这道题实际上难度已经极大减少,我在写代码的过程中也没有太多的疑问,唯一困住的就是在写手续费相关算法时不太会算,这可能和本身数学不太好有关吧。因为这本身毕竟只是一个很简单的数学问题。所以在写整道题上并没有花太多时间,一个多小时就写完了。

在实现取款余额更新的地方,需要判断是借记卡还是信用卡,我使用了正则表达式来判断:

//取款更新余额操作
Pattern pattern01 = Pattern.compile("62\\d{17}");
Matcher matcher01 = pattern01.matcher(cardNO);
if(matcher01.find())
{
    if(account.getBank().getBankNO() != aTM.getBank().getBankNO()) {
        account.setBalance(balance - amount - amount * aTM.getCharges());
    }
    else
        account.setBalance(balance - amount);
    if(account.getBalance() < 0)
    {
        System.out.println("Sorry,your account balance is insufficient.");
        System.exit(0);
    }
    if (balance - amount < 0) {
        System.out.println("Sorry,your account balance is insufficient.");
        System.exit(0);
    }

}
Pattern pattern02 = Pattern.compile("66\\d{17}");
Matcher matcher02 = pattern02.matcher(cardNO);
if(matcher02.find())
{
    if(amount > balance)
    {
        if(balance > 0)
        {
            if(account.getBank().getBankNO() != aTM.getBank().getBankNO()) {
                account.setBalance(balance - amount - amount * aTM.getCharges() - (amount - balance) * 0.05);
            }
            else
                account.setBalance(balance - amount - (amount - balance) * 0.05);
            if((balance - amount) < -50000.00)
            {
                System.out.println("Sorry,your account balance is insufficient.");
                System.exit(0);
            }
        }
        else if(balance - amount > -50000.00 && balance <= 0)
        {
            if(account.getBank().getBankNO() != aTM.getBank().getBankNO())
                account.setBalance(balance - amount - amount * aTM.getCharges() - amount * 0.05);
            else
                account.setBalance(balance - amount - amount * 0.05);
        }

        else
        {
            System.out.println("Sorry,your account balance is insufficient.");
            System.exit(0);
        }
    }
    else
    {
        if(account.getBank().getBankNO() != aTM.getBank().getBankNO()) {
            account.setBalance(balance - amount - amount * aTM.getCharges());
        }
        else
            account.setBalance(balance - amount);
    }
    if(account.getBalance() < -50000)
    {
        System.out.println("Sorry,your account balance is insufficient.");
        System.exit(0);
    }
}

PowerDesigner类图和SourceMonitor生成报表内容如下:

 

 

 

 

圈复杂度还有23说明还是写的有些复杂了。

二、踩坑心得

对于题目集7踩坑倒不是很大,做题目的过程并没有遇到特别难的点,问题最多的就当属题目集8的8-1了。这道题的类设计我做的很有问题。例如同样的Account类:

老师写的部分代码:

class Account{
    private String accountNO;
    private double balance = 0;
    private User user = null;
    private Bank bank = null;
    private static ArrayList<Card> list = new ArrayList<Card>();
    public Account() {
        super();
        // TODO Auto-generated constructor stub
    }

    public Account(String accountNO, double balance, User user, Bank bank) {
        super();
        this.accountNO = accountNO;
        this.balance = balance;
        this.user = user;
        this.bank = bank;
    }

    public void addCard(Card card) {
        list.add(card);
    }

    public void removeCard(Card card) {
        list.remove(card);
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public String getAccountNO() {
        return accountNO;
    }

    public void setAccountNO(String accountNO) {
        this.accountNO = accountNO;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Bank getBank() {
        return bank;
    }

    public void setBank(Bank bank) {
        this.bank = bank;
    }

    public ArrayList<Card> getList() {
        return list;
    }

    public void setList(ArrayList<Card> list) {
        Account.list = list;
    }

    public static Account getAmountbyCardNO(String cardNO) {
        Iterator<Card> cardItr = Account.list.iterator();
        Card card = null;

        while(cardItr.hasNext()) {
            card = cardItr.next();
            if(card.getCardNO().equals(cardNO)) {
                return card.getAccount();
            }
        }

        return null;
    }
}

我写的部分代码:

class Account{
    ArrayList<BankCount> mycount=new ArrayList<>();
    public void Yangguo(){
        BankCount one=new BankCount("中国建设银行","3217000010041315709");
        BankCount two=new BankCount("中国建设银行", "3217000010041315715");
        one.cardnumb.add("6217000010041315709");
        one.cardnumb.add("6217000010041315715");
        two.cardnumb.add("6217000010041315718");
        mycount.add(one);
        mycount.add(two);
    }
    public void Guojing(){
        BankCount one =new BankCount("中国建设银行","3217000010051320007");
        one.cardnumb.add("6217000010051320007");
    }
    public void Zhangwuji(){
        BankCount one=new BankCount("中国工商银行", "3222081502001312389");
        BankCount two=new BankCount("中国工商银行","3222081502001312390");
        BankCount three=new BankCount("中国工商银行", "3222081502001312399");
        one.cardnumb.add("6222081502001312389");
        two.cardnumb.add("6222081502001312390");
        three.cardnumb.add("6222081502001312399");
        three.cardnumb.add("6222081502001312400");
        mycount.add(one);
        mycount.add(two);
        mycount.add(three);
    }
    public void Weixxiaobao(){
        BankCount one =new BankCount("中国工商银行", "3222081502051320785");
        one.cardnumb.add("6222081502051320785");
        BankCount two=new BankCount("中国工商银行", "3222081502051320786");
        two.cardnumb.add("6222081502051320786");
        mycount.add(one);
        mycount.add(two);
    }
}

可以很明显的对比出我的类写的并不好,类间设计存在很大的问题。看了老师的主类后,我才知道原来这些个人信息都是要放在主类内。我现在写的代码只需要有几个人的信息,那如果成百上千人的信息的时候,我的代码就完全失效了。所以,从长远考虑,如若未来做大工程的项目,需要庞大的用户信息,类设计是非常重要的,类设计没有写好,后续的问题会非常大。

三、改进建议

这三次题目集的SourceMonitor生成报表可以看到,我的代码圈复杂程度都比较高,有一次题目甚至达到了78,这是个非常需要改进的问题。

另外,老师有强调过一些地方要学会写注释,由于很多时候写代码的时候我自己的已经能看懂才会写上去,所以注释经常会忘记或认为这个地方好像不太需要写相应注释,这个问题需要改进。

最后,每次写题我都有点拖延,这是个大问题,需要改进。

四、总结

从题目集1到现在的题目集9,难度真的跨越度还蛮大的,但是一次次的题目集的练习,写代码的技巧,算法能力,速度都有所提升了。但是说是否每一次题目我都很好的理解透彻彻了,这肯定是没有的,我还有很多不懂的地方,比如说正则表达式还是用的一般般,只能一些简单的用法,每次使用还要借助网页的正则表达式测试工具;再者,类设计这个大问题希望在日后的学习中能相应改进,能设计得规范、逻辑性强。

最后,希望老师能日后继续多多指正我的问题,希望我在Java的程序学习上少走弯路!