哈工大软件构造Lab2

1实验目标概述

本次实验训练抽象数据类型(ADT)的设计、规约、测试,并使用面向对象编程(OOP)技术实现ADT。具体来说:针对给定的应用问题,从问题描述中识别所需的ADT;设计ADT规约(pre-condition、post-condition)并评估规约的质量;根据ADT的规约设计测试用例;ADT的泛型化;根据规约设计ADT的多种不同的实现;针对每种实现,设计其表示(representation)、表示不变性(rep invariant)、抽象过程(abstraction function)使用OOP实现ADT,并判定表示不变性是否违反、各实现是否存在表示泄露(rep exposure);测试ADT的实现并评估测试的覆盖度;使用ADT及其实现,为应用问题开发程序;在测试代码中,能够写出testing strategy并据此设计测试用例。

2实验环境配置

在 Eclipse IDE 中安装配置 EclEmma(一个用于统计 JUnit 测试用例的代码覆盖度的 plugin)直接从Eclipse Market下载安装即可。
在这里给出你的GitHub Lab2仓库的URL地址(Lab2-学号)。
https://github.com/ComputerScienceHIT/Lab2-1183710129

3实验过程

3.1Poetic Walks

该任务主要是实验一个图的模块,并基于此使用。
(1)完善Graph接口类,并运用泛型的思想,将String拓展为泛型L类;
(2)实现Graph类的方法:add、set、remove、vertices、sources、targets;
(3)利用实现的Graph类,应用图的思想,实现GraphPoet类,如果输入的文本的两个单词之间存在桥接词,则插入该桥接词;若存在多个单一桥接词,则选取边权重较大者。

3.1.1 Get the code and prepare Git repository从https://github.com/rainywang/Spring2020_HITCS_SC_Lab2/tree/master/P1获取初始代码

Git命令:
git init
git remote add origin [email protected]:ComputerScienceHIT/Lab2-1183710129.git pull origin master
git add .
git commit -m “init”
git push origin master

3.1.2 Problem 1: Test Graph

这部分主要是针对Graph设计测试策略,编写测试用例主要利用等价类划分的思想进行测试,测试策略如下:
哈工大软件构造Lab2
编写覆盖以上条件的测试用例。

3.1.3 Problem 2: Implement Graph

3.1.3.1 Implement ConcreteEdgesGraph

1.实现Edge

Fileds 作用
private final L source; 起始节点
private final L target; 目标节点
private final int weight; 边权值
Method 作用
public L getsource() 返回有向边起始节点
public L gettarget() 返回有向边目标节点
public int getweight()) 返回边权值
public String toString() 使用@Override注释toString以确保正确覆盖Object方法的toString方法

2.实现ConcreteEdgeGraph

Method 作用
public boolean add(L vertex) 调用vertices.add,其返回结果为boolean且满足spec定义。
public int set(L source, L target, int weight) 输入source,target,weight,确定一条有向边。具体做法:如weight!=0,移去可能已经存在的边,然后加入新的边,如weight=0.寻找可能已经存在边并删除。
public boolean remove(L vertex) 从vertices中删去,传入的参数vertex点,遍历edges,寻找是否有边的起点或者是终点是该vertex,删去。注意在使用迭代器遍历时要使用iterator.remove方法保证安全。
public Set vertices() 返回vertices集合
public Map<L, Integer> sources(L target) 根据传入的target参数寻找以targe为终点的边。返回一个键值对为(点,权重)的map。
public Map<L, Integer> targets(L source) 根据传入的source参数寻找以source为起点的边。实现同上。

哈工大软件构造Lab2
关于AF,RI和rep exposure:
哈工大软件构造Lab2
哈工大软件构造Lab2

3.1.3.2 Implement ConcreteVerticesGraph

1.实现Vertex

Field 作用
private final L name 节点名字
private final Map<L, Integer>sources = new HashMap<>() 所有以name为目标节点的边,<起始节点name,边的权重>.
private final Map<L, Integer>targets = new HashMap<>() 所有以name为起始节点的边,<目标节点name,边的权重>
Method 作用
public L getname() 返回该节点的name
public Map<L, Integer> getsources() 根据传入的target参数寻找以targe为终点的边。返回一个键值对为(点,权重)的map。
public Map<L, Integer> gettargets() 根据传入的source参数寻找以source为起点的边。实现同上。
public boolean removesource(L source) 检查输入满足source!=null,调用sources.remove,并返回(不存在则返回false)。
public boolean removetarget(L target) 检查满足target!=null。调用targets.remove(),返回。
public boolean setsource(L source, int weight) 检查输入满足source!=null,weight>=0。当weight==0时,调用this.removeSource,当weight>0时,调用Map.put修改source并且记录初始值。
public boolean settarget(L target, int weight) 检查输入满足target!=null,weight>=0,当weight=0时,调用this.removeTarget,当weight>0时,调用targets.put并返回(不存在则返回false)。

