软件构造Lab1

实验一

一、实验目标概述

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

另一方面,利用 Git 作为代码配置管理的工具,学会 Git 的基本使用方法。

    1. 基本的 Java OO 编程
    1. 基于 Eclipse IDE 进行 Java 编程
    1. 基于 JUnit 的测试
    1. 基于 Git 的代码配置管理

二、实验环境配置

IDE:

IntelliJ IDEA 2020.3.1 (JDK 1.8 Junit 4.12)

屏幕截图 2021-06-02 202013.png

Git:

Git version 2.24.1.windows.2

屏幕截图 2021-06-02 202249.png

Lab url:

url : https://github.com/ComputerScienceHIT/HIT-Lab1-1190200708.git

三、实验过程

3.1 Magic Square

3.1.1 功能

MagicSquare 主要实现了以下功能:

    1. 读取所给的五个 txt 文件,并用数组保存;
    1. 检验所给的五个 txt 文件是否为幻方矩阵
    •   2.1 检验文件是否为空
    •   2.2 检验每行是否存在小数
    •   2.3 检验每行是否存在负数
    •   2.4 检验每行是否存在非法字符
    •   2.5 检验行的数量和列的数量是否相同
    •   2.6 检验每行元素个数是否相同
    •   2.7 检验行、列、对角线元素和是否相同
    1. 若是幻方矩阵则返回 true,否则抛出并打印错误;
    1. 检验要求创建的幻方矩阵的数是否合法,考虑奇数或偶数时的异常,若不存在异常,则生成 n*n 的矩阵,并写入 6.txt 文件
3.1.2 函数结构如下:

屏幕截图 2021-06-02 204032.png

3.1.3 MagicSquare方法设计:
isLegalMagicSquare()
  • 设计思路:

首先通过 System.getProperty(“user.dir”) + “\src\P1\txt\” + fileName 和 Scanner 读取文件,每次读取按行读取,读取后,将每行元素作为参数,调用 Float_Neg_tabs()函数检验每行文本是否存在小数、负数、除\t 以外的其他字符。若读取的数都为正数,且每行元素个数相同,且行数与列数相同,则调用 MagicSquareCalculate()函数计算读取的矩阵是否为幻方矩阵。

  • 所调用的函数:

public static int Float_Neg_tabs(String Number);
屏幕截图 2021-06-02 205614.png

功能:

用于检验读取到的每行元素是否存在非法数据,若字符串合法则返回 0,若字符串中含有负数,则返回 1,若字符串中含有非’\t’的字符,则返回 2,若字符串结尾为非’\t’字符,则返回 3,若字符串中含有小数,则返回 4.

实现过程:

对读取的字符串分析,若字符串最后一个字符为非’0’-‘9’且非’\t’,则返回 3,表明,当前字符串的结尾为非’\t’字符;对字符串每个字符检查,若存在字符大于’9’或者小于’0’,则检查是否为’.’或‘\t’或’-‘,若存在’-’符号,则表明存在负数,函数返回 1;若存在’.‘符号,则表明存在小数,函数返回 4;若该符不为以上三种符号,则存在其他非法字符,返回2;对以上检查完毕后,若无异常则,返回 0;

public static boolean MagicSquareCalculate(int[][] Num, int count)
屏幕截图 2021-06-02 205357.png

*功能:*计算每行每列对角线元素和是否相同,若相同则返回 true,否则返回 false。

*实现过程:*首先计算第一行元素和,与每行、每列、写对角线元素和比较,若相等,则表明该矩阵为幻方矩阵,否则不为幻方矩阵。

3.1.4 generateMagicSquare()设计:

设计思路:

修改后的程序:

首先判断参数是否为负数或偶数,并抛出相应异常。若检验出参数为正奇数,则此时可以通过所给代码生成幻方矩阵。并将幻方矩阵通过 PrintWriter 写入到6.txt 中,并通过函数判断是否为幻方矩阵。源程序生成幻方矩阵思路(Siamese 方法):

1.首先将 1 放置在第一行中间;

2.顺序将 2,3,…等数依次放在右上方格中;

3.当右上方格出界的时候,由另一边进入;

