哈工大2021软件构造lab1总结

哈工大2021软件构造lab1总结

作为软件构造的第一次实验,感觉内容本身不是很难,里面功能的实现用上学期在数据结构和算法分析两门课里学到的知识就可以解决(尽管其实已经忘没了)。这次实验主要目的还是准备实验环境并且熟悉java编程过程和其他工具的使用。所以在这里主要还是想记录一下自己在配置各种环境(主要是eclipse、git和travis ci的使用)的时候遇到的问题。

目录

哈工大2021软件构造lab1总结

0 环境配置即基本操作

0.1 配置JDK

0.2 安装IDE

0.3 git及github

0.4 Junit的使用

0.5 关于使用travis ci在线build

1 实验任务一:幻方

3.1 Magic Squares

3.1.1 isLegalMagicSquare()

3.1.2 generateMagicSquare()

2 实验任务二:王八画画

3.2 Turtle Graphics

3.2.1 Problem 1: Clone and import

3.2.2 Problem 3: Turtle graphics and drawSquare

3.2.3 Problem 5: Drawing polygons

3.2.4 Problem 6: Calculating Bearings

3.2.5 Problem 7: Convex Hulls

3.2.6 Problem 8: Personal art

3.2.7 Submitting

3 实验任务3: 朋友圈

3.3 Social Network

3.3.1 设计/实现FriendshipGraph类

3.3.2 设计/实现Person类

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

3.3.4 设计/实现测试用例

4 总结


0 环境配置即基本操作

0.1 配置JDK

这里先简单说明一下jdk和jre以及IDE的区别:

  • jdk是java开发工具包,里面包含有java工具以及java的基础类库。理论上讲,安装配置好jdk后,我们就可以直接通过命令行进行java编程了。
  • jre是java运行时环境,是运行java程序必不可少的运行平台。
  • IDE则是集成开发环境,可理解为一种可视化编程程序,简化我们的程序开发过程。像实验要求的IDEA、eclipse都是IDE的一种。

