先聊一聊作为一个新手首次使用java的一些感受吧,具体的实验细节放到后面:
(1)java编写代码需要更好的分块,且更需要了解各种接口即权限,它不像之前用的C语言只在一个文件下编程。
(2)同时java的包装好的函数也比c多好多,需要大量记背,并善加利用,能极大地减少代码行数,增加可读性。这一点真的极其重要,完成一个任务,你用的工具不同,编码效率完全不同,就好比拿刀的永远打不过拿枪的(大概)。
(3)对于图像的处理也是c中没有遇到的,需要花些心思去理解java的画图时用的纸和笔。
(4)面向对象编程,java更贴近实际问题,需要注意类及类的方法和函数的命名,不能随便用a,b,c等,特别容易混乱,善用名称,能够增加可读性,使得之后的拓展和利用更加方便。
以下是这次实验的思路,我挑重点聊一聊:
1 Magic Squares
这个任务是对矩阵进行操作,对已有的五个矩阵进行判断,判断其是否为 Magic Squares(即各行各列和主次对角线的数字之和相等)。并且还要创建一个新的大小为n*n的 Magic Squares,并检验它。整体而已想法不是很难,主要考验java的基础操作——文件操作、数组、字符串操作等。同时还有一些细节方面需要注意,需要考虑程序的健壮性,将一些非法输入单独讨论,得以优雅的退出。
1.1 isLegalMagicSquare()
设计和实现思路如下:
(1)利用readLine()将文件按行读取,得到矩阵的行数m
(2)再利用split("\t")将每行划分,得到一个字符矩阵和矩阵的列数n,这里要判断m是否等于n,还有每行是否都达到n个数字,若不达要求则给出相应提示并且返回false
(3)利用Integer.parseInt,将字符串转为int类型,得到矩阵data[][],这里要注意转换不成功则说明存在非法输入(例如小数点等等),同时若有负数也不符合要求,都需要给出相应提示并且返回false
(4)计算出第一行的数字之和sum,作为初始值。之后计算每一行,每一类还有主次对角线的数字之和与sum对比,若有不相等的,则返回false,若判断完所有都相等则返回true
1.2 generateMagicSquare()
设计和实现思路如下:
(1)理解已给出的代码:改代码的思想是将1到nn填入nn的矩阵中,按照右上斜行的填发,使得每行每列都达到(n^3+n)/2,同时从(0,n/2)处开始填起,使得主次对角线也达到该值
(2)流程图:
(3)对于n为负数和偶数的异常理解
n为偶数时,数组越界,产生在填满一斜行(i%n==0)时,行号加一,n为偶数时会产生在(n-1,k)处恰好填满一斜行,然后行号加一得到(n,k)超出矩阵范围产生数组越界,而n为奇数时不会。
n为负数时,数组的长度为负,导致错误。
(4)补充拓展部分:首先将n<0和n为偶数的情况单独讨论,然后创建txt文档,在文档中写入生成的矩阵
2 Turtle Graphics
该任务的核心是利用已有的函数,完善,并实现相应的功能,首先需要我们熟悉各各函数的接口,在调用时不出错误。同时,还考验了我们对于绘图及平面几何的一些基础知识。
2.1 Problem 1: Clone and import
2.2 Problem 3: Turtle graphics and drawSquare
这里要求完成画一个矩形,比较简单,利用已有函数,画直线、转弯循环四次即可。
3.2.3 Problem 5: Drawing polygons
这里要求画一个正多边形,已知边数,先求得内角度数,这里调用calculateRegularPolygonAngle函数由边数算出角度,由凸多边形外角和为360°,故正n边形,内角为180°-(360°/n),然后与上面正方形做法类似,画n条边,转n次即可(注:转的角度应是外角而非内角)。
还有一个已知角度求边数的函数,这里要注意,角度是double类型,套公式算出边数时,时double类型的,要将其转为int,不能简单地强转,因为那样做的话就相当于舍位,double类型是个近似值,例如对于结果求得是4.9999,其期望的结果应该是5,而不是4。我这里采用了四舍五入,但其实一般的结果都在整数附近,有什么更好的想法也是可以的。
2.4 Problem 6: Calculating Bearings
首先实现两个点之间的转的角度计算,即calculateBearingToPoint函数,利用math.atan2计算出(x1,y1)与(x2,y2)构成的直线与x正半轴所得的角度,转成角度制,由于海龟的零度为y轴正方向且顺时针旋转为正,故需要用90°减去算得的角度,再减去现在的方向角得到转角。该值可能为负数,加360°转为正值即可。
2.5 Problem 7: Convex Hulls
这里采用Gift−Wrapping 算法,首先遍历找到横坐标最小的点,它一定在凸包上。由于这个点的左下方一定没有点了,故初始方向选为x负半轴,以该方向为坐标轴建立极坐标,找到夹角最小的点作为下一个点,方向变为两点连线方向,最后返回到初始点,结束。在calculateBearings函数中利用上述函数计算两点间的转角记录到集合中,最后返回集合。
需要注意,我们求的是最小凸包,如果有两点极坐标角度相等的点,优先取距离较远的点
2.6 Problem 8: Personal art
随便画,开心就好
3 Social Network
该任务要创建FriendshipGraph类和Person类,以实现关系网。根据测试代码需要在Person类中定义姓名,朋友等信息,以及用名字创建一个新人、添加朋友等方法;在FriendshipGraph类定义关系网中的人及他们的关系,还有添加新人、添加关系、求两人间距离的方法。
3.1 设计/实现FriendshipGraph类
设计和实现思路:
一个大数组用于储存人,同时记录人数,添加新人、添加关系比较简单,不再赘述,最后时求两人间距离的方法,利用广度优先搜索。
过程:
(1)广度优先搜索中,由于节点是Person而不是以往的数字,记录已走过的人和走到某个人处的步数不是很方便。我采用的方法是给Person类中添加人在关系网中编号,以及先广搜索走到这个人的步数。
(2)还有题目中的附加要求姓名不能重复,创建方法boolean isunique(Person p)进行判断,在添加新人时进行判断,若重复则给出提示然后退出程序。
3.2 设计/实现Person类
实现思路:
保存人的姓名,朋友等信息,以及用名字创建一个新人、添加朋友等方法。
3.4 设计/实现测试用例
这里就仿照给出的main函数代码,构造一张图,求两个人间的最小距离,利用assertEquals()将期望值与实际值进行比较。
以上就是完成lab1的一些想法与心得,虽然可能会有些想法可能会比较低级,简单,但这就是一个新手最直观的感受,希望能给大家带来一点点的帮助。