存在问题

  1. 书写报告时间过长:本打算周一写完,但拖到了周五清明假。
    流程图画图时间较长,测试用例设计部分截图较多,重写了P3。需要改进的地方在于编程时应该随时查看报告,避免偏离报告要求;代码做好注释,便于报告文字梳理。

  2. 对ADT和泛型了解不深入,设计ADT和OOP过程中要确保封装性。

UML图可由eclipse的插件Green UML生成,安装插件自行百度。

3.1 Poetic Walks (MIT)

题目

http://web.mit.edu/6.031/www/sp17/psets/ps2/,遵循该页面内的要求完成编程任务。获取初始代码的地址:https://github.com/rainywang/Spring2019_HITCS_SC_Lab2/tree/master/P1

3.1 Problem 1: Test Graph

刚开始看题目时对test没思路,因此留到了后面完成。先初始化有向图(以ConcreteVerticesGraph,ConcreteEdgesGraph同理)。
在这里插入图片描述

代码如下:

final Graph<String> graphv = new ConcreteVerticesGraph<String>();
    @Before
	public void Initialized()
	{
    	graphv.add("d1");
    	graphv.add("d2");
    	graphv.add("d3");
    	graphv.add("d4");
    	graphv.add("d5");
    	graphv.add("d6");
    	graphv.set("d1","d2", 1);
    	graphv.set("d1","d5", 4);
    	graphv.set("d5","d6", 3);
    	graphv.set("d2","d3", 2);
    	graphv.set("d2","d4", 5);
	}
之后的测试类比较简单。注意要测试toString:ConcreteVerticesGraphtoStringTest()

Problem 2: Implement Graph
只需补充补充empty函数
在这里插入图片描述

3.1.2 Implement ConcreteEdgesGraph

完成ConcreteEdgesGraph.java部分需要参考Graph.java文件,这部分未遇到困难。

设计和实现思路:
(1) Edge类(不可变类型):
定义begin表示起点,end表示终点,weight表示边长。并且定义相应的get函数: getbegin(),getend()和getweight()。
checkRep函数检测begin != null,end != null和weight > 0。

toString函数:将Edge类中的begin,end,和weight都转换成String类型,

(2) empty()函数:函数功能新建一个ConcreteEdgesGraph类
return new ConcreteEdgesGraph();
(3) add函数:函数功能是增加新顶点到顶点集中
定义vertices集合为顶点集。检测待添加的点是否在vertices中,若不存在则添加至vertices并返回true,否则返回false。
(4) set函数:功能:在有向图ConcreteEdgesGraph中删除,添加或更新一条有向边。
设计思路:遍历edges中的所有边,如果重量非零,则添加边缘或更新该边缘的重量; 具有给定标签的顶点如果尚不存在则会添加到图形中。如果权重为零,则删除边(如果存在)。

(5) remove函数:函数功能:去除指定顶点以及包括该顶点的所有边
如果顶点不包括在有向图中,则返回false
设计思路及过程:
如果顶点包括在有向图中,则在有向图的顶点集vertices删除该顶点,遍历有向图的边集合edges,找到所有以该顶点为起点或终点的边并删除。

(6) vertices函数:功能是获取所有顶点。
有向图的所有顶点都存储在顶点集vertices中,故直接返回vertices。
(7) sources函数:功能是获取所有以指定顶点为终点的边的起点及其边长。
设计思路及过程:定义一个Map类型targetMap用于存储结果,遍历有向图的边集合edges,找到所有以该顶点为终点的边,将边的起点和边长添加至targetMap。

(8) targets函数:功能是获取所有以指定顶点为起点的边的终点以及这些边的权重。
设计思路及过程:
定义一个Map类型sourceMap用于存储结果,遍历有向图的边集合edges,找到所有以该顶点为终点的边,将边的起点和边长添加至sourceMap。

(9) checkRep:用于检查代码
检查顶点集和边集是否为空

(10) toString函数:将有向图转换成字符串

3.1.3 Implement ConcreteVerticesGraph