2.实现ConcreteVerticeGraph

Method 作用
public boolean add(L vertex) 检查输入满足vertex!=null。遍历点集vertices,若已存在vertex则返回false,否则调vertices.add并返回true
public int set(L source, L target, int weight) 遍历点集,分别检查vertices中是否存在source vertex和target vertex,若均不存在则调用vertices.add并调用source.setTarget和target.setSource设置边和权值,
public boolean remove(L vertex) 检查输入满足vertex!=null。如果输入节点不存在则返回false,否则,遍历vertices中的每一个节点调用v.remove在targes和sources中删除该节点。
public Set vertices() 遍历点集,找到Label与vertex相同的点并加入Set中,最后返回Set。
public Map<L, Integer> sources(L target) 遍历点集.如果没有target则返回空集合,否则调用targetVertex.getSources(target)
public Map<L, Integer> targets(L source) 遍历点集如果没有target则返回空集合,否则调用sourceVertex.getTargets(source)

关于AF,RI和rep exposure:
哈工大软件构造Lab2
哈工大软件构造Lab2

3.1.4 Problem 3: Implement generic Graph

3.1.4.1 Make the implementations generic

将两个实例类中的所有String类的参数替换为泛型的参数(声明、函数参数、返回值、rep)

3.1.4.2 Implement Graph.empty()

修改Graph.empty为:
哈工大软件构造Lab2
这里以ConcreteEdgesGraph作为Graph默认的实例类,也可以用ConcreteVerticesGraph,二者是等价的
使用Double类进行泛型测试,测试图为:
哈工大软件构造Lab2
测试结果为:
哈工大软件构造Lab2

3.1.5 Problem 4: Poetic walks

3.1.5.1 Test GraphPoet

关于测试策略:
哈工大软件构造Lab2
具体测试:
哈工大软件构造Lab2
哈工大软件构造Lab2

3.1.5.2 Implement GraphPoet

public GraphPoet(File corpus) 打开文件,读取文件输入,识别序列,构建图结构。具体:利用BufferedReader.readLine方法读取全部输入后用string.split以空格划分,保存在数组中,随后每次取相邻元素,在图中新增边。
public String poem(String input) 还是利用相同方法分割输入字符串,声明一个StringBuilder保存返回结果。每次读取一个词,然后以当前词为source,下一个词为target,在graph中寻找符合此条件的边,记录权值,结束后选择权值最大的,利用StringBuilder. Append方法,将节点名字加入字符串。
public String toString() 调用ConcreteEdgesGraph的toString方法,输出图结构

关于AF,RI和rep exposure:
哈工大软件构造Lab2
哈工大软件构造Lab2

3.1.5.3 Graph poetry slam

原始数据是网上的一篇作文。
哈工大软件构造Lab2

3.1.6 Before you’re done

请按照http://web.mit.edu/6.031/www/sp17/psets/ps2/#before_youre_done的说明,检查你的程序。
如何通过Git提交当前版本到GitHub上你的Lab2仓库。
git add .
git commit -m “xxx”
git push -u origin master
在这里给出你的项目的目录结构树状示意图。
哈工大软件构造Lab2

3.2 Re-implement the Social Network in Lab1

继承P1中ConcreteEdgesGraph或者ConcreteVerticesGraph类 实现FriendshipGraph,通过基本操作实现FriendshipGraph中addVertex,addEdge和getDistance三个接口,要求不能修改父类rep。

3.2.1 FriendshipGraph类

将以前的邻接表结构改为新的有向图结构。
声明:
哈工大软件构造Lab2
作为存放person点的有向图,这里采用ConcreteVerticesGraph这一实现,更加符合我们对关注的是每一个“人”的抽象。

Method 作用
public boolean addVertex(Person e) 遍历父类的vertices(),如果存在一个元素的name域与Person的name域相等,证明这个点已经存在,输出提示,否则调用父类的add(person)将该点加入
public void addEdge(Person p1, Person p2) 先调用父类的set(p1,p2,1),如果返回值为0证明这两个点之间不存在边,否则证明这两个点之间已经有边存在,输出提示
public int getDistance(Person p1, Person p2) 使用BFS算法求p1与p2之间的最短距离,BFS需要遍历邻居节点时调用父类接口的targets(p1)就可以获得p1的所有邻居节点。
public Setpersons() copy一份vertices,存储图中所有的顶点,即关系网络中的所有人。
public static void main(String[] args) 与Lab1相同

