您好,欢迎访问代理记账网站
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

HIT2020春软件构造lab1

HIT 2020年春季学期
计算机学院《软件构造》课程

**Lab 1实验报告

目录

1 实验目标概述

2 实验环境配置

3 实验过程

3.1 Magic Squares

3.1.1 isLegalMagicSquare()

3.1.2 generateMagicSquare()

3.2 Turtle Graphics

3.2.1 Problem 1: Clone and import

3.2.2 Problem 3: Turtle graphics and drawSquare

3.2.3 Problem 5: Drawing polygons

3.2.4 Problem 6: Calculating Bearings

3.2.5 Problem 7: Convex Hulls

3.2.6 Problem 8: Personal art

3.2.7 Submitting

3.3 Social Network

3.3.1 设计/实现FriendshipGraph类

3.3.2 设计/实现Person类

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

3.3.4 设计/实现测试用例

4 实验进度记录

5 实验过程中遇到的困难与解决途径

6 实验过程中收获的经验、教训、感想

6.1 实验过程中收获的经验和教训

6.2 针对以下方面的感受

实验目标概述

本次实验通过求解三个问题,训练基本Java 编程技能,能够利用Java 开

发基本的功能模块,能够阅读理解已有代码框架并根据功能需求补全代码,能够

为所开发的代码编写基本的测试程序并完成测试,初步保证所开发代码的正确性。

另一方面,利用Git 作为代码配置管理的工具,学会Git 的基本使用方法。

  1. 基本的Java 编程

  2. 基于Eclipse IDE 进行Java 编程

  3. 基于JUnit 的测试

  4. 基于Git 的代码配置管理。

实验环境配置

实验电脑:windows64位,8G内存,1T固态内存

Java环境配置:下载安装jdk 8,并且配置JAVA_HOME环境变量截图如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

命令行验证环境如下:

在这里插入图片描述

实验ide使用:由于实验中需要用到junit和git,但是可供选择的eclipse中继承这二者需要较多操作,因此我在安装eclipse后,采用idea方式进行编程,可以在内部集成git,直接右键push即可,如下图:

在这里插入图片描述

遇到的问题:在去年夏季学期中曾经安装过java环境,因此本次实验没有遇到与此相关的困难。利用idea集成git后提交时候,经常出现提交不上去,超时的情况,即使科学上网也并不稳定。后来经过查阅资料得知,可以在提交时候idea也有强制提交(-f)指令,利用这个指令就可以解决。

实验过程

请仔细对照实验手册,针对四个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但无需把你的源代码全部粘贴过来!)。

为了条理清晰,可根据需要在各节增加三级标题。

Magic Squares

在任务首先给出了幻方的定义,然后要求编程判断是否时幻方,并且对于不是幻方的情况指出是什么原因。用
抛出异常加异常处理的方式处理。最后还利用已有函数生成幻方,并用自己编写的函数判断。考察的是文件读写操作与java中基本操作的使用。

isLegalMagicSquare()

  1. 首先创建文件流,用于读取文件:利用FileReader和BufferedReader,以及readline函数,实现读取文件中一行内容。

在这里插入图片描述

  1. 对于读取到的内容进行处理:数字之间用”\t”间隔,所以使用了split函数。读取到的内容存放在String类型数组中。为了便于后续判断是否是幻方。我们记录下读取的总行数row,最大列数max_col,最小列数min_col。这是因为可能出现行列不相等,或者中间有的位置没有数字,导致最小的列数不等于最大列数。

  2. 对于异常情况进行判断,其中包括,含有的不是正整数。这个我创建了isnumber函数,用正则表达式筛选,如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OCrVJKkk-1622101998375)(media/22b19f61f7c0f531489792530fd0c6d2.png)]

    此外,针对最小,最大列数不相等,说明有空数据;列数不等于行数,说明行列数量不相等都做出了判断。如果不是用”\t”分割,那么分割后的结果在判断时候也有问题,也可以判断出来。对于普通的求和之后不相等,利用数组matrix存储了每次读到的数值(这里用到了字符串转int类型),然后处理matrix数组即可。

  3. 对于正确的幻方,输出“这是幻方“

  4. 最终代码如下:

public static boolean isLegalMagicSquare(String fileName){
        try {
            FileReader reader1 = new FileReader(fileName);
            BufferedReader br1 = new BufferedReader(reader1);
            String myline;
            int row = 0;//记录行数量
            int max_col = 0;
            int min_col = 0;
            int flag = 0;//初始化标志

            myline = br1.readLine();
            String[] get_col = myline.split("\t");
            int size = get_col.length;
            int [][] matrix = new int[size][size];//存储数据
            br1.close();
            reader1.close();
            FileReader reader = new FileReader(fileName);
            BufferedReader br = new BufferedReader(reader);

            while((myline = br.readLine())!=null){
                String[] num = myline.split("\t");
                int i = num.length;
                row += 1;//读取一行
                max_col = Math.max(i, max_col);
                if(flag == 0 ){
                    min_col = i;
                    flag = 1;
                }

                min_col = Math.min(i, min_col);
                for(int temp = 0; temp < i; temp++){
                    if(isNumber(num[temp])==false){
                        System.out.println("含有非正整数!");
                        return false;
                    }
                }
                for(int k = 0;k<i;k++){
                    matrix[row-1][k] = Integer.parseInt(num[k]);
//                    System.out.println(matrix[row-1][k]);
                }

            }

            if(row != max_col){
                System.out.println("不是幻方,行列数量不相等");
                return false;
            }
            if(min_col != max_col){
                System.out.println("不是幻方,含有空数据");
                return false;
            }
            //验证幻方
            int[] row_sum = new int[max_col];
            int[] col_sum = new int[max_col];
            int left_cross_sum = 0;
            int right_cross_sum = 0;
            for(int i = 0; i < row ; i++){
                for(int j = 0;j<max_col;j++){
                    row_sum[i] += matrix[i][j];//第i行的和

                }
                if(i >=1 ){
                    if(row_sum[i-1]!=row_sum[i]){
                        System.out.println("行和数值不满足要求!");
                        return  false;
                    }
                }

            }
            for(int j = 0;j<max_col;j++){
                for(int i = 0; i < row ; i++){
                    col_sum[j] += matrix[j][i];//第j列的和
                }
                if(j >=1 ){
                    if(col_sum[j-1]!=col_sum[j]){
                        System.out.println("列和数值不满足要求!");
                        return  false;
                    }
                }

            }
            for(int i = 0;i<row;i++){
                left_cross_sum += matrix[i][i];//左对角线之和
            }
            for(int i = 0;i<row;i++){
                right_cross_sum += matrix[i][max_col-i-1];//左对角线之和
            }
            if(left_cross_sum!=right_cross_sum){
                System.out.println("左右对角线之和不相等");
                return false;
            }

        }
        catch(IOException e1){
            System.out.println(e1);
        }
        catch(ArrayIndexOutOfBoundsException e2){
            System.out.println("不是幻方,行列数量不相等");
            return false;
        }
        catch(NegativeArraySizeException e2){
            System.out.println("不是合理的矩阵!不是幻方!");
        }
        System.out.println("这是幻方!");
        return true;
    }
}

generateMagicSquare()

该模块要求利用已经给出的函数进行改造,针对输入的n为偶数,或者为负数,抛出异常,并且进行异常处理。用try
catch语句即可实现。最后将文件输入到6.txt中,用文件流操作创建文件即可。

  1. 针对n是偶数:这部分要求抛出的异常是数组越界。经过实验,输入偶数确实会导致这个异常,但是可以进行预处理,避免进行不必要的测试。在函数开头部分加上了如下的try:
try{
            //偶数
            int[] a = {1, 2};
            if (n%2 == 0){
                System.out.println(a[3]);
            }
            if(n < 0){
                System.out.println(a[n]);
            }
        }
这就实现了n的两种情况的异常抛出,然后用catch处理即可:
  1. 正常调用函数,输出到文件:利用File writeName = new
    File(地址),然后利用这一对象,创建文件,文件写入流,以及缓冲写入流。