实现方式同ConcreteVerticesGraph.java,此时只有vertices存储顶点,没有集合存储边,因此在vertex类中定义sourceMap和targetMap来存储边
(1) Vertex类(可变类型):
定义的变量有顶点的名字name,存储所有以该顶点为终点的所有有向边起点和边长的sourcemap和存储所有以该顶点为起点的所有有向边终点和边长的targetmap。
定义的函数有:获取上述变量的getname, getsourceMap ,gettargetMap,addSource,addSource,addSource 和addSource函数。
checkup函数:检测begin != null,end != null和weight > 0。
toString函数:将Vertex类中的begin,end和weight都转换成String类型,并返回:begin.toString()+weight+end。
(2) empty()函数:return new ConcreteVerticesGraph();
(3) add函数:定义vertices集合为顶点集。检测待添加的点是否在vertices中,若不存在则添加至vertices并返回true,否则返回false。
(4) set函数:功能:在有向图ConcreteVerticesGraph中删除,添加或更新一条有向边。
设计思路:确定边是否存在,若weight>0,如果边存在,则更新边并返回原边长,否则添加边返回0;若weight<=0,如果边存在,则删除边并返回原边长,否则返回0。
(5) remove函数:函数功能:取出指定顶点以及包括该顶点的所有边。
去除该点v,遍历所有点的sourcemap和targetmap,如果遇到以v.getname为起点或终点对应的边则移除。
(6) vertices函数:功能获取所有顶点的名字。
有向图的所有顶点都存储在顶点集vertices中,故直接返回vertices的名字集合。
(7) sources函数:功能是获取所有以指定顶点为终点的边的起点及其边长。
遍历顶点集合vertices,找到指定顶点并返回该顶点的sourcesmap。
(8) targets函数: 功能是获取所有以指定顶点为起点的边的终点以及这些边的权重。
遍历顶点集合vertices,找到指定顶点并返回该顶点的targetmap。
(9) checkRep: 用于检查代码。
顶点名字不为空。

(10) toString函数: 将有向图转换成字符串。

3.1.4 Problem 3: Implement generic Graph

遇到的问题是刚开始对泛型操作不了解,经过同学指点才debbug成功。
1.将原文件ConcreteVerticesGraph.java和中所有String类型改为L,
2.class Vertex { 改为class Vertex {
} }
3.Graph,ConcreteVerticesGraph,ConcreteEdgesGraph后均添加
例如:
在这里插入图片描述
4.empty函数在这里插入图片描述

3.1.5 Problem 4: Poetic walks

3.1.5.1 Test GraphPoet

设计和实现思路:创建两个用做语料库的文件first.txt和seven.txt
first.txt的输入语句为:
“Test the system.”
seven.txt的输入语句为:
“Please tell who is superstar. Please tell two culture sports open.”
过程:
调用poem根据输入语句"Test the system."
输出"Test of the system."
调用poem根据输入语句"Please tell who is superstar. Please tell two culture sports open."
输出"Please tell who is superstar. Please tell two culture sports flowers open."

3.1.5.2 Implement GraphPoet

设计和实现思路:
(1) GraphPoet:根据指定文件建立语料库。
设计思路:输入文件,初始化myword为空,按行处理文件,按空格切割得到词语并全部小写。为避免重名,若词语不在myword中,则放入myword中。调用add函数放入graph中,调用set函数设置相邻顶点的边权值为两顶点的边数,,最后生成语料库

(2) Poem:根据语料库和输入语句生成一段诗歌。
设计思路:
按空格切割用户输入语句input,得到数组inputword,将inputword里的词语全部小写放入列表inputlist里,初始化i=0。inputlist(i)和inputlist(i+1)是否在语料库中,在语料库中找到中间点词语maxString使得两个点距离最大。在input里面增加桥接词语MaxString,依次循环直到i>=inputlist.size()-1,最后输出诗歌.
(3) checkRep:有向图不为空
(4) ToString:

3.2 Re-implement the Social Network in Lab1

在这里简要概述你对该任务的理解。
在本次实验中,基于在 3.1 节 Poetic Walks 中定义的 Graph及其两种实现,重新实现 Lab1 中 3.3 节的 FriendshipGraph 类。

3.2.1 FriendshipGraph类

给出你的设计和实现思路/过程/结果。
(1)先创建有向图graphL:
Graph graphL = new ConcreteEdgesGraph();
(2)addEdge函数:在有向图中增加边。调用set函数。

(3)addVertex函数:在有向图中增加顶点。调用add函数。

