Java10-16周学习总结

前言

  在pta题目集6中,共有两道题,分别是电费计费系列1-座机计费和多态测试。第二题相对容易,第一题难度一般,因为给了类图帮助答题,涉及多态的构建和类的构造以及类与类之间的关系,通过题目所给信息,构造相应的方法,通过测试能够一步步实现题目所要求的功能。

  在pta题目集7中,共有三道题,电费计费系列2-手机+座机计费,sdut-Collection-sort--C~K的班级和阅读程序,按照题目需求修改程序。题目整体难度偏容易,根据前一题目集计费系列,更改相应的正则表达式和添加手机计费的类和函数方法,即可实现手机计费功能。第二题和第三题题目都给了代码,只需修改其代码,学习到递代器和集合等知识,便可以完成这两道题目。

  在pta题目集8中,共有三题,分别是电信计费系列3-短信计费,7-2 编写一个类Shop(商店)、内部类InnerCoupons(内部购物券)和动物发声模拟器(多态)。题目难度一般,其中第一题在前几题的基础上稍加修改即可完成,第二题使用内部类的概念可完成,第三题运用多态的知识便可以完成。

  在实验五中,要求修改农夫过河的代码,并将用户界面改为图形界面,自行设计其界面效果,通过先用BorderPane创建一个面板,用pane和GridPane分别创建农夫、狼、羊、白菜过河区域和按钮区域,并将这几个区域加入BorderPane类面板中,然后用几个文本文字代表农夫,羊,狼,白菜,通过使用PathTransition动画类移动这些文字实现过河的动作,测试无误后可以正常进行农夫过河小游戏。

设计与分析

  PTA题目集6:

 7-1 电信计费系列1-座机计费

实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
南昌市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。

输入格式:

输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码除区号外由是7-8位数字组成。
本题只考虑计费类型0-座机计费,电信系列2、3题会逐步增加计费类型。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
注意:
本题非法输入只做格式非法的判断,不做内容是否合理的判断(时间除外,否则无法计算),比如:
1、输入的所有通讯信息均认为是同一个月的通讯信息,不做日期是否在同一个月还是多个月的判定,直接将通讯费用累加,因此月租只计算一次。
2、记录中如果同一电话号码的多条通话记录时间出现重合,这种情况也不做判断,直接 计算每条记录的费用并累加。
3、用户区号不为南昌市的区号也作为正常用户处理。

输出格式:

根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,
单位元)。假设每个用户初始余额是100元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。

错误处理:
输入数据中出现的不符合格式要求的行一律忽略。

建议类图:
参见题目给的图1、2、3(此处省略),可根据理解自行修改。

后续扩展说明:
后续题目集将增加手机用户,手机用户的计费方式中除了与座机计费类似的主叫通话费之外,还包含市外接听电话的漫游费以及发短信的费用。在本题的设计时可统一考虑。
通话记录中,手机需要额外记录拨打/接听的地点的区号,比如:
座机打手机:t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
短信的格式:m-主叫号码,接收号码,短信内容
m-18907910010 13305862264 welcome to jiangxi
m-13305862264 18907910010 thank you

 

 

 

 

 

 

 度量分析:

 

 

 

   这题考察通过对所给类图能够完成类和类方法构造以及类之间相互调用,题目含义清楚,创建了类图给的信息、计费等类,也使用了抽象类的知识,刚开始使用正则表达式判断输入格式是否正确,再通过输入格式符合哪一个正则表达式来选择对应选项,然后使用相应方法来创建座机用户或者创建座机用户的通话记录,最后输入创建用户的数据信息,能够完成所有测试点。

