CS61B srping 2018 project00-NBody https://sp18.datastructur.es/

Getting the Skeleton Files ,网站上应该有仓库地址,这个也行,https://gitee.com/heqilaoge/skeleton-sp18。

拉下来找到proj0 ,就能开始作业。可以不使用IDE。这个作业是个 快速学习java基本语法和知识的教程,也可以快速重温java基础知识和语法。。。
后面内容变多,又有点语焉不详,为的就是让你自己摸索。。。

The Planet Class and Its Constructor

创建Planet类

public class Planet {
    public double xxPos;
    public double yyPos;
    public double xxVel;
    public double yyVel;
    public double mass;
    public String imgFileName;

    public Planet(double xP, double yP, double xV,
            double yV, double m, String img) {
        xxPos = xP;
        yyPos = yP;
        xxVel = xV;
        yyVel = yV;
        mass = m;
        imgFileName = img;
    }

    public Planet(Planet p) {
        xxPos = p.xxPos;
        yyPos = p.yyPos;
        xxVel = p.xxVel;
        yyVel = p.yyVel;
        mass = p.mass;
        imgFileName = p.imgFileName;
    }
}

通过 javac Planet.java TestPlanetConstructor.java 和 java TestPlanetConstructor来测试。(这些文件在 proj0的skeleton里边都有)

规则介绍


继续写 Planet 类

calcDistance 方法 计算两个 星体之间的距离

    public double calcDistance(Planet p) {
        double dx = p.xxPos - xxPos;
        double dy = p.yyPos - yyPos;
        return Math.sqrt(dx * dx + dy * dy);
    }

javac Planet.java TestCalcDistance.java 和java TestCalcDistance测试

calcForceExertedBy 计算星体之间的力

   public double calcForceExertedBy (Planet p){
        double G= 6.67*Math.pow(10, -11);
        double r = this.calcDistance(p);
        double force =(G*this.mass*p.mass)/(r*r);
        return force;

   }

plaintext javac Planet.java TestCalcForceExertedBy.java java TestCalcForceExertedBy 测试
calcForceExertedByX and calcForceExertedByY 测试x和y方向上的分力

   public double calcForceExertedByX (Planet p){
        double r = this.calcDistance(p);
        double force =this.calcForceExertedBy(p);
        double dx=p.xxPos-this.xxPos;
        double fx=force*dx/r;
        return fx;
   }

   public double calcForceExertedByY(Planet p){
    double r = this.calcDistance(p);
    double force =this.calcForceExertedBy(p);
    double dy=p.yyPos-this.yyPos;
    double fx=force*dy/r;
    return fx;
   }

plaintext javac Planet.java TestCalcForceExertedByXY.java java TestCalcForceExertedByXY 测试

calcNetForceExertedByX and calcNetForceExertedByY 计算某一方向上的合力;

Planet[] allPlanets = {samh, rocinante, aegir};
samh.calcNetForceExertedByX(allPlanets);
samh.calcNetForceExertedByY(allPlanets);

接收一个数组,计算数组内部(除了本身)所有星体对他的合力

  public double calcNetForceExertedByX(Planet[] allPlanets) {
        double fx = 0;
        for (Planet p : allPlanets) {
            if (this.equals(p)) {
                continue;

            }
            fx += this.calcForceExertedByX(p);
        }
        return fx;
    }

    public double calcNetForceExertedByY(Planet[] allPlanets) {
        double fy = 0;
        for (Planet p : allPlanets) {
            if (this.equals(p)) {
                continue;

            }
            fy += this.calcForceExertedByY(p);
        }
        return fy;
    }

javac Planet.java TestCalcNetForceExertedByXY.java java TestCalcNetForceExertedByXY测试

update方法,
比如samh.update(0.005, 10, 3) ,给samh施加一个x方向10牛,y方向3牛,0.005秒的力,计算其加速度,计算速度,计算位置。


   public void update(double dt, double fX, double fY) {
        double ax = fX / this.mass;
        double ay = fY / this.mass;
        double vx = this.xxVel + ax * dt;
        double vy = this.yyVel + ay * dt;
        double px = this.xxPos + vx * dt;
        double py = this.yyPos + vy * dt;
        this.xxVel = vx;
        this.yyVel = vy;
        this.xxPos = px;
        this.yyPos = py;
    }

javac Planet.java TestUpdate.java java TestUpdate测试


NBody.java

这个类没有构造函数,就是用来模拟运行 星球运行的,
readRadius方法,用来读取data/planets中的半径数据。examples/BasicInDemo有对In的介绍

public class NBody {
    public static double readRadius(String planetsTxtPath) {
        In in = new In(planetsTxtPath);
        int count = in.readInt();
        double radius = in.readDouble();
        return radius;
    }

    public static void main(String[] args) {

    }
}

