关于Lab1的算法问题

      1. isLegalMagicSquare()

要想判断是否为幻方,首先是读取阶段,要将文件内容读出,这可以利用封装后的BufferReader来实现;然后就是处理阶段,要将读到的内容加以处理,首先通过split函数以字符\t来将字符串分割,然后将获得的每一个子串放到字符串数组中,利用字符串的valueof函数将其转变为整型数字;接下来就是判断阶段,在分割转换的过程中,就可以筛选出未用\t将数字分隔、带有小数、带有负数以及行列数不相等的所有不合要求的方阵,其后,遍历转换后的数组,查找里面是否有0,若到此为止均为出错,那就求出所有的行列和以及对角线和作比较,若和均相等,则该方阵是一个magicsquare。

首先main函数中利用循环的方式确保读取5个文件,分别以五个文件为参数调用子函数

在读取、处理过程中判断行列数,并存到二维数组中

利用上面提到的思路,判断方阵中的数字以及输入格式是否满足条件

计算并比较行、列以及对角线的和

生成MagicSquare的算法分析:

   实现方法:该算法首先将1放到第0行的最中间那列的位置上,在接下来的操作中,放置好n后,向右上方一格移位。若右上方一个是空格子,则直接将n+1填入;若格子已经被其他数字占用,则将n+1放到放置n的格子下方的格子中;若n已放置到边缘上(不含顶点),则向右上方移动到上方(右方)的一个虚拟的格子中,然后落到最下方(最左方)的格子中;若n放置到顶点上,则按照格子被占用的方法处理,直接将n+1放到放置n下方的格子中。

异常分析:

n为偶数时:

由分析可得,当输入n为偶数时,右下角填入的数字i会满足i % n=0,然后执行row++会导致越界,从而报错。

当n为负数时:

数组magic[n][n]不能被正确定义,所以程序会抛出异常。

处理异常:

由上述异常分析知,只要在程序运行数组定义之前判断n的奇偶性和正负性,不符合要求直接返回false即可阻止程序报错,异常结束。

判断新的方阵是否为magicsquare:

只需在成功生成方阵之后,调用isLegalMagicSquare函数判断即可。

    1. Turtle Graphics

该任务主要是运用turtle绘制图形和解决凸包问题。

最关键的点在于凸包问题的解决,解决凸包问题又与上面计算两点之间的角度等函数密切相关,整个任务环环相扣。

      1. Problem 1: Clone and import

通过git clone + http将github上的文件克隆到本地仓库中,然后将他们导入eclipse。

      1. Problem 3: Turtle graphics and drawSquare

只需要利用turtle包中的forward函数和turn函数即可实现。

通过查看Turtle.java文件可以发现:

forward函数可以实现直行,参数是步长;turn函数可以实现改变方向,参数为转动角度,因此,只需要让每一次直行的步长相同,并且在每次直行完之后转动90°,经过四次循环即可完成正方形的绘制。

      1. Problem 5: Drawing polygons
  1. implement:

通过函数前的注释描述可知,该函数要用来求得一个正多边形的一个角的角度,如代码中的注释所写,正多边形的内角和公式为180 * (n - 2),其中,n为边数,也就是n-正多边形,由于正多边形的每一个角都相等,所以总度数除以角的数目即可得到答案。但值得注意的是,该函数返回值为double类型,所以在进行除法的时候,要保证除数或者被除数中有一个是double类型。

  1. breaking(破坏实现后的函数):

将内角和公式中的n-2修改为n-3,程序运行结果必然会出错,用Junit4进行测试

该函数的功能应该是判断实现的函数的返回值是否正确。

通过draw函数来调用calculate函数,从而通过后者来获得需要转动的角度,若calculate函数的设计出现问题,那么draw函数最后呈现出来的形状也一定会出现问题。现在绘制出的多边形均正常,因此,calculate函数的实现没有问题。

Problem 6: Calculating Bearings

  1. Implement calculateBearingToPoint:

该函数的功能是在绘制时,让一个已知的点处的箭头指向另一个点。

实现该函数的主要思路为:首先确定两个点之间的连线(从出发点到终点的有向线段)与north方向之间的夹角θ,这就需要利用坐标求出tan然后再利用反函数得到相应的弧度,然后转为角度。在此之后,不能忘记在初始点处,箭头并不是指向north的,而是一个给定的角度α,所以要进一步计算,通过推演发现,当α小于θ时,直接顺时针旋转θ – α;当当α大于θ时,需要顺时针旋转360 – α + θ。

  1. Implement calculateBearings:

该函数的功能是能够完成连续的箭头指向功能,即给出多组点(至少两组),能够完成一个连贯的从前一个点指向后一个点的操作。

实现该函数的要点在于:首先构造出存储点坐标的list,然后实现从中依次取出各点的坐标;其次,利用两个点的坐标调用calculateBearingToPoint函数,这就来到了最重要的一个点,就是currentBearing的值,首先要知道这个值是怎么变化的,一开始默认为0,经过第一次转向后,它的值就是刚才这两点之间的夹角,然后再转就是两次的加和,如果超过了360,说明转动了一圈多,减去360即可。所以,Bearing的计算过程就是将所有转向的角度(也就是集合中所有现有的值)加和,然后判断其与360的关系,若大于360,即减去360,否则,就按原值计算。

      1. Problem 7: Convex Hulls

.该函数的功能是得到一个凸包的最小点集合。

实现方法:受上面实现的函数的启发,只需要找到最左下角的,然后调用函数calculateBearings,调用calculateBearing函数时,要遍历除了自己以外的所有点,然后进行比较,选出顺时针转动角度最小的下一个点,然后将经过的点都放进List中,然后将新的List作为参数送回calculateBearings函数,循环进行直到回到了开始的那个点(最左下角的点)。

其中有一个比较困扰的问题,就是在同一条直线上(或者说同一个角度方向)上会同时有多个点,这个时候就要选取最远的,根据角度和横坐标的大小即可确定他们的远近关系。

将获得的list中的点与原来的点集对应起来,放进Set中,函数实现就完成了。

      1. Problem 8: Personal art

通过改变每次使用的pencolor、起始的角度以及每次的步长来实现一个复杂图形的绘制。

    1. Social Network

通过创建两个类构建关系网(也就是一个有向图),然后寻找两个人之间间隔的人数,也就是寻找一个有向图中两个点之间的最短路径的长度。

      1. 设计/实现FriendshipGraph类

该类的目的是实现社交网络的构建,然后从中得到两点之间的距离。

实现该类的大致思路是首先利用addVertex将所有人存进List中,然后通过addEdge来是他们之间建立起关系(也就是连接上有向边),然后通过getDistance来得到距离的值。

我实现getDistance的思路是BFS,借用List模拟一个队列queue,然后每次比较队头是否为终点,若是,返回distance;若不是,继续循环,直到找到终点,若最后队列空了或者队中出现循环(无法停下来),终止循环,返回-1,表示没有这条路径存在。

      1. 设计/实现Person类

通过分析该问题可知,Person类无非就几个属性:名字、朋友和添加朋友的功能,一开始在定义一个Person的时候,可以使用name来定义,然后将他的朋友加入到List<他的朋友>中(可以通过Graph类中的addEdge来调用),这样一来就可以实现上面所提到的BFS搜索了。

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

直接在main中调用Graph类中的函数,存入Vertex、Edge,然后输出distance即可。

      1. 设计/实现测试用例

测试文件中测试了FriendshipGraph中三个函数的正确性。通过给出几个Person,然后利用他们来测试即可。

测试addVertex函数的思想是检测一下最后的Vertex中是不是包含了所有的Person即可。

测试addEdge函数时,检测每一个Person的friends属性,看他们的friends是否都正确。

测试getDistance函数的思路是给出几组人,每组两个,分别作为函数的参数,看看输出的int值是否符合预期。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值