(4)getDistance函数:计算两个顶点per1,per2之间的距离。
设计思路:以per1为起点进行广度优先搜索,计算到per2的距离。
流程图如下:记graphL.targets(per1)为per1的朋友列表。比较当前顶点的sources集合与上个顶点的sources集合,若有相同元素,则在同一层,否则不在同一层。

3.2.2 Person类

给出你的设计和实现思路/过程/结果。
定义ArrayList类型的namelist用于存储顶点名字来检查重名。
定义getName函数来获取顶点名字。

3.3 Playing Chess

3.3.1 ADT设计/实现方案

设计了哪些ADT(接口、类),各自的rep和实现,各自的mutability/ immutability说明、AF、RI、safety from rep exposure。
必要时请使用UML class diagram(请自学)描述你设计的各ADT间的关系。
(1) Game类(实现Action接口)
(1.1) rep和实现
(1.1.1) 构造方法Game

(1.1.2) Initial()函数:如果是国际象棋,需要将所有 Piece 对象放置到棋盘上的初始位置。如果是围棋棋盘的初始状态是棋盘上无任何棋子。
(1.1.3) (Action接口 Override)PutChess:放子(异常情况在主程序中考虑),调用setpiece函数将棋子放在目标位置,并设置棋子状态。

(1.1.4) (Action接口 Override)MoveChess:移子(异常情况在主程序中考虑)先调用getpiece函数取出原来位置的棋子,后调用removePiece函数将原来位置棋子移除,最后调用setPiece函数将棋子放置在目标点。

(1.1.5) (Action接口 Override)PullChess:提子(异常情况在主程序中考虑)调用deletepiece和removepiece函数删除目标位置的棋子。

(1.1.6) (Action接口 Override)EatChess:吃子(异常情况在主程序中考虑)先调用deletepiece和removepiece函数删除目标位置的棋子,后调用setpiece和removepiece函数将原来位置的棋子移动至目标位置。
举例说明可变性与不可变性,AF,RI和safety from rep exposure,其他ADT类似
(1.2) mutability/ immutability说明
定义的chessBoard是可变类型,
定义的gamename是不可变类型。
(1.3) AF:(值到其对应的抽象值的映射)R → A。
在这里插入图片描述
(1.4) RI:(值到布尔值的映射)R → boolean。
RI(“go”) =true ,R(“chess”) = true, R(“choice”) =false。

(1.5) safety from rep exposure(客户端对其的调用不可以直接修改内部数据。)
(1) 将类中所有的属性(变量)定义为private类型。
在这里插入图片描述
(2)方法或者返回immutable data,或者返回本应该返回的mutable data的副本,或者返回一个不可修改的mutable data
(2) Player类
(2.1)rep和实现
(2.1.1) 构造方法Player
(2.1.2)getname()函数:获得玩家名字
(2.1.3)gethistory()函数:获得该玩家操作历史
(3)Board类
(3.1) rep和实现
(3.1.1) 构造方法Board。

(3.1.2) getPiece:获得指定位置的棋子。

(3.1.3)setPiece:在指定位置放置棋子。

(3.1.4)removePiece:删除指定位置的棋子

(3.1.5)Islegal:是否是合法坐标,判断坐标是否超出棋盘范围。

(3.1.6)Ispiece:判断棋子是否在棋盘中。遍历一遍棋盘,若找到返回true,否则返回false。
(3.1.7)getpiecenum:获得指定玩家在棋盘中的棋子数。初始化num=0,遍历棋盘中的所有棋子,若遇到该玩家的棋子,则num加一,直到所有棋子都访问过后返回num。
(3.1.8)Isatpiece :判断某位置中是否有棋子。
(4)Piece类
(4.1) rep和实现
(4.1.1)构造方法Piec
(4.1.2)函数deletepiece():将棋子移除不能再放回
函数setstate():设置棋子状态
(4.1.3)Isbelong函数:判断棋子是否属于某个棋手。
(5)Position类
(5.1) rep和实现
(5.1.1)构造方法Position
(5.1.2)getx()和gety()
(6)Action接口
(6.1.1)PutChess:放子(异常情况在主程序中考虑)
调用setpiece函数将棋子放在目标位置,并设置棋子状态。
(6.1.2)MoveChess:移子(异常情况在主程序中考虑)
先调用getpiece函数取出原来位置的棋子,
后调用removePiece函数将原来位置棋子移除,
最后调用setPiece函数将棋子放置在目标点。
(6.1.3)PullChess:提子(异常情况在主程序中考虑)
调用deletepiece和removepiece函数删除目标位置的棋子。
(6.1.4)EatChess:吃子(异常情况在主程序中考虑)
先调用deletepiece和removepiece函数删除目标位置的棋子,
后调用setpiece和removepiece函数将原来位置的棋子移动至目标位置。

