HIT-2022软件构造实验一

目录:

1 Magic Squares

1.1 isLegalMagicSquare()

1.2 generateMagicSquare()

2 Turtle Graphics

2.1 Problem 1: Clone and import

2.2 Problem 3: Turtle graphics and drawSquare

2.3 Problem 5: Drawing polygons

2.4 Problem 6: Calculating Bearings

2.5 Problem 7: Convex Hulls

2.6 Problem 8: Personal art

2.7 Submitting

3 Social Network

3.1 设计/实现FriendshipGraph类

3.2 设计/实现Person类

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

       3.4 设计/实现测试用例

正文:

1.Magic Squares

该实验主要分为2部分:实现magicsquare的判断和阅读并修改实现magicsquare的生成代码。

其中第一个部分主要由读取文件和判断2个部分组成。读取文件要注意java的代码实现以及对非法字符的识别(可以采用正则表达式快速实现)。判断部分大体分为行、列、斜对角的和是否相等的判断,可以分别用3个函数来判断,最终判断是否都返回true。

1.1        isLegalMagicSquare()

  1. 读取文件:java是一行一行的读取文件字符串。用squareL列表存储所有数字的字符串。读取文件的主要步骤:创建filename的File变量fd,然后创建fd的FileReader变量,再根据这个变量创建BufferReader变量读取文件流。每读一行就将其根据“\t”分割为一个个数字的字符串储存在aquareL内,同时用n存储行数备用。直到读取的一行字符串为null停止,文件读取完毕,关闭BufferReader、FileReader,进入下一步。
  2. 转换字符串数组为int类型的数组。首先将字符串列表转换为字符串数组方便定位,然后循环每一个元素,同时开始检查合法性(首先判断是否含有小数和负数,通过检查字符串是否含有“-”和“.”;然后判断是否含有“ ”,如果含有那说明其中有些地方不按照“\t”分割;然后通过正则表达式判断[^1-9\\t],含有其他非法字符则不容许下一步),多次判断是为了可以识别错误类型。检查都通过就可以转换为int类型并存放到数组里。最后还需要检查是否为行列相等的矩阵,将转换后的数组大小与n2比较即可。

    //判断是否为小数或负数
    if(square[i].contains(".") || square[i].contains("-")){
        System.out.println("包含非正整数");
        return false;
    }
    //判断是否不为\t分割
    if(square[i].contains(" ")){
        System.out.println("非\\t分割");
        return false;
    }
    //判断是否含有其他字符
    if(square[i].matches("[^1-9\\t]")){
        System.out.println("包含非法字符");
        return false;
    }

  3. 判断该矩阵是否为Magic。先计算第一行的总和为标准,通过3个函数分别判断行、列、斜角是否总和相等,内部都是只要发现总和不等便中断并返回false。最后将3个函数的结果&&赋给result,返回result。

     

 

1.2        generateMagicSquare()

       1.判断输入边数,偶数和负数则函数退出。

        2.创建文件操作相关的变量:File、FileWriter、BufferWriter。

        3.生成MagicSquare。

//生成magic square
        int magic[][] = new int[n][n];                      //初始化二维数组
        int row = 0, col = n / 2, i, j, square = n * n;     //从magic[0][n/2]开始
        for (i = 1; i <= square; i++) {                     //遍历n方次,i逐次加一,遍历完生成结束
            magic[row][col] = i;                            //将magic[row][col]赋值,且赋值从1开始依次递增1
            if (i % n == 0)
                row++;                                      //当每遍历过n个数时,下一次赋值在当次赋值位置的同列下一行
            else {                                          //若未遍历过n个数,则
                if (row == 0)                               //若行数为0,下一次赋值在最后一行
                    row = n - 1;
                else                                        //行数不为0就每次减一
                    row--;
                if (col == (n - 1))                         //若列数为n-1,下一次赋值在第0列
                    col = 0;
                else                                        //列数不为n-1就每次加一
                    col++;
            }
        }

        4.将生成的数组以“\t”分割写入文件6.txt中,如果到行尾则不写“\t”,写入完成关闭FileWriter、BufferWriter结束。

 

以下为1-5和6的测试结果:

 

2.Turtle Graphics

该任务要理解和利用接口的操作,用给的turtle按照程序走对路。难点有二:其一是小数除法需要注意,有时需要强转为浮点数类型;其二是求解凸包问题的算法,不好想不好实现。

2.1        Problem 1: Clone and import

  1. 访问github仓库并且将代码下载到指定文件夹
  2. 在idea内创建本地仓库,需要指定一个空文件夹,然后生成仓库
  3. Git常用有commit(将代码提交到本地仓库)、push(将本地仓库的该分支提交到远程仓库)、checkout(切换到另一个分支)、rebase(将分支并到另一个分支末尾)、merge(将两个分支合并)。
  4. Git提交是每完成一个阶段性任务提交一次,并且写好标签。Master分支在某个部分完成时才更新。每开一个新任务就开一个分支,并且在其上工作。

2.2        Problem 3: Turtle graphics and drawSquare

主要调用turtle的forward和turn方法:画正方形需要调用4次前进和转90度,一个循环即可。​​​​​​​

