软构lab1的写完感想

    1. Magic Squares

这次任务的目的是要求设计一个程序:

任务一:能够从五个已经提供的txt文档中读入数据,来判断输入的数据能否构成一个MagicSquare,若是则返回true,若不是则返回false且说明原因。MagicSquare是一个正方形图形,他的每一行、每一列和对角线的数字之和都相等。

任务二:对给出的generateMagicSquare函数进行扩充,使之能够产生一个MagicSquare并且将其输入到文本6.txt中,然后对其判断是否为MagicSquare。并且满足若输入的为奇数能产生MagicSquare,而输入偶数或者负数会返回false。

      1. isLegalMagicSquare()

思路:先利用filereader和BufferedReader读入txt中数据,读入后,首先需要判断读入的数据能否构成一个矩阵,根据实验手册,需要判断的三张错误分别为矩阵中某些数字不是正整数,行列数不相等、并非矩阵,不是以\t作为分隔符。对三种错误进行判断并输出返回false。当没有这些错误时,分别计算矩阵每一行、每一列、对角线的和是否相等来判断能否构成MagicSquare,若是并返回true。

过程:

先用\t分割

eachlline=temp1.split("\t");

1、判断是不是方阵

if(eachlline.length!=linenum)

                {

                    System.out.println(fileName+"NOT SQUARE");

                    return false;

2、有某些非正整数,同时对是否有非\t作判断

if (eachlline[i].contains("-")) {//存在负数

                        System.out.println(fileName + " EXIST NEGATIVE");

                        return false;

                    }

                    else if (eachlline[i].contains(".")) {//存在分数

                        System.out.println(fileName + " EXIST FLOAT");

                        return false;

                    }

                    else if(!eachlline[i].matches("[0-9]+")) {//存在非数字的字符,如果有非\t符分割会在这里提示

                        System.out.println(fileName + " NOT NUMBER,IT COULD CONTAIN ' ' OR OTHERS");

                        return false;

                    }

                    else if(Integer.parseInt(eachlline[i])==0) {//存在0

                        System.out.println(fileName + " EXIST ZERO");

                        return false;

                    }

                }

3、判断行列对角线的值是否相等

先存入二维数组,计算对角线值再与每行每列作比较

for(j=0;j<len1;j++)

        {

            s3=s3+SQUARE[j][j];

        }

        for(j=0;j<len1;j++)

        {

            for(m=0;m<len1;m++)

            {

                s1=s1+SQUARE[j][m];

            }

            if(s1!=s3)

            {

                return false;

            }

            s1=0;

        }

        for(j=0;j<len1;j++)

        {

            for(m=0;m<len1;m++)

            {

                s2=s2+SQUARE[m][j];

            }

            if(s2!=s3)

            {

                return false;

            }

            s2=0;

        }

        return true;

结果:

 

结果:12是,3不是方阵,4有负数,5不是方阵

      1. generateMagicSquare()

流程图:

 

思路:生成函数已给出,只需要增加部分功能:(1) 将产生的magic square写入文件\src\P1\txt\6.txt中;(2) 当输入的n不合法时(n为偶数、n为负数等),不要该函数抛出异常并非法退出,而是提示错误并“优雅的”退出——函数输出false结束。所以我们只需要在开始判断是否满足n的合法输入并且增加写入文件的操作。

过程:while (n <= 0 || n % 2 == 0) {//n不为正奇数数时输出false

            System.out.println("FALSE");

            n = sc.nextInt();

        }

判断输入是否是正奇数。

File file = new File("src/P1/txt/6.txt");

        PrintWriter output = new PrintWriter(file);

        for (i = 0; i < n; i++) {

            for (j = 0; j < n; j++)

                output.print(magic[i][j] + "\t");

            output.println();

        }

        output.close();

写入文件。

注:该函数是罗伯法,详见巧填幻方——罗伯法 - 知乎 (zhihu.com)

    1. Turtle Graphics

这次任务是为了实现一个绘图工具Trurtle Graphics,需要我们完成的任务为:画出一个正方形,计算正多边形内角,由正多边形内角得到边数,计算从一个点到另外一个点所需要转过的角度,给定一系列点计算每次转过的角度并返回在集合中,计算一系列点中的凸包,调用函数绘制图形,使用junit进行单元测试。

      1. Problem 1: Clone and import

首先打开实验手册提供的网站,从上面下载P2的包,并解压导入idea中。

本地仓库由链接了git的idea建立,即使用idea中vcs->创建git仓库,再由git的commit进行提交。

      1. Problem 3: Turtle graphics and drawSquare

重复前进转弯90即可:

for(int i=0;i<4;i++)

        {

            turtle.forward(sideLength);

            turtle.turn(90);

        }

      1. Problem 5: Drawing polygons

计算正多边形内角只需根据正多边形内角=(边数-2)/sides写出calculateRegularPolygonAngle (int sides)

然后画正多边形只需调用此函数即可:

public static void drawRegularPolygon(Turtle turtle, int sides, int sideLength) {

        //throw new RuntimeException("implement me!");

        double angle=calculateRegularPolygonAngle(sides);

        for (int i=0;i<sides;i++)

        {

            turtle.turn(180-angle);

            turtle.forward(sideLength);

        }

    }

      1. Problem 6: Calculating Bearings

计算前进方向的偏转角需要调用atan2函数得到弧度,然后调用toDegree转换成角度,考虑到只能顺时针转,需要给负值加360度。

public static double calculateBearingToPoint(double currentBearing, int currentX, int currentY,

                                                 int targetX, int targetY) {

        //throw new RuntimeException("implement me!");

        double x=targetX-currentX;

        double y=targetY-currentY;

        double theta=Math.atan2(y,x);

        theta=theta*180/Math.PI;

        double Bearing=90-theta-currentBearing;

        if(Bearing<0)

            return Bearing+360;

        return Bearing;

    }

      1. Problem 7: Convex Hulls

Gift wrapping algorithm:先找到最左下角的点加入集合,然后比较剩余点到此点的偏转角,找到偏转角最小的加入集合,当偏转角相同时,需要找到最长的一条边的点加入集合。

public static Set<Point> convexHull(Set<Point> points) {

        //throw new RuntimeException("implement me!");

        int index=0;

        ArrayList<Point> Convexlist=new ArrayList<Point>() ;

        ArrayList<Point> Oringin=new ArrayList<Point>() ;

        Oringin.addAll(points);

        int len=Oringin.size();

        if(len<4)

            return points;

        Point temp=Oringin.get(0);

        for(Point p:points)

        {

            if(p.x()<temp.x())

            {

                temp=p;

            }

            else if (p.x()==temp.x()&&p.y()<temp.y())

            {

                temp=p;

            }

        }

        int count=0;

        Convexlist.add(temp);

        Oringin.remove(temp);

        Point start=temp;

        Point pointfront=temp;

        do {

            if(count==1)

            {

                Oringin.add(start);

            }

            double tempangle=360;

            double tempdis=0;

            for(Point p1:Oringin)

            {

                double angleval=calculateBearingToPoint(0,(int)pointfront.x(),(int)pointfront.y(),(int)p1.x(),(int)p1.y());

                double disval=((int)pointfront.x()-(int)p1.x())*((int)pointfront.x()-(int)p1.x())+((int)pointfront.y()-(int)p1.y())*((int)pointfront.y()-(int)p1.y());

                if(tempangle>angleval)

                {

                    temp=p1;

                    tempangle=angleval;

                    tempdis=disval;

                }

                else if(tempangle==angleval&&tempdis<disval)

                {

                    temp=p1;

                    tempangle=angleval;

                    tempdis=disval;

                }

            }

            Convexlist.add(temp);

            Oringin.remove(temp);

            pointfront=temp;

            count++;

        }while(Convexlist.get(Convexlist.size()-1)!=start);

    Set<Point> result=new HashSet<Point>();

    result.addAll(Convexlist);

    return result;

    }

      1. Problem 8: Personal art

public static void drawPersonalArt(Turtle turtle) {

        //throw new RuntimeException("implement me!");

        drawRegularPolygon(turtle,17,40);//正十七边形

    }

      1. Submitting

       

  1.     2.       Social Network

本次任务要求实现Person和FriendshipGraph两个类,用FriendshipGraph来构建Person之间的关系来模拟社交网络,能够计算出每两个Person之间的最短路径。

  1.         2.      1.设计/实现FriendshipGraph类

思路:功能有1、创建一个邻接表(表示图)2、增加顶点和增加边3、计算距离

1、创建邻接表

public HashMap<Person,ArrayList<Person>> namelist=new HashMap<Person,ArrayList<Person>>();//存储每个人和他们的朋友

2、增加顶点和增加边

public void addVertex(Person p)//增加点

    {

        if(namelist.containsKey(p))

        {

            System.out.println(p.getname()+" has been used");

            System.exit(0);

        }

        else namelist.put(p,new ArrayList<Person>());

    }

public void addEdge(Person myname0,Person myname1)//增加边

    {

        if(!namelist.containsKey(myname0)) {

            System.out.println(myname0+"do not exist");

            System.exit(0);

        }

        else if(!namelist.containsKey(myname1)){

            System.out.println(myname1+"do not exist");

            System.exit(0);

        }

        namelist.get(myname0).add(myname1);

    }

3、计算距离

使用广度优先搜索,创建visited数组保存访问过的点,创建map二元组建立各个点到源点关系,创建queue1作为队列。

  1. 源点入队列,进入已visited数组,进入map,对应值为0.
  2. 每次取出队列顶点,将其未访问的好友进行入queue1和入map,改好友p的map对应值为队首对应值加一,如果遇到这个好友恰是终点返回这个好友的map值。
  3. 如果队空了还没有返回-1.

