软件构造lab2

目录

1 实验目标概述 1
2 实验环境配置 1
3 实验过程 1
3.1 Poetic Walks 1
3.1.1 Get the code and prepare Git repository 1
3.1.2 Problem 1: Test Graph 1
3.1.3 Problem 2: Implement Graph 1
3.1.3.1 Implement ConcreteEdgesGraph 2
3.1.3.2 Implement ConcreteVerticesGraph 2
3.1.4 Problem 3: Implement generic Graph 2
3.1.4.1 Make the implementations generic 2
3.1.4.2 Implement Graph.empty() 2
3.1.5 Problem 4: Poetic walks 2
3.1.5.1 Test GraphPoet 2
3.1.5.2 Implement GraphPoet 2
3.1.5.3 Graph poetry slam 2
3.1.6 Before you’re done 2
3.2 Re-implement the Social Network in Lab1 2
3.2.1 FriendshipGraph类 2
3.2.2 Person类 3
3.2.3 客户端main() 3
3.2.4 测试用例 3
3.2.5 提交至Git仓库 3
3.3 Playing Chess 3
3.3.1 ADT设计/实现方案 3
3.3.2 主程序ChessGame设计/实现方案 3
3.3.3 ADT和主程序的测试方案 3
3.4 Multi-Startup Set (MIT) 4
4 实验进度记录 4
5 实验过程中遇到的困难与解决途径 4
6 实验过程中收获的经验、教训、感想 4
6.1 实验过程中收获的经验和教训 4
6.2 针对以下方面的感受 4

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实验环境配置
简要陈述你配置本次实验所需环境的过程,必要时可以给出屏幕截图。
特别是要记录配置过程中遇到的问题和困难,以及如何解决的。
实验环境设置请参见 Lab-0 实验指南。
除此之外,本次实验需要你在 Eclipse IDE 中安装配置 EclEmma(一个用于
统计 JUnit 测试用例的代码覆盖度的 plugin)。请访问 http://www.eclemma.org,了解 EclEmma 并学习其安装、配置和使用。

  1. 根据助教在群里发的链接,完成Eclipse和JDK11的安装,然后去网上查询Java运行环境的配置,配置计算机的环境变量。
    2.注册GitHub账号,并且授权GitHub classroom,获取lab2的GitHub classroom的URL地址。
  2. Git代码配置管理。首先安装最新版Git,获取个人GitHub的URL地址,通过在Git bash输入指令建立管理本地仓库,将文件push到远程仓库。
    遇到的困难:
    1.在配置环境时,最早的参考教程是针对Mac OS,并且本地路径的设置出错,导致走了很多弯路。
  3. 在安装Git之后,未第一时间在Git的安装目录注册user.name和user.email,导致后面输入命令时bash显示commend not found。
    Eclemma安装:
    从Eclipse 3.6开始, Eclipse Marketplace Client 允许从Eclipse中直接安装EclEmma。按照以下步骤操作,或将上面的按钮拖放到正在运行的Indigo工作区中。
    1.从Eclipse菜单中选择Help → Eclipse Marketplace。
    2.搜索“EclEmma”。
    3.单击“ 安装”以获取条目“EclEmma Java代码覆盖率”。
    4.按照安装向导中的步骤操作。

3实验过程
请仔细对照实验手册,针对三个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
3.1Poetic Walks
在这里简要概述你对该任务的理解。
任务:分别新建两个类ConcreteEdgesGraph,ConcreteVerticesGraph 实现Graph接口。

Graph接口要求实现add(添加新节点),set(添加新边),remove(移除节点),vertices(获得所有的节点集合),sources(target)获得以target为目标节点的边的起始节点,targes(source)获得以source为起始节点的边的目标节点。