4.当右上方格中已经填有数,则把数填入正下放的表格中;

5.按照以上步骤直到填写完所有方格。

流程图如下:
屏幕截图 2021-06-02 210238.png

3.2 Turtle Graphics

Turtle Graphics 主要实现以下几个功能:

    1. 画正方形
    1. 计算正多边形内角角度
    1. 通过正多边形内角,计算正多边形的边数
    1. 画正多边形
    1. 已知当前对 y 轴正半轴的偏角,求从点 current 到点 target 需要旋转的角度
    1. 当前方向为 y 轴正半轴时,求从 xCoords 的点到 yCoords 的点需要旋转的角度的 List
    1. 当前方向为 x 轴正半轴时,求从点 A 到点 B 需要旋转的角度
    1. 在给定一些点的坐标的时候,求这些点的凸包的集合
    1. 绘画出个人作品
    1. 测试以上功能
3.2.1 Problem 3: Turtle graphics and drawSquare:

设计思路:

利用 turtle 的 forward 和 turn 方法,完成转动角度,向前移动等操作,画出边长,并确定多边形的内角。

过程:

使 turtle 首先向当前方向移动 sideLength 个单位,然后使用 turn 方法,向右转 90 度,再向当前方向移动 sideLength 个单位,再使用 turn 方法,向右转 90度,再向当前方向移动 sideLength 个单位,再向右转 90 度,再向当前方向移动sideLength 个单位,即可得到一个边长为 sideLength 的正方形。

运行结果:

该图形的运行结果如下,成功绘制出边长为 40 个单位的正方形。
屏幕截图 2021-06-02 211416.png

3.2.2 Problem 5: Drawing polygons:

设计思路

  1. calculateRegularPolygonAngle
    利用公式即可求正多边形内角。

    Angle = 180 ∗ (sides − 2)/sides

  2. drawRegularPolygon
    使用已经实现的正多边形内角公式,即可计算出要绘制的正多边形的内角,
    进行绘制。

过程

  1. calculateRegularPolygonAngle
    利用公式很容易计算出所求的内角。
  2. drawRegularPolygon
    利用已经实现的计算正多边形内角的公式,即很容易计算出内角,通过 turtle的 turn 方法,即可实现角度的转换,在每绘制一条边的时候,转动角度 180-angle。

运行结果:

屏幕截图 2021-06-02 211731.png

3.2.3 Problem 6: Calculating Bearings

设计思路

  1. calculateBearingToPoint
    通过斜率计算角度,即可计算出要旋转的角度
  2. calculateBearings
    通过斜率计算角度,将所得到的角度保存到 List 中

过程

  1. calculateBearingToPoint

比较 currentX 与 targetX 的值

(1) 若 currentX 与 targetX 的值相等,则说明两点在直线 x=currentX 上。若 currentY>targetY,则说明此时需要将角度调整为 y 的负半轴,因此此时转动的角度为((540 - currentBearing) % 360 + 360) % 360
若 currentY < targrtY,则说明此时需要将角度调整为 y 的正半轴,因此此时转动的角度为((360 - currentBearing) % 360 + 360) % 360;由于 turtle 方法只能向右转动,通过加 360 并取余得到为正的角度。

(2) 若此时 currentX < targetX,则说明此时 current 在 target 左侧,即可通过斜率计算公式,和 Math 库函数中的 atan 函数,计算角度。与 x 轴正半轴角度为 angle = (Math.atan((double) (targetY - currentY) / (double) (targetX - currentX))) * 180 / Math.PI;如图所示,即可得到当前的与 x 轴的夹角,以靠近 y 的正半轴为正,靠近 y的负半轴为负,不难得出,实际需要转动的角度为((450 - angle - currentBearing) % 360 + 360) % 360同理,通过加 360 并取余得到为正的角度。
屏幕截图 2021-06-02 211929.png

(3) 若此时 currentX>targetX,则说明此时 current 在 target 右侧,即可通过斜率计算公式,和 Math 库函数中的 atan 函数,计算角度。与 x 轴正半轴角度为 angle = (Math.atan((double) (targetY - currentY) / (double) (targetX - currentX))) * 180 / Math.PI;如图所示,即可得到当前的与 x 轴的夹角,以靠近 y 的正半轴为正,靠近 y的负半轴为负,不难得出,实际需要转动的角度为((630 - angle - currentBearing) % 360 + 360) % 360同理,通过加 360 并取余得到为正的角度。
屏幕截图 2021-06-02 211952.png

  1. calculateBearings

