欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

软件构造课程Lab1实验报告

程序员文章站 2024-02-08 18:18:52
...

1 实验目标概述

本次实验通过求解四个问题(其中一个可选),训练基本Java编程技能,能够利用Java OO开发基本的功能模块,能够阅读理解已有代码框架并根据功能需求补全代码,能够为所开发的代码编写基本的测试程序并完成测试,初步保证所开发代码的正确性。另一方面,利用Git作为代码配置管理的工具,学会Git的基本使用方法。

l 基本的Java OO编程

l 基于Eclipse IDE进行Java编程

l 基于JUnit的测试

l 基于Git的代码配置管理

2 实验环境配置

简要陈述你配置本次实验所需开发、测试、运行环境的过程,必要时可以给出屏幕截图。

特别是要记录配置过程中遇到的问题和困难,以及如何解决的。

为了更好、更方便快捷地编写实验代码,构建实验包和提交实验数据,需要配置的实验环境有git,eclipse,java11.0.2等等

配置环境过程:

  1.  配置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()

按步骤给出你的设计和实现思路/过程/结果。

该方法的实现总体上可以分为以下几个步骤:

  1.  用FileInputStream类读取文件,InputStreamReader作为转换类, BufferedReader作为修饰类创建一个读入文件对象。使用try-resource方法创建以检测文件读写异常以及免写close()方法。用将文件中的数据按regex
    

“\t”分隔成的字符串数组转化为整形二维数组,记录该二维数组的行数和列数。如果在转化过程中(如下图)发现无法转化的字符,抛出NumberFormatException异常,进入异常处理程序:调用e.printStackTrace()说明异常原因,打印“该矩阵中某些字符不是正整数”,返回fasle.

  1.  将行数和列数进行比较,
    

a)
如果行列数不相同,打印”“该矩阵行列不相等,不是方阵”,返回false;

b)
如果每一行的列数不相等,打印”“
该数据结构不为矩阵”,返回false;

c)
如果矩阵的每一行的元素的和、每一列的元素的和、主对角线的元素的和以及逆对角线的元素的和不均相同,打印“该矩阵不是MagicSquare”,返回false;

d)
若上述问题都没有出现,返回true。

测试结果为:

3.1.2 generateMagicSquare()

  1.  程序流程框图
    
  2.  程序设计思路:
    
  3.  首先检验输入参数n:如果n为负数或者偶数,则直接报错退出。
    

如果参数n为正奇数,则初始化一下变量:

int magic[][] = new int[n][n]; //创建一个空矩阵

 int row = 0, col = n / 2, i, j, square = n * n;  //对矩阵的额行数,列数进行初始化,声明循环变量i,j;初始化square
  1.  进入循环,循环变量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++。此函数部分结束,进入下一个循环。
    
  2.  运行测试截图(生成矩阵时n=5):
    

图1:运行成功

图2:输入负数

图3:输入偶数

  1.  将该生成的数组导入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

  这是一个简单的绘图过程。总体思想就是调用一个流程四次:
  1.  调用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

  1.  创建并初始化变量
    

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

需要完成的任务如下:

  1.  addEdge,为朋友圈增加朋友关系。
    
  2.  addVertex,为朋友圈增加人。
    
  3.  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

(仅为思想,并未实现)
两个或更多相同内容的推特,只取其中一个作分析。