Poet:给定一组单词(文件输入),对于两个相邻的单词a和b,认为存在一条由a到b的有向边,通过Graph接口构造有向图。再给定一由单词组成的句子,如果句子中两个相邻单词之间在Graph图中有一个中间单词则将中间单词插入到两单词之间(如果有多个则插入权重最大的那个)
3.1.1Get the code and prepare Git repository
如何从GitHub获取该任务的代码、在本地创建git仓库、使用git管理本地开发。
从https://github.com/rainywang/Spring2019_HITCS_SC_Lab2/tree/master/P1 获得实验代码。
git init
git remote add origin git@github.com:ComputerScienceHIT/Lab2-1170300512.git
git push -u origin master
Git add .
Git commit -m “init”
Git push origin master

3.1.2Problem 1: Test Graph
以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。
我选用ConcreteEdgesGraph作为Graph的具体实现,如需要测试,将Graph里原empty()方法修改为: public static Graph empty() {
//throw new RuntimeException(“not implemented”);
return new ConcreteEdgesGraph();
}

GraphInstanceTest.java:
针对这个测试,我们可使用抽象类,针对边和定点两种实现的测试类,并且我们所有的测试都与具体的实现无关。
在测试中,使用emptyInstance()方法来获取新的空图,所有的测试策略都根据需要实现的功能来设计。
具体的strategy已在test测试文件中标注,如下:

3.1.3Problem 2: Implement Graph
以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。
3.1.3.1Implement ConcreteEdgesGraph
先介绍ConcreteEdgesGraph,后Edge类,最后测试类
ConcreteEdgesGraph类:
public boolean add(String vertex)
思路:如果在vertices的Set集合中成功添加了顶点string,则返回true
public int set(String source, String target, int weight)
思路:如果找到指定边,weight=0,删除边;weght>0,更改边;未找到,增加边,返回并checkrep()
public boolean remove(String vertex)
思路:如果不含该点,返回false。否则遍历edges,如果某个edge的source或是target与vertex相等,则删除该边。最后删除vertex点。并checkRep。
public Set vertices()
思路:返回vertices的Set,注意做到safety from rep exposure ,使用Collections.unmodifiableSet()方法。
public Map<String, Integer> sources(String target)
思路:建立一个map,遍历edges,如果某个edge的edge.getTarget()和传入参数target相等,则将该边的source和weight存入map中,其它置0
public Map<String, Integer> targets(String source)
思路:建立一个map,遍历edges,如果某个edge的edge.getSource()和传入参数source相等,则将该边的target和weight存入map中,其它置0
public String toString()
思路: graph不为空,则将每个边的toString连接起来,调用String.concat()方法
private void checkRep()
思路:n个点,最多构成n*(n-1)/2条有向边,因此存在这种不可变的数学关系
Edge类:
Field:private String source;
private String target;
private int weight;
Constructor:public Edge(String source, String target, int weight) { //构造方法
this.source= source;
this.target = target;
this.weight = weight;
checkRep();
}
public void checkRep() // source和target不能是null,并且 weight >= 0
public String getsource() // 返回起点
public String gettarget() // 返回终点
public int getweight() // 返回权重
public String tostring() { //tostring
return source+"-"+target+"-"+weight;
}
public boolean equals(String source,String target,int weight) //判断两条边是否相等 ,先判断一个对象是否是另一个对象的实例 ,如果是再判断source ,target ,weight等是否都相等.
public int hashcode() //复写hashCode方法,@return hash address

测试类:
根据实现的功能来制定相应的test判断是否匹配
测试ConcreteEdgesGraph的tostring方法:匹配string,判断是否相等
测试getSource()方法: 建立特定edge,返回source, 判断是否匹配
测试getTarget()方法:建立特定edge,返回target, 判断是否匹配
测试getWeight()方法:建立特定edge,返回weight, 判断是否匹配
测试Edge里的toString()方法:建立特定edge,返回string, 判断是否匹配
测试equals()方法:设置多条边, 相等:和自己,和其他边; 不等:source,target,weight存在不相等
测试hashCode()方法:设置多条边, 相等:和自己,和其他边(source,target,weight存在不等)不等