主要代码分析:

     String regex="[u][-][0]{1}[7]{1}[9]{1}[1]{1}[0-9]{6,8}\\s[0-2]{1}";
     String regex1="[t][-][0]{1}[0-9]{9,11}\\s[0]{1}[0-9]{9,11}(\\s[0-9]{4}[.]([1-9]{1}|[1]{1}[0-2]{1})[.]([1-9]{1}|[1-2]{1}[0-9]{1}|[3]{1}[0-1]{1})\\s(20|21|22|23|[0-1]{1}[0-9]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})){2}";
     String tmp;
        while(true) {
            tmp = input.nextLine();
            Boolean a=tmp.matches(regex);
            Boolean b=tmp.matches(regex1);
            if(tmp.equals("end")) {
                break;
            }
            if(a) {
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("u-", "");
                int aa=0;
                for(User user1: Users) {
                    if(user1.getNumber().equals(z)) {
                        aa=1;
                        break;
                    }
                }
                if(aa==0) {
                    User user=new User();
                    Users.add(user);
                    user.setNumber(z);
                    if(x[1].equals("0")) {
                        user.getChargeMode().getChargeRules().add(new LandPhoneInCityRule());
                        user.getChargeMode().getChargeRules().add(new LandPhoneInProvinceRule());
                        user.getChargeMode().getChargeRules().add(new LandPhoneInlandRule());
                    }
                }
            }
            if(b) {
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("t-", "");
                for(User user: Users) {
                    String d=x[2]+" "+x[3];
                    String d1=x[4]+" "+x[5];
                    CallRecord callRecord=new CallRecord(z,x[1],d,d1);
                    if(user.getNumber().equals(z)&&!z.equals(x[1])) {
                        user.getUserRecords().add(callRecord);
                    }
                    if(user.getNumber().equals(x[1])&&!z.equals(x[1])) {
                        user.getUserRecords().add1(callRecord);
                    }
                }
            }
        }
        Comparator<User> comparator=new Comparator<User>() {
            public int compare(User user1,User user2) {
                return user1.getNumber().compareTo(user2.getNumber());
            }
        };

代码思路:

  先使用了两个正则表达式进行格式的判断,然后看输入的正确格式符合哪一个正则表达式,用此执行下一步创建座机用户或者通话记录,并将用户存入对应用户类集合中,再对集合的compare()方法进行重写,以用户电话号码从小到大排序输出集合中的用户数据。

优缺点:

  优点:

1.使用了正则表达式来判断输入格式的正确性,能够很好的正确的判断出输入格式是否有误,能够使得代码变得更加清晰,降低了代码的复杂度。

2.能够重写集合的compare()方法,使得用户数据正确有序的输出。

  缺点:

1.对正则表达式的使用中,在创建用户通话记录的正则表达式中,时间日期刚开始写的时候还有误差,应该更加考虑周全,对时间日期的把握到位。

PTA题目集7:

  7-1 电信计费系列2-手机+座机计费

  

实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
1、针对市内座机用户采用的计费方式(与电信计费系列1内容相同):
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
假设本市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
2、针对手机用户采用实时计费方式:
月租15元,市内省内接电话均免费,市内拨打市内电话0.1元/分钟,市内拨打省内电话0.2元/分钟,市内拨打省外电话0.3元/分钟,省内漫游打电话0.3元/分钟,省外漫游接听0.3元/分钟,省外漫游拨打0.6元/分钟;
注:被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定,比如以下案例中,南昌市手机用户13307912264在区号为020的广州接听了电话,主叫号码应被计算为拨打了一个省外长途,同时,手机用户13307912264也要被计算省外接听漫游费:
u-13307912264 1
t-079186330022 13307912264 020 2022.1.3 10:00:25 2022.1.3 10:05:11

输入:
输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,含手机和座机用户
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题在电信计费系列1基础上增加类型1-手机实时计费。
手机设置0或者座机设置成1,此种错误可不做判断。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
输入格式增加手机接打电话以及收发短信的格式,手机接打电话的信息除了号码之外需要额外记录拨打/接听的地点的区号,比如:
座机打手机:
t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:
t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11

注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。

输出:
根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条通讯、短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。

