HIT实验一心得

一.Magic Square (幻方)

1.1内容概述

1.2实现思想

二.Turtle Graphics

2.1TurtleSoup

三. Social Network

3.1 内容概述

3.2 person类设计

3.3 FriendshipGraph类设计

四.感言

写在前面:本分享内容仅个人愚见,若有任何错误之处请不吝指出

1.1 MagicSquare内容概述

在介绍实验内容之前,先简单介绍一下什么是MagicSquar。
MagicSquare即幻方,是一个古老的有趣问题。大体就是对于一个方阵,若其各行数和,各列数和及两个主对角线(分开加和)的和相同,则此方阵为幻方。
回到实验,实验任务也很简单,主要有两个任务。
第一个任务,读入给定的5个文本文件,并判断其中的矩阵是否为幻方。文件示意图如下:

的在这里插入图片描述
要求矩阵中数字都为正整数,且数字与数字之间以\t分隔。判断其中内容是否合法,不合法给出对应输出即可。
第二个任务,将一个给定的函数写入到程序中,print其输出,并写出自己对该程序的运行流程理解。函数如下:
在这里插入图片描述
其中n为要生成的矩阵的行(列)数。

1.2实现思想

第一个任务的实现思路较为清晰。首先,用Files.readAllLine读入文件内容,赋给List,而后遍历List,用String.split(“\t“”)将每行的字符串转换为字符数组即可,最后再遍历各个字符数组用”[1-9][0-9]*"正则匹配判断其是否为正整数即可。
但是,作为一个初学java且粗心大意的萌新,并没有看到实验手册里提示的\t分割符,而且自己试split的时候分割符直接摁的tab(血的教训)分隔失败了。当时没办法,就只能硬写,当然现在看来,当初的解决办法多少有点屎山。那就介绍一下我当时的思路。由于参考价值不大,所以我会给出我的实现源码,以清晰的说明我的思路。
首先还是使用readAllLine方法并遍历得到每一行的字符串:
在这里插入图片描述
遍历每一行的字符串,并置一个标记符j及一个步进符p,j初始置为行首,然后用str.subString(p,p+1)
切割字符串,并将切下来的串与\D匹配:

在这里插入图片描述
如果匹配成功(即步进符p到了分割符\t的位置),接下来判断该矩阵是否合法,设置如下两个判断准则:
1.若步进符p等于标识符j(说明j位置为非数字,不合法),return false
否则若p!=j,即说明j与p间为合法数字,用subString(j,p)将起始位置与\t之间的数字切割下来,转换为数字,存在数组之中,并将标识符j置到p的位置(j=p),并开始下一轮循环,直到字符串遍历结束。
在这里插入图片描述
2.若匹配失败,但步进符p已经走到了字符串末尾,说明标识符j在这一行的最后一个数字的首位。这个数字仍需要切割保存:
在这里插入图片描述
并将j置为p(置到这一行末尾),跳转到下一次循环时,判断到循环结束,开始下一行的字符切割。

在所有字符行循环结束后,即完成了对文件内容的读取。完成后对字符数量进行简单判断,判断矩阵是否为方阵。详细的合法性判断在下一个函数中进行。
在这里插入图片描述

随后到了第二步,判断该矩阵是否为幻方,在第一步中已经将所有的数都储存到了arg数组中,随后按要求计算每行每列及主对角线的和即可,先用sqrt(arg.size())求出矩阵的行数(列数)置为m策略如下:
1.每行和:采用双重循环j为每一列步进符,i为每一行步进符。采用arg.get(i+jm)完成每行加和。
在这里插入图片描述
2.每列和:在上述的双重循环中,采用arg.get(i
m+j)完成每列加和:
在这里插入图片描述
3.正对角线和:同时步进i和j,采用arg.get(i*m+j)完成正对角线和
在这里插入图片描述
4.反对角线和:与上同理,反向遍历列数j即可。
在这里插入图片描述
5.判断其和是否相等:遍历sum数组,若其中所有项都相等,则该矩阵为幻方:
在这里插入图片描述

而关于任务二原理的解释,让我们在此引用一下古人编写的一段七言绝句:
奇幻七绝
先填上行正中央,
依次斜填切莫忘。
上格没有顶格填,
顶格没有底格放。