File writeName = new File("./src/P1/txt/6.txt");
        try{
            writeName.createNewFile();
            FileWriter fw = new FileWriter(writeName);
            BufferedWriter bw = new BufferedWriter(fw);
            for(int s = 0;s<n;s++){
                for(int k = 0;k<n;k++){
                    bw.write(magic[s][k]+"\t");
                }
                bw.write("\n");
            }
            bw.flush();
            bw.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
写入时注意也要用\\t分割输入的数字,并且每行输入结束要输入\\n换行。

Turtle Graphics

考察利用现有的函数,如何去组合创造出我们想要的图案的能力。已经给出了基本的转向,前进等函数,利用这些实现例如画正方形,多边形等。同时,考察了数学思维和编程结合的思想:如何利用已有公式,快速获得正确结果。同时,要注意运算时对于浮点数的精度损失问题。

Problem 1: Clone and import

首先安装git,并且将git集成到本地的idea中,一键管理:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fYMxNUJf-1622101998379)(media/97ad07381ed0be824a1e7aa55f1322d4.png)]

用git实现版本控制:首先在科学上网的情况下,在idea中登录github,并且授权登录。

然后新建项目时,选择建立版本控制的文件,如下图:

选择对应的仓库后,仓库上的代码就可以直接下载到idea中,并且进行编写。

利用普通方法:在利用github 给出的地址,点击clone,把代码保存到本地的github
desktop里

或者在网页版,找到对应的链接,在git
bash中运行下载到本地。个人使用的是第一种,比较方便。

下载后,注意我们放在了P2中,但是源文件中的代码,直接是turtle
的package,所以需要修改为package
P2.turtle,余下的一些库等等也同理修改。文件中的test文件,需要重构到test文件夹的P2目录下。这里我在idea中利用junit插件,首先创立文件夹test,并且指定为测试源,然后一键生成即可。如下图:

在这里插入图片描述

在这里插入图片描述

点击junit test,选择junit 4,就有如下文件产生:

在这里插入图片描述

然后把原有的TurtleSoupTest中的内容拖过来即可。

Problem 3: Turtle graphics and drawSquare

public static void drawSquare(Turtle turtle, int sideLength) {

        for(int i = 0;i<4;i++){
            turtle.forward(sideLength);
            turtle.turn(90);
        }

    }

编写循环,一共四次,每次走定长,然后右转90度即可。

Problem 5: Drawing polygons

  1. 首先根据边数算出每个内角的度数,在转弯时调用这个函数。经过查阅资料,多边形内角和是angle

    180*(边数-2).因此对于正多边形,每个角的度数就是n分之一倍的angle。不需要别的操作,直接return即可。注意,结果是double类型,这里保留两位小数,要用180.00
public static double calculateRegularPolygonAngle(int sides) {
        return (180.00)*(sides-2)/sides;

    }
  1. 根据内角度数,计算多边形边长。这里利用上一步的公式,推导出角度和边长的关系,是:sides

    360/(180-angle)。注意,浮点数angle除法得到的数字需要进行舍入,所以要对于是加一还是减一做出判断,而不是简单的直接转换成int。

    当结果是int类型,标志是对1取余等于0,就直接转成int输出;

    当结果是浮点数,那么首先取出浮点数的前两位(这是上一个函数的要求,便于计算比较):

    DecimalFormat df = new DecimalFormat("########.00");

    然后分别对取整数后的sides,加一或者减一,带入上一步的函数中计算。如果恰好相等,就直接返回。如果都不行,那么就返回直接取整的本身(因为一共只有这三种可能)

public static int calculatePolygonSidesFromAngle(double angle) {
        double temp = 360/(180-angle);
        int t = (int) temp;
        //temp是浮点
        if(temp%1 != 0){
            //限制小数点两位
            DecimalFormat df = new DecimalFormat("########.00");
            double add_one = (180.00)*(t-1)/(t+1);
            add_one = Double.parseDouble(df.format(add_one));
            if(add_one == angle) return t+1;

            double minus_one = (180.00)*(t-3)/(t-1);
            minus_one = Double.parseDouble(df.format(minus_one));
            if(minus_one == angle) return t-1;

        }
        return (int)temp;

    }
  1. 绘制正多边形。这里没看到要求是凸多边形或者可以是凹多边形。为了后面自定义画图时候好看点,采用了凸多边形。这里注意,要调整角度(前两行),否则会向内凹。
public static void drawRegularPolygon(Turtle turtle, int sides, int sideLength) {
        double angle=180-calculateRegularPolygonAngle(sides);
        turtle.turn(270.0+angle);
        for(int i = 0;i<sides;i++){
            turtle.turn(angle);
            turtle.forward(sideLength);
        }
    }

