软件构造Lab1

发布时间 2023-04-11 20:49:27作者: dfhkjsbc

实验目标概述

本次实验通过求解三个问题,训练基本 Java 编程技能,能够利用 Java OO 开发基本的功能模块,能够阅读理解已有代码框架并根据功能需求补全代码,能够为所开发的代码编写基本的测试程序并完成测试,初步保证所开发代码的正确性。另一方面,利用 Git 作为代码配置管理的工具,学会 Git 的基本使用方法。

l 基本的 Java OO 编程

l 基于 Eclipse IDE 进行 Java 编程

l 基于 JUnit 的测试

l 基于 Git 的代码配置管理

实验环境配置

2.1 IDEA

在官网下载了安装包并成功安装IntelliJ IDEA 2022.3.2(Ultimate Edition) 

2.2 JDK

之前在软件工程导论的实践项目中已经配置好了JDK8

2.3 Git

在官网下载安装程序,勾选Windows系统并按步骤进行安装

2.4 Junit

我用的是IDEA自带的Junit4,首先点击Project Structure

在窗口中添加Junit4并apply

 

实验过程

3.1 Magic Squares

本题与Magic Squares有关,即幻方。通过实验要求描述以及查阅资料可知,幻方一个n阶的魔法平方是n×n个数的排列,通常是不同的整数,在一个平方中,所有行、所有列和两个对角线中的n个数之和为相同的常数。

实验要求写出判断n*n矩阵是否是幻方的函数isLegalMagicSquare(),并对要求对各种特殊情况作出反应,最后对已给的五个文件进行测试;读懂函数generateMagicSquare(),并在main()中对其进行测试,再将它生成的n*n矩阵写入第六个文件并对其进行是否为幻方的测试。

3.1.1 isLegalMagicSquare()

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

  1. 函数分析

本题要求编写一个函数isLegalMagicSquare()判断一个txt文件中保存的矩阵是否为符合幻方要求的矩阵。输入参数为txt文件的文件路径,函数返回一个boolean值,若符合要求返回true,否则返回false

幻方的正确性:每一行、每一列、两条对角线上的元素相加之和相等

幻方的合法性:行数和列数相等;元素之间用\t分隔;元素必须是不同的正整数。

  1. 实现思路

首先将读入文件,若打开失败则结束程序

依次用Scanner读入文件的每一行,并以“\t切割字符串存入myline

以行为单位处理字符串:

设置变量row记录已读入的行数;col记录列数,初始化为myline的长度,用以判断行列元素个数是否相等

myline自带的方法将字符转换为数字存入matrix_row,若符合一切矩阵的合理性要求,则将matrix_row存入matrix,否则报错并结束程序

至此为止文件读入及数据处理完成

接下来判断该矩阵是不是幻方,具体思路是:

以第一行和第一列为基准,首先计算出第一行及第一列的元素和,作比较,若不等则提示不是幻方,若相等则继续计算

对于每一行、每一列的计算使用两个for循环即可,由于计算过第一行和第一列的元素

循环从第二行、列开始即可;对于两条对角线的计算,首先将第一行、列位于两条对角线上的元素加入对角线和,再通过循环计算对角线和

若存在任意一行、列、对角线上元素和与第一行不相等,则判断不是幻方

 

  1. 实现结果

 

3.1.2 generateMagicSquare()

  1. 程序流程图
  1. 代码实现

将第一个数字填入首行的中间位置,下移至最后一行然后沿右上格进行填入数字;若填至最右边一列就再从最左边的列开始;若填至最上面的一行则从最后一行再次填起;若遇到可以整除n的一行则将数字填在原位置正下方的格子里。

循环赋值直到正好将方格填完。

错误分析

输入n为偶数时,报错:数组下标越界,因为会访问到matrix[][n]

输入n为负数时,报错及出错原因:数组负长度异常

  1. 实现报错退出、文件读写和判断生成矩阵

测试结果

 

3.2 Turtle Graphics

本题的主要任务是将实验的代码导入P2包里,实现TurtleSoup里的各种方法,控制Turtle绘制自定义图案并完成TurtleSoupTest中的测试

3.2.1 Problem 1: Clone and import

如何从GitHub获取该任务的代码、在本地创建git仓库、使用git管理本地开发。

  1. 获取任务代码:进入报告里的链接,下载相关代码文件,新建directory将代码放进去并将其markSources Root
  2. 使用Git管理本地开发:先用Git创建本地仓库,然后和远程仓库连接,git pull拉取代码。实现一个功能后用git add .上传项目文件,然后commitpush提交到远程仓库上。
  3. 主要任务:利用已给的forwardturn方法画一个矩形,并测试(实例化对象是turtle,参数sideLength已给)
  4. 实现思路及代码

