软件构造课程Lab1实验报告
1 实验目标概述
本次实验通过求解四个问题(其中一个可选),训练基本Java编程技能,能够利用Java OO开发基本的功能模块,能够阅读理解已有代码框架并根据功能需求补全代码,能够为所开发的代码编写基本的测试程序并完成测试,初步保证所开发代码的正确性。另一方面,利用Git作为代码配置管理的工具,学会Git的基本使用方法。
l 基本的Java OO编程
l 基于Eclipse IDE进行Java编程
l 基于JUnit的测试
l 基于Git的代码配置管理
2 实验环境配置
简要陈述你配置本次实验所需开发、测试、运行环境的过程,必要时可以给出屏幕截图。
特别是要记录配置过程中遇到的问题和困难,以及如何解决的。
为了更好、更方便快捷地编写实验代码,构建实验包和提交实验数据,需要配置的实验环境有git,eclipse,java11.0.2等等
配置环境过程:
-
配置Java实验环境
首先你需要下载一个java编译器,并记录它所在的位置(如图1)
(图1)
然后右键单击我的电脑—属性—高级系统设置
点击环境变量
如下图,在系统变量中新建CLASSPATH,输入文字:
.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;
然后新建JAVA_HOME系统变量,将你的jre路径导入:
至此,java环境配置完毕。验证方法如下:
搜索“CMD”,单击后出现命令行窗口,输入java -version,如果显示了java的版本等相关信息,表明java环境配置成功(我的java版本是11.0.2)
2.配置git与github
新建一个本地仓库,其实也就是新建一个文件夹。最简单的创建方式就是直接在桌面鼠标右键,新建文件夹(test),然后进去该文件夹。鼠标右键,打开git -> Git Bash
Here -> git init。执行命令后目录下创建一个.git文件夹。
添加需要上传到github的代码到本地仓库如何添加,首先将需要上传的代码复制粘贴到本地仓库,这里用git库test文件夹。
然后git
status,这时候会发现多了一些东西,这些东西就是你刚刚复制进来的文件,显示为红色,就是待添加到本地仓库的意思
git add + 需要添加的文件名 或者git add --all 将所有的文件全部添加
将add的文件commit到仓库。git commit -m “修改说明”。-m后面添加的是对本次操作的说明
将本地的仓库关联到github上
输入命令:
git remote add
origin (你自己的github账号)
test link(URL):[email protected]
com:leiphp/awesome-python3-webapp.git
然后再使用命令:git
pull --rebase origin master
这样,
你就成功地将文件传入到你的github账号的远程仓库中去了
在这里给出你的GitHub Lab1仓库的URL地址(Lab1-学号)。
https://github.com/ComputerScienceHIT/Lab1-1170300809.git
3 实验过程
请仔细对照实验手册,针对四个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但无需把你的源代码全部粘贴过来!)。
为了条理清晰,可根据需要在各节增加三级标题。
3.1 Magic
Squares
3.1.1任务,要求编写一个public static
Boolean isLegalMagicSquare(String fileName)函数,其中函数的参数filename为导入的文件的名称;将P1中的5个txt文件分别导入,然后返回他们是否为MagicSquare的一个boolean值。所谓MagicSquare,即每一行的元素的和、每一列的元素的和、主对角线的元素的和以及逆对角线的元素的和均相同的矩阵。在判断过程中,需要处理几种异常情况,例如:矩阵中的元素不全为正整数,文件读取异常等等。
3.1.2任务,要求用Junit测试public static boolean
generateMagicSquare(int n)函数;绘制该函数的程序流程图;解释它如何根据输入的参数(奇数n)生成一个n×n的Magic Square,据此为上述代码添加中文注释;将产生的magic square写入文件\src\P1\txt\6.txt中;当输入的n不合法时(n为偶数、n为负数等),不要该函数抛出异常并非法退出,而是提示错误并“优雅的”退出——函数输出false结束;利用你前面已经写好的isLegalMagicSquare()函数,在main()函数判断该函数新生成的文本文件6.txt是否符合magic square的定义。
3.1.1 isLegalMagicSquare()
按步骤给出你的设计和实现思路/过程/结果。
该方法的实现总体上可以分为以下几个步骤:
-
用FileInputStream类读取文件,InputStreamReader作为转换类, BufferedReader作为修饰类创建一个读入文件对象。使用try-resource方法创建以检测文件读写异常以及免写close()方法。用将文件中的数据按regex
“\t”分隔成的字符串数组转化为整形二维数组,记录该二维数组的行数和列数。如果在转化过程中(如下图)发现无法转化的字符,抛出NumberFormatException异常,进入异常处理程序:调用e.printStackTrace()说明异常原因,打印“该矩阵中某些字符不是正整数”,返回fasle.
-
将行数和列数进行比较,
a)
如果行列数不相同,打印”“该矩阵行列不相等,不是方阵”,返回false;
b)
如果每一行的列数不相等,打印”“
该数据结构不为矩阵”,返回false;
c)
如果矩阵的每一行的元素的和、每一列的元素的和、主对角线的元素的和以及逆对角线的元素的和不均相同,打印“该矩阵不是MagicSquare”,返回false;
d)
若上述问题都没有出现,返回true。
测试结果为:
3.1.2 generateMagicSquare()
-
程序流程框图
-
程序设计思路:
-
首先检验输入参数n:如果n为负数或者偶数,则直接报错退出。
如果参数n为正奇数,则初始化一下变量:
int magic[][] = new int[n][n]; //创建一个空矩阵
int row = 0, col = n / 2, i, j, square = n * n; //对矩阵的额行数,列数进行初始化,声明循环变量i,j;初始化square
-
进入循环,循环变量i初始化为0,i<square时持续循环,i每次循环自增1。循环体中,先将i赋值给magic[row][col],之后判断i%n是否为0:若是,row自增后继续循环;若不是,则进入下一个函数部分:首先判断ro是否为0,若是,row=n-1;若不是,row--。再判断col是否为n-1,若是,col=0;若不是,col++。此函数部分结束,进入下一个循环。
-
运行测试截图(生成矩阵时n=5):
图1:运行成功
图2:输入负数
图3:输入偶数
-
将该生成的数组导入6.txt
图4:包中文件分布
图5:6.txt内容
图6:6.txt运行截图
3.2 Turtle
Graphics
运用P2中的turtle库按照要求绘制图形或计算数值
3.2.1 Problem 1: Clone and import
从课程群中下载P2文件夹
3.2.2 Problem 3: Turtle graphics and drawSquare
这是一个简单的绘图过程。总体思想就是调用一个流程四次:
-
调用turtle.forward()方法,参数为sidelength,让其向前行走sidelength单位并留下轨迹
调用turtle.turn()方法,参数为90.0f,让其逆时针转90度。
3.2.3 Problem 5: Drawing polygons
首先,声明并初始化变量float EveryAngleNum=180.0f-(180.0f*(sides-2))/sides;
为下一步绘制提供转向角度
建立for循环,循环变量i初始化为0,循环条件为i<sides,每循环一次i自增1,循环体为:
i.
调用turtle.forward()方法,参数为sidelength,让其向前行走sidelength单位并留下轨迹
ii.
调用turtle.turn()方法,参数为90.0f,让其逆时针转90度。
3.2.4 Problem 6: Calculating Bearings
-
创建并初始化变量
int[] xlist=new int[100];
//坐标数组x
int[] ylist=new int[100];
//坐标数组y
int NumOfPoints=0; //点数
int i=0; //循环变量
List<Double>
bearings =new ArrayList(); //返回的数组
Double
decadesDouble=0.0; //每次转动的角度
Double tanDouble=0.0;
//每次转动的tan值
将list中的坐标分别输入xlist和ylist,然后对每一对点,计算其tan值(y2-y1)/(x2-x1),然后用Math库中的atan函数和toDegree函数计算出以角度形式表示的转动角度,并将其add进bearings列表中。
返回bearings列表。
3.2.5 Problem 7: Convex Hulls
首先将points集合中的点导入到数组allPoints中,然后在数组中找出横坐标最小的点中纵坐标最小的点,并将其设为startpoint,将startpoint压入栈中。
将点按照极角从小到大排序,然后扫描该数组,将第一个非栈中元素压入栈中
从上述压入元素的下一个元素开始遍历数组:
如果元素不在栈中的话,将其压入栈中,然后对栈进行如下操作:
用IsPackage(检验三个点是否符合凸包要求)循环检验栈顶、栈顶-1、栈顶-2三个元素,如果不符合,栈顶-1位置改为栈顶元素,弹栈;如果符合,跳出该循环。
4.将栈中元素加入集合中,返回集合。
3.2.6 Problem 8: Personal art
如图
3.2.7 Submitting
如何通过Git提交当前版本到GitHub上你的Lab1仓库。
3.3 Social
Network
需要完成的任务如下:
-
addEdge,为朋友圈增加朋友关系。
-
addVertex,为朋友圈增加人。
-
getDistance,得出朋友圈中两个人的关系距离。
3.3.1 设计/实现FriendshipGraph类
给出你的设计和实现思路/过程/结果。
数据结构:allPeople集合,存储朋友圈里的所有Person类对象;
两个工具方法:isFriend(Person
a,Person b),用于检测两个人是不是朋友
getPerson(int
n) ,得到标号为n的人对象
要求方法:
addVertex(Person
a):
如果a不在allPeople中,调用allPeople.add(a);
如果a在allPeople中,继续遍历
getDistance方法(弗洛伊德算法)
设立一个二维数组,大小为allpeople.size();将allPeople中的每个元素与一个1-size()内的整数构成一一映射,用getPerson(int
i)方法实现该映射。
然后将该二维数组初始化。若两人无关系,则两人初始距离为Maxdistance;若两人为朋友,初始距离为1;若两人为同一人,则距离为0;
遍历allpeople数组,将任意一个人插入到二维数组的任意两个人中,得到一个新距离。如果新距离小于原距离,则用该新距离替换该位置原来的距离。
返回需要的距离即可。
3.3.2 设计/实现Person类
Person类实际效果如下图:
public
String name;
int num;
Set<Person> FriendsSet =new HashSet<Person>();//该人朋友的集合
public Person(String name); //构造函数,输入的为该人的名字
public void AddFriend(Person
Friend); //添加朋友到FriendsSet中
public String
getName(); //返回该人的姓名
public void setNum(int number); //设定该人的编号,getDistance函数中需要用到。
3.3.3 设计/实现客户端代码main()
给出你的设计和实现思路/过程/结果。
3.3.4 设计/实现测试用例
设计:testaddVertex() 用testset={Person.getName()=”David”}作为样例,
Friendship.addVertex(new Person(“David”))来进行测试,用assertEqual()进行Junit测试,若输出为true,则测试成功
3.4 Tweet
Tweet
Src
P4
Twitter
…….java
test
P4
Twitter
…….java
3.4.1 Problem 1: Extracting data from tweets
思路:
1.getTimespan
循环遍历tweets数组,将其中对象的发表时间的最小值和最大值记录下来,分别为min和max,然后生成一个Timespan变量,将min作为start,max作为end输入,就得到了相应的Timespan。
getMentionedUsers
将所有推特的内容放入一个字符串变量allString中,然后将其以非法字符切分,得到字符串数组;遍历字符串数组,将第一个字符为@的字符串留下,其余全部移除,返回字符串数组
3.4.2 Problem 2: Filtering lists of tweets
writtenBy
新设一个推特类型的列表tList,遍历输入的tweets列表,如果该tweet的作者名为username,将该推特添加到tList;返回tList。
InTimespan
新设一个推特类型的列表tList,遍历输入的tweets列表,如果该tweet的发表时间在Timespan内,将该推特添加到tList;返回tList。
containing
新设一个推特类型的列表tList,遍历输入的tweets列表,如果该tweet包含输入的words字符串数组的所有内容,将该推特添加到tList;返回tList。
3.4.3 Problem 3: Inferring a social network
guessFollowsGraph
将推特列表遍历,用getMentionedUsers得到其提及的人,导入map,返回
influencers
建立<String,Integer>类型的Map,遍历推特数组后用getMentionedUsers得到所有被提及的人,以及他们被提及的次数,导入Map,根据被提及的次数排序后按从高到低顺序导入一个String列表中,返回
3.4.4 Problem 4: Get smarter
(仅为思想,并未实现)
两个或更多相同内容的推特,只取其中一个作分析。
上一篇: Telnet模拟http发送GET POST请求hTTP
下一篇: java中List的排序问题