具体步骤解释如下:
(1)先将1放在第一行的最中央(仅限奇数阶幻方)
(2)下一个数放在这个数的右上方
(3)若要填的数超出了第一行,就将其放在最底行
(4)若要填的数超出了最右列就将其放在第一列。
(5)若这个数要放的位置已经有数,则将该数放在前一个填数的同列的下一行。
这五个步骤正是实验所给算法中的构造思想,具体流程图如下所示:
在这里插入图片描述

2.1 TurtleSoup

实验的第二大模块采用了MIT的代码框架,对我这个编程小白来说,面对不熟的语言,没接触过的框架和读不懂的实验说明,给了当时的我很大的心理压力。但是在明了实验任务后,框架中的spec简单直白的说明了我的编程任务,我也是第一次感觉到这个编程模式对防止代码快速废弃的巨大优势。

接下来,展示一下其中较为复杂的任务,给出部分代码示例:
1.Drawing polygons
其spec如下,即输入正多边形的边长和边数,画出该正多边形:

我们认识到奇数边正多边形的最上顶点总是“尖的”,且垂线总是平分该顶点所在角,而偶数边正多边形最上两个点总是水平的,于是我们进行分类讨论:
(1)若为偶数边正多边形,先按默认方向前进一个边长,随后循环边数-1次,每次循环先转一个内角的度数,随后前进边长,代码如下:
(2)若为奇数边正多边形,先旋转一个内角/2,在前进边长,后与上同理开始循环旋转前进,部分示例如下:
在这里插入图片描述
2.ConVex Hulls
其spec如下,具体内容介绍可参照大佬的解读凸包算法
在这里插入图片描述
这里采用spec中的提示,采用gift-wrapping算法来解决这个问题。
思路:先找到最左下点,赋给start和temp,而后用 calculatebearingtopoint函数得到temp到每个点的角度,选择最小角度点(若角度相同选择距离更远点)赋给temp并加入凸包集中,循环直到temp=start。
过程:1.找到最左下点:
在这里插入图片描述
2.循环得到最小角度点(同角度最长距离)

3.当加入凸包点=start时退出循环,否则加入凸包集。

3.1Social Network内容概述

本任务主要要求构造一个图的数据结构来表示一个社交网络结构,每个“person”在图中都作为一个节点,若两个人有直接社交关系,则在图中两个顶点间有一条无向边。实现addEdge,addVex及getDistance三个方法

3.2Person类设计

Person类设计两个属性 String name及int seq,name为该person的名字,seq为其与图中点关联的序号。除构造方法及get和set外,无特殊方法设计。

3.3 FriendshipGraph类设计

FriendshipGraph类无属性设计,主要实现要求的addVex,addEdge及getDistance方法。
addvertex方法:每加入一个person,将其的seq属性置位点的序号,并生成一个带边链表的数组arraylist,序号seq即为该person在arraylist中的位置。
addEdge方法:若两个person name不同则将两个person p1,p2,添加到互相的边链表中,否则返回false。
Check方法:检测目前所有person的name是否有重复,若有重复返回false。
getDistance方法:设计edge数组edge【x】=y表示点x在y的边链表中。
首先:将第一个person加入队列,对其关联点进行先广遍历,当队列为空时结束遍历(即遍历第一个person的所有关联点)。
遍历时:在遍历person的所有关联节点时,更新edge数组,将edge[x]=y(其中x为该节点的序号seq,y为被遍历person的序号seq)。
队列遍历结束后:先判断若edge[x](x为person2的序号seq),若edge[x]从未更新(即没有点指向它)且person1与person2不是同一个person,则两人无社交关系,返回-1.否则循环当edge[x]不等于person1的序号seq,则将x更新为edge[x],继续循环,每一轮循环距离+1,最后返回距离。

4.感言

这次实验让我这个初识java的小白学会了基本的编程技巧。当时感觉“类”这个设计确实有趣,但没有感觉到它有什么明显的优势和用处。但是之后才明白java和c的底层逻辑差距在哪,以及“类”这个概念设计的高明之处,继承,扩展,实现,指派这才是java的精华。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值