3.1.3.2Implement ConcreteVerticesGraph
先介绍ConcreteVerticesGraph类,再Vertex类,最后测试类
ConcreteVerticesGraph类:
public boolean add(String vertex)
思路:若vertices()中已包含vertex,返回false,否则新建一个顶点将其加入vertices即可。
public int set(String source, String target, int weight)
思路:添加两个顶点,如果存在source,看map是否包含target,若weight=0,remove该target在map中,weight>0则改变,checkrep
public boolean remove(String vertex)
思路:如果vertices()不包含vertex,返回false。否则遍历所有点,如果某点和vertex存在映射关系,则将这种关系删除。最后将vertex对应的点从vertices中删除即可。checkrep
public Set vertices()
思路:遍历vertices,找到每个点对应的string,添加进set即可。
public Map<String, Integer> sources(String target)
思路:如果找不到target对应的点,返回全权重为0map。否则遍历vertices,其它点距离置0,返回target对应的起点点图。
public Map<String, Integer> targets(String source)
思路:如果找不到source对应的点,返回全权重为0map。否则调用getTarget,其它点距离置0,返回source对应的目标点图。
public String toString()
思路: graph不为空,则将每个边的toString连接起来,调用String.concat()方法
private void checkRep()
思路: vertices的size大于0

Vertex类
Fields:private String source;
private Map<String, Integer> targetmap;
Constructor:public Vertex(String source, Map<String, Integer> targetmap) { // 构造方法
this.source = source;
this.targetmap = targetmap;
checkRep();
}
public void checkRep() // source不为空
public String getsource() // 返回起点
public Map<String, Integer> gettargetmap() // 返回终点map
public String tostring() // tostring

测试类
根据实现的功能来制定相应的test判断是否匹配
测试ConcreteVerticesGraph的tostring函数:匹配string,判断是否相等
测试vertex的getsource方法:建立特定vertex,返回source, 判断是否匹配
测试vertex的gettargetmap方法:建立特定vertex,返回targetmap, 判断是否匹配
测试vertex的tostring方法:建立特定vertex,返回string, 判断是否匹配

3.1.4Problem 3: Implement generic Graph
3.1.4.1Make the implementations generic
将具体类的声明更改为:
public class ConcreteEdgesGraph implements Graph
class Edge
Public class ConcreteVerticesGraph implements Graph
class Vertex
更新两个实现以支持任何类型的顶点标签,使用占位符L代替String。
以前,可能已声明类型为Edge或的变量List。那些将需要成为Edge和List<Edge>。
同样,可能已经调用了类似new ConcreteEdgesGraph()或的构造函数new Edge()。例如,那些将需要成为new ConcreteEdgesGraph()和new Edge()。
3.1.4.2Implement Graph.empty()
选择ConcreteEdgesGraph来使用和实施Graph.empty()

