1 实验目标概述
本次实验通过求解三个问题,训练基本 Java 编程技能,能够利用 Java OO 开发基本的功能模块,能够阅读理解已有代码框架并根据功能需求补全代码,能够为所开发的代码编写基本的测试程序并完成测试,初步保证所开发代码的正确性。另一方面,利用 Git 作为代码配置管理的工具,学会 Git 的基本使用方法。
2 实验环境配置
在官网上下载IDEA、JDK和Git并安装,IDEA内自有JUnit,直接下载即可。在为JDK配置环境变量的时候,在系统环境变量中新建一个“JAVA_HOME”环境变量,变量值为JDK的安装路径。然后在Path的环境变量中添加一个“%JAVA_HOME%bin”的变量值。
在这里给出你的GitHub Lab1仓库的URL地址:
3 实验过程
请仔细对照实验手册,针对四个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但无需把你的源代码全部粘贴过来!)。
为了条理清晰,可根据需要在各节增加三级标题。
3.1 Magic Squares
幻方是一个n*n的方阵,每个元素都是正整数,且每行每列和两个对角线上的元素的和相等。该实验要求写出程序判断输入一个矩阵是否是幻方,并且写出构造奇数阶幻方的代码(该代码实现方法已经给出,只需理解实现方法并修改代码判断输入的值是否符合要求即可),并用所写的判断程序判断生成的是否是幻方。
3.1.1 isLegalMagicSquare()
第一步:先判断读取的是不是方阵。先读取文件,获取输入的“矩阵”的行数,实现方法是逐行读取,直至读空;接下来以行数为基准,再次读取文件,并以/t为分隔符,将各个元素分隔开,获得每行的列数,与之前所得的行数作比较。
第二步:判断各个元素值是否符合要求(正整数)。实现方法是利用正整数的正则表达式^[1-9][0-9]*与各个元素作比较,不符合要求则报错返回。
第三步:判断各行各列及对角元素的和是否相等。实现方法是先将各个元素转换成int型存储在n*n的二维数组中,再逐行逐列以及对角线元素求和并比较。实现代码见下,实现过程中通过以第一行元素和为基准与其余所求值1比较来判断:
for (int j = 0; j < n; j++) row_sum[0] += array[0][j]; int sum = row_sum[0];//以第一行的和为基准,与其余所求值比较判断 //计算每行的和 for (int i = 1; i < n; i++) { for (int j = 0; j < n; j++) row_sum[i] += array[i][j]; if(row_sum[i] != sum) { System.out.println("error:sums of rows are not equal, " + fileName + " is not a magic square"); return false; } } //计算每列的和 for (int j = 0; j < n; j++){ for (int i = 0; i < n; i++) col_sum[j] += array[i][j]; if(col_sum[j] != sum){ System.out.println("error:sums of columns are not equal to the rows', " + fileName + " is not a magic square"); return false; } } //主对角线和 for (int i = 0; i < n; i++) main_dia += array[i][i]; if(main_dia != sum){ System.out.println("error:sum of main diagonal is not equal to the rows' and columns', " + fileName + " is not a magic square"); return false; } //次对角线和 for (int i = 0; i < n; i++) minor_dia += array[n - 1 - i][i]; if(minor_dia != sum){ System.out.println("error:sum of minor diagonal is not equal to the rows' and columns', " + fileName + " is not a magic square"); return false; }
3.1.2 generateMagicSquare()
该函数功能是生成一个奇数阶的幻方,具体实现方法已直接给出,实现方式可理解为从第一行中间位置开始,依次为矩阵右上方位置赋值,每次赋值加一。若当前为右边界,则赋值到左边界的相应行;若当前为上边界,则赋值到下边界的相应列;若对应右上元素已经被赋值(每n次赋值就会遇到一次),则赋值到当前元素的相对下一行,并据此继续依次按上述方法赋值,直至完成方阵的全部赋值。由于生成的是奇数阶方阵,需要对原代码稍加补充,判断调用者所给的参数是否为正奇数,补充代码见下:
if (n % 2 == 0 || n < 0) { System.out.println("The input of the n is illegal, please input a positive odd number."); return false; }
测试生成就一个5阶方阵,结果见下:
该函数的逻辑流程图:
3.2 Turtle Graphics
通过git将已经写好的代码clone下来,通过实现drawSquare函数、calculateRegularPolygonAngle函数、drawRegularPolygon函数、calculateBearingToPoint函数、calculateBearingsh函数、convexHull函数、drawPersonalArt函数来完成所有的问题,同时还要通过TurtleSoupTest.java中的测试用例。
3.2.1 Problem 1: Clone and import
用git clone和代码地址即可获取该任务的代码到本地、并用git代码在本地创建git仓库和使用git管理本地开发。
3.2.2 Problem 3: Turtle graphics and drawSquare
函数drawSquare的实现要求利用forward和turn方法完成一个正方形的绘制。forward方法能够让小海龟在画面上前进给定单位距离,turn方法能够让小海龟右转向90度。
由于每次绘图开始时海龟朝向Y轴正方向,因此只需让小海龟前进sideLength个单位,再右转90度,重复4次即可完成一个正方形的绘制。
实现代码见下:
3.2.3 Problem 5: Drawing polygons
该问题要求根据给出的正多边形边数,计算正多边形的内角度。
正n边形内角和为(n-2)*180°,故所求内角为((n-2)*180°)/n=180°-360°/n。
3.2.4 Problem 6: Calculating Bearings
该问题要求给出正多边形角度,计算正多边形边数,仍利用上述公式,反推即可得出边数,但是由于角度以double型数据存储,得出的边数值非正整数,用Math.round四舍五入即可。
3.2.5 Problem 7: Convex Hulls
凸包问题,要求计算包住点集所有点的最小点集集合。实现过程中主要利用calculateBearingToPoint函数来计算两点之间的角度。从最右上角的点开始,易知该点一定在所求集合内,从该点开始每次遍历所有点,找到从该点到其余各点中转角最小的点,该点即目标点,将目标点加入集合,此后再以该目标点为基准,继续上述过程,直到再次返回到最开始的点。若在遍历时发现了多个相同最小偏转角度的点,则以距离最远的点作为目标点。主要部分的实现代码见下:
1.1.1 Problem 5: Drawing polygons
该问题要求根据给出的正多边形边数,计算正多边形的内角度。
正n边形内角和为(n-2)*180°,故所求内角为((n-2)*180°)/n=180°-360°/n。
1.1.2 Problem 6: Calculating Bearings
该问题要求给出正多边形角度,计算正多边形边数,仍利用上述公式,反推即可得出边数,但是由于角度以double型数据存储,得出的边数值非正整数,用Math.round四舍五入即可。
1.1.3 Problem 7: Convex Hulls
凸包问题,要求计算包住点集所有点的最小点集集合。实现过程中主要利用calculateBearingToPoint函数来计算两点之间的角度。从最右上角的点开始,易知该点一定在所求集合内,从该点开始每次遍历所有点,找到从该点到其余各点中转角最小的点,该点即目标点,将目标点加入集合,此后再以该目标点为基准,继续上述过程,直到再次返回到最开始的点。若在遍历时发现了多个相同最小偏转角度的点,则以距离最远的点作为目标点。主要部分的实现代码见下:
3.2.6 Problem 8: Personal art
利用turn、forward就可以实现一些简单图像的绘画。个人的绘画内容如下图:
原创文章,作者:kirin,如若转载,请注明出处:https://blog.ytso.com/267706.html