新建变量 currentBearing,保存当前与 y 轴正半轴的角度,比较 xCoords.get(i)与 xCoords.get(i + 1)的值(i 从 0 开始到 n-2)

(1) 若 xCoords.get(i)=xCoords.get(i + 1)判断 yCoords.get(i) 与 yCoords.get(i + 1)的关系此时与 1 中(1)情况类似(详细分析在 1 中),若 yCoords.get(i)> yCoords.get(i + 1)element = ((540 - currentBearing) % 360 + 360) % 360;若 yCoords.get(i)< yCoords.get(i + 1)element = ((360 - currentBearing) % 360 + 360) % 360;

(2) 若 xCoords.get(i) < xCoords.get(i + 1)此时与 1 中(2)情况类似(详细分析在 1 中),element = ((450 - angle - currentBearing) % 360 + 360) % 360;

(3) 若 xCoords.get(i)>xCoords.get(i + 1)此时与 1 中(3)情况类似(详细分析在 1 中),element = ((630 - angle - currentBearing) % 360 + 360) % 360;此时 currentBearing+=element 并对 360 求余,保存旋转后的角度。并将 element元素添加到 List 中。当 xCoords 与 yCoords 中的元素遍历后,返回 List。

3.2.4 Problem 7: Convex Hulls

设计思路

利用 graham 凸包扫描算法,实现求凸包的功能。Graham 扫描的思想是先找到凸包上的一个点,然后从那个点开始按逆时针方向逐个找凸包上的点,实际上就是进行极角排序,然后对其查询使用。

过程

1.将 points 中的所有点,放在坐标系中,以最下面的点为坐标原点,对所有点进行平移;

2.求每个点与 O 点的连线与 x 轴正半轴所形成的夹角,并对其进行排序,若角度相同,则取与 O 点较近的元素,认为其较小,此时认为 O 点最小;

3.取步骤 2 中,所排列的集合中,取出最小的 3 个点,假设当前的方向一致为 X 正半轴,分别计算 point1 到 point2、point2 到 point3,需要转动的角度 angle1、angle2。由于第一次取出的是 O 点与最下角的点,因此第一次一定 有angle1 < angle2。此时将 point1、point2、point3 也存入栈内。

4.继续从排列好的集合中取出新的元素 point3,取出栈顶两个元素作为 point2和 point1,再将这两个元素压栈,若满足 angle1 < angle2,则将 point3 存在栈中。若 angle1 >= angle2,则进入步骤 5 中。

5.若 angle1 >= angle2,则先弹一次栈,该点不满足凸包的定义,再弹两次栈分别作为 point2 和 point1,此时计算 angle1 和 angle2,若满足 angle1 < angle2,则将point3 压栈,并进入步骤 4,否则继续进行步骤 5.

6.重复以上操作,直到 points 中所有元素都被遍历后,栈中的元素即为所求的凸包。

以下为具体实例:

屏幕截图 2021-06-02 212646.png

3.2.4 Problem 8: Personal art

设计思路

利用循环,foreach 等操作,变换颜色,旋转角的度数,画出的图形的个数,完成一副具有个人色彩的绘画。

过程

首先利用 foreach 语句,取出 pencolor 中的所有颜色,用每个颜色的笔画一些团,利用循环取余等操作,完成在循环数不同时,绘画出不同图形的操作。

运行结果

屏幕截图 2021-06-02 212938.png

3.2.5 Problem : Submitting

通过 git 命令

git add . 添加文件到本地库

git commit -m “TurtleSoup” 提交文件到本地库

git remote add origin git@github.com:ComputerScienceHIT/HIT-Lab1-1190200708.git 关联到远程库

git push origin master 推送到 github

3.3 Social Network

Social Network 主要实现了以下功能:

    1. 建立 java 版的数据结构,有向图。
    1. 并完成增加边、节点的操作。
    1. 广度搜索计算两个人之间最短的距离。
    1. 对输入进行检查,若不符合条件抛出相应的异常。