public static Graph empty() {
//throw new RuntimeException(“not implemented”);
return new ConcreteEdgesGraph<>();
}
测试GraphStaticTest,测试通过。
3.1.5Problem 4: Poetic walks
3.1.5.1Test GraphPoet
Testing strategy
给定一个input。从文件中读取poet,调用Graph.poem()后
观察输出与预期是否相等
对mugar-omni-theater.txt测试如下:
public void testmugar() throws IOException {
final GraphPoet nimoy = new GraphPoet(new File(“src/poet/mugar-omni-theater.txt”));
final String input = “Test the system.”;
assertEquals(“Test of the system.”,nimoy.poem(input));
}
public void testmugartostring() throws IOException {
final GraphPoet nimoy = new GraphPoet(new File(“src/P1/poet/mugar-omni-theater.txt”));
assertEquals(“This-is-1\nis-a-1\na-test-1\ntest-of-1\nof-the-1\nthe-Mugar-1\nMugar-Omni-1\nOmni-Theater-1\nTheater-sound-1\nsound-system.-1\n”,nimoy.tostring());
}
3.1.5.2Implement GraphPoet
fields:private final Graph graph = Graph.empty(); //有向图
public GraphPoet(File corpus) throws IOException //从语料库的图形中创建一个新的poet。先读文件,并把文件中的单词存在alist中。使用BufferedReader读取文本文件中的数据,分解成多个部分。然后调用Graph类中的方法,将单词转化为图,添加顶点,set边,其中权值全部设置为1.
public String poem(String input) 遍历input中所有单词,调用Graph.targets()和Graph.sources()方法。如果该单词的targets和后面一个单词的sources有交集,则添加一条bridge,并且在两个单词的bridge中随机选择一个插入到字符串中。
public void checkRep() //检查图是否为空
public String toString() //调用gragh的tostring方法
3.1.5.3Graph poetry slam
Main由给出input,生成poem
3.1.6Before you’re done
请按照http://web.mit.edu/6.031/www/sp17/psets/ps2/#before_youre_done的说明,检查你的程序。
如何通过Git提交当前版本到GitHub上你的Lab2仓库。
在这里给出你的项目的目录结构树状示意图。
git add .
git commit -m “change”
Git remote add origin git@github.com:ComputerScienceHIT/Lab2-1170300512.git
git push -u origin master
目录结构树状示意图
src
P1
graph
ConcreteEdges.java
ConcteteVertices.java
Gragh.java
poet
GraghPoint.java
Main.java
mugar-omni-theater.txttest
P1
graph
ConcreteEdgesGraphTest.java
ConcreteVerticesGraphTest.java
GraghInstanceTest.java
GraghStaticTest.java
poet
GraghpoemTest.java

3.2Re-implement the Social Network in Lab1
在这里简要概述你对该任务的理解。
任务:这个实验是基于在Poetic Walks中定义的Graph及其两种实现,重新实现Lab1中的 FriendshipGraph类。我们需要尽可能复用ConcreteEdgesGraph或 ConcreteVerticesGraph中已经实现的add()和set()方法,而不是从零开始。另外基于所选定的 ConcreteEdgesGraph 或 ConcreteVerticesGraph的rep来实现,而不能修改父类的rep。
3.2.1FriendshipGraph类
给出你的设计和实现思路/过程/结果。
设计和实现思路:继承ConcreteEdgesGraph,根据实验指导的提示,类中需要增加一些非法情况的判断,例如人已经存在,或者边已经存在等。
public boolean addVertex(Person name) // 向图中添加成员
思路:把参数添加到图中,作为图的一个顶点,直接调用父类的this.add()即可。
public boolean addEdge(Person name1, Person name2) //加上关系
思路:判断点是否存在,若存在直接加上边即可
public int getDistance(Person name1, Person name2) //获得距离
思路:先判断点是否在图中,然后广搜

3.2.2Person类
给出你的设计和实现思路/过程/结果。
Person类较为简单,主要是根据FriendshipGraph类的需求编写的。它用于描述每个成员的性质,主要是实例化姓名的构造方法,getName()方法
3.2.3客户端main()
给出你的设计和实现思路/过程/结果。
main()函数主体部分就是实验指导上的要求:先new一个FriendshipGraph类的对象,然后添加顶点,添加边。
3.2.4测试用例
给出你的设计和实现思路/过程/结果。
设计和实现思路:在测试包Test中创建了一个 FriendshipGrapgTest.java文件后,通过注解的方式@Test表示这是一个测试方法。
主要使用的方法:assertEquals方法。都是通过判断预期值和实际值是否相等来返回true或false。
过程:
对于addVertex()方法,主要测试了添加的点是否存在。
对于addEdge()方法,测试了边是否存在和是否有超出unconnected边。
对于getDistance方法,测试了距离实际值是否和预期值相等。
3.2.5提交至Git仓库
如何通过Git提交当前版本到GitHub上你的Lab3仓库。
git add .
git commit -m “change”
Git remote add origin git@github.com:ComputerScienceHIT/Lab2-1170300512.git
git push -u origin master