3.3.2 主程序MyChessAndGoGame设计/实现方案

辅之以执行过程的截图,介绍主程序的设计和实现方案,特别是如何将用户在命令行输入的指令映射到各ADT的具体方法的执行。
主程序的设计和实现方案:
主程序的实现步骤如下:
(1) 定义Menu函数:显示用户游戏规则。

(2) 按棋子颜色定义双方玩家为whiteper和blackper。

(3) 输入游戏名称,根据游戏名称调用initial函数创建棋盘。
(4) 之后白棋玩家和黑棋玩家交替输入操作,直到有一方输入end认输。
用switch语句将用户在命令行输入的指令映射到各ADT的具体方法的执行。

3.3.3 ADT和主程序的测试方案

介绍针对各ADT的各方法的测试方案和testing strategy。
介绍你如何对该应用进行测试用例的设计,以及具体的测试过程。
(1) 测试用例的设计以及具体的测试过程:
Position类只有get函数不需要测试。
(1.1)GameTest中需要测试initial函数初始化出的棋盘,检测棋子数量,围棋0,国际象棋32

(1.2)PlayerTest中只需测试AddHistory函数

(1.3)PieceTest中只需检测Isbelong函数

(1.4)BoardTest
初始化一个空的棋盘。
(1.4.1)getPieceTest:在棋盘(0,1)处放一个棋子,调用getpiece,其返回值为true则通过测试。
(1.4.2)setPieceTest:调用setPiece函数在棋盘(0,1)处放一个棋子,检测(0,1)处棋子的颜色和名字。
(1.4.3)removePieceTest:在棋盘(0,1)处放一个棋子,调用removePiece将棋子移除,后检测(0,1)处是否有棋子,若无则通过测试。
(1.4.4)IslegalTest:若输入坐标(9,0)返回false, 输入坐标(1,0)返回true,则通过测试。
(1.4.5)IspieceTest:在棋盘(0,1)处放一个棋子,调用IsPiece检测该棋子是否在棋盘中,若在则通过测试。
(1.4.6)getpiecenumTest:初始化为国际象棋,若调用 getpiecenum得到白棋玩家和黑棋玩家棋子均为16,则通过测试。
(1.4.7)IsatpieceTest:在棋盘(0,1)处放一个棋子,调用getpiece若检测(1,0)为true,若检测(5,5)为false则通过测试。
(1.5)ActionTest:
(1.5.1)PutChessTest:棋盘初始化为围棋,调用PutChess将一个棋子放入,检测是否放入成功。
(1.5.2)MoveChessTest:棋盘初始化为围棋,调用MoveChess进行行移子操作,检测是否成功。
(1.5.3)PullChessTest:棋盘初始化为围棋,调用PullChess进行提子操作,检测是否成功。
(1.5.4)EatChessTest:棋盘初始化为国际象棋,调用EatChess进行吃子操作,检测是否成功。
以后要边写实验边看报告要求,这次虽然程序虽然可以运行,却不符合ADT设计要求
遇到的错误:
(1)遇到异常情况直接终止程序,在实验课上改为遇到异常情况提示用户重新输入。
(2)定义的ADT存在代码暴露的风险。
chessBoard不是private的,所以这个类型的客户端能访问它,暴露给客户端。
在这里插入图片描述
改进方案:将Action改为接口,Game里将chessBoard定义为private的,在Game类中实现Action接口的函数。

备注

P1 ConcreteVerticesGraphTest调试遇到问题

1.vertices始终为空

原因:通过add对vertices进行初始化,显然只能输入字符串名称,不
能输入source,target和weight
在这里插入图片描述
解决方案:通过set对vertices进行初始化
在这里插入图片描述

2. vertices出现重根

原因是每次都新new v1与v2,put进入vertices。
解决方案:new之后对v1与v2是否在vertices里进行检查。
在这里插入图片描述

		**排版难免疏忽,欢迎指正。**
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