(提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。

 度量分析:

 主要代码分析:

     String regex="[u][-][0]{1}[0-9]{9,11}\\s[0-2]{1}";
        String regex1="[t][-][0]{1}[0-9]{9,11}\\s[0]{1}[0-9]{9,11}(\\s[1-9]{1}[0-9]{3}[.]([1-9]{1}|[1]{1}[0-2]{1})[.]([1-9]{1}|[1-2]{1}[0-9]{1}|[3]{1}[0-1]{1})\\s(20|21|22|23|[0-1]{1}[0-9]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})){2}";
        String regex2="[t][-][0]{1}[0-9]{9,11}\\s[1]{1}[0-9]{10}\\s[0]{1}[0-9]{2,3}(\\s[1-9]{1}[0-9]{3}[.]([1-9]{1}|[1]{1}[0-2]{1})[.]([1-9]{1}|[1-2]{1}[0-9]{1}|[3]{1}[0-1]{1})\\s(20|21|22|23|[0-1]{1}[0-9]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})){2}";
        String regex3="[t][-][1]{1}[0-9]{10}\\s[0]{1}[0-9]{2,3}\\s[1]{1}[0-9]{10}\\s[0]{1}[0-9]{2,3}(\\s[1-9]{1}[0-9]{3}[.]([1-9]{1}|[1]{1}[0-2]{1})[.]([1-9]{1}|[1-2]{1}[0-9]{1}|[3]{1}[0-1]{1})\\s(20|21|22|23|[0-1]{1}[0-9]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})){2}";
        String regex4="[t][-][1]{1}[0-9]{10}\\s[0]{1}[0-9]{2,3}\\s[1]{1}[0-9]{10}\\s[0]{1}[0-9]{2,3}\\s([0-9]|[a-z]|[A-Z]|[ ]|[,]|[.]){1,}";
        String regex5="[u][-][1]{1}[0-9]{10}\\s[1-2]{1}";
        String regex6="[t][-][1]{1}[0-9]{10}\\s[0]{1}[0-9]{2,3}\\s[0]{1}[0-9]{9,11}(\\s[1-9]{1}[0-9]{3}[.]([1-9]{1}|[1]{1}[0-2]{1})[.]([1-9]{1}|[1-2]{1}[0-9]{1}|[3]{1}[0-1]{1})\\s(20|21|22|23|[0-1]{1}[0-9]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})){2}";
        String tmp;
        while(true) {
            tmp = input.nextLine();
            Boolean a=tmp.matches(regex);
            Boolean b=tmp.matches(regex1);
            Boolean c=tmp.matches(regex2);
            Boolean d=tmp.matches(regex3);
            Boolean e=tmp.matches(regex4);
            Boolean f=tmp.matches(regex5);
            Boolean g=tmp.matches(regex6);
            if(tmp.equals("end")) {
                break;
            }
            if(a) {//创建座机用户
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("u-", "");
                int aa=0;
                for(User user1: Users) {
                    if(user1.getNumber().equals(z)) {
                        aa=1;
                        break;
                    }
                }
                if(aa==0) {
                    User user=new User();
                    Users.add(user);
                    user.setNumber(z);
                    ((LandlinePhoneCharging)user.getChargeMode()).setMonthlyRent(20);
                    if(x[1].equals("0")) {
                        user.getChargeMode().getChargeRules().add(new LandPhoneInCityRule());
                        user.getChargeMode().getChargeRules().add(new LandPhoneInProvinceRule());
                        user.getChargeMode().getChargeRules().add(new LandPhoneInlandRule());
                    }
                }
            }
            if(b) {//座机打座机
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("t-", "");
                for(User user: Users) {
                    String d1=x[2]+" "+x[3];
                    String d2=x[4]+" "+x[5];
                    CallRecord callRecord=new CallRecord(z,z.substring(0,4),x[1],x[1].substring(0,4),d1,d2);
                    if(user.getNumber().equals(z)&&!z.equals(x[1])) {
                        user.getUserRecords().add(callRecord);
                    }
                    if(user.getNumber().equals(x[1])&&!z.equals(x[1])) {
                        user.getUserRecords().add1(callRecord);
                    }
                }
            }
            if(c) {//座机打手机
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("t-", "");
                for(User user: Users) {
                    String d1=x[3]+" "+x[4];
                    String d2=x[5]+" "+x[6];
                    CallRecord callRecord=new CallRecord(z,z.substring(0,4),x[1],x[2],d1,d2);
                    if(user.getNumber().equals(z)) {
                        user.getUserRecords().add(callRecord);
                    }
                    if(user.getNumber().equals(x[1])) {
                        user.getUserRecords().add3(callRecord);
                    }
                }
            }
            if(d) {//手机打手机
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("t-", "");
                for(User user: Users) {
                    String d1=x[4]+" "+x[5];
                    String d2=x[6]+" "+x[7];
                    CallRecord callRecord=new CallRecord(z,x[1],x[2],x[3],d1,d2);
                    if(user.getNumber().equals(z)) {
                        user.getUserRecords().add2(callRecord);
                    }
                    if(user.getNumber().equals(x[2])) {
                        user.getUserRecords().add3(callRecord);
                    }
                }
            }
            if(e) {//短信
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("m-", "");
                String d1="";
                for(int i=2;i<x.length;i++) {
                    if(x.length==i+1) {
                        d1=d1+x[i];
                    }
                    else {
                        d1=d1+x[i]+" ";
                    }
                }
                for(User user: Users) {
                    MessageRecord messageRecord=new MessageRecord(z,x[1],d1);
                    if(user.getNumber().equals(z)) {
                        user.getUserRecords().add4(messageRecord);
                    }
                    if(user.getNumber().equals(x[1])) {
                        user.getUserRecords().add5(messageRecord);
                    }
                }
            }
            if(f) {//创建手机用户
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("u-", "");
                int aa=0;
                for(User user1: Users) {
                    if(user1.getNumber().equals(z)) {
                        aa=1;
                        break;
                    }
                }
                if(aa==0) {
                    User user=new User();
                    Users.add(user);
                    user.setNumber(z);
                    ((LandlinePhoneCharging)user.getChargeMode()).setMonthlyRent(15);
                    if(x[1].equals("1")) {
                        user.getChargeMode().getChargeRules().add(new PhoneInCityRule());
                        user.getChargeMode().getChargeRules().add(new PhoneInProvinceRule());
                        user.getChargeMode().getChargeRules().add(new PhoneInlandRule());
                        user.getChargeMode().getChargeRules().add(new PhonetellInlandRule());
                        user.getChargeMode().getChargeRules().add(new PhoneMessageRule());
                    }
                }
            }
            if(g) {//手机打座机
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("t-", "");
                for(User user: Users) {
                    String d1=x[3]+" "+x[4];
                    String d2=x[5]+" "+x[6];
                    CallRecord callRecord=new CallRecord(z,x[1],x[2],x[2].substring(0,4),d1,d2);
                    if(user.getNumber().equals(z)) {
                        user.getUserRecords().add2(callRecord);
                    }
                    if(user.getNumber().equals(x[2])) {
                        user.getUserRecords().add1(callRecord);
                    }
                }
            }
        }
        Comparator<User> comparator=new Comparator<User>() {
            public int compare(User user1,User user2) {
                return user1.getNumber().compareTo(user2.getNumber());
            }
        };
        Collections.sort(Users,comparator);
        for(User user: Users) {
            System.out.printf("%s %.1f %.1f",user.getNumber(),user.calCost(),user.calBalance());
            System.out.println();
        }

 

代码思路:题目集7-1该题目也为电费收费系列,该题在座机的基础上添加了手机计费功能,添加相应的正则表达式和手机收费类,能够完成手机的计费功能,再用sort()方法排序,通过printf来输出手机用户的数据信息。

优缺点:

优点:1.能够很好的使用正则表达式,正确对输入格式进行判断。

2.设计的类简洁明了,结构清晰,代码复杂度低,代码可读性强。

3.对数据封装的改进,将属性隐藏,提高代码安全性。

缺点:1.该题未使用座机功能,故有些代码未使用,可删去,减少代码数量,使代码更加清晰简洁。

PTA题目集8:

7-1 电信计费系列3-短信计费(50分)

实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。

输入:
输入信息包括两种类型
1、逐行输入南昌市手机用户开户的信息,每行一个用户。
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐 3-手机短信计费)
例如:u-13305862264 3
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题只针对类型3-手机短信计费。
2、逐行输入本月某些用户的短信信息,短信的格式:
m-主叫号码,接收号码,短信内容 (短信内容只能由数字、字母、空格、英文逗号、英文句号组成)
m-18907910010 13305862264 welcome to jiangxi.
m-13305862264 18907910010 thank you.