Problem 6: Calculating Bearings

  1. 首先编写函数,求出从当前角度,沿当前点出发,到目标点的朝向角度应该转多大。注意这个数如果是负数,就要加上360;如果超过360,就要取余。计算公式如下:
return (360-currentBearing+angel)%360;

注意这里用到了atan2函数,正切值当x坐标是0,趋于无穷,这个我们要单独处理,如下:

double angel = Math.toDegrees(Math.atan2(width,high));
        if(width == 0){
            if(high>0){
                //目标点在上方,转270度
                angel = 0;
            }
            if(high == 0) angel =0;
            if(high <0) angel = 180;
        }
  1. 对于给出的点的列表,给出每次行动转动的角度,并返回列表。对于点列表中的每两个挨着的点,调用函数求出转角,并add到list中即可。
public static List<Double> calculateBearings(List<Integer> xCoords, List<Integer> yCoords) {
        List<Double> angel = new ArrayList<Double>();
        int x_size = xCoords.size();
        angel.add(0,calculateBearingToPoint(0,xCoords.get(0),yCoords.get(0),xCoords.get(1),yCoords.get(1)));
        for(int i = 2;i<x_size;i++){

            angel.add(i-1,calculateBearingToPoint(angel.get(i-2),xCoords.get(i-1),yCoords.get(i-1),xCoords.get(i),yCoords.get(i)));
        }
        return angel;
    }

Problem 7: Convex Hulls

凸包算法,没啥说的,都是火炬,查阅资料编写如下。

public static Set<Point> convexHull(Set<Point> points) {
        try{
            if(points.size()<3) return points;
            Set<Point>Points = new HashSet<Point>();
            Point[] P = points.toArray(new Point[points.size()]);
            boolean[] exist = new boolean[points.size()];
            int i,startpoint = 0,nextpoint, endpoint;
            double minX = P[0].x();
            for(i =1;i<P.length;i++){
                if(P[i].x()<minX||(P[i].x()==minX&&P[i].y()<P[startpoint].y())){
                    minX = P[i].x();
                    startpoint = i;
                }
            }
            endpoint = startpoint;
            double currentBearing = 0.0;
            do{
                double minangle = 360.0;
                nextpoint = startpoint;
                for(i = 0;i<P.length;i++){
                    if(i != startpoint){
                        double angle = calculateBearingToPoint(currentBearing,(int)P[startpoint].x(),(int)P[startpoint].y(),(int)P[i].x(),(int)P[i].y());
                        if(!exist[i]){
                            if(angle<minangle){
                                minangle = angle;
                                nextpoint = i;
                            }
                            else if(angle == minangle){
                                double dis1 = Math.pow(P[i].x()-P[startpoint].x(),2.0)+Math.pow(P[i].y()-P[startpoint].y(),2.0);
                                double dis2 = Math.pow(P[nextpoint].x()-P[startpoint].x(),2.0)+Math.pow(P[nextpoint].y()-P[startpoint].y(),2.0);

                                if(dis1 > dis2){
                                    nextpoint = i;
                                }
                            }
                        }
                    }
                }
                currentBearing = (currentBearing+minangle)%360;
                startpoint = nextpoint;
                exist[nextpoint] = true;


            }
            while(endpoint !=startpoint);
            exist[endpoint] = true;
            for(i = 0;i<P.length;i++){
                if(exist[i]){
                    Points.add(P[i]);
                }
            }
            return Points;
        }
        catch (Exception e){
            throw new RuntimeException("implement me!");
        }

    }

Problem 8: Personal art

这个大家自己花花就行!
随便写几个循环,正方形,圆形,正多边形,来回画
里面有color,可以用6种不同颜色绘制,有正多边形和自己编写的圆形,并且设计了合理的步长,代码如下:

public static void drawPersonalArt(Turtle turtle) {
        turtle.color(PenColor.PINK);
        drawSquare(turtle,20);

        for(int i = 1;i<=20;i++){
            drawCircle(turtle,4);
            drawCircle(turtle,4);
            drawSquare(turtle,20);
            turtle.turn(calculateRegularPolygonAngle(20));
            drawRegularPolygon(turtle,10,30);
            drawRegularPolygon(turtle,10,30);
            if(i%6 ==1){
                turtle.color(PenColor.PINK);
            }
            if(i%6 ==2){
                turtle.color(PenColor.YELLOW);
            }if(i%6 ==3){
                turtle.color(PenColor.RED);
            }if(i%6 ==4){
                turtle.color(PenColor.GREEN);
            }if(i%6 ==5){
                turtle.color(PenColor.ORANGE);
            }if(i%6 ==6){
                turtle.color(PenColor.MAGENTA);
            }

        }

    }