在这里给出你的项目的目录结构树状示意图。
项目名称: Lab2_1170300512
src
P2
FriendshipGraph.java
Person.java
Main.java
test
P2
FriendshipGraphTest.java

3.3Playing Chess
3.3.1ADT设计/实现方案
Board类:
mutable,包含String property和List piece两种数据类型,分别标识了棋盘的种类和记录了摆放在棋盘上的棋子。
changeProperty方法,用来修改棋盘的种类。
addPiece方法,用来在棋盘上添加一个棋子。
getPiece方法,返回所有棋子。
isOccupied方法,查询棋盘上某个位置的情况。
changePos方法,移动棋盘上的某个棋子。
numOfPiece方法,用来统计棋盘上的棋子状况。
Game类:
Mutable,包含List player和Board board两种数据类型,分别存储了所有玩家,和生成一个棋盘。
generatePlayer方法,在游戏中添加一名玩家。
getPlayer方法,返回在游戏中的玩家。
generateBoard方法,根据玩家输入的类型,初始化棋盘,如果是chess则生成8x8的棋盘并向棋盘添加国际象棋中的棋子,如果是go则只生成一个18x18的棋盘。
generatePiece方法,用于围棋,生成一个棋子,摆放在棋盘上。
checkIsOccupied方法,调用Board类中的isOccupied方法,查询棋盘上某一位置的情况。
move方法,移动棋子。
deletePiece方法,用于删除棋盘上的某一棋子。
eat方法,用于国际象棋,一个子吃掉另一个子。
Piece类:
mutable,包含String name,String owner,Integer X,Integer Y四种数据类型,分别存储棋子名称,拥有该棋子的玩家,和棋子的坐标。
getName方法,返回棋子的名称。
getOwner方法,返回拥有该棋子的玩家。
changeName方法,更改棋子名称。
changeOwner方法,更改拥有该棋子的玩家。
getPosx方法,返回横坐标。
getPosy方法,返回纵坐标。
changePosx方法,修改横坐标。
changePosy方法,修改纵坐标。
Player类:
包含String name一种数据结构,存储玩家姓名。
getName方法,返回玩家姓名。
3.3.2主程序MyChessAndGoGame设计/实现方案
辅之以执行过程的截图,介绍主程序的设计和实现方案,特别是如何将用户在命令行输入的指令映射到各ADT的具体方法的执行。
先判断游戏类型:
根据输入的是chess还是go调用函数初始化棋盘。
再输入玩家姓名:
根据姓名初始化玩家。
读取命令:
将命令按空格拆分成字符串数组,第一个元素存储操作,其余元素存储坐标。
根据命令和棋盘上的实际情况给出反馈:

3.3.3ADT和主程序的测试方案
介绍针对各ADT的各方法的测试方案和testing strategy。
介绍你如何对该应用进行测试用例的设计,以及具体的测试过程。
BoardTest:
棋盘是一个对象,棋子放在棋盘上,所有关于棋子的基本操作都被集成在Board类里面,在棋盘类中测试:
添加棋子,调用检查是否占用函数判断是否添加成功。
检查是否占用,看函数返回值与期望是否相同。
移动位置,移动一个棋子的位置,检查提子点和落子点的占用情况。
统计,调用该函数,检查返回的棋子总数,玩家分别拥有的棋子数是否正确。
GameTest:
游戏的具体操作与具体的游戏类型有关,所以与chess和go有关的操作集成在了Game类里,并通过多次调用Board类中的方法来实现相应功能。
生成棋子,检查返回值是否为指定棋子,是否在指定位置。
检查是否占用,该函数有三个功能,分别测试其返回值。
移动棋子,用于国际象棋,测试提子点和落子点的占用情况。
删除棋子,用于围棋,检测删除某棋子后位置的占用情况。
吃子,用于国际象棋,检测棋子名称,吃子和被吃子的位置以及占用情况。
3.4 Multi-Startup Set (MIT)
请自行设计目录结构。
注意:该任务为选做,不评判,不计分。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值