2.3        Problem 5: Drawing polygons

  1. 首先计算该多边形的内角。利用之前实现的calculateRegularPolygonAngle函数计算。公式
  2. 如果是三角形则先转30度,如果是四边形则不转,如果是5及以上的边数则转450-计算的内角度数。
  3. Turtle前进、旋转180-内角度数,重复sides次。

​​​​​​​​​​​​​​2.4        Problem 6: Calculating Bearings

  1. 首先完成calculateBearingToPoint,可以计算当前点到目标点需要转的角度
    1. 首先计算相对位置,x=targetX-currentX,y=targetY-currentY
    2. 计算与x轴的夹角(-180~180),利用math.atan2和math.todegree。
    3. 将x轴为基准的度数转换为以y轴为基准的度数。
    4. 计算需要旋转的度数
    5. 返回求得的需要旋转的度数。
  2. 先创建一个数组bearings存放double类型的值,用来存放旋转的角度
  3. 遍历xCoords和yCoords列表,分别计算相邻两项之间转动的角度,利用calculateBearingToPoint方便计算,存储到bearings。
  4. 返回bearings

2.5        Problem 7: Convex Hulls

 

先将points集合转换为列表pointList方便操作。

  1. 首先要排除集合中只有0/1/2个点的情况,直接调用size方法检查元素个数,小于三直接返回points集合。如果有超过两个点,下一步。
  2. 遍历列表寻找y最小的点,如果有相同的y,取x最小的点。计该点为P0
  3. 建立stack存放是凸包的点集,首先将P0放入,将该点作为基准,寻找其他点中和该点夹角最小的点(调用calculateBearingToPoint),如遇见相同度数的点,取距离最大的点。记为p2.
  4. 将p2加入stack,同时在每次循环寻找的点集中去掉p2,重复上述循环,直到又一次加入P0.
  5. 将stack转换为set,返回该集合。

算法思路如图:

 

​​​​​​​​​​​​​​2.6        Problem 8: Personal art

计划画出多个正六边形错位旋转形成的复杂图案。

  1. 计算正六边形内角度数(calculateRegularPolygonAngle),加一赋给angle作为每次turtle旋转的角度。
  2. 设置6种颜色放入列表中循环使用。
  3. 循环让turtle前进,转向,每完成6次转向
  4. 边长减一,直到边长为1停止。

 

​​​​​​​​​​​​​​2.7        Submitting

完成后在P2分支上提交一次,然后将P2rebase到master分支上,然后将master分支更新到P2所处的位置,将其push到GitHub,完成提交。

​​​​​​​3.Social Network

该任务要求创建Person和FriendShipGrapgh类,分别代表人物和画出的有向图。其中person只需要存储姓名,重写equal方法即可。FriendShipGrapgh需要存包含的person列表(点集)和单向图(使用链表存取每个人的关系对象,再使用列表存取这些链表)。最后还需要用广度优先搜索查询路径长度。

​​​​​​​​​​​​​​3.1        设计/实现FriendshipGraph

        由分析可知:

        属性:

        List<Person> persons,存放图中的人物点集;

        List<LinkedList>relation,存放人物之间的关系(单向)

        Int relationNumber,存放关系总数(边数)

        方法:

  1. 构造方法两个,无参和带参构造
  2. addvertex:首先判断persons内是否含有该人物,若含有则直接返回,否则将该人物加入点集persons,并且在relation中加入以该人物为首位元素的链表。
  3. Addedge:首先遍历persons,若没有起始人物或目标人物,直接返回,否则在relation中寻找以起始人物为第一元素的链表,判断链表内是否含有目标人物,含有则直接返回,不含有则在尾端加上,维护relationNumber。
  4. Getdistance;采用BFS,创建距离列表赋初值为-1,创建一个队列加入起始人物,设置其距离为0,开始遍历队列。查询该人物的所有关系对象,如果没有加入到队列则加入,并且将其对应的距离列表的值改为前者的值加一。直至遍历完成,查找目标人物对应的距离并返回,如果队列内查不到说明无法达到,输出-1.

​​​​​​​​​​​​​​3.2        设计/实现Person

属性:

String name,存储人物名字

方法:

  1. 有参和无参构造方法
  2. Equals:判断人物名字是否相等,返回boolean。
  3. Get:获取对象的名字

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

按照手册实例创建main,输出为:​​​​​​​

 

3.4        设计/实现测试用例

  1. addvertex方法测试:按照手册加入4个人物,通过比对persons的值确认。首先测试正常情况,然后测试重复加入同一人的情况。测试结果都与预期相符。
  2. Addedge方法测试:加入4个人物,加入rachel->ross,ross->rachel两条边,比对graph的relation确认。首先测试正常情况,然后加入rachel->rachel测试,然后加入不存在的jack测试是否可以加入边,最后测试是否可以重复加同一条边。结果与预期相符。
  3. Getdistance测试:加入加入4个人物,加入rachel->ross,ross->rachel,ross->ben,ben->ross4条边。首先测试rachel到rachel,rachel到可达的ben,kramer到不可达的ben.然后测试加入ben->kramer后kramer到ben的距离是否为-1.结果与预期相符。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值