注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。

本题只考虑短信计费,不考虑通信费用以及月租费。

 

度量分析:

 该题目是根据题意和所给类图,设计相应的类和类方法,整体难度低,只需在计费系列前几题的基础上,仿造其类和类方法的构造,创建短信正则表达式,以及计算一条短信内字符数量的方法,通过输入样例测试得出对应输出,可完成所有测试点,解答该题目。

主要代码分析:

String regex4="[m][-][1]{1}[0-9]{10}\\s[1]{1}[0-9]{10}[ ]{1}([0-9]|[a-z]|[A-Z]|[ ]|[,]|[.]){1,}";
        String regex5="[u][-][1]{1}[0-9]{10}\\s[1-3]{1}";
        String tmp;
        while(true) {
            tmp = input.nextLine();
            Boolean e=tmp.matches(regex4);
            Boolean f=tmp.matches(regex5);
            if(tmp.equals("end")) {
                break;
            }
            if(e) {//短信
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("m-", "");
                String d1=tmp.substring(26);
                for(User user: Users) {
                    MessageRecord messageRecord=new MessageRecord(z,x[1],d1);
                    if(user.getNumber().equals(z)) {
                        int i=d1.length()/10;
                        if(d1.length()%10!=0) {
                            i=i+1;
                        }
                        for(int k=0;k<i;k++) {
                            user.getUserRecords().add4(messageRecord);
                        }
                    }
                    if(user.getNumber().equals(x[1])) {
                        user.getUserRecords().add5(messageRecord);
                    }
                }
            }
            if(f) {//创建手机用户
                String []x=tmp.split(" ");
                String z=x[0].replaceFirst("u-", "");
                int aa=0;
                for(User user1: Users) {
                    if(user1.getNumber().equals(z)) {
                        aa=1;
                        break;
                    }
                }
                if(aa==0) {
                    User user=new User();
                    Users.add(user);
                    user.setNumber(z);
                    ((LandlinePhoneCharging)user.getChargeMode()).setMonthlyRent(0);
                    if(x[1].equals("3")) {
                        user.getChargeMode().getChargeRules().add(new PhoneMessageRule());
                    }
                }
            }
        }