最后化成了这个样子:
在这里插入图片描述

Submitting

在待提交的文件右键,选中git,推送

Social Network

刻画一个社交网络表示出人与人之间的关系。注意要能够拓展到有向图,人与人之间的关系是相互的。注意在处理的过程中遇到异常情况要提醒并且退出。比如同时出现一样的名字等。

设计/实现FriendshipGraph类

需要两个列表,一个用来存储Person类的对象,一个用来记录都加入了谁,避免重复加点。

  1. AddEdge的设计:对于两个加关系的人people1 和people2
    ,分别调用Person类的add_friend方法,将对方加到自己的朋友list中即可。

  2. addVertex:注意加点时判断namelist中是否已经有该名字,用list的contains方法判断,如果重复了就提示,并退出代码设置为0.

public int addVertex(Person new_Person){
        if(new_Person.getName() == ""){
            System.out.println("名字未设置!");
            return 1;
        }
        if(nameList.contains(new_Person.getName())){
            System.out.println("名字重复");
            return 2;
        }else{
            nameList.add(new_Person.getName());
        }
        people.add(new_Person);
        return 0;
    }
  1. getdiatance方法:利用广度优先搜索,采用队列的数据结构实现。
public int getDistance(Person Person1, Person Person2){
        if(Person1 == Person2){
//            System.out.println("They are the same guys!");
            return 0;
        }
        Queue<Person> queue = new LinkedList<>();
        Map<Person, Integer> distantMap = new HashMap<>();
        queue.offer(Person1);
        distantMap.put(Person1, 0);
        while(!queue.isEmpty()){
            Person topPerson = queue.poll();
            int nowDis = distantMap.get(topPerson);
            List<Person> friend_List = topPerson.get_Friend_List();
            for(Person ps: friend_List){
                if(!distantMap.containsKey(ps)){
                    distantMap.put(ps, nowDis+1);
                    queue.offer(ps);
                    if(ps == Person2){
                        return distantMap.get(Person2);
                    }
                }
            }
        }
        return -1;
    }

设计/实现Person类

Person类中有两个属性:人名String
name和朋友列表friend_list。注意在初始化时候需要输入人名,因此Person类需要构造器。

还有getName方法,便于查询人名;在设计getdistance方法中,需要找到队列中队首的所有朋友,因此设计了get_friendlist,找到一个对象的所有朋友。

最后还有add_friend方法,用于向对象的朋友列表属性中添加朋友。

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

都是现成的,代码粘下来:

public static void main(String[] args){
        FriendshipGraph graph = new FriendshipGraph();
        Person rachel = new Person("Rachel");
        Person ross = new Person("Ross");
        Person ben = new Person("Ben");
        Person kramer = new Person("Kramer");
        graph.addVertex(rachel);
        graph.addVertex(ross);
        graph.addVertex(ben);
        graph.addVertex(kramer);
        graph.addEdge(rachel, ross);
        graph.addEdge(ross, rachel);
        graph.addEdge(ross, ben);
        graph.addEdge(ben, ross);
        System.out.println(graph.getDistance(rachel, ross));
//should print 1
        System.out.println(graph.getDistance(rachel, ben));
//should print 2
        System.out.println(graph.getDistance(rachel, rachel));
//should print 0
        System.out.println(graph.getDistance(rachel, kramer));
    }
}

在这里插入图片描述

设计/实现测试用例

测试add_Edge,可能出现声明了人之后,没加入到图中的情况

@Test
    public void addEdge() {
        FriendshipGraph graph = new FriendshipGraph();
        Person p1 = new Person("p1");
        Person p2 = new Person("p2");
        Person p3 = new Person("p3");

        graph.addVertex(p1);
        graph.addVertex(p2);
        //p3没加入到图中
        assertEquals(1, graph.addEdge(p2,p3));
        assertEquals(0, graph.addEdge(p2,p1));


    }