ReadPlanets方法 就是用In方法把planets里边的 星球数据读出来,然后放到一个数组里。

  public static Planet[] readPlanets(String planetsTxtPath) {

        int countOfPlanets = 5;

        Planet[] planets = new Planet[5];
        In in = new In(planetsTxtPath);
        in.readInt();
        in.readDouble();

        while (countOfPlanets != 0) {
            double xxPos = in.readDouble();
            double yyPos = in.readDouble();
            double xxVel = in.readDouble();
            double yyVel = in.readDouble();
            double mass = in.readDouble();
            String planetName = in.readString();
            Planet newP = new Planet(xxPos, yyPos, xxVel, yyVel, mass, planetName);
            countOfPlanets -= 1;
            planets[countOfPlanets] = newP;
        }
        return planets;

    }

javac Planet.java NBody.java TestReadPlanets.java java TestReadPlanets测试


Drawing the Initial Universe State 分四步骤把初始“宇宙”状态画出来,因为都在main中进行,所以不会有对应测试。

        StdDraw.picture(xxPos, yyPos, "images/" + imgFileName);
    }

 public static void main(String[] args) {
        double T = Double.parseDouble(args[0]);
        double dt = Double.parseDouble(args[1]);
        String filename = args[2];
        double radius = NBody.readRadius(filename);
        Planet[] planets = NBody.readPlanets(filename);

        // draw bg
        StdDraw.setScale(-radius , radius);
        StdDraw.clear();
        StdDraw.picture(0, 0, "images/starfield.jpg");
        for (Planet p : planets) {
            p.draw();
        }
    }

把这四步做完,输入`javac NBody.java

java NBody 157788000.0 25000.0 data/planets.txt` 就应该能看见5个静止的星球的画面。到这里已经,注意!不一定准确

让星球动起来 Creating an Animation

要把时间打撒成单位时间,然后一段时间位移一点,大概就是这意思。


public class NBody {
    public static double readRadius(String planetsTxtPath) {
        In in = new In(planetsTxtPath);
        int count = in.readInt();
        double radius = in.readDouble();
        return radius;
    }

    public static Planet[] readPlanets(String planetsTxtPath) {

        int countOfPlanets = 5;

        Planet[] planets = new Planet[5];
        In in = new In(planetsTxtPath);
        in.readInt();
        in.readDouble();

        while (countOfPlanets != 0) {
            double xxPos = in.readDouble();
            double yyPos = in.readDouble();
            double xxVel = in.readDouble();
            double yyVel = in.readDouble();
            double mass = in.readDouble();
            String planetName = in.readString();
            Planet newP = new Planet(xxPos, yyPos, xxVel, yyVel, mass, planetName);
            countOfPlanets -= 1;
            planets[countOfPlanets] = newP;
        }
        return planets;

    }

    public static void main(String[] args) {
        StdDraw.enableDoubleBuffering();

        double T = Double.parseDouble(args[0]);
        double dt = Double.parseDouble(args[1]);
        String filename = args[2];
        double radius = NBody.readRadius(filename);
        Planet[] planets = NBody.readPlanets(filename);

        // draw bg
        StdDraw.setScale(-radius, radius);
        StdDraw.clear();
        StdDraw.picture(0, 0, "images/starfield.jpg");
        for (Planet p : planets) {
            p.draw();
        }

        double timeVariable = 0;

        while (timeVariable < T) {

            timeVariable += dt;
            double[] xForces = new double[5];
            double[] yForces = new double[5];
            for (int i = 0; i < 5; i++) {
                xForces[i] = planets[i].calcNetForceExertedByX(planets);
                yForces[i] = planets[i].calcNetForceExertedByY(planets);

            }
            StdDraw.picture(0, 0, "images/starfield.jpg");
            for (int i = 0; i < 5; i++) {
                planets[i].update(dt, xForces[i], yForces[i]);

                planets[i].draw();

            }
            StdDraw.show();
            StdDraw.pause(10);

        }
        StdOut.printf("%d\n", planets.length);
        StdOut.printf("%.2e\n", radius);
        for (int i = 0; i < planets.length; i++) {
            StdOut.printf("%11.4e %11.4e %11.4e %11.4e %11.4e %12s\n",
                    planets[i].xxPos, planets[i].yyPos, planets[i].xxVel,
                    planets[i].yyVel, planets[i].mass, planets[i].imgFileName);
        }
    }

}

提醒,不合适的绘制背景和 show 、pause方法的调用会导致画面闪烁,动画并不如预期般顺滑。
最后要 打印出更新后的planets数据,网站已经提供了解决
javac NBody.java java NBody 157788000.0 25000.0 data/planets.txt来测试

后面的内容,难度很大,我不再尝试了。

posted @ 2024-12-03 14:36  刘老六  阅读(44)  评论(0)    收藏  举报