文章目录
- 1 实验目标概述
- 2 实验环境配置
- 3 实验过程
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 实验环境配置
在github上git clone老师的仓库,然后再在eclipse中选择import a existed project。
私有仓库地址
3 实验过程
请仔细对照实验手册,针对三个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
3.1 Poetic Walks
构造一个泛型接口Graph,可以采用两种不同的方式实现,分别是点图和边图。在problem4当中,根据已经构造的graph,生成一个有关语言的图,并根据这个图自动补齐输入词组。
3.1.1 Get the code and prepare Git repository
git init
git remote add origin https://github.com/ComputerScienceHIT/Lab2-1180300410.git
git clone
3.1.2 Problem 1: Test Graph
现在Graph当中采用一种方法构造一个emptyGraph,这里采用ConcreteEdgesGraph。
public static <L> Graph<L> empty() {
Graph<L> graph = new ConcreteEdgesGraph<L>();
return graph;
}
3.1.3 Problem 2: Implement Graph
3.1.3.1 Implement ConcreteEdgesGraph
采用一个Set集合和List<Edge>列表分别保存图的顶点和边。
// Abstraction function:
// represent a set of edges from a source
// Representation invariant:
// the weight is nonnegative
// edges are less than n * (n + 1)
// only an edge between the a source and a target
其中有add,remove,set,sources,targets等操作。除此之外,还有另外一个Edge类来保存边,域中有source边,target边和权值。
3.1.3.2 Implement ConcreteVerticesGraph
采用一个List<Vertex>保存图。
// Abstraction function:
// vertices represent the node in a graph
// two maps in Vertex represent the in and out edge to a vertex
// Representation invariant:
// Vertex may not be null
// elements in in map is similar to out map
// weight -> nonnegative
// Safety from rep exposure:
// use private and final to protect
与3.1.3.1有相同的操作。其中还有另外一个Vertex类来保存一个点,以及与这个点相邻的点的信息,用一个Map<L, Integer>分别保存相邻的顶点和边的权值。
3.1.4 Problem 3: Implement generic Graph
3.1.4.1 Make the implementations generic
将上面完成的两个文件中所有用到String的地方改成即可实现泛型。
3.1.4.2 Implement Graph.empty()
采用ConcreteEdgesGraph实现,构造一个空的ConcreteEdgesGraph。
3.1.5 Problem 4: Poetic walks
3.1.5.1 Test GraphPoet
// Testing strategy
// Partition of input:empty String, one word, some words
3.1.5.2 Implement GraphPoet
根据读入的文件构造一个图,再根据这个图对输入进行补全。
for (int i = 0; i < (words.length - 1); i++) {
sources = graph.sources(words[i + 1].toLowerCase());
targets = graph.targets(words[i].toLowerCase());
sb.append(words[i].toLowerCase() + " ");
int weight = 0;
String bridge = "";
for (String word : targets.keySet()) {
if (sources.keySet().contains(word)) {
if (sources.get(word)+ targets.get(word) > weight) {
weight = sources.get(word) + targets.get(word);
// sb.append(word + " ");
bridge = word;
}
}
}
if (weight > 0) {
sb.append(bridge.toLowerCase() + " ");
}
}
sb.append(words[words.length - 1].toLowerCase());
3.1.5.3 Graph poetry slam
3.1.6 Before you’re done
请按照http://web.mit.edu/6.031/www/sp17/psets/ps2/#before_youre_done的说明,检查你的程序。
如何通过Git提交当前版本到GitHub上你的Lab2仓库。
在这里给出你的项目的目录结构树状示意图。
在eclipse中按照图形化的界面提交。commit and push。
项目名称: Lab2-1180300410
src
P0
graph
….java
poet
….java
….txt
test
P1
graph
…Test.java
poet
…Test.java
….txt
3.2 Re-implement the Social Network in Lab1
基于3.1完成的图实现Lab1中的FriendshipGraph。
3.2.1 FriendshipGraph类
private Graph<Person> graph = Graph.empty();
public void addVertex(Person person) {
graph.add(person);
}
public void addEdge(Person person1, Person person2) {
graph.set(person1, person2, 1);
}
getDistance依然采用DFS实现。
3.2.2 Person类
此处直接将Lab1的Person类copy过来就可。
3.2.3 客户端main()
采用与Lab1相同的客户端main。
public static void main(String[] args) {
FriendshipGraph graph = new FriendshipGraph();
Person rachel = new Person("Rachel");
Person ross = new Person("Ross");
Person ben = new Person("Ben");
Person kramer = new Person("Kramer");
//Person k = new Person("Ben");
//graph.addVertex(k);
graph.addVertex(rachel);
graph.addVertex(ross);
graph.addVertex(ben);
graph.addVertex(kramer);
graph.addEdge(rachel, ross);
graph.addEdge(ross, rachel);
graph.addEdge(ben, ross);
graph.addEdge(ross, ben);
System.out.println(graph.getDistance(rachel, ross));
System.out.println(graph.getDistance(rachel, ben));
System.out.println(graph.getDistance(rachel, rachel));
System.out.println(graph.getDistance(rachel, kramer));
}
3.2.4 测试用例
仍然采用与Lab1相同的测试用例。
3.2.5 提交至Git仓库
如何通过Git提交当前版本到GitHub上你的Lab3仓库。
在这里给出你的项目的目录结构树状示意图。
在eclipse中按照图形化的界面提交。commit and push。
项目名称: Lab2-1180300410
src
P2
FriendshipGraph.java
Person.java
test
P2
FriendshipGraphTest.java
3.3 Playing Chess
3.3.1 ADT设计/实现方案
3.3.1.1 Position类
//fields
private int x;
private int y;
// Abstraction function:
// x is the x line in the UCS
// y is the y line in the UCS
// (0, 0) is the left and down corner
// Representation invariant:
// both are nonnegative
// Safety from rep exposure:
// use private
3.3.1.2 Player类
//fields
private final String name;
private final Type color;
private List pieceList = new ArrayList<>();
// Abstraction function:
// the name of player represent a player
// player1 use WHITE while player2 use BLACK
// the pieces the player has are in the pieceList
// Representation invariant:
// the name may not be similar
// all the fields may not be null
// Safety from rep exposure:
// use private and final and defined copy
3.3.1.3 Action类
the search and calculate piece number method in a game. no constructor, AF, RI and so on.
3.3.1.4 Type类
- the type and color of pieces.
- BLACK and WHITE in go game.
- the others in chess game.
- besides BLACK and WHITE also represent the color.
3.3.1.5 Piece类
//fields
private final Type type;
private final Player player;
// Abstraction function:
// the type is the kind of the piece
// player is the owner of the piece
// Representation invariant:
// type and player are not null
// Safety from rep exposure:
// use private and final
3.3.1.6 Board类
//fields
private int size;
private final Map<Position, Piece> board = new HashMap<>();
// Abstraction function:
// size is the size of the board
// the map’s key is a position on the board
// the map’s value is the piece on the position
// Representation invariant:
// size is nonnegative. in fact, it’s 8 or 19
// the map is not null
// Safety from rep exposure:
// use private, final, and defined copy
3.3.1.7 Game类
//fields
private Board gameBoard;
private final Player player1;
private final Player player2;
private final Action action = new Action();
private final StringBuilder sb = new StringBuilder("");
// Abstraction function:
// use gameBoard to represent a board in a game
// two players are player1 and player2
// sb to record the operation
// Representation invariant:
// gameBoard, player1, and player2 is not null
// Safety from rep exposure:
// use private and final
3.3.2 主程序MyChessAndGoGame设计/实现方案
辅之以执行过程的截图,介绍主程序的设计和实现方案,特别是如何将用户在命令行输入的指令映射到各ADT的具体方法的执行。
初始化部分:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Game game;
while (true) {
System.out.println("请输入游戏(chess or go): ");
String s = input.next();
围棋部分:
if (s.equals("go")) {
System.out.println("请输入玩家1的名字: ");
String player1 = input.next();
String player2;
while(true)
{
System.out.println("请输入玩家2的名字: ");
player2 = input.next();
if(! player2.equals(player1))
break;
System.out.println("不允许重名,请重新输入");
}
game = new Game(player1, player2);
game.init(false);
int i = 1;
while (s != "end") {
i = i % 2;
System.out.println("现在是" + game.getPlayer(i).getName() + "操作: ");
System.out.println("1. 落子");
System.out.println("2. 提子");
System.out.println("3. 打印棋盘");
System.out.println("4. 查询位置");
System.out.println("5. 计算我的棋子数目");
System.out.println("6. 计算对方棋子数目");
System.out.println("7. 跳过");
System.out.println("end. 结束");
s = input.next();
if(s.equals("end"))
break;
int choose = Integer.valueOf(s);
switch(choose) {
case 1:
System.out.println("请输入落子位置: ");
game.put(new Position(input.nextInt(), input.nextInt()), new Piece(i == 1 ? Type.WHITE : Type.BLACK, game.getPlayer(i)));
i = i + 1;
break;
case 2:
System.out.println("请输入要移除棋子的位置: ");
game.remove(game.getPlayer(i), new Position(input.nextInt(), input.nextInt()));
i = i + 1;
break;
case 3:
game.print();
break;
case 4:
System.out.println("请输入要查询的位置: ");
Position p = new Position(input.nextInt(), input.nextInt());
System.out.println(game.search(p) == null ? "此处无棋子" : game.search(p).pieceImformation());
break;
case 5:
System.out.println(game.getPlayer(i).getName() + "的棋子数量是" + game.calculatePieceNumber(game.getPlayer(i)));
break;
case 6:
System.out.println(game.getPlayer(i + 1).getName() + "的棋子数量是" + game.calculatePieceNumber(game.getPlayer(i + 1)));
break;
case 7:
game.skipe(game.getPlayer(i));
i = i + 1;
break;
default:
System.out.println("请重新输入");
continue;
}
}
game.history();
break;
}
国际象棋部分:
else if (s.contentEquals("chess")) {
System.out.println("请输入玩家1的名字: ");
String player1 = input.next();
String player2;
while(true)
{
System.out.println("请输入玩家2的名字: ");
player2 = input.next();
if(! player2.equals(player1))
break;
System.out.println("不允许重名,请重新输入");
}
game = new Game(player1, player2);
game.init(true);
int i = 1;
while (s != "end") {
i = i % 2;
System.out.println("现在是" + game.getPlayer(i).getName() + "操作: ");
System.out.println("1. 移子");
System.out.println("2. 吃子");
System.out.println("3. 打印棋盘");
System.out.println("4. 查询位置");
System.out.println("5. 计算我的棋子数目");
System.out.println("6. 计算对方棋子数目");
System.out.println("7. 跳过");
System.out.println("end. 结束");
s = input.next();
if(s.equals("end"))
break;
int choose = Integer.valueOf(s);
switch(choose) {
case 1:
System.out.println("请输入要移动棋子的位置: ");
Position source = new Position(input.nextInt(), input.nextInt());
System.out.println("请输入要移动到的位置: ");
Position target = new Position(input.nextInt(), input.nextInt());
game.move(game.getPlayer(i), source, target);
i = i + 1;
break;
case 2:
System.out.println("请输入要移动棋子的位置: ");
Position source1 = new Position(input.nextInt(), input.nextInt());
System.out.println("请输入要吃棋子的位置: ");
Position target1 = new Position(input.nextInt(), input.nextInt());
game.eat(game.getPlayer(i), source1, target1);
i = i + 1;
break;
case 3:
game.print();
break;
case 4:
System.out.println("请输入要查询的位置: ");
Position p = new Position(input.nextInt(), input.nextInt());
System.out.println(game.search(p) == null ? "此处无棋子" : game.search(p).pieceImformation());
break;
case 5:
System.out.println(game.getPlayer(i).getName() + "的棋子数量是" + game.calculatePieceNumber(game.getPlayer(i)));
break;
case 6:
System.out.println(game.getPlayer(i + 1).getName() + "的棋子数量是" + game.calculatePieceNumber(game.getPlayer(i + 1)));
break;
case 7:
game.skipe(game.getPlayer(i));
i = i + 1;
break;
default:
System.out.println("请重新输入");
continue;
}
}
game.history();
break;
} else {
System.out.println("请重新输入 ");
}
}
3.3.3 ADT和主程序的测试方案
3.3.3.1 ActionTest
// Testing strategy:
// when the result is null, or not null
// when the result is zero, or negative
3.3.3.2 BoradTest
//Testing strategy:
// the board is empty or not empty
3.3.3.3 PieceTest
//Testing strategy:
// divided into piece with the same or different name
3.3.3.4 PlayerTest
//Testing strategy:
// the player have no piece or some pieces
3.3.3.5 PositionTest
//Testing strategy:
// divided into:
// 1. X is different and Y is different
// 2. only X 3. only Y
// 4. both are different