代码思路:创建短信格式的正则表达式,且创建短信类,通过输入短信的正确格式,判断短信字符数量,根据题意进行添加手机用户的短信记录,然后根据题目短信收费规则,得出对应的短信费用并输出,能够完成该题目的所有测试点,成功完成此题目。

优缺点:

优点:1.很好的根据题目题意,使用sort方法,构造正确的短信正则表达式,构造出相应正确的类方法,构造判断字符数量的方法,以此来判断是否加入多次短信记录,并且能够完成输出样例所给要求。

2.设计的类简洁明了,结构清晰,代码复杂度低,代码可读性强。

缺点:1.代码有些bug,如果要输出短信内容,则该代码会输出错误,因为此代码通过字符长度来创建加入多个短信记录。

实验五:

  修改实验四农夫过河游戏的代码,将用户界面改为图形界面,界面效果自行设计。并画出修改后的类图,说明在界面中使用了哪些技巧以达到较好地界面效果。

 

 

 

度量分析:

 

 

 阅读所给题目描述,通过javafx将用户界面改为图形界面,先用BorderPane创建一个面板,用pane和GridPane分别创建农夫、狼、羊、白菜过河区域和按钮区域,并将这几个区域加入BorderPane类面板中,然后创建几个按钮对应开始游戏按钮和四个功能选项,并将这些按钮加入GridPane类对象中,同时还创建了一个矩形区域来模拟小河,使用了PathTransition动画类,让农夫、羊、狼、白菜能够有移动过河的动作。将之前实验代码,放入对应按钮的事件中,同时更改部分代码,将内容输出改为放入文本显示区域(TextArea类对象),然后将Boat类放入Main类中,作为Main类的内部类,将显示状态方法和菜单方法,然后代码一一放入并写出各部分的注释,完成实验。

