前言:
最近的三次实验是对于电信计费的设计,包括座机,手机,信息。有很多的要求,包括:跨省聊天什么的。不同的情况的要价是不同的,所以我们需要对这些情况进行讨论。题目是给出了类图的,只需要进行
方法的具体解释就行。时间必须符合"yyyy.MM.dd HH:mm:ss"格式,使用SimpleDateFormat类。这是最麻烦的点,但在第三次作业中可不考虑这种。格式依旧:号码+英文空格符+总的话费+英文空格符+余额,可以合理的利用之前的方式来分割。很不错。
第五次:
第五次大作业是多边形的收尾,可以多次利用前面的来判定五边形的很多情况。
public static void choice1(ArrayList<Point> ps) { JudgePoint.wrongNumberOfPoints(ps, 5); Cross t = new Cross(ps.get(0),ps.get(1),ps.get(2),ps.get(3),ps.get(4)); if(t.isPentagon()) { System.out.println("true"); } else System.out.println("false"); }
这是第一个判定,很简单但也很基础,在第一次判定时我就出错了,但这很重要的,所以不可以小看,可利用四边形来进行判定这会非常简单,如上。
public static void choice2(ArrayList<Point> ps) { JudgePoint.wrongNumberOfPoints(ps, 5); Cross t = new Cross(ps.get(0),ps.get(1),ps.get(2),ps.get(3),ps.get(4)); if(t.isPentagon()==false){ System.out.println("not a pentagon"); //System.exit(0); }else{ if(t.ConvexOrConcave()==true){ System.out.print("true " + OutFormat.doubleFormat(t.perimeter()) + " " + OutFormat.doubleFormat(t.area())); }else{ System.out.println("false"); } } }
public static void choice3(ArrayList<Point> ps) { JudgePoint.wrongNumberOfPoints(ps, 7); if(ps.get(0).equals(ps.get(1))){ System.out.print("points coincide"); return; } Line l = new Line(ps.get(0),ps.get(1)); Cross c = new Cross(ps.get(2),ps.get(3),ps.get(4),ps.get(5),ps.get(6)); if(c.isPentagon()){ if(l.isCoincide(c.l12)||l.isCoincide(c.l23)||l.isCoincide(c.l34)||l.isCoincide(c.l45)||l.isCoincide(c.l51)) { System.out.print("The line is coincide with one of the lines"); return; } ps = c.getIntersections(l); //System.out.println(ps.get(0) + " " + ps.get(1)); int num = ps.size(); if (num == 2) { double[] ds = c.calArea(ps.get(0), ps.get(1)); Arrays.sort(ds); System.out.print(num + " " + OutFormat.doubleFormat(ds[0]) + " " + OutFormat.doubleFormat(ds[1])); } else { System.out.print(num); } }else if(c.isQuadr()) { if(l.isCoincide(c.l12)||l.isCoincide(c.l23)||l.isCoincide(c.l34)||l.isCoincide(c.l45)||l.isCoincide(c.l51)) { System.out.print("The line is coincide with one of the lines"); return; } Quadr q1 = c.quadrilateral(); ps = q1.getIntersections(l); int num = ps.size(); if (num == 2) { //if(ps.get(0).equals(p1) ) double[] ds = q1.calArea(ps.get(0), ps.get(1)); Arrays.sort(ds); System.out.print(num + " " + OutFormat.doubleFormat(ds[0]) + " " + OutFormat.doubleFormat(ds[1])); } else { System.out.print(num); } }else if(c.isTriangle()) { if(l.isCoincide(c.l12)||l.isCoincide(c.l23)||l.isCoincide(c.l34)||l.isCoincide(c.l45)||l.isCoincide(c.l51)) { System.out.print("The line is coincide with one of the lines"); return; } Triangle t = c.triangle(); ps = t.getIntersections(l); int num = ps.size(); if (num == 2) { double[] ds = t.calArea(ps.get(0), ps.get(1)); Arrays.sort(ds); System.out.print(num + " " + OutFormat.doubleFormat(ds[0]) + " " + OutFormat.doubleFormat(ds[1])); } else System.out.print(num); } else { System.out.print("not a pentagon"); } }
如上两种方法也是同样的,更可以结合三角形进行判定,有之前的经验,我们可以做的更轻松些。
第六次:
从第六次作业开始,时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。这个明显时很重要的。所以我们必须对其进行更好地划分和处理才行。
String[] array = dateString.split("\\."); int year = Integer.valueOf(array[0]); int month = Integer.valueOf(array[1]); int day = Integer.valueOf(array[2]); if (month < 1 || month > 12) { return false; } int[] monthLengths = new int[] { 0, 31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (isLeapYear(year)) { monthLengths[2] = 29; } else { monthLengths[2] = 28; } int monthLength = monthLengths[month]; if (day < 1 || day > monthLength) { return false; } return true; } /** 是否是闰年 */ private static boolean isLeapYear(int year) { return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0); } public boolean judge(String input) { return false; }
分割出时间年月日,对其进行具体的如上的格式的判断。这确实是很重要的事情。如何将坐标分割开,这必须要找到准确的点可以利用sunstring()来进行分割(这是我目前唯一能想到的方式)但缺点很明显,无法广泛地进行利用只能用在这种少数的点上。再多出一些点就无法进行操作了。未实现第一题,第二三题也不可能得以实现。在完成实验过程中,我完全还是按照面向过程的形式进行书写的。在后续的2个题中我发现了是第一个题的升级,难度在一级一级的上升,但可以利用第一题的大部分进行数字提取,接下来就只是单纯的分类计算了。切割在下下个题的用处会变得跟大的。
第八次:
public class Main {
public static void main(String[] args) {
ArrayList<String> l1 = new ArrayList<String>();
ArrayList<String> l2 = new ArrayList<String>();
Test t = new Test(l1,l2);
t.testAndInput();
calculate a = new calculate(l1, l2);
a.display();
}
}
class Test{
ArrayList<String> l1 = new ArrayList<String>();//用于保留u
ArrayList<String> l2 = new ArrayList<String>();//用于保留m
public Test(ArrayList<String> l1,ArrayList<String> l2){
this.l1 = l1;
this.l2 = l2;
}
public void testAndInput(){
Scanner scan = new Scanner(System.in);
String lineWords;
while (!"end".equals(lineWords = scan.nextLine())){
if(lineWords.matches("u-1[0-9]{10} 3")) {//判断是哪个
//u-13305862264 3 ->13305862264
l1.add(lineWords.substring(2,lineWords.length()-2));//进行切割,保留后面的,取前不取后。
}
if(lineWords.matches("m-1[0-9]{10} 1[0-9]{10} [0-9a-zA-z,.\\s]{1,}") ){
l2.add(lineWords);
}
}
}
}
class calculate{
private ArrayList<String>l1 ;
private ArrayList<String> l2;
public calculate(ArrayList<String>l1 , ArrayList<String> l2) {
this.l1 = l1;
this.l2 = l2;
}
public void display() {
float fee = 0;//费用
float balance =100;//余额
int c1=0, c2=0, c3=0,total=0;//分别为三种情况
Collections.sort(l1);
for(String user:l1) {
for(String record:l2) {
total += c3;
if(user.equals(record.substring(2,13))) {//判断是否为同一个人的电话号码。
//m-18907910010 13305862264 welcome to jiangxi.--->welcome to jiangxi.
c1 = (record.length()-26)/10;//判断字数是否超过10个,超过10个字的算多次短信。
c2 = (record.length()-26)%10;
if(c2 !=0)//c2不为0,说明要另算。
c3 = c1+1;
else
c3 = c1;
if(total+c3<=3)//total+c3为短信条数。
fee += 0.1*c3;
if(total+c3>3&&total+c3<=5)
fee = (float) (0.3+0.2*(total+c3-3));
if(total+c3>5)
fee = (float) (0.7+0.3*(total+c3-5));
}
}
System.out.println(user+" "+fee+" "+(balance-fee));
//重新开始,初始化,但可只对于c3
fee = 0;
balance =100;
c3=0;
total=0;
}
}
}
对于前几次而言,最后一次的实验很简单。要求不太高,对着格式来就行。
类图:
ChargeMode是计费方式的抽象类: chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。 getMonthlyRent()方法用于返回月租(monthlyRent)。 UserRecords是用户记录类,保存用户各种通话、短信的记录,
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、 市内接听电话、省内(不含市内)接听电话、省外接听电话的记录 以及发送短信、接收短信的记录。
图2中CommunicationRecord是抽象的通讯记录类: 包含callingNumber拨打号码、answerNumber接听号码两个属性。 CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。
calCost(ArrayList callRecords)方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。
心得体会:
1.在这几次实验中,我感绝学到的更多了,包括类与类之间的关系,合理运用抽象类是真的方便啊。但多态还是挺迷的,我还是有点不知道有多大的用处,在实验中,我不知道该合理的使用在哪些位置,或者是在哪合理的使用。
2.但对于类之间的关系我明显也没有看明白太多,感觉理解起来还是有点困难的。不论如何进行处理,都还是更加偏向于自己的想法,无法完全理解类的想法,更偏向于过程。
3.在完成最后一次作业时,知道更简单的方式,放弃了上两次的代码,这确实很不面向过程。就是有耍点小聪明在里面罢了。
4,在这次实验中,我更加凸出了思维,在写下这些代码时,我不时地添加注释使我保持更清晰的代码思路,确实还是很有帮助的。