(详细内容可以参考https://blog.csdn.net/cai649399010/article/details/22154999

以下是配置过程:

1. 首先进入官网https://www.oracle.com/java/technologies/javase-downloads.html下载对应版本的jdk(注意实验要求的是jdk8或jdk11),可以选择免安装版或安装版(我当时下载的是免安装版,感觉两者没有什么区别)。下载完成后解压压缩包,然后开始配置。

2. 右键此电脑点击属性,打开高级系统设置:

3. 然后点击环境变量,在系统变量中新建 JAVA_HOME 变量 ,变量值填写解压后jdk文件夹所在的目录。

4. 随后在变量path最后添加%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;(注意别落下分号)

5. 最后在系统变量中新建变量CLASSPATH,变量值填写   .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar(注意开头的.别忘了)

6. 运行cmd 输入 java -version (java 和 -version 之间有空格),若如图所示 显示版本信息 则说明安装和配置成功。

0.2 安装IDE

这里我用的是eclipse(主要老师上课PPT演示里用的也是eclipse,不然的话用IDEA有代码补齐,敲代码能方便不少)。还是进入官网https://www.eclipse.org/downloads/里下载并安装。这个过程比较简单,就跳过了。之后如何在eclipse里创建项目编辑并运行都比较基础,这里主要贴一下怎么选jdk版本和编译器。

新建一个项目时可以选择使用的jdk(jre)的版本:

见上图,JRE那栏里勾选第一个选项选择使用的是eclipse里自带的jre(从1到15都有),第二栏则是使用我们自己下载配置的。这两个选哪个都无所谓,只要jre(jdk)的版本与编译器里的版本一致就行。

然后是选择编译器的jdk版本:

上方选项栏window->preference,随后进入java栏里的compiler项,在第一个下拉栏里就可以选择编译器版本。

0.3 git及github

git的使用方式比较简单,可以参考网上的教程(想系统学习的话推荐菜鸟教程,某一步骤出问题话就csdn。热心网友,永远的神)。这里贴出我遇到的一个小问题:

在第一次把本地仓库的内容推给github时,git窗口显示推送失败:

这里是因为远程仓库中的readme.md文件与本地仓库不符(或者可能本地仓库初始化完就没有这个文件),所以需要把远程仓库的内容和本地仓库合并,就是输入这个命令:git pull --rebase origin master(origin是你远程仓库的URL地址或者拉取克隆到本地后起的仓库名)。合并完成后就可以正常提交了。

0.4 Junit的使用

Junit是java的一种单元测试框架,可以理解为一个库,里面放着各种用来对程序的某一模块进行测试的方法,同时还附加了一个可视化窗口和错误提示。Junit的使用方式和java编程没有太多区别,基本上就是调用各种函数去测试你的代码,看看它们在给定的输入下是否能给出正确的输出。具体的测试类及方法可以上网参考,这里就不赘述了。我主要记录一下我在使用Junit时遇到的问题。

使用Junit首先需要在项目中引入Junit的相关jar文件。首先右键需要添加测试的项目,单击Java build path,在右侧libraries一项中选择add librariy...,在弹出的界面中选择Junit,之后再选择使用的版本即可。

这里我一开始选择的版本是Junit5,然而在运行测试时永远提示初始化失败:

在疯狂百度无果后,我更换了Junit的版本,但运行后依然报错。最终我查看创建的测试类的属性,突然发现运行时使用的Junit版本默认为Junit5,改到Junit4后再次运行,终于成功进行了测试。

0.5 关于使用travis ci在线build

看到实验环境配置的PPT里提到要将实验代码脱离IDE环境提交,保证可以在线运行,所以我就尝试了以下使用travis ci进行在线build看了一下。关于travis ci的使用方式我主要参考了这位学长的博客https://blog.csdn.net/qq_41662115/article/details/88379632(这就是一代代哈工大人通过实验相互联系在一起、传递知识的羁绊吗,泪目了)至于如何在IDEA中操作我还没有探索,有需要的话建议学习一下maven的用法,可能会有帮助。

从前辈的博客中可以看到使用travis ci进行在线build需要将java项目转化为maven项目,然而我在转化后有时会遇到这样的情况,本来我实验写的好好的,敲着代码,唱着歌,突然运行的时候就报错了:Error occurred during initialization of boot layer java.lang.module.FindException: Module not found。这东西我至今没分析出原因,在网上也没搜出有效的解决方案。最后在误打误撞之下把项目更新了之后就没有这种问题了:

这里推测可能是在线运行是在哪里改动了我java项目的模块配置文件,但具体原因还不确定。

以上就是我对实验环境建立过程的总结,虽然叙述的很冗长但很多地方还是不够完整、精确,看来我和前辈们相比确实还差的很远(惭愧)。

1 实验任务一:幻方

我最开始也说过了,这次试验内容本身属于引导型实验,不会在过程上太难为大家。这第一个任务就更是了,比chun较shu基bai础gei。

3.1 Magic Squares

(ps:这里为方便和实验指导书对接,接下来有关实验的内容二级标题、三级标题都用的是实验报告里的)

任务要求读取一个n*n的矩阵并判断其结构是否满足幻方的定义,即行和、列和以及左右对角线的和是否均相等,随后要求对一个输入行数生成幻方的函数进行分析并改进,生成方法是奇数幻方的对角线生成法。任务代码部分比较简单,主要意图应该是帮助我们熟悉java编程的具体过程,熟悉java各种类、方法的应用,并了解Junit的使用方法。

3.1.1 isLegalMagicSquare()

这里难点主要在于怎么从文件中读取数据,然后读出的数据又该怎么存储。这里我们要用到Scanner类(对类的引用要注意大写)来进行读取操作。根据实验指导书的提示,我们需要一行一行的读取数据,然后用'\t'将得到的数据分隔成数组。显然,这里要用到.nextline()函数了。我在这里用的是while(.hasnext())循环读取数据的,应该算比较合理,每次读出的一行数据存成字符串,再用.split('\t')将其分割成一个字符数组。再对字符数组里的每一位都进行.Integer.parseInt()操作把数组里的所有元素都转换回整型数放到用来存放数据的数组里。这里注意可以在此处直接进行非法判断。

然后关于用什么方法来存放矩阵。注意到每个文件中存放的矩阵大小都不一样,所以需要动态存放矩阵数据,即使用ArrayList。我的办法是先将所有数据全部存入动态数组中,同时在读取数据时记录下每一行数据的数量n(数据合法的话每一行的n都是一样的),然后定义一个大小为n*n的数组并把动态数组的值赋进去(d[i][j]=a[i*n+j])。

最后把得到的数组根据幻方的定义进行按行、按列、对角线累加就行,比较简单。

3.1.2 generateMagicSquare()

这一部分的关键在于理解幻方到底怎么填。这里用到的办法其实是最简单的奇数阶幻方填法,就是不断向当前位置的右上方移动,具体原理看这里https://blog.csdn.net/m0_38013346/article/details/80221403(里面的第一个口诀就是。话说我小学的时候学校好像当课外拓展内容教过,果然知识就是用来就饭吃的)。懂了这个步骤之后再看代码画流程图就很简单了(说实话好像不懂也能画?)。

这里需要思考的地方就在异常处理(输入行数n为偶数时报错那个。后面那个输个负数进去当数组大小,要是不报错就鬼了)。这个问题其实主要是数学原理。我们知道在幻方里填数就是向右上角移动,因此每当输入n个数时肯定就会回到原来的位置,进而我们需要向下移动一位然后继续循环。问题就处在这里。当n是奇数的时候,每输n个数进去当前的位置永远不会在最后一行,但偶数就没这个性质(关于这个现象我没证明,有需要的话请自行解决,这可是计算机实验)。所以在代码中,每当执行到i是n的倍数时,若n是奇数,就可以保证row<n-1,即row++后仍然在数组定义的大小范围内;而若n是偶数,则保证不了row!=n-1,若刚好n==n-1了,那程序就gg了。

程序拓展很简单就不说了,检测一下不合法抛个异常就行了。

2 实验任务二:王八画画

任务二给的程序代码是个带窗口界面的画图小程序,基本就是靠着输入前进的距离和每次调转的角度来用小乌龟的运动轨迹表示某个图形,算是致敬经典程序了(依稀记得小学微机课还带着用这个东西画五角星,历史真的是螺旋上升式发展的)。这里的任务都是完成指定功能的代码,而且基础代码也都给出来了,所以只要先把给出的代码都读懂(其实就是Turtle.java的代码),编写出完整程序也不难。

3.2 Turtle Graphics

此任务要求按照给定的设计规约完成小程序的各个模块,并最终综合实现图形的绘制。该部分强调了“设计”这一部分的应用,尤其需要我们读懂设计规约并根据要求设计出合理的方法,并最终通过测试。通过此部分任务,我初步体会到了面向对象的含义与设计过程。

3.2.1 Problem 1: Clone and import

这里就是要打开老师给的github地址,把代码下下来,然后导入(import)到eclipse里进行补全,然后再推到仓库里。git使用方法在前面提到过,比较基础,总之有困难找度娘。

3.2.2 Problem 3: Turtle graphics and drawSquare

这一部分要求我们画正方形,其实就是用来帮我们熟悉这个程序的。阅读Turtle.java,发现了forward()和turn()函数,功能人如其名,很好理解。那么画正方形就很好实现了,循环四次,每次前进距离为正方形的边长(forword(length)),然后旋转90度(turn(90))(这里注意到旋转是顺时针旋转,后面会用)。

3.2.3 Problem 5: Drawing polygons

这里先是要是实现两个程序:给正多边形边数,求内角大小;给正多边形内角,求边数。只需要简单的初中数学知识(我可耻地选择百度)就能完成(多边形外角和为360°,且边数等于内(外)角数,故用360除以边数即是外角的大小,再用180减去外角就能得到内角;求边数同理反过来即可)。

然后我们要利用写完地程序让小乌龟画正多边形,过程同画正方形。但需要注意转过的角度。我们函数求出的是内角,但小乌龟顺时针旋转,需要转过的角度是外角,要注意转换角度。

3.2.4 Problem 6: Calculating Bearings

这一部分要编写两个函数,一个是给定当前坐标和朝向,求出想要到达目标坐标需要先转过多少角度;另一个是给了一堆点,返回一个数组给出每次转向下一个点转过的角度。显然,完成第一个函数后第二个只要循环调用就解决了。

所以只看第一个。初中三角函数题(还是说因为有反三角函数所以是高中题?)这里的偏角都是顺时针偏角,注意到这一点后再看求解办法。不难发现,这里要用arctan函数求角度。具体数学推导自己计算即可(注意arctan函数的值域和定义域的范围),这里只要注意java中的反三角函数的返回值类型:Math类中的atan(即arctan)返回的角度是弧度制,需要调用toDegrees()方法转化成角度制。

3.2.5 Problem 7: Convex Hulls

好了,检验你算法设计与分析听课质量的时候到了。如果你还记得当时凸包问题如何求解,那么这个问题就已经解决了一半,接下来把代码写上就行了;如果不记得,请怀揣着对你算法老师的歉意点击这个网址https://blog.csdn.net/u014688145/article/details/72200018/。我在这个问题中使用的是Graham-Scan算法,其中对点进行排序时因为嫌麻烦用的是冒泡排序,时间复杂度较大。总体来讲,这个问题的代码还是有一定复杂度的,毕竟涉及到排序、求向量外积并进行比较还有堆栈的理解和使用,如果基础不牢的话可能会花费点时间(比如我)。最后注意一下,这里的点使用集合HashSet类存储的,其遍历需要使用Iterator,即遍历器。

3.2.6 Problem 8: Personal art

最后一个问题要我们编写代码,让小乌龟的轨迹呈现出有艺术气息的形状。这里主要就是用到前进函数和转角函数以及变色函数(.color())。如果有兴趣的话(时间来得及的话)可以好好花时间设计一下。(这里我画了一个179角星就跑了,十分惭愧。)

3.2.7 Submitting

提交代码到GitHub,基础操作。

3 实验任务3: 朋友圈

最后一个part的任务里没有像求凸包一样略微复杂的问题,难度主要体现在了类和函数的设计上(保证二者相互协调,使程序结构合理)。显然,根据上学期数据结构与算法这门课中学到的知识,我们应该将朋友圈建模为图。在这一前提下,实现FriendshipGraph的思路就很清晰了。

3.3 Social Network

在任务三要求按照功能需求设计class并完成相关方法,使用合理的模型构建社交关系网(图),实现节点增加、边的增加以及求最小距离等功能。在这一部分中,我们不止需要完成方法的设计,更要自己设计相对应的类,设计过程更为完整。更加接近软件构造的实际过程。

3.3.1 设计/实现FriendshipGraph

老实说我觉得这一步放最前面不太合理,因为FriendshipGraph类作为一个图首先建立在它的节点上,所以个人觉得应该先从Person类的设计开始。

显然,关系网的构建需要使用图这一数据结构进行建模。这里为便于随意增加节点数目,故使用邻接表的结构来存储关系图。在FriendshipGraph类中,每个节点都是一个Person类的变量,故定义一个List<Person>链表—member来存储当前关系网中的所用成员,每增加一个成员person,便用member.add(person)方法将person链入链表中,即addVertex的实现方法。而对于addEdge方法的实现,则利用Person类中中的friends变量存储(具体见3.3.2),每连接两个对象,便在双方的friends链表中将对方链入,以此形成一个邻接表结构。形成邻接表后,便可以通过floyd算法得到从任意一个点到另外一个点的最短路径,进而可计算出任意两点间的距离,由此实现getDistance方法(这里其实也可以直接用广度优先搜索来得到最短路径及其长度,若搜索失败则返回-1)。

3.3.2 设计/实现Person类

定义一个List<Person>链表—friends来存储该person类中所有与之相连的节点,随后每新链结一个节点,便通过addFriend函数将其链入friends链表。其余结构较为简单,代码如下:

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

控制台提示输入数字进行对应操作,界面如下:

代码大致结构如下:

通过switch语句实现选择,外层套一个while语句,当输入为4时停止循环,退出程序。

3.3.4 设计/实现测试用例

addVertex:定义两个HashSet:e和a。e用于存放所有加入节点的名字,a用于存放graph中所有节点的名字。当二者内容相等时即证明节点加入成功。

addEdge:在FriendGraph类中定义isConnected方法,用于判断两个点是否连通。测试连接两个不连通节点前后两节点的连接状态即可。

getDistance:完成图的建立后,测试各个节点的距离,然后连接某些点以改变一些点的最小距离,测试更改后对应节点的最小距离。

最后注意有关同名节点的异常处理和有向图/无向图的区别即可。

4 总结

实验的内容覆盖面很广,所以最好熟悉一下java的各种使用方法,还有各种数据结构以及算法的使用。最最最重要的一点,要把握好时间的安排。这次实验内容虽然不难完成,但也需要花不少时间去熟悉。不要在提交截止日期前一天玩生死时速,这么搞在各种意义上都没有什么好处。另外,使用git提交代码时的网速不太稳定(墙),所以最好及时提交,也可以保证版本控制良好。

总之,祝大家学习好。

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值