主要代码分析:

public class Main extends javafx.application.Application {
    private static boolean isStart = false;    // 是否已经开始
    private static boolean gameOver=false,//游戏结束标志,默认为false,代表游戏进行中,未结束
            win=false;     //游戏输赢标志,默认为false,代表未赢得游戏。
    Button button1, button2, button3, button4,button0; // 控制按钮
    private MaterialObject farmer=new Person("farmer","未过河");
    private MaterialObject wolf=new Animal("wolf","未过河");
    private MaterialObject sheep=new Animal("sheep","未过河");
    private MaterialObject cabbage=new Plante("cabbage","未过河");
    private Boat boat=new Boat();
    private AbstractRule gameOverRule=new GameOverRule(); //游戏结束规则
    private AbstractRule gameSuccessRule=new GameSuccessRule(); //游戏输赢规则
    @Override
    public void start(Stage primaryStage) throws Exception {
        BorderPane rootPane = new BorderPane(); // 边界布局面板
        Pane pane =new Pane();
        rootPane.setPadding(new Insets(10)); // 边缘内侧空白距离
        Rectangle rect0=new Rectangle(270, 0, 100, 300);
           rect0.setArcHeight(10);
         rect0.setArcWidth(10);
            rect0.setFill(Color.BLUE);
            //创建一个矩形
            Text rect=new Text(50,40,"农夫");
            Text rect1=new Text(50,100,"狼");
            Text rect2=new Text(50,160,"羊");
            Text rect3=new Text(50,220,"白菜");
            rect.setFill(Color.RED);
            rect1.setFill(Color.RED);
            rect2.setFill(Color.RED);
            rect3.setFill(Color.RED);
            pane.getChildren().add(rect0);
            pane.getChildren().add(rect);
            pane.getChildren().add(rect1);
            pane.getChildren().add(rect2);
            pane.getChildren().add(rect3);
            rootPane.setTop(pane);
        // 控制按钮
        GridPane controlPane = new GridPane();
        controlPane.setAlignment(Pos.CENTER);
        controlPane.setPadding(new Insets(11.5, 12.5, 13.5, 14.5));
        controlPane.setHgap(5.5);
        controlPane.setVgap(5.5);
        
        int helpRowNumNum = 4;
        int buttonWidth = 100;    // 按钮的宽
        int buttonHeight = 50;    // 按钮的高
        // controlPane.setRight(buttonRight);
        Button buttonEnter = new Button("开始游戏");
        buttonEnter.setPrefSize(buttonWidth, buttonHeight);
        controlPane.add(buttonEnter, helpRowNumNum+2, 1);
        
        rootPane.setLeft(controlPane);
        
        // 面板按钮
        GridPane attrPane = new GridPane();
        attrPane.setAlignment(Pos.CENTER);
        attrPane.setPadding(new Insets(11.5, 12.5, 13.5, 14.5));
        attrPane.setHgap(5.5);
        attrPane.setVgap(5.5);
    
        int helpRowNumNum2 = 14;
        int buttonWidth2 = 200;
        int buttonHeight2 = 50;
        button1 = new Button("1: 农夫独自过河");
        button1.setPrefSize(buttonWidth2, buttonHeight2);
        attrPane.add(button1, 0+helpRowNumNum2, 1);
        button2 = new Button("2: 农夫带狼一起过河");
        button2.setPrefSize(buttonWidth2, buttonHeight2);
        attrPane.add(button2, 3+helpRowNumNum2, 1);
        button3 = new Button("3: 农夫带羊一起过河");
        button3.setPrefSize(buttonWidth2, buttonHeight2);
        attrPane.add(button3, 0+helpRowNumNum2, 3);
        button4 = new Button("4: 农夫带白菜一起过河");
        button4.setPrefSize(buttonWidth2, buttonHeight2);
        attrPane.add(button4, 3+helpRowNumNum2, 3);
        button0 = new Button("退出游戏");
        button0.setPrefSize(buttonWidth2, buttonHeight2);
        attrPane.add(button0, 6+helpRowNumNum2, 5);
        
        rootPane.setCenter(attrPane);
        
        /****************控制事件****************/
        // 1: 农夫独自过河
        button1.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if(!isStart){
                    return;
                }
                PathTransition pt;
                if(farmer.getPlace().equals("未过河")) {
                    pt=new PathTransition(Duration.millis(3000),new Line(50,30,550,30),rect);
                }
                else {
                    pt=new PathTransition(Duration.millis(3000),new Line(550,30,50,30),rect);
                }
                pt.play();
                boat.crossRiver(farmer);
                ((Animal) sheep).eat(cabbage,(Person) farmer);//同下
                ((Animal) wolf).eat(sheep,(Person) farmer);//狼吃羊,如果羊不在同一边,则吃不到,如果在同一边,羊被吃
                showStatus((Person)farmer,(Animal)wolf,(Animal)sheep,(Plante)cabbage);
                gameOver = gameOverRule.judge((Person)farmer,(Animal)wolf,(Animal)sheep,(Plante)cabbage,gameOver);
                if(gameOver) {
                    win=gameSuccessRule.judge(null, (Animal)wolf, (Animal)sheep,(Plante)cabbage, null);
                    Alert alert = new Alert(AlertType.ERROR);
                    alert.setTitle("游戏提示");
                    alert.setHeaderText(null);
                    if(win) {
                        alert.setContentText("游戏结束!恭喜你获得游戏胜利");
                    }else {
                        alert.setContentText("游戏结束!很遗憾,游戏失败");
                    }
                    Optional<ButtonType> result = alert.showAndWait();
                    if (result.get()!=null) {
                        System.exit(0);
                    }
                }
                else {
                    menu();
                }
            }
        });
}

