哈工大2021春软件构造实验总结
文章目录
一、实验一
1. 实验概述
1.1 Magic Squares
- 介绍:n阶幻方是一个n*n矩阵,其中矩阵的数通常为不同的整型数,每一行之和,每一列之和,两条对角线之和,都需要保持一致。
- 本任务要求对幻方进行判断,并要求能够处理输入文件的各种特殊情况,例如:文件中的数据不符合 Magic Square 的定义(行列数不相等、并非矩阵等)、矩阵中的某些数字 并非正整数、数字之间并非使用\t分割等。若遇到这些情况,终止程序 执行(isLegalMagicSquare 函数返回 false),并在控制台输出错误提示信息。
1.2 Turtle Graphics
- 该任务是通过调用turtle的方法库,主要是方法forword(units)和turn(degrees),实现一系列的画图操作
- 凸包问题的解决
(1)介绍:凸包问题是在平面上的一系列点中,找到一个最小的点集,使之能够包围所有的点,类似于边界,而这一最小点集即平面上这些点的凸包。
(2)解决思路:采用Jarvis步进法,先找到最左下角的点(点的X分量最小,若多个点X分量相同,选择其中Y分量最小的点),则它一定是凸包的一个顶点。接着相对于前一个点,找到两点连线与上一连线夹角最小的点。在一搜索过程中,需要遍历凸包外其他所有的点。重复以上过程,直到回到起始点。特别的,三个点以内的凸包为其本身。
(3)实现代码
for(Point k : points)
{
if(k.equals(currentPoint))
continue;
//找到最近加入凸包的点与凸包外所有点之间转动角度最小的点,加入凸包
angle = calculateBearingToPoint(preAngle, (int)currentPoint.x(), (int)currentPoint.y(), (int)k.x(), (int)k.y());
if (nextAngle > angle) {
distance = Math.pow(k.x()-currentPoint.x(), 2)+Math.pow(k.y()-currentPoint.y(), 2);
nextAngle = angle;
nextPoint = k;
}
//如果角度相等,选择距离最远点
else if (nextAngle == angle) {
if(distance < (Math.pow(k.x()-currentPoint.x(), 2)+Math.pow(k.y()-currentPoint.y(), 2)))
{
distance = Math.pow(k.x()-currentPoint.x(), 2)+Math.pow(k.y()-currentPoint.y(), 2);
nextPoint = k;
}
}
}
- 个性化画图展示
1.3 Social Network
本任务刻画的社交网络是无向图,FriendshipGraph代表社交网络中的朋友关系,并且能够计算图中两人的社交距离,Person用来定义社交网络的对象。
(1)main函数实现
2. 实验感受
(1)初次接触软件构造的实验,最大感受就是应该提前学习Java编程语言;
(2)遇到问题多思考,多与同学交流经验,你遇到的困难(Git、Github等)有可能别人已经遇到并已经解决
二、实验二
1. 实验概述
1.1 Poetic Walks
-
任务描述
此任务第一部分是实现类型Graph,它是带有标记顶点的可变加权有向图的抽象数据类型。
可变图:可以在图中添加和删除顶点和边
有向边:边从源顶点到目标顶点
加权边:边与正整数权重相关联
标记的顶点:顶点通过某种不可变类型的标签来区分,例如它们可能有String名称或IntegerID -
可变加权有向图的接口的实现分为两种,一种是以边为对象,另一种是以顶点对象,要求独立完成所需要的方法功能。
-
GraphPoet: 用语料库初始化,然后在给定输入的情况下,使用由该语料库定义的词亲和图来诗意地转换输入,其中:顶点是不区分大小写的单词,并且边权重是有序的邻接计数。
(1)实现结果
1.2 Re-implement the Social Network in Lab1
- 任务描述:FriendshipGraph中应提供addVertex()、addEdge() 和getDistance()三个方法:针对addVertex() 和addEdge() ,需要尽可能复用ConcreteEdgesGraph或ConcreteVerticesGraph中已经实现的add()和set()方法,而不是从0开始写代码实现或者把你的Labl相关代码直接复制过来;针对getDistance()方法,请基于你所选定的ConcreteEdgesGraph或ConcreteVerticesGraph的rep来实现,而不能修改其rep。
- 通过将社交网络定义ConcreteEdgesGraph或ConcreteVerticesGraph,再调用第一部分实现的方法实现社交网络的方法功能即可。
(1)社交距离的设计思路:
从person_1起,通过广度优先搜索+队列遍历社交图,每到新一层的社交网络,距离+1,直至到person_2,其中某人的直接朋友可以采用方法sources(L target)或者targets(L source)得知;
(2)社交距离的实现:
while (!queue.isEmpty()) {
Person outQueuePerson = queue.poll();
socialDistance = Path.get(outQueuePerson);
//对于出队人的所有直接朋友
for (Person e : personGraph.sources(outQueuePerson).keySet()) {
if (!Path.containsKey(e)) {
Path.put(e, socialDistance + 1);
if (e == person_2)
return Path.get(person_2);
}
queue.offer(e); //直接朋友全入队
}
}
2. 实验感受
(1) 面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?
面向过程是以“算法”为中心,通过使用函数实现各个步骤,并依次调用实现的函数解决问题;
面向对象是以“对象”为中心,在设计好相应的对象后(对象的属性),将对象在整个问题中的相关行为封装到一起(对象的方法),然后各个对象共同将整个事情完成;
区别:
- 面向过程的出发点是综合分析,面向对象的出发点是构造对象。
- 面向过程是一种自顶向下的编程,面向对象是将事物高度抽象化,所以首先要建立抽象数据类型(ADT)。
- 面向过程传递的是参数或全局变量,面向对象的直接调用方法。
(2)在给出ADT的规约后就开始编写测试用例,优势是什么?你是否能够适应这种测试方式?
- 提前写好测试用例,可以一开始就明确用户需求,根据需求明确编码,而在编码过程中,也可以及时根据测试进行核实,确认其是否符合要求,测试可以去除程序本身bug之外脱离用户需求的问题,即步步为赢。
- 对于初次使用此种方法,使用起来有些别扭,需要一定的时间来消化,最重要的是要明确ADT及其规约。
(3)为ADT撰写specification, invariants, RI, AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?
- 首先能够明确ADT的书写规范和用户需求,其次有利于及时记录编写者的思考和灵感,以便编写者以后或者其他人使用和改进。
三、实验三
1. 实验概述
1.1 管理系统的介绍
-
应用一:值班表管理(DutyRoster):
对于一个单位的 n 个员工,在每个时间段内,每天只能安排唯一一名员工在单位值班,且不能出现某天无人值班的情况(值班表不能出现空缺);每个员工若被安排值班 m 天 (m>1),那么需要安排在连续的 m 天内。值班表内需要记录员工的名字、职位、手机号码,以便于外界联系值班员。 -
应用二:操作系统进程调度管理(ProcessSchedule)
计算机上有一个单核 CPU,操作系统可以创建多个进程,它们被调度在 CPU 上执行,操作系统可自由决定在各个时段内执行哪个线程。操作系统可挂起某个正在执行的进程,也可以在后续时刻恢复执行被挂起的进程。
注意:每个时间只能有一个进程在执行,其他进程处于休眠状态(被挂起);一个进程的执行可以被分为多个时间段;在特定时刻,CPU可以“闲置”,即操作系统没有调度执行任何进程;操作系统对进程的调度无规律,可看作是随机调度。 -
大学课表管理(CourseSchedule)
针对某个班级,其课程都是周期性出现的,而且周期数与学期的总周数保持一致。所以每学期的第一天应该从周一开始,否则会破坏课程的周期性。对于每一门课而言一门课程每周可以出现 1 次,也可以安排多次且由同一位教师承担并在同样的教室进行;允许课表中有空白时间段(未安排任何课程);考虑到不同学生的选课情况不同,同一个时间段内可以安排不同的课程,一位教师也可以承担课表中的多门课程。
1.2 管理系统的实现策略
- DutyIntervalSet的结构
值班表管理系统继承于CommonIntervalSet,并实现IDutyIntervalSet,CommonIntervalSet是三个app中可复用的方法,而IDutyIntervalSet通过不同接口之间的组合,实现了三个差异性(空白,重复,周期)的结合。
通过在DutyIntervalSet中定义nbis,npis,nois等属性,并在构造器中建立委托关系,进而做到永久地绑定,避免继承大量无用的方法。 - ProcessIntervalSet
操作系统进程管理系统继承于CommonMutiIntervalSet,并实现IProcessIntervalSet,CommonMutiIntervalSet是三个app中可复用的方法,而IProcessIntervalSet通过不同接口之间的组合,实现了无周期,无重叠。
- CourseIntervalSet
大学课表管理系统继承于CommonMutiIntervalSet,并实现I CourseIntervalSet,CommonMutiIntervalSet是三个app中可复用的方法,而ICourseIntervalSet通过不同接口之间的组合,实现了有周期。
1.3 管理系统的APP实现
APP采用IDEA下的GUI进行开发设计。
- 排班管理系统
(1)以下为排班管理系统的框架:
(2)APP的界面为:
- 操作系统的进程调度管理系统
以下是操作系统的代码框架:
以下是课表管理系统的APP界面:
- 大学课表管理系统
以下是课表管理系统的代码框架:
以下是课表管理系统的APP界面:
2. 实验感受
通过软件构造这门课,我的编程能力有了进一步的提高,也深刻感受到面向对象编程和面向过程编程的差异,还有可复用编程给程序员带来的巨大福利,不过我的课堂感受就是课堂上的例子真的超级重要,无论是对知识点的理解,有时候听课听的稀里糊涂,看完示例有时候会茅塞顿开,而且示例对实验也有很大的帮助,最后一点就是提前进行Java入门很重要;
总结
本文对哈工大2021春软件构造实验进行了简要概述,并简要介绍了实验的部分实现策略。