public int getDistance(Person myname0,Person myname1)

    {

        Queue<Person> queue1=new LinkedList<Person>();

        ArrayList<Person> visited=new ArrayList<Person>();

        if(myname0==myname1)return 0;

        queue1.offer(myname0);

        Person temp;

        Map<Person,Integer> map=new HashMap<>();

        map.put(myname0,0);

        int dis=0;

        while (!queue1.isEmpty())

        {

            temp=queue1.poll();

            dis=map.get(temp);

            for(Person p:namelist.get(temp))

            {

                if(!visited.contains(p))

                {

                    map.put(p,dis+1);

                    visited.add(p);

                    queue1.offer(p);

                    if(p==myname1)

                        return map.get(myname1);

                }

            }

        }

        return -1;

    }

结果:

 

      1. 设计/实现Person类

思路:Person类应该能记录人名,同时由于实验要求知道是否同名会报错,应该让Person有一个静态集合存人名。

过程:

1、建立一个集合存所有人

        if(allpeople==null)

        {

            allpeople=new HashSet<String>();

        }

        else if(allpeople.contains(myname))

        {

            System.out.println(myname+" has been used");

            System.exit(0);

        }

        allpeople.add(myname);

        this.myname=myname;

   2、建立返回人名的功能

    public String getname()

    {

        return myname;

}

3、建立判断是否已经存入该名字的功能(设计时想给friendshipgraph类使用,实际并未用上)

    public boolean exist(String name)

    {

        return allpeople.contains(name);

    }

}

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

原报告已有主体,这里仅修改一点。

public static void main(String arg[]){

       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));

//should print -1

    System.out.println("IF Ross = Rachel");

    ross=new Person("Rachel");

    }

}

      1. 设计/实现测试用例

思路:对addVertex ,addEdge ,getDistance三个功能进行测试。对于addVertex,设计test用例addVertextest,在里面建立四个Person对象全部执行addVertex,然后判断allpeople里面是都有这些对象即可。对于addEdge,只需设计test用例addEdgetest,在里面同样建立四个Person对象,执行addVertex后,执行addEdge然后判断他们的朋友中是否包含彼此即可。对于getDistance,只需设计test用例getDistancetest,在里面建立五个Person对象,执行addVertex后,执行addEdge后,使得三种距离等价类都存在,即距离为-1,距离为0,距离为正整数。

过程

  1. addVertextest:

public void addVertextest() {

        Person zhao = new Person("zhao");

        Person qian = new Person("qian");

        Person sun = new Person("sun");

        Person li = new Person("li");

        G.addVertex(zhao);

        G.addVertex(qian);

        G.addVertex(sun);

        G.addVertex(li);

        assertTrue(G.namelist.containsKey(zhao));

        assertTrue(G.namelist.containsKey(qian));

        assertTrue(G.namelist.containsKey(sun));

        assertTrue(G.namelist.containsKey(li));

}

2、addEdgetest:

public void addEdgetest() {

        Person zhao = new Person("zhao");

        Person qian = new Person("qian");

        Person sun = new Person("sun");

        Person li = new Person("li");

        G.addVertex(zhao);

        G.addVertex(qian);

        G.addVertex(sun);

        G.addVertex(li);

        G.addEdge(zhao, qian);

        G.addEdge(sun, li);

        G.addEdge(qian, zhao);

        G.addEdge(li, sun);

        G.addEdge(zhao, li);

        G.addEdge(li, zhao);

        assertTrue(G.namelist.get(zhao).contains(qian));

        assertTrue(G.namelist.get(zhao).contains(li));

        assertTrue(G.namelist.get(qian).contains(zhao));

        assertTrue(G.namelist.get(sun).contains(li));

        assertTrue(G.namelist.get(li).contains(sun));

        assertTrue(G.namelist.get(li).contains(zhao));

        assertTrue(G.namelist.get(sun).contains(li));

        assertTrue(!G.namelist.get(zhao).contains(sun));

}

3、getDistancetes

public void getDistancetest()

    {

        Person zhao = new Person("zhao");

        Person qian = new Person("qian");

        Person sun = new Person("sun");

        Person li = new Person("li");

        Person zhou=new Person("zhou");

        G.addVertex(zhao);

        G.addVertex(qian);

        G.addVertex(sun);

        G.addVertex(li);

        G.addVertex(zhou);

        G.addEdge(zhao, qian);

        G.addEdge(sun, li);

        G.addEdge(qian, zhao);

        G.addEdge(li, sun);

        G.addEdge(zhao, li);

        G.addEdge(li, zhao);

        int zero=G.getDistance(zhao,zhao);

        int neone=G.getDistance(zhao,zhou);

        int a=G.getDistance(zhao,li);

        int b=G.getDistance(zhao,qian);

        int c=G.getDistance(zhao,sun);

        int d=G.getDistance(qian,li);

        int e=G.getDistance(sun,li);

        int f=G.getDistance(qian,sun);

        assertEquals(0,zero);

        assertEquals(-1,neone);

        assertEquals(1,a);

        assertEquals(1,b);

        assertEquals(1,e);

        assertEquals(2,d);

        assertEquals(2,c);

        assertEquals(3,f);

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值