代码思路:用BorderPane创建一个面板,用pane和GridPane分别创建农夫、狼、羊、白菜过河区域和按钮区域,并将这几个区域加入BorderPane类面板中,然后创建几个按钮对应开始游戏按钮和四个功能选项,并将这些按钮加入GridPane类对象中,同时还创建了一个矩形区域来模拟小河,使用了PathTransition动画类来让农夫、狼、羊、白菜文本移动,来模拟过河的动作,让界面效果更加简洁明了。最后通过点击按钮来实现相应的操作,能够正常进行农夫过河小游戏。

优缺点:

优点:1.通过学习javafx的相关知识,能够很好的使用pane和PathTransition等类,以及相应类方法。

2.修改过后的图形界面简洁直观,动画效果明显,能够再点击按钮后正确的显示出过河的动作。

缺点:1.图形界面没有插入图片来表示农夫、狼、羊、白菜和小河,可能动画效果不是很美观,后续完善修改时要注意美观度,理解图片的相对路径来使用图片,并以图片移动来表示过河动作。

采坑心得

 PTA题目集六 第一题:

 compare方法因为排序参考因素不同,应该对其进行重写,在查阅相关资料,了解compare方法的正确含义后,以字符从小到大的顺序进行排序,得到对应正确的输出结果。

PTA题目集七 第一题 :

此处为正则表达式的构建,创建座机或者手机的通话记录的正则表达式时,我刚开始对其中的时间日期判断错误,有许多非法输入测试点无法通过,要注意题目所给的输入样例和输入信息,然后构造正确的正则表达式。