3.2.2 Problem 3: Turtle graphics and drawSquare

循环执行4次,每次forward前行sideLength的距离,然后画笔方向旋转90 度,继续 下一次执行。即可得到所要求的正方形

实现结果

 

3.2.3 Problem 5: Drawing polygons

  1. 主要任务

创建多边形:首先需要实现函数calculateRegularPolygonAngle,计算多边形的内角,并测试;然后实现函数drawRegularPolygon,绘制一个多边形,类比正方形进行绘制即可。

  1. 实现思路及代码

从网上查得多边形内角和计算公式,除以边数即得内角

绘制多边形思路与正方形差不多,因计算内角为静态方法可直接调用

 

  1. 实现结果

此处展示八边形

 3.2.4 Problem 6: Calculating Bearings

  1. 主要任务

计算轴承,即计算从起始点到终点需要旋转的角度,主要有两个函数,点对点的calculateBearingToPoint,和计算连续几个轴承的函数calculateBearings

  1. 实现思路及代码

先计算两个坐标连线与垂线的夹角,若角度小于零则取正,否则计算360 去该角度,在将计算结果减去初偏角加上90,再对360取余便得到最后的结

第二个函数,连续计算即可

3.2.5 Problem 7: Convex Hulls

  1. 主要任务
  2. 实现思路及代码

可以先通过点的个数分类讨论,当点的个数为0时返回空集,点的个数小于 等于3时可直接返回。

运用Gift wrapping算法,先找到凸包上一个点,然后从那个点开始按逆时针 方向逐个找凸包上的点,每次都选择转向角最小且点间距离最长的点加入集 合中,计算转向角度可使用上题的calculateBearingToPoint函数。其中相同 转向角点之间的取舍,可以在循环中使用标记变量Dist_target记录其与当前 目标点的距离,如果之后出现了新的目标点,就用Dist_target和计算得到的 当前点的距离Dist_temp来比较,取更大者为新的Dist_target

3.2.6 Problem 8: Personal art

利用循环,使每一次的颜色和步数不同,change代表了尖锐程度 

3.2.7 Submitting

  1. 打开要上传的文件夹,打开Git bash,利用$git init语句初始化本地仓库 
  2. 利用$git remote add origin语句添加仓库URL
  3. $git add将文件传入暂存区
  4. $git commit -m“”提交并添加版本形容
  5. 最后用$git push -u origin master将文件上传

3.3 Social Network

先创建Person类,再以Person为元素创建一个关系网,即Person为元素的无向图

3.3.1 设计/实现FriendshipGraph

采用邻接表来存储朋友

  1. 构造方法 
  1. addVertex方法

在关系网中添加成员,若该成员已存在,则报错并退出程序

  1. addEdge方法

为关系网中的两位成员添加关系,若其中任意一位成员不存在,或是该两位 成员已有关系,则报错并退出。注:此处采用的是单箭头模式,即若两位成 员有关系,需添加两次,有顺序之分

  1. getDistance方法

利用广度优先搜索算法

主要使用的数据结构:队列:辅助数据结构;set:标记该朋友是否被访问; map:记录每一个朋友与from之间的距离;

初始化:将初始元素入队;标记初始元素被访问过;

判断简单初始情况:若初始元素与目标元素相同时:直接返回0

当目标元素与初始元素有关系时:直接返回1

处理其他情况:将map对应的值全部初始化为0,此举的可行性是基于:不 与初始元素相连通的元素进入不了while循环而直接返回-1,而map只在 while当中使用

具体思路:当队列非空时,将队首元素出队并记录,使其连接的未被访问过 的元素入队,并将该元素所对应的map的值更改为与其相连的元素对应的值 加一;

处理错误情况:若初始元素或目标元素都不存在于该关系网中时,报错并退 出程序

 3.3.2 设计/实现Person

设计private类型的属性name,基本的方法getNamesetName

 

3.3.3 设计/实现客户端代码main()

  1. 原始实验报告中的版本

注释掉graph.addEdge(rachel,ross);

预期:因为未给rachelross添加关系,故除了rachel到本人的距离为0 外,和其他任何一个人都没有关系,也不连通,故距离都为-1

 

  1. 若新建Person对象时添加重复名字

Ben添加两次

3.3.4 

设计/实现测试用例

新建测试文件夹,点击goto选项直接进入test文件

测试addVertex方法

  1. 测试addEdge方法
  1. 测试getDistance方法

构造一个复杂图,来测试getDistance