根据实验手册简要撰写。
简要陈述你配置本次实验所需开发、测试、运行环境的过程,必要时可以给出屏幕截图。
特别是要记录配置过程中遇到的问题和困难,以及如何解决的。
在这里给出你的GitHub Lab1仓库的URL地址。
请仔细对照实验手册,针对三个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但无需把你的源代码全部粘贴过来!)。
为了条理清晰,可根据需要在各节增加三级标题。
- 首先将给出的文件以文件流的形式进行导入,如果不存在该名称的文件,则返回File isn’t exist.
- 使用String s将录入矩阵一行一行进行读取,如果读入的行不为null的时候,将该行存入List中,否则报错
- 然后以“\t”为划分符号,将List存入数据存入一个二维数组nums
- 然后进行判断是否边长相等,矩阵中是否存在负数,是否严格用\t进行划分的
- 然后就是进行横向,纵向和对角线的和是否相等的判断
- double[] sum_line = new double[side_length];//计算横向的和
double[] sum_alley = new double[side_length];//计算竖向的和
double sum_left_slanting ;//计算左斜向的和
double sum_right_slanting ;//计算右斜向的和
for (int i = 0; i < side_length; i++) {
sum_line[i] = nums[i][0];
sum_alley[i] = nums[0][i];
}
for (int i = 0; i < side_length; i++) {
//判断横向和纵向的数组和是否相等
for (int j = 0; j < side_length-1; j++) {
sum_line[i] = sum_line[i]+ nums[i][j+1];
sum_alley[i] = nums[j+1][i] + sum_alley[i];
//注意:数组的横坐标纵坐标应该反过来
}
if (i > 0 && (sum_line[i] != sum_line[i - 1] || sum_alley[i] != sum_alley[i - 1])) {
return false;
}
}
//判断左斜向和右斜向是否相等
sum_left_slanting = nums[side_length-1][0];
sum_right_slanting = nums[0][0];
for (int i = 0; i < side_length - 1; i++) {
sum_right_slanting = sum_right_slanting + nums[i+1][i+1];
sum_left_slanting = sum_left_slanting + nums[side_length-1-i-1][i+1];
}
if(sum_right_slanting != sum_left_slanting){
return false;
} - if(sum_line[0] != sum_alley[0] || sum_alley[0] != sum_left_slanting ){
return false;
}
return true;
- 首先判断输入的数据是否为正奇数,否则返回“输入的n不符合格式!请输入正奇数!
- 然后创建二维数组magic对新建的幻方进行存储,其余请见注释。
- 完成之后将形成的幻方导入6.txt,并将导入上一个函数进行查看
- 注意最后bufferwriter关闭后才能导入成功
- int magic[][] = new int[n][n];
int row = 0, col = n / 2, i, j, square = n * n;
for (i = 1; i <= square; i++) {
magic[row][col] = i;//代码初始化将其设置为第一行中间的位置
if (i % n == 0)//如果当前数字能被n整除,则往下一行同一列存放下一个元素,以n为循环进行填满
row++;
else {
if (row == 0)//如果是第一行,则下一个元素将出现为最后一行
row = n - 1;
else
row--;//否则将往上一行
if (col == (n - 1))//如果是最后一列,则下一个元素将出现在第一列
col = 0;
else
col++;//否则将往右边一列
}
}//重复n * n次即可将幻方填满
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
System.out.print(magic[i][j] + "\t");
System.out.println();
}
File magicFile = new File("./src/P1/txt/6.txt");
BufferedWriter bufferedwriter = new BufferedWriter(new FileWriter(magicFile));
for (int k = 0; k < n; k++) {
for (int l = 0; l < n; l++) {
String content = String.valueOf(magic[k][l]);
bufferedwriter.write(new String(content + "\t"));
}
bufferedwriter.write("\n");
}
bufferedwriter.close();//没有将bufferwriter关闭无法将内容写入
return true;
使用给出的函数在java内进行画图,并对凸包函数进行编写
- 进入需要拷贝的仓库,右击后点击Git Bash Here后进入
- 输入git init后,可以看到目标文件夹下面生成.git文件
- 然后输入git add .将该文件夹下的所有文件添加
- 输入git commit -m “//注释” 写注释便于对不同版本进行区分
- 输入git remote add origin 仓库地址 将本地代码关联到github上
- 输入git pull –rebase origin master 获取远程库与本地仓库进行合并
- 最后输入git push -u origin master把当前分支推送到远程
-
-
- Problem 3: Turtle graphics and drawSquare
-
1、Forward()函数是以当前方向向该方向走的步数
2、Turn()函数是以当前方向顺时针方向进行填入度数的旋转
public static void drawSquare(P2.turtle.Turtle turtle, int sideLength) {
for (int i = 0; i < 4; i++) {
turtle.forward(sideLength);
turtle.turn(90);
}
}
1、CalculateRegularPolyginAngle()函数是输入多边形的边长,如果输入的边长小于等于2的话,则返回0并且输出“请输入大于2的整数边长!”,如果满足条件的话,则使用公式angle = 180 – (double)360 / sides计算angle的大小并返回
public static double calculateRegularPolygonAngle(int sides) {
double angle;
while(sides <= 2){
System.out.println("请输入大于2的整数边长!");
return 0;
}
angle = 180 - (double)360 / sides;
return angle;
}
2、calculatePolygonSidesFromAngle()函数是输入正多边形的内角,运用外角的知识计算出边数,注意:如果返回的边数的大小并不是整数的话,则遵守四舍五入的原则进行返回
public static int calculatePolygonSidesFromAngle(double angle) {
int n = (int) ((360.00) / (180.00 - angle));
if(Math.abs((n+1) - (360.00) / (180.00 - angle)) < 0.5){
n++;
}
return n;
}
3、同理于前面画正方形的原理,先进行forward()操作,然后进行转向turn(),应该注意由于应该是顺时针旋转的话,旋转的角度应该为(180-angle)
public static void drawRegularPolygon(P2.turtle.Turtle turtle, int sides, int sideLength) {
double angle = calculateRegularPolygonAngle(sides);
for (int i = 0; i < sides; i++) {
turtle.forward(sideLength);
turtle.turn(180.0 - angle);
}
}
1、calculateBearingToPoint()函数计算起始点和目标点的顺时针旋转角度,其中应该区分在一条线上的情况,应为当两个点在一条线的情况时,无法使用反三角函数将角度导出,其次也应该注意,由于使用反三角函数导出的角度为弧度制,故还需要类型强制转移为角度制的角度,如果为负数的情况,则转化为其正的补角。
public static double calculateBearingToPoint(double currentBearing, int currentX, int currentY,
int targetX, int targetY) {
if(currentX == targetX && currentY < targetY){
double degree = (0 - currentBearing);
if(degree < 0){
degree += 360;
}
currentBearing = degree;
return currentBearing;
} else if(currentX == targetX && currentY > targetY){
double degree = (180 - currentBearing);
if(degree < 0){
degree += 360;
}
currentBearing = degree;
return currentBearing;
} else if(currentY == targetY && currentX < targetX){
double degree = (90 - currentBearing);
if(degree < 0){
degree += 360;
}
currentBearing = degree;
return currentBearing;
} else if(currentY == targetY && currentX > targetX){
double degree = (270 - currentBearing);
if(degree < 0){
degree += 360;
}
currentBearing = degree;
return currentBearing;
} else if(currentX == targetX && currentY == targetY){
currentBearing = 360;
return currentBearing;
}
else {
double degree = Math.toDegrees(Math.atan2(targetY - currentY, targetX - currentX));
//由于为弧度制,故还要转化为角度制
degree = 90 - degree - currentBearing;
if (degree < 0) {
degree += 360;
}
currentBearing = degree;
return currentBearing;
}
2、calculateBearings()函数,调用上面的calculateBearingToPoints()函数对给定集合的每个点进行角度的计算。
public static List<Double> calculateBearings(List<Integer> xCoords, List<Integer> yCoords) {
List<Double> bearings = new ArrayList<>();
double bear = 0;
if(xCoords.size() == yCoords.size()){
int size = xCoords.size();
for (int i = 0; i < size-1; i++) {
bearings.add(calculateBearingToPoint(bear, xCoords.get(i), yCoords.get(i),
xCoords.get(i+1), yCoords.get(i+1)));
bear = calculateBearingToPoint(bear, xCoords.get(i), yCoords.get(i),
xCoords.get(i+1), yCoords.get(i+1));
}
} else {
System.out.println("Please ensure that the numbers of xCoords equal to the yCoords'.");
}
return bearings;
}
1、通过找到最左上角的点,然后遍历每个点找到角度最小的点,最后连在一起即可,知道最后连到开始的点
public static Set<Point> convexHull(Set<Point> points) {
if(points.size() < 3) {
return points;
}
HashSet<Point> result =new HashSet<Point>();
Point tmp=points.iterator().next();
Point start = tmp;
Point targ = tmp;
double angle = 0, a1 = 0, at = 0;
for(Point p:points) {
if(p.x < start.x || (p.x == start.x && p.y > start.y))
start = p;
}
result.add(start);
Point ptr = start;
while(true) {
at = TurtleSoup.calculateBearingToPoint(angle, ptr.x, ptr.y, targ.x, targ.y);
for(Point q:points) {
if(targ == q)
continue;
a1 = TurtleSoup.calculateBearingToPoint(angle, ptr.x, ptr.y, q.x, q.y);
if(a1 < at) {//选择偏转角度最小的
targ = q;
at = a1;
}else if(a1 == at) {//选择距离更大的
double dist=(ptr.x - ptr.y) * (ptr.x - ptr.y) + (targ.x - targ.y) * (targ.x - targ.y);
double dis1=(ptr.x - ptr.y) * (ptr.x - ptr.y) + (q.x - q.y) * (q.x - q.y);
if(dis1 > dist) {
targ = q;
at = a1;
}
}
}
if(targ == start)//终止条件
break;
else {
angle=at;
result.add(targ);
ptr = targ;
}
}
return result;
}
运用函数,画出一个蓝色的线条的五角星
- 进入需要拷贝的仓库,右击后点击Git Bash Here后进入
- 输入git init后,可以看到目标文件夹下面生成.git文件
- 然后输入git add .将该文件夹下的所有文件添加
- 输入git commit -m “//注释” 写注释便于对不同版本进行区分
- 输入git remote add origin 仓库地址 将本地代码关联到github上
- 输入git pull –rebase origin master 获取远程库与本地仓库进行合并
- 最后输入git push -u origin master把当前分支推送到远程
即为利用集合Set,列表List,队列等知识构造一个单向的朋友圈,并需要推断出来两个朋友之间是否有关系,是几层的关系。
-
-
- 设计/实现FriendshipGraph类
-
FriendshipGraph类中,存在一个Set<Person>FriendCircle作为整个人群的集合,使用函数addEdge()将需要判断的人加入该集合,然后每个Person类还有List<Person>people_surround,利用函数public void addEdge()将一个人的名字单方向加入另外一个人的List中,然后利用getDistance()函数用队列进行广度优先搜索,每次遍历过后利用函数Init_Index()将每个人的index进行初始化。即可完成FriendshipGraph的构建。
-
-
- 设计/实现Person类
-
Person()类包含三个元素,首先是人名String name,其次是每个人的距离为1的朋友圈List<Person>people_surround 以及判断一个人是否在队列循环的时候已经判断过了的标志
Int index,若未经标记则为0,已经遍历过一遍了则将index变为1
-
-
- 设计/实现客户端代码main()
-
包含于FriendshipGraph()中了
-
-
- 设计/实现测试用例
-
创建函数getDistance()的测试,其中包含了对addVertex,addEdge的测试
创建六个对象并创建5个问题分别针对1、相邻有线相连2、中间有中转后进行相连3、自己连接自己长度为0 3、两者之间没有路相连,则返回-1 4、多于两步,这时候则要测试是否有判断上一级不相等再加1的代码
请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。
每次结束编程时,请向该表格中增加一行。不要事后胡乱填写。
不要嫌烦,该表格可帮助你汇总你在每个任务上付出的时间和精力,发现自己不擅长的任务,后续有意识的弥补。
日期 | 时间段 | 任务 | 实际完成情况 |
2024-03-16 | 20:00-21:30 | 问题1文件中的矩阵导入并存为数组 | 按计划完成 |
2024-03-16 | 21:30-23:30 | 问题1的isLegalMagicSquare函数并进行测试 | 延期1.5小时完成 |
2024-03-17 | 10:00-11:30 | 补充isLegalMagicSquare函数中对于“\t”分隔符,负数和边长不相等问题的解决+ | 按计划完成 |
2024-03-17 | 16:00-17:30 | 将generateMagicSquare函数导入,进行理解写出注释并将生成的矩阵进行导入操作,并画出流程图 | 延期0.5小时完成 |
2024-03-18 | 20:00-21:30 | 将Turtle导出并进行drawSquare()的编写 | 延期0.5小时完成 |
2024-03-18 | 22:00-23:00 | 修改代码中的不兼容和错误 | 按时完成 |
2024-03-18 | 23:00-23:30 | 写方法drawRegularPolygon(), calculatePolygonSidesFromAngle()和calculateRegularPolygonAngle() | 按时完成 |
2024-03-19 | 19:00 – 22:00 | 写方法calculateBearingToPoint(), calculateBearings(), convexHull(),drawPeronalArt()并检查测试用例 | 延期0.5小时 |
2024-03-20 | 18:30-21:30 | 完成3.3任务代码层面 | 按时完成 |
2024-03-23 | 19:00-19:30 | 撰写实验报告 | 按时完成 |
遇到的困难 | 解决途径 |
导入生成的矩阵时,运行后6.txt文件仍然为空文件 | 使用BufferedWrite导入的时候,应该在后面添加.close()进行关闭后才可以导入 |
对矩阵进行取值的时候,取值位置发生错误 | 应该注意二维数组的横纵方向与数学上的横纵坐标的差异 横坐标从左往右,而纵坐标则是从上往下 |
上传文件到github仓库 判断两点之间若在一条直线上的时候不能直接用反三角函数进行计算 | 代码不熟悉,多操作几次就行 将特殊情况单独提出来进行编码即可 |
第一次实验过程中,有太多的东西需要开头学习和练习,ecplice, git,turtle,junit test都是难点。遇到困难卡住不要害怕,尽力想办法去解决,如果实在解决不了再选择放弃。
- Java编程语言是否对你的口味?与你熟悉的其他编程语言相比,Java有何优势和不足?
Java作为一个新的语言,相比于传统的C语言和C++,是一种更加典型的面向对象进行编程的语言。作为面向对象编程的语言,它所进行的编程动作更加贴近于现实中人类的思想,理解起来更加容易。不足之处也有存在,由于是由一个个对象组成,相比于面向过程的编程语言,编程者对于整个事件的执行顺序和步骤可能理解没有相比于C语言等更加容易。
- 关于Eclipse或IntelliJ IDEA,它们作为IDE的优势和不足;
IDEA:
它的优势在于提供了智能的编码支持,无论是代码补全、格式化还是语法高亮,都极大地提高了我的编码效率。同时,IDEA的插件生态系统丰富多样,可以满足各种特定的开发任务。此外,IDEA还集成了构建工具和版本控制系统,使得项目管理和构建流程更加便捷。在调试和性能分析方面,IDEA也表现出色,帮助我更好地优化代码。
不足之处:它的系统资源占用相对较大,有时候会让计算机运行得缓慢。此外,IDEA的启动速度相对较慢,特别是在加载较多插件和组件时,需要耐心等待。
- 关于Git和GitHub,是否感受到了它在版本控制方面的价值;
感受到了。通过GitHub,开发者可以轻松地追踪代码的变动,并记录每次提交的修改内容。这不仅有助于开发者回顾和理解代码的历史版本,还能方便地对比不同版本之间的差异,甚至在必要时回滚到特定的版本。这种能力对于确保代码的稳定性和一致性至关重要。
- 关于CMU和MIT的作业,你有何感受;
感受:说国外快乐教育都是假的,国外顶尖学府的学生的作业也是有难度,有挑战的,没有编程技能的磨砺,就没有能力的提升。
- 关于本实验的工作量、难度、deadline;
适中
- 关于初接触“软件构造”课程;
觉得非常适合软件工程专业的同学,相当于一定程度上走出象牙塔和社会需求进行了接触,尤其是Test测试用例和Spec用例规约的引入收获颇丰