3.2.2 Person类

由于继承了ConcreteVerticesGraph,所以可以调用父类的rep和function,因此Person类就不需要过多的修饰。
哈工大软件构造Lab2

3.2.3 客户端main()

Lab1实验手册给出。

3.2.4 测试用例

与Lab1相同。

3.2.5 提交至Git仓库

如何通过Git提交当前版本到GitHub上你的Lab2仓库。
git add .
git commit -m “xxx”
git push -u origin master
在这里给出你的项目的目录结构树状示意图。
哈工大软件构造Lab2

3.3 Playing Chess

3.3.1 ADT设计/实现方案

1.Position(mutable)
哈工大软件构造Lab2

Method 作用:
public boolean set(int x, int y) 修改位置的横纵坐标
public int getX()public int getY() 得到横纵坐标

2.Piece(mutable)
哈工大软件构造Lab2

Method 作用:
public String Name() 得到棋子的名字
public Color color() 得到棋子的颜色
public Piece clone() 返回一个与该棋子具有相同属性的不同棋子

3.Player(mutable)
哈工大软件构造Lab2

Method 作用:
public String Name() 得到玩家的名字
public Color color() 得到玩家的颜色
public boolean addpiece(Piece e) 该玩家获得一枚棋子
public void addstep(String step) 添加一步到该玩家的走棋历史中
public List History() 得到该玩家的走棋历史
public Set pieces() 得到该玩家所拥有的棋子

4.Board(mutable)
哈工大软件构造Lab2

Method 作用:
public int size() 得到棋盘的大小
public Piece[][] pieces() 得到棋盘上棋子的分布
public void set(Piece piece, Position point) 向该棋盘上指定位置上放置一枚棋子
public Piece get(Position s) 获得棋盘上某位置的状态

5.Actions(interface)

Method 作用:
public boolean CreatePlayer(String name) 创造一个不重复的新玩家
public boolean Detach(Position point) 移除棋盘上指定位置上的棋子
public Board board(); 得到棋盘的状态
public boolean Islegal_Position(Position point); 判断一个坐标是否在该棋盘上
public void Skip(); 放弃此回合
public Piece Query(Position s); 查询某个位置的占用情况(空闲,或者被某一方的什么棋子所占用)
public int Calculate(Player player); 计算玩家在棋盘上的棋子总数
public Player GetPlayer1(); 返回玩家1的对象
public Player GetPlayer2(); 返回玩家2的对象

6.InternationalChess(实例类)
哈工大软件构造Lab2
提前初始化国际象棋的棋子
哈工大软件构造Lab2

Method 作用:
public boolean Move(Position s, Position t) 将s上的棋子移动到t上
private boolean Rule(Piece E, Position s, Position t) 判断国际象棋各个兵种行棋的步骤是否符合规则

7.ChineseGo(实例类)
哈工大软件构造Lab2

Method 作用:
public boolean Place(Position s) 将s上的棋子移动到t上

3.3.2 主程序MyChessAndGoGame设计/实现方案辅之以执行过程的截图,介绍主程序的设计和实现方案,特别是如何将用户在命令行输入的指令映射到各ADT的具体方法的执行。

(1)主函数:
哈工大软件构造Lab2
运行过程:
哈工大软件构造Lab2
(2)以国际象棋为例
(3)根据不同选项进行不同操作的函数,查询和计算不会轮换对手
哈工大软件构造Lab2
(4)程序结束,打印双方走棋历史
哈工大软件构造Lab2

3.3.3 ADT和主程序的测试方案

1.ActionsInstanceTest

Test 策略:
@Test(expected=AssertionError.class) make sure assertions are enabled with VM argument: -ea
public void test_CreatePlayer_GetPlayer() 有重复玩家、无重复玩家
public void test_Detach() 有无棋子、坐标在棋盘内、坐标不在棋盘内

2.BoardTest

Test 策略:
public void test() 检查棋盘大小是否相等、在棋盘上放置棋子,看能否得到正确的棋子

3.PieceTest

Test 策略:
public void test() 判断名字、颜色是否相等,该棋子和它的克隆不相等

4.PlayerTest

Test 策略:
public void test() 检查玩家名字,颜色是否相等,添加棋子重复和不重复,能否得到正确的走棋历史

5.PositionTest

Test 策略:
public void test() 能够得到正确的横纵坐标,检查toString