测试add_Vertex: 如果名字重复,return 2,如果名字为空,说明未输入,return 1;正常返回0

if(new_Person.getName() == ""){
            System.out.println("名字未设置!");
            return 1;
        }
        if(nameList.contains(new_Person.getName())){
            System.out.println("名字重复");
            return 2;
        

测试getdistance:自己加入点和边测试即可。自己到自己,一个点到不存在的点,以及经过多步长的距离。

Main的测试:

public void main() {
        FriendshipGraph graph1 = new FriendshipGraph();
        Person a = new Person("a");
        Person b = new Person("b");
        Person c = new Person("c");
        Person d = new Person("d");
        graph1.addVertex(a);
        graph1.addVertex(b);
        graph1.addVertex(c);
        graph1.addVertex(d);
        graph1.addEdge(a,b);
        graph1.addEdge(b,a);
        graph1.addEdge(c,b);
        graph1.addEdge(b,c);
        graph1.addEdge(b,d);
        graph1.addEdge(d,b);
        graph1.addEdge(c,d);
        assertEquals("expected distance",1,graph1.getDistance(a,b));
        assertEquals("expected distance",1,graph1.getDistance(b,c));
        assertEquals("expected distance",1,graph1.getDistance(c,d));
        assertEquals("expected distance",2,graph1.getDistance(a,c));
        assertEquals("expected distance",1,graph1.getDistance(b,d));
        assertEquals("expected distance",2,graph1.getDistance(a,d));

    }

实验进度记录

请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。

每次结束编程时,请向该表格中增加一行。不要事后胡乱填写。

不要嫌烦,该表格可帮助你汇总你在每个任务上付出的时间和精力,发现自己不擅长的任务,后续有意识的弥补。

日期时间段任务实际完成情况
2021-5-1317:04从github classroom导入项目按计划完成
2021-5-1621:00-00:40编写完成任务1按计划完成
2021-5-2119:00-0:09编写完成任务2,并且一起push,修改GitHub上的文件目录结构遇到困难,按计划完成
2021-5-2210:00-22:00完成任务3,写报告按计划完成
2021-5-2309:00-12:54写完报告,push按计划完成

实验过程中遇到的困难与解决途径

遇到的难点解决途径
集成git与junit查阅csdn,,购买科学上网工具,自己动手解决
提交失败处理询问同学,学会强制提交
Java的数据类型,类的构建方式,构造器不熟悉看教程,看网课,问同学,自己动手试着更改

实验过程中收获的经验、教训、感想

实验过程中收获的经验和教训

多看文档,积累debug经验,任务要及时提交,不能拖延。有问题积极讨论。

针对以下方面的感受

  1. Java编程语言是否对你的口味?

    对口,很舒服

  2. 关于Eclipse IDE

    不友好,功能很多,但是不熟练的难以上手,导入包之类的比较方便,但是下载包和插件太慢,不如idea。并且没自己嵌入junit和git,手动配置耽误时间。Eclipse下载安装也需要java环境。

  3. 关于Git和GitHub

    不错的平台,用了很久了

    Git命令现在可以用插件集成了,不用手动书写;新建分支等操作可以在idea中直接实现。

  4. 关于CMU和MIT的作业

    不错,很有意思

  5. 关于本实验的工作量、难度、deadline

    工作量适中,难度可以,deadline也算可以

  6. 关于初接触“软件构造”课程

动手敲代码很爽,谢谢。
延。有问题积极讨论。

针对以下方面的感受

  1. Java编程语言是否对你的口味?

    对口,很舒服

  2. 关于Eclipse IDE

    不友好,功能很多,但是不熟练的难以上手,导入包之类的比较方便,但是下载包和插件太慢,不如idea。并且没自己嵌入junit和git,手动配置耽误时间。Eclipse下载安装也需要java环境。

  3. 关于Git和GitHub

    不错的平台,用了很久了

    Git命令现在可以用插件集成了,不用手动书写;新建分支等操作可以在idea中直接实现。

  4. 关于CMU和MIT的作业

    不错,很有意思

  5. 关于本实验的工作量、难度、deadline

    工作量适中,难度可以,deadline也算可以(?气抖冷)

  6. 关于初接触“软件构造”课程

动手敲代码很爽,谢(wo)谢(gan)。


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进