1 实验目标概述
本次实验通过求解三个问题,训练基本 Java 编程技能,能够利用 Java OO 开发基本的功能模块,能够阅读理解已有代码框架并根据功能需求补全代码,能够为所开发的代码编写基本的测试程序并完成测试,初步保证所开发代码的正确性。另一方面,利用 Git 作为代码配置管理的工具,学会 Git 的基本使用方法。
l 基本的 Java OO 编程
l 基于 Eclipse IDE 进行 Java 编程
l 基于 JUnit 的测试
l 基于 Git 的代码配置管理
2 实验环境配置
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 实验过程
3.1 Magic Squares
本题与Magic Squares有关,即幻方。通过实验要求描述以及查阅资料可知,幻方一个n阶的魔法平方是n×n个数的排列,通常是不同的整数,在一个平方中,所有行、所有列和两个对角线中的n个数之和为相同的常数。
实验要求写出判断n*n矩阵是否是幻方的函数isLegalMagicSquare(),并对要求对各种特殊情况作出反应,最后对已给的五个文件进行测试;读懂函数generateMagicSquare(),并在main()中对其进行测试,再将它生成的n*n矩阵写入第六个文件并对其进行是否为幻方的测试。
3.1.1 isLegalMagicSquare()
按步骤给出你的设计和实现思路/过程/结果。
- 函数分析
本题要求编写一个函数isLegalMagicSquare()判断一个txt文件中保存的矩阵是否为符合幻方要求的矩阵。输入参数为txt文件的文件路径,函数返回一个boolean值,若符合要求返回true,否则返回false。
幻方的正确性:每一行、每一列、两条对角线上的元素相加之和相等
幻方的合法性:行数和列数相等;元素之间用\t分隔;元素必须是不同的正整数。
- 实现思路
首先将读入文件,若打开失败则结束程序
依次用Scanner读入文件的每一行,并以“\t”切割字符串存入myline
以行为单位处理字符串:
设置变量row记录已读入的行数;col记录列数,初始化为myline的长度,用以判断行列元素个数是否相等
用myline自带的方法将字符转换为数字存入matrix_row,若符合一切矩阵的合理性要求,则将matrix_row存入matrix,否则报错并结束程序
至此为止文件读入及数据处理完成
接下来判断该矩阵是不是幻方,具体思路是:
以第一行和第一列为基准,首先计算出第一行及第一列的元素和,作比较,若不等则提示不是幻方,若相等则继续计算
对于每一行、每一列的计算使用两个for循环即可,由于计算过第一行和第一列的元素
循环从第二行、列开始即可;对于两条对角线的计算,首先将第一行、列位于两条对角线上的元素加入对角线和,再通过循环计算对角线和
若存在任意一行、列、对角线上元素和与第一行不相等,则判断不是幻方
- 实现结果
3.1.2 generateMagicSquare()
- 程序流程图
- 代码实现
将第一个数字填入首行的中间位置,下移至最后一行然后沿右上格进行填入数字;若填至最右边一列就再从最左边的列开始;若填至最上面的一行则从最后一行再次填起;若遇到可以整除n的一行则将数字填在原位置正下方的格子里。
循环赋值直到正好将方格填完。
错误分析
输入n为偶数时,报错:数组下标越界,因为会访问到matrix[][n]
输入n为负数时,报错及出错原因:数组负长度异常
- 实现报错退出、文件读写和判断生成矩阵
测试结果
3.2 Turtle Graphics
本题的主要任务是将实验的代码导入P2包里,实现TurtleSoup里的各种方法,控制Turtle绘制自定义图案并完成TurtleSoupTest中的测试
3.2.1 Problem 1: Clone and import
如何从GitHub获取该任务的代码、在本地创建git仓库、使用git管理本地开发。
- 获取任务代码:进入报告里的链接,下载相关代码文件,新建directory将代码放进去并将其mark为Sources Root
- 使用Git管理本地开发:先用Git创建本地仓库,然后和远程仓库连接,git pull拉取代码。实现一个功能后用git add .上传项目文件,然后commit、push提交到远程仓库上。
- 主要任务:利用已给的forward和turn方法画一个矩形,并测试(实例化对象是turtle,参数sideLength已给)
- 实现思路及代码
3.2.2 Problem 3: Turtle graphics and drawSquare
循环执行4次,每次forward前行sideLength的距离,然后画笔方向旋转90 度,继续 下一次执行。即可得到所要求的正方形
实现结果
3.2.3 Problem 5: Drawing polygons
- 主要任务
创建多边形:首先需要实现函数calculateRegularPolygonAngle,计算多边形的内角,并测试;然后实现函数drawRegularPolygon,绘制一个多边形,类比正方形进行绘制即可。
- 实现思路及代码
从网上查得多边形内角和计算公式,除以边数即得内角
绘制多边形思路与正方形差不多,因计算内角为静态方法可直接调用
- 实现结果
此处展示八边形
3.2.4 Problem 6: Calculating Bearings
- 主要任务
计算轴承,即计算从起始点到终点需要旋转的角度,主要有两个函数,点对点的calculateBearingToPoint,和计算连续几个轴承的函数calculateBearings
- 实现思路及代码
先计算两个坐标连线与垂线的夹角,若角度小于零则取正,否则计算360减 去该角度,在将计算结果减去初偏角加上90,再对360取余便得到最后的结 果
第二个函数,连续计算即可
3.2.5 Problem 7: Convex Hulls
- 主要任务
- 实现思路及代码
可以先通过点的个数分类讨论,当点的个数为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
- 打开要上传的文件夹,打开Git bash,利用$git init语句初始化本地仓库
- 利用$git remote add origin语句添加仓库URL
- 用$git add将文件传入暂存区
- 用$git commit -m“”提交并添加版本形容
- 最后用$git push -u origin master将文件上传
3.3 Social Network
先创建Person类,再以Person为元素创建一个关系网,即Person为元素的无向图
3.3.1 设计/实现FriendshipGraph类
采用邻接表来存储朋友
- 构造方法
- addVertex方法
在关系网中添加成员,若该成员已存在,则报错并退出程序
- addEdge方法
为关系网中的两位成员添加关系,若其中任意一位成员不存在,或是该两位 成员已有关系,则报错并退出。注:此处采用的是单箭头模式,即若两位成 员有关系,需添加两次,有顺序之分
- getDistance方法
利用广度优先搜索算法
主要使用的数据结构:队列:辅助数据结构;set:标记该朋友是否被访问; map:记录每一个朋友与from之间的距离;
初始化:将初始元素入队;标记初始元素被访问过;
判断简单初始情况:若初始元素与目标元素相同时:直接返回0;
当目标元素与初始元素有关系时:直接返回1;
处理其他情况:将map对应的值全部初始化为0,此举的可行性是基于:不 与初始元素相连通的元素进入不了while循环而直接返回-1,而map只在 while当中使用
具体思路:当队列非空时,将队首元素出队并记录,使其连接的未被访问过 的元素入队,并将该元素所对应的map的值更改为与其相连的元素对应的值 加一;
处理错误情况:若初始元素或目标元素都不存在于该关系网中时,报错并退 出程序
3.3.2 设计/实现Person类
设计private类型的属性name,基本的方法getName和setName
3.3.3 设计/实现客户端代码main()
- 原始实验报告中的版本
注释掉graph.addEdge(rachel,ross);
预期:因为未给rachel和ross添加关系,故除了rachel到本人的距离为0以 外,和其他任何一个人都没有关系,也不连通,故距离都为-1
- 若新建Person对象时添加重复名字
将Ben添加两次
3.3.4
设计/实现测试用例
新建测试文件夹,点击goto选项直接进入test文件
测试addVertex方法
- 测试addEdge方法
- 测试getDistance方法
构造一个复杂图,来测试getDistance