软件构造Lab1的实现思路

 Magic Squares

在这里简要概述你对该任务的理解:

  • 该实验主要包含两项任务:
  1. 编写isLegalMagicSquare()判断一个n×n的矩阵是否为Magic Square,如果是,返回true,否则返回false。
  2. 理解完善给定的generateMagicSquare()方法,针对n为奇数的幻方的生成算法进行理解完善。
  • 幻方的特点:N 阶幻方是 n 个数字在一个正方形中的排列(通常为不同的整数)。所有行,所有列的数字和,以及两个对角线的和等于同一个常数。

1.isLegalMagicSquare()

(1)问题求解思路:

首先读取文件最大行数,最大列数,判断最大行数与最大列数是否相等,若相等则生成一个n*n的矩阵,并将该矩阵初始化为0之后加入数据,由于共有n行、n列以及两条对角线,于是用一个[2n+2]数组存储行之和列之和以及对角线之和,并在添加数据时判断是否为正整数,判断数据是否规范。

(2)设计思路

①使用java输入流进行文本读入,首先读取最大行数与最大列数并判断是否相等,若不等则返回不是矩阵的结果;

将字符串按行读入并存入String数组,并在读取数据过程中进行数据合法性检验,若不是正整数则报错;

第一行为参考,计算出各行列及对角线的和判断各值是否相等,如果不等返回false并抛出和不相等的异常,在函数最后若无上述异常则说明幻方成立,返回true。

④main函数进行测试

⑤得到如下运行结果:

2.generateMagicSquare()

按步骤给出你的设计和实现思路/过程/结果。

  • 设计思路

(1)使用罗伯法构造一个n为奇数的nxn幻方。罗伯法的算法具体为:

把1(或最小的数)放在第一行正中;按以下规律排列剩下的(n×n-1)个数

①每一个数放在前一个数的右上一格;

②如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列;

③如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行;

④如果这个数所要放的格已经超出了顶行且超出了最右列,那么就把它放在底行且最左列;

⑤如果这个数所要放的格已经有数填入,那么就把它放在前一个数的下一行同一列的格内。

⑵对函数public static boolean generateMagicSquare(int n) 进行分析解读:

(3)对已有代码进行完善,当输入n为负数或者偶数时进行报错

(4)编写main函数进行测试

(5)输入n为15  生成如下所示6.txt

  • 异常分析
  1. 创建数组时元素个数不能为负数

 

2.分n次每次写n个数据,每结束时不能在最后一行,否则row会++,n为偶数会在i%n==0时row++后填写magic[][]时出现越界情况,而函数第一行开始,注定偶数行为结束行,因此n不能为偶数

Turtle Graphics

在这里简要概述你对该任务的理解。

  • 理解:该任务要求我们根据代码注释提示补全代码利用这些函数实现旋转,前进,换色等功能实现一个绘制工具Trurtle Graphics。
  1. Problem 1: Clone and import

(1)访问https://github.com/rainywang/Spring2020_HITCS_SC_Lab1/tree/master/P2下载P2文件夹,获得任务代码

(2)在本地创建git仓库

(3)git init初始化本地仓库

(4)git add remote origin 添加远程库源

(5)在远程仓库创建master分支

(6)git pull origin master将远程仓库同步到本地

(7)git add->git commit->git push 将本地文件加入本地仓库,将本地仓库同步到远程仓库。

Problem 3: Turtle graphics and drawSquare

  • 问题描述:当给定爬行长度sideLength,使little turtle画一个边长为sideLength的正方形。
  • 求解思路:turtle前进sidelength,右转90度,循环四次.即为正方形其中forward(int units) 的功能是向前平移units个单位;turn(double degrees) 的功能为顺时针转90°

 

Problem 5: Drawing polygons

  • 问题描述及求解思路:

(1)calculateRegularPolygonAngle

给定正整数sides(>2)边数,返回内角度数,通过数学公式return (double)180*(sides-2)/sides实现。

2public static int calculatePolygonSidesFromAngle(double angle)

给出浮点数angle(0<angel<180),返回以angle为内角度数的正n边形边数。

利用多边形外角和360°,公式为:sides=360/(180-angle)。

(3)drawRegularPolygon

给定边数画多边形,调用calculateRegularPolygonAngle(sides)计算正多边形的内角为rotation,调用turtle.forward和turtle.turn进行前进和转向n次即可得到n边形。

​​​​​​​Problem 6: Calculating Bearings

  • 问题描述:

计算当前向量与目标向量的夹角。其中当前向量由当前点、当前方向决定,目标方向由当前点、目标点决定,当前方向由当前方向与竖直向上方向(y轴正方向)的夹角表示,目标向量的方向由当前点与目标点的连线与竖直向上方向(y轴正方向)的夹角表示。

  • 解决思路:

默认初始角度为0,然后从第一个点走向第二个点后,朝向不变,然后以此朝向作为下一次旋转的初始角度,再计算第二个点到第三个点的旋转角度,依次类推。先求当前点与目标点的连线与y轴夹角的正切值,tan=(targetX-currentX)/(targetY-currentY),然后调用Math库中的atan将其转化为弧度,再由公式——角度=弧度*180/π——求得角度值,即为当前向量与y轴正方向的夹角,与currentBearing(当前方向)作差,得到结果