设计/实现 FriendshipGraph 类

设计思路
用一个 HashSet 保存有向图的节点,在每一个 Person 的对象中,设私有变量,保存每个人认识的人。通过 HashSet 实现类似邻接表的存储结构,并且能够避免添加重复等问题,查找效率较高。人与人之间距离应该用广度搜索,方便记录距离。

过程

设置两个私有变量,private HashSet<Person>personArrayList 保存有向图的每一个节点,即 Person;count 保存当前已经存入的人数。
设置一个构造函数,对 FriendshipGraph 初始化。

addVertex 函数用于添加顶点,将图中的每个人都保存到 personArrayList 中。

addEdge 函数用来添加边,若需要添加一条边,则调用 person1 的方法,将person2 的信息保存到 person1 的私有变量中。

getDistance 函数通过广度搜索获得 person1 与 person2 的之间的距离。

广度搜索步骤:

    1. 将 person1 保存到 HashSet<Person>Search 中;
    1. 将 person1 认识的人保存到 HashSet<Person>Search_Next 中;
    1. 将 Search 和 Search_Next 都保存到新的 HashSet<Person>Search_assist 中;
    1. 初始化 distance = 1;
    1. 若 Search_Next 中含有 person2,返回 distance,即为所求距离。否则将Search 清空,将 Search_Next 保存到 Search 中,在将 Search 中所有的人认识的人的 HashSet 中所有的元素添加到 Search_Next,再将 Search_Next中所有在 Search_assist 中保存的元素消除掉,再将所有 Search_Next 元素添加到 Search_assist 中。此时 distance++;
    1. 重复步骤 5,若 Search_Next 最终为空,则不存在距离,返回值为-1;否则,person1与person2之间存在路径,且 person1与person2距离为distance。
设计/实现 Person 类

设计思路

Person 中存在私有变量 HashSet<Person> friend,保存当前 Person 的朋友,并提供一个方法,用于添加当前 Person 的 friend。

过程

用一个私有变量 HashSet<Person> friend,保存当前 Person 的朋友;再用一个私有变量保存当前 Person 的姓名。设置一个构造函数,用所给字符串命名当前 Person。设置一个方法,用于给当前 Person 添加 friend。即可完成对每个人,及其好友的设定。

四、实验感受

针对以下方面的感受:

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

(2) 关于 Eclipse IDE

(3) 关于 Git 和 GitHub

(4) 关于 CMU 和 MIT 的作业

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

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

(1) Java 语言的语法与 C 语言和 C++语言很接近,使得学习起来比较容易。并且对 C++来说进行了简化和一定的提高,提供了丰富的类库和 API 文档,以及第三方开发包工具包,因此实际体验非常好。

(2) Eclipse 在外观设计方面较 IDEA 略有差距,但 eclipse 总体体验还不错。实际体验上可能 IDEA 的自动修复与智能提示等功能更加强大。

(3) GitHub 让我可以将自己的代码保存到网上,使得在任意终端都可以查看自己的代码,Git 使本地回退版本更加容易,总体体验很棒。

(4) CMU 与 MIT 的作业设计非常精妙,略有难度,但总体不错。

(5) 工作量略大,但是感觉报告内容过多,希望可以略微削减报告内容。Deadline 提前规划后还好。

(6) 了解了软件构造一些基本概念,对我写程序有很大益处
文档,以及第三方开发包工具包,因此实际体验非常好。

(2) Eclipse 在外观设计方面较 IDEA 略有差距,但 eclipse 总体体验还不错。实际体验上可能 IDEA 的自动修复与智能提示等功能更加强大。

(3) GitHub 让我可以将自己的代码保存到网上,使得在任意终端都可以查看自己的代码,Git 使本地回退版本更加容易,总体体验很棒。

(4) CMU 与 MIT 的作业设计非常精妙,略有难度,但总体不错。

(5) 工作量略大,但是感觉报告内容过多,希望可以略微削减报告内容。Deadline 提前规划后还好。

(6) 了解了软件构造一些基本概念,对我写程序有很大益处

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值