3.2.1 Problem 1: Clone and import
3.2.2 Problem 3: Turtle graphics and drawSquare
3.2.3 Problem 5: Drawing polygons
1.实验目标概述
本次实验通过求解三个问题,训练基本 Java 编程技能,能够利用 Java OO 开
发基本的功能模块,能够阅读理解已有代码框架并根据功能需求补全代码,能够
为所开发的代码编写基本的测试程序并完成测试,初步保证所开发代码的正确性。
另一方面,利用 Git 作为代码配置管理的工具,学会 Git 的基本使用方法。
l 基本的 Java OO 编程
l 基于 Eclipse IDE 进行 Java 编程
l 基于 JUnit 的测试
l 基于 Git 的代码配置管理
2.实验环境配置
(1)安装IDEA
在官网上下载并安装IDEA,并配置好相应环境。
IDEA中自带JUnit.
(2)安装Git
在官网下载并安装Git,并按教程设置好用户名、邮箱等基本信息。
(3)安装JDK
IDEA可以自行配置JDK
GitHub Lab1仓库的URL地址:
https://github.com/ComputerScienceHIT/HIT-Lab1-2021111824.git3实验过程
请仔细对照实验手册,针对三个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但无需把你的源代码全部粘贴过来!)。
为了条理清晰,可根据需要在各节增加三级标题。
3.实验过程
3.1Magic Squares
Magic Square为一个由正整数组成的正方形,其每一行、每一列以及两条对角线的整数和都相等。
该任务主要分为两个方面。第一,编写一个JAVA程序,用于判断所给的5个txt是否为Magic Square;第二,扩充给定的generateMagicSquare()函数,用来生成Magic Square并写入6.txt,并且调用isLegalMagicSquare()函数来判断其是否为Magic Square。
3.1.1 isLegalMagicSquare()
首先,要先从给定的txt中读取文件,使用BufferedReader,逐行读入文本,然后使用String的split方法将字符串用“\t”分割,然后保存在字符串数组中。接着,使用Interger.valueOf将字符串转换为整型数字,保存在二维数组中。在过程中判断该文本是否为n*n矩阵以及数字间是否用“\t”分隔。
然后,将二维数组中每行、每列以及两条对角线的数字相加,比较和是否相等,以及判断数组中是否存在非正整数,若全部符合,则返回true;若出现其他情况,则提示相应错误并返回false。
3.1.2 generateMagicSquare()
该函数为生成Magic Square的方法。
首先,初始化一个空的n*n矩阵,并使i = 1,以row = 0, col = n/2为第一个元素i的位置,然后使row--,col++,并使i++,然后将i填入其中,依次循环,直到i > n*n为止,要注意在此过程中数组下标不能越界,因此要添加if (row == 0)以及if (col == n - 1)等判断语句。然后,将生成的Magic Square输出并写入6.txt,并使用isLegalMagicSquare()函数来判断其是否符合Magic Square要求。
其程序流程图为:
(1)如果输入的 n 为偶数,函数运行之后在控制台产生以下输出:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 12
at MagicSquare.generateMagicSquare(MagicSquare.java:17)
at MagicSquare.main(MagicSquare.java:121)
因为输入偶数之后,上述算法将不再适用,会出现数组下标越界情况,即会抛出以上异常。
(2)如果输入的 n 为负数,函数运行之后在控制台产生以下输出:
Exception in thread "main" java.lang.NegativeArraySizeException
at MagicSquare.generateMagicSquare(MagicSquare.java:11)
at MagicSquare.main(MagicSquare.java:121)
因为数组下标只能为正整数,不可能存在负数,所以会抛出以上异常。
若输入合法,则运行结果为:
若输入n为偶数,则提示输入偶数错误,并优雅地退出
若输入n为负数,则提示输入负数错误,并优雅地退出
3.2 Turtle Graphics
根据要求以及代码中给出的注释来补全代码,使其能实现以下功能:绘画正方形、计算正多边形内角度数、已知正多边形内角度数求正多边形边数、画正多边形、计算起点到终点旋转角度、凸包以及绘画自己设计的图形。并完成对上述功能的测试。
3.2.1 Problem 1: Clone and import
在该项目文件夹处右键点击Git Bash Here,输入git init 完成初始化,使用git clone指令从GitHub获取该任务的代码,并使用git add、git commit、git push等指令进行代码的提交和推送。
3.2.2 Problem 3: Turtle graphics and drawSquare
针对该问题,首先我们需要先阅读分析一下turtle中为我们提供的方法,如forward、turn、color和draw,然后使用提供的方法绘画一个正方形,只需要循环四次forward(sideLength)并turn(90)即可。
3.2.3 Problem 5: Drawing polygons
该问题要求绘画正多边形,我们要根据数学公式计算出正多边形的内角度数,绘画过程中每次旋转的度数就为正多边形内角度数的补角。
这里绘画了一个正六边形:
3.2.4 Problem 6: Calculating Bearings
计算每次方位改变旋转的角度,这里使用math.atan2函数,使用角度的转换确定最终的Bearings。用以上方法可以得到每两个点之间的角度的改变,即方法calculateBearingToPoint;而要实现函数Calculating Bearings计算一系列点的旋转角度,只需要多次调用上述的函数即可计算出这个关于角度的序列。
3.2.5 Problem 7: Convex Hulls
凸包(Convex Hull)是一个计算几何(图形学)中的概念。给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。
该函数的功能是求出包围所有点的凸包。
我们首先找出最左下角的点作为起始点,然后每次循环找到转向角最小同时距离最大的点加入集合,最后即解决了凸包问题。
3.2.6 Problem 8: Personal art
该问题为根据自己的想法,利用turtle中所提供的方法来绘制一个图案,过程中会运用到大量的循环。
3.2.7 Submitting
在项目文件夹中打开Gitbash,输入git push origin master即可将当前版本提交到GitHub上Lab1仓库。
3.3 Social Network
该任务要求我们实现一个社交网络图。
首先,要建立一个Person类,为社交网络中的人,含有name、friends等属性,并且能实现getName、addFriends等方法。把每个人看作社交网络图中的顶点。
然后,建立一个FriendshipGraph类,用其实现addVertex、addEdge、getDistance等功能,完善社交网络图。
3.3.1 设计/实现FriendshipGraph类
首先,建立一个集合set来保存person,并用set.add()方法来实现addVertex,即向集合中加入新的对象,注意要使用set.contains()方法来判断集合中是否已存在名字相同的对象,若存在,则不能将该person加入集合。
然后,使用Person类中的addFriends()方法将有朋友关系的person放入彼此的朋友集合中。
最后,使用BFS方法来计算社交网络图中两个person之间的距离,实现getDistance()方法。
3.3.2 设计/实现Person类
定义Person类时,需要name以及friends(朋友集合)两个属性,并能够实现getName()以及addFriends()等基本方法。
3.3.3 设计/实现客户端代码main()复制并运行实验指导书中给出的main()函数,得到与预期相同的结果。
(1)复制并运行实验指导书中给出的main()函数,得到与预期相同的结果。
(2)当注释掉第10行代码时,由于rachel指向ross的关系消失,导致运行getDistance()时,rachel不存在到达任何人的路径,所以运行结果应为-1、-1、0、-1。实际运行结果与想法一致。
(3)将第 3 行引号中的“Ross”替换为“Rachel”时,由于在addVertex函数中已经增加了判断是否存在重复人名的功能,所以程序将会提示“名称重复,Rachel已经存在”,并退出程序。
3.3.4设计/实现测试用例
(1)设计addVertex()的测试用例,即测试addVertex()能成功将person加入集合中,并且对于有重复姓名的person不加入集合中。
(2)设计addEdge()的测试用例,即测试加入了新边后,friends集合中是否加入新的person。
(3)设计getDistance()的测试用例,即测试两个person之间的distance是否正确。
最后测试的总结果为:
4 实验进度记录
请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。
日期 | 时间段 | 任务 | 实际完成情况 |
2023-03-04 | 17:30-20:30 | 编写问题1的isLegalMagicSquare函数并进行测试 | 按计划完成 |
2023-03-05 | 09:00-10:00 | 编写问题1的generateSquare函数并进行测试 | 按计划完成 |
2023-03-05 | 14:00-17:00 | 编写问题2 | 编写凸包问题时遇到困难,未完成 |
19:00-21:00 | 编写问题2凸包问题 | 按计划完成 | |
2023-03-06 | 18:00-21:00 | 编写问题3 | 按计划完成 |
2023-03-07 | 18:00-20:00 | 编写问题3测试用例 | 遇到困难,未完成 |
2023-03-08 | 17:00-19:00 | 编写问题3测试用例 | 按计划完成 |
5 实验过程中遇到的困难与解决途径
遇到的困难 | 解决途径 |
在编写问题2时,不会编写凸包问题 | 在网上查找凸包的相关资料以及解决凸包问题的途径,并参考学习别人的解决方法,最后解决凸包问题。 |
在向GitHub远程提交代码时,总是显示错误,无法成功提交。 | 向助教咨询解决办法,更改了提交文件的路径,最后成功提交。 |
在安装JDK时,使用了错误的版本。 | 使用IDEA自带的功能成功配置了符合要求版本的JDK。 |
通过查阅资料、观看教学视频、向基础较好的同学请教等方式来学习JAVA语言。 |
6 实验过程中收获的经验、教训、感想
6.1 实验过程中收获的经验和教训(必答)
通过完成实验,我更好地掌握了JAVA语言,并学会了使用JUnit来编写测试用例以及如何使用Git和GitHub来进行十分便捷的版本控制。在实验过程中,我也认识到程序的健壮性也是程序非常重要的质量指标,想要写出较为完善的程序,考虑到各种可能出现的意外情况是很有必要的。而且,在使用一门语言进行编程时,一定要熟练地掌握其语法以及基本的方法,否则会在实践过程中很难用程序来实现自己的想法。
6.2 针对以下方面的感受(必答)
(1)Java编程语言是否对你的口味?与你熟悉的其他编程语言相比,Java有何优势和不足?
Java语言虽然语法有些复杂并且学习过程比较困难,但是其作为面线对象语言具有的强大功能给程序的实现带来了很大的便利。所以我还是比较喜欢Java语言的。
与其他语言相比其优点有:跨平台、可移植性,安全性,面向对象,简单性,高性能,分布式,多线程,健壮性。其缺点为:运行速度较慢,不能和底层、操作系统等打交道,删除了指针、不够灵活。
(2)关于Eclipse或IntelliJ IDEA,它们作为IDE的优势和不足;
我使用的IDE为IntelliJ IDEA
优势:UI界面简洁清晰,环境配置简单、功能比较完善、能自动配置JUnit以及JDK,使用起来十分便利。
不足:在处理大型项目时可能出现卡顿等现象。
(3)关于Git和GitHub,是否感受到了它在版本控制方面的价值;
是的,在使用Git以及GitHub时,我深刻感受到了他们带给版本控制的便利性,终于不用再使用copy副本的的方法来保存修改之前的文件。
(4)关于CMU和MIT的作业,你有何感受;
我觉得CMU和MIT的作业都十分富有趣味,并且难度也可以接受,对我们的编程能力有很强的锻炼作用,也能提高我们对编程学习的积极性。
(5)关于本实验的工作量、难度、deadline;
我觉得实验的工作量有点大,但是由于deadline时间比较靠后,所以做实验的时间还是比较充分的,实验安排比较合理。对于实验的难度,在刚刚接触实验时,我觉得实验对我来说十分困难,但是,在不断地学习、研究后,又觉得实验具有挑战性但不是不可完成,所以我认为实验难度也是合理的。
(6)关于初接触“软件构造”课程;
“软件构造”这门课程采用理论课与实验相结合的方法来锻炼我们更好、更强的编程能力,对我们来说是十分有意义的一门课程,我认为我从中收获颇多。