​​​​​​​Problem 7: Convex Hulls

  • 问题描述:

该题为凸包问题,给出一组点的坐标,求最少的点的集合,使其他所有点都在这些点围成的闭合凸多边形内。

  • 解决思路:

扫描list列表,根据坐标选出最左下角的点作为点B。添加一个点A,A位于B点稍下的位置。将(A,B)作为向量Vec1。

扫描所有的不处于凸包中的点,计算A点与该点之间的夹角,夹角通过两向量点击与向量的模计算cos然后通过acos函数获得,找到形成夹角最小的点,如果有多个选择距离当前直线距离最远的那个点(其实可以选择距离前一个点最远的点)。将点B作为新的A,点C作为新的B,再次循环。当新找到的节点是最左边的初始节点时结束循环。

​​​​​​​Problem 8: Personal art

设计了一个螺旋图,该图形经过了900次循环,每次步长为原长的1/9,每次以循环变量的中间位十位为判断标准获得下一个线条颜色,最后调整前进方向,旋转80度,进入下一次循环。Submitting

  1. 将完成的项目复制到本地仓库中,输入git add .将所有文件全部加入本地仓库;
  2. 输入 git commit -m “备注” 指令,将文件暂存到本地目录并且添加备注说明;
  3. 输入 git push -u origin master指令,将本地仓库同步到远程仓库。

​​​​​​​Social Network

在这里简要概述你对该任务的理解。

通过Person和FriendshipGraph两个类,模拟社交网络,提供添加节点以及节点之间添加边,并用BFS计算两节点之间最短路的功能。

  • ​​​​​​​设计/实现FriendshipGraph

先建立一个Node类,存放有关点的相关信息点代表的Person,点与点之间的边代表联系。采用邻接矩阵的方式来存储无向图其中visited数组表示在广度优先搜索的时候,是否已经访问过,parent数组则存储着在搜索中父节点的下标。

  • ​​​​​​​设计/实现Person

(1)用String name存放当前节点的名字;

(2)Set<Person> friends = new HashSet<Person>():存放以当前节点为起点的所有边的终点;

(3)boolean vis:在BFS中标记当前节点是否被访问过;

(4)public String name():返回当前节点的name属性值;

(5)public void add_friend(Person new_friend):向当前节点的friends集合中添加一个新节点,即在当前节点与目标节点之间添加一条单向边;

(6)public Set<Person> get_friends():返回当前节点的friends属性;

  • ​​​​​​​设计/实现客户端代码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");

graph.addVertex(rachel);

graph.addVertex(ross);

graph.addVertex(ben);

graph.addVertex(kramer);

graph.addEdge(rachel, ross);

graph.addEdge(ross, rachel);

graph.addEdge(ross, ben);

graph.addEdge(ben, ross);

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));

}

  • 设计/实现测试用例

1.AddEdge方法测试

@Test

public void addEdgeTest() {

Person a = new Person("A");

Person b = new Person("B");

FriendshipGraph graph = new FriendshipGraph();

graph.addVertex(a);

graph.addVertex(b);

//添加单向边

graph.addEdge(a, b);

assertTrue(a.getFriend().contains(b));

assertFalse(b.getFriend().contains(a));

//添加双向边

graph.addEdge(b, a);

assertTrue(b.getFriend().contains(a));

}

2.GetDistance测试

assertEquals(1, graph.getDistance(a, b));

assertEquals(-1, graph.getDistance(b, a));

assertEquals(2, graph.getDistance(a, c));

assertEquals(-1, graph.getDistance(c, a));

 

实验过程中收获的经验教训、感想

  1. 实验过程中收获的经验教训

这是初次接触软件构造课程,觉得很有难度。并且在之前没有使用过Git和GitHub,导致使用很不熟练。需要多加练习。同时这也是第一次用Java语言去解决问题,一定要注意其与C语言的共性和差异,不断动手实践,学以致用。同时在本次试验中,接触到了很多算法,例如BFS等,但是在应用的过程中仍然不太熟练,所以平时一定要注意归纳总结,把经典的算法牢记于心并学以致用。

   ​​​​​​​2.针对以下方面的感受

(1)Java编程语言是否对你的口味?

在学习过C语言之后学习Java相对较容易,但是初次使用Java去解决实际的问题,还是有很多知识盲区,需要多多学习、积累经验。

(2)关于Eclipse IDE

Eclipse IDE使用较为方便,当编程出错时它会智能提供一些解决方案,给我们思路。

(3)关于Git和GitHub

第一次使用Git和GitHub,十分不熟练,并且GitHub访问不太稳定,但是他们是很强大且有用的学习工具,所以要好好使用它们。

(4)关于CMU和MIT的作业

第一次接收觉得难度较大,且为英文版,需要攻克。

(5)关于本实验的工作量、难度、deadline

实验还是很具有挑战性,有难度,希望可以适当延长每个实验的deadline,不至于太仓促。

(6)关于初接触“软件构造”课程

初次接触“软件构造”课程,觉得难度挺大,这是一门需要不断动手实践积累经验的课程,一定要动手去实践,希望实验的时间可以延长一些。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值