PTA题目集八 第一题:

 

 

 该题目比较简单,只需要在前几题基础上进行修改即可完成。如果一条短信字符数量超过10个则每10个字符算一条短信,该方法先计算字符个数,然后有几条则加入重复条数量的短信记录到手机用户中,但缺陷在于如果要求输出短信内容,则输出错误。

实验五:

  

 

 该题目使用动画时,记得需要创建PathTransition类对象,同时构造方法内可以加入动画的进行时间和路线以及要进行动画的结点,当然也可以构造对象之后定义,play()方法用于开始动画。

改进建议

题目集六、七、八 7-1:

1.由SourceMonitor以及PowerDesigner软件测评结果可以得知,代码复杂度低,因为吸取了前面题目集的教训,使用正则表达式,减少了许多if-else语句的使用。但是使用正则表达式需要注意格式的问题,需要做到准确无误,此题一开始使用正则表达式时我对通话记录的输入有所遗漏,后面发现是日期和时间地方的正则表达式有误导致测试点无法通过,故需要多训练使用正则表达式,熟悉它。

2.这些题目集的7-1 即第一题均为电信计费系列题目,整体难度不大,但如果当作一次作业来做,可能会懵,因此老师分为几次作业降低难度。在后续的遇到此类代码繁多的题目不能畏惧,细心仔细,一步步构造类和类方法,理解类与类之间的关系,能够很好的完成该类题目。

实验五:

由SourceMonitor的评测图以及PowerDesigner软件测评结果可知,代码复杂度低,类与类之间的调用明显,代码不繁杂,代码的复用性也高。将用户界面转换成图形界面时,使用javafx方面的知识,需要提高自学能力,查询相关的知识,翻阅课本来获取所需的类和方法,在后续要对图形界面的美观度和按钮位置等进行修改,使得图形界面更加美观简洁。

总结

 在java这几周的学习中,老师讲了javafx、集合容器、正则表达式等方面的知识,学习了一些java的进阶知识,同时复习了前几周学习的继承与多态、内部类等的知识。在前几周学习相对清楚的情况下,学习这些进阶知识就不会那么累,相对易于理解,只需要上课认真听课,课后温习写代码多加练习即可。当然学习javafx方面的知识时,应该多自学,很多类和方法都需要自己去看,去查阅,才能够理解和掌握相应需要的javafx知识。在java面向对象的学习中,应该多加练习代码,多提高自己的算法能力,其实也是在打牢基础,为以后更难的java知识做铺垫。同时扩展自己的知识面,多在网上学习一些Java的知识,或从书中寻找所需类和类方法,避免学习后面的知识时,困难重重。

这次的题目集六、题目集七、题目集八和实验五,让我明白了许多还需要提高的地方:

1.对于正则表达式虽然学习了许多,但掌握的不牢固,使用正则表达式时要考虑周全,同时需要结合题目所给条件和题意,多注意格式,避免出现一些小错误而导致输出结果有误。

2.对集合容器类方法函数要使用正确,并理解正确详细,compare方法和sort方法都是经常使用的,对于函数重写方面的知识也需熟悉掌握。

3.对于题目给出的类图要理解透彻,不要因为类图里面的类和类方法过多而产生畏惧的心理,要用于面对困难,仔细浏览题目,正确理解题意,会发现其实该题目不难,只是没有去尝试。

4.对集合容器类相应的一些知识还不够理解掌握,以及javafx的许多含义和类都不了解。容器类的许多方法还需多背,对容器类对象的调用需要多加理解、练习。javafx方面的知识还需要自己多去学习,提高自主学习能力。

5.多学会自主学习,做学习时间安排表,课后多查阅java知识资料,可以在博客园、CSDN、MOOC等地方查阅相关Java的方法、知识,通过其中的Java文章和课程,巩固自己对java的理解,并且多记住一些Javafx的基本函数和语法,对java的一些基本数据类型要了解透彻,然后多写Java代码练习java,提升自己使用java编程的能力。

posted @ 2022-06-18 12:28  Z..阳  阅读(124)  评论(0)    收藏  举报