这段时间都在寝室里自学Java,就想自己写个小程序玩一玩。同时,我也是个三体迷,就想着能不能用学的Java来模拟一下三体运动。这个程序算是我正式写模拟三体运动前的一个尝试。

一、程序分析

首先来百度一番查一下太阳、水星、金星和地球的各种参数(非精确):

1.太阳:

质量:kg

2.水星:

质量:kg

轨道半径:m

公转速度:m/s

3.金星

质量:kg

轨道半径:m

公转速度:m/s

4.地球

质量:kg

轨道半径:m

公转速度:m/s

模拟的方式,我采用了万有引力公式和牛顿运动定律的微分形式来模拟。这种方法误差和计算量都比较大,但对这种粗略的模拟,还是可以的。首先用万有引力公式计算出各个行星受到的太阳引力(行星之间的引力就忽略不计了,没必要,当然加上也是可以的),进而计算出每个行星的加速度。用一个变量time来表示时间微元,用每个行星当前的速度vector乘以time就得到行星位移的微元,然后再将行星速度vector更新为vector+行星的加速度乘以时间,再将行星的位置画出来。将这些过程写在一个循环体里,就可宜不断更新行星的位置了。

这里面用到的vector,加速度等都是向量,Java并没有处理向量运算的类,需要自己写一个自定义类Vector2D。每个行星也都定义为自定义类Actor类的子类。绘制行星等在Univers类中。程序入口为Main类。

包结构

  1. main包:Main类
  2. vector2D包:Vector2D类
  3. actor包:Actor类
  4. univers包:Univers类

二、代码编写

1.Vector2D类

package Vector2D;
import java.awt.Point;public class Vector2D {public static Vector2D baseX = new Vector2D(1, 0);    //x方向的单位向量public static Vector2D baseY = new Vector2D(0, 1);    //y方向的单位向量private double x;            //向量的x坐标private double y;           //向量的y坐标private double model;       //向量的模private float theta;      //向量的辐角public Vector2D(double x,double y) {this.x = x;this.y = y;this.model = Math.sqrt(this.x*this.x+this.y*this.y);this.theta = (float) Math.atan(y/x);}public Vector2D(Point p1,Point p2) {x = p2.getX() - p1.getX();      y = p2.getY() - p1.getY();model = Math.sqrt(x*x+y*y);theta = (float) Math.atan(y/x);}public double getX() {return x;}public double getY() {return y;}public double getModel() {return model;}public double getTheta() {return theta;}//向量加法public Vector2D plus(Vector2D vector2D_2) {return new Vector2D(x+vector2D_2.getX(), y+vector2D_2.getY());}//向量减法public Vector2D sub(Vector2D vector2D_2) {return new Vector2D(x-vector2D_2.getX(),y-vector2D_2.getY());}//求相反向量public Vector2D inverse() {return new Vector2D(-x,-y);}//数乘public Vector2D multi(double r) {return new Vector2D(r*x, r*y);}//向量点积public double dot(Vector2D vector2D) {return vector2D.x*this.x+vector2D.y*this.y;}//获得单位化向量public Vector2D normal() {return new Vector2D(x/model, y/model);}//求垂直向量public Vector2D perp() {return new Vector2D(-y,x);}//向量旋转public Vector2D roatation(double theta) {double temp = x*Math.cos(theta)-y*Math.sin(theta);double newY = x*Math.sin(theta)+y*Math.cos(theta);return new Vector2D(temp, newY);}public String toString() {return String.format("("+x+","+y+")");}
}

2.Actor类

package actor;import java.awt.*;
import Vector2D.Vector2D;public class Actor {public double mass;                //质量public Point position;             //点位置public Vector2D acceleration;       //加速度public Vector2D vector;               //速度public Vector2D displacement;        //位移public Vector2D force;                //受力public Actor(double mass,Point position) {this.mass = mass;this.position = position;}public void drawActor(Graphics g,int height,int width) {g.fillOval(position.x-width/2, position.y-height/2,height, width);}
}

3.Univers类

package univers;import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.datatransfer.SystemFlavorMap;
import javax.swing.JPanel;
import Vector2D.Vector2D;
import actor.Actor;public class Univers extends JPanel implements Runnable{private static double G = 6.67E-11;                        //万有引力常数private Point[] star = new Point[500];                     //背景的星星private Point origSun = new Point(319,239);                //太阳的位置private Point origEarth = new Point(469,239);              //地球的初始位置private Point origVenus = new Point(429,239);              //金星的初始位置private Point origMercury = new Point(378,239);            //水星的初始位置private Actor sun = new Actor(2E30,origSun);               //太阳private Actor earth = new Actor(6E24,origEarth);           //地球private Actor venus = new Actor(4.9E24, origVenus);        //金星private Actor mercury = new Actor(3.3E23, origMercury);    //水星private Vector2D earthPosition = new Vector2D(origSun,origEarth);     //地球的位置向量private Vector2D venusPosition = new Vector2D(origSun, origVenus);    //金星的位置向量private Vector2D mercuryPosition = new Vector2D(origSun, origMercury);//水星的位置向量        private Vector2D vectorEarth = new Vector2D(0, 3E4);        //地球当前速度private Vector2D vectorVenus = new Vector2D(0, -3.5E4);     //金星当前速度private Vector2D vectorMercury = new Vector2D(0,4.8E4);     //水星当前速度private long time = 1;public Univers2() {for(int i=0;i<500;i++) {int x=(int) (Math.random()*640);int y=(int) (Math.random()*480);star[i] = new Point(x,y);}}private void calculate() {mercuryCalculate();venusCalculate();earthCalculate();}//地球轨道的计算private void earthCalculate() {Vector2D delta_displacement = vectorEarth.multi(time*1e-9); //乘1e9是对长度缩放earthPosition = earthPosition.plus(delta_displacement);double current_acceleration = G*2.0e30/(earthPosition.getModel()*earthPosition.getModel()*1e18);earth.acceleration = earthPosition.normal().multi(-current_acceleration);vectorEarth = vectorEarth.plus(earth.acceleration.multi(time));}//金星轨道的计算private void venusCalculate() {Vector2D delta_displacement = vectorVenus.multi(time*1e-9); //乘1e9是对长度缩放venusPosition = venusPosition.plus(delta_displacement);double current_acceleration = G*2.0e30/(venusPosition.getModel()*venusPosition.getModel()*1e18);venus.acceleration = venusPosition.normal().multi(-current_acceleration);vectorVenus = vectorVenus.plus(venus.acceleration.multi(time));}//水星轨道的计算private void mercuryCalculate() {Vector2D delta_displacement = vectorMercury.multi(time*1e-9); //乘1e9是对长度缩放mercuryPosition = mercuryPosition.plus(delta_displacement);double current_acceleration = G*2.0e30/(mercuryPosition.getModel()*mercuryPosition.getModel()*1e18);mercury.acceleration = mercuryPosition.normal().multi(-current_acceleration);vectorMercury = vectorMercury.plus(mercury.acceleration.multi(time));}//绘制所有行星@Overridepublic void paint(Graphics g) {// TODO 自动生成的方法存根super.paint(g);for(int i=0;i<500;i++) {                //让背景闪烁g.setColor(Color.white);if(Math.random()>0.5) {g.setColor(Color.gray);}g.fillOval(star[i].x,star[i].y,2,2);}g.setColor(Color.red);sun.drawActor(g,30,30);g.setColor(Color.gray);g.fillOval((int)(origSun.x+mercuryPosition.getX()-1),(int)(origSun.y-mercuryPosition.getY()-1), 6, 6);g.setColor(Color.yellow);g.fillOval((int)(origSun.x+venusPosition.getX()-1),(int)(origSun.y-venusPosition.getY()-1), 6,6);g.setColor(Color.blue);g.fillOval((int)(origSun.x+earthPosition.getX()-1), (int)(origSun.y-earthPosition.getY()-1),6, 6);}@Overridepublic void run() {// TODO 自动生成的方法存根setBackground(Color.black);while(true) {repaint();calculate();time += 100;        //数字可以随便填try {Thread.sleep(1);} catch (InterruptedException e) {// TODO 自动生成的 catch 块e.printStackTrace();}}}
}

4.Main类

package main;import java.awt.Container;
import javax.swing.JFrame;
import univers.Univers;
import univers.Univers;public class Main extends JFrame{private Univers univers = new Univers();private Container container = getContentPane();private Thread renderThread = new Thread(univers);public Main() {setTitle("行星运动");setSize(640,480);setDefaultCloseOperation(EXIT_ON_CLOSE);container.add(univers);setVisible(true);renderThread.start();}public static void main(String[] args) {// TODO 自动生成的方法存根new Main();}}

三、运行结果

灰色的为水星,黄色的为金星,蓝色的为地球,红色是太阳。

        

下篇文章来写三体运动的模拟。自学Java会遇到很多问题,如有问题还请多多指正。

用Java模拟行星的运动相关推荐

  1. java 模拟时钟_java模拟时钟

    本次课程设计采用时间片轮转调度算法来实现模拟进程调度任务的执行过 程. 用 Java 模拟进程调度过程,可以方便地将运行结果直观地表示出来.Java 语言 独有的多...... 本次课程设计采用时间片 ...

  2. 233网校java_java辅导:使用java模拟登陆考试大

    java辅导:使用java模拟登陆考试大 2009年1月5日来源:233网校网校课程 在线题库评论 分享到 public static void loginexamda() { URL url = n ...

  3. JAVA同时输入用户名和密码_用java模拟设计一个简单的“用户注册”程序。当用户输入用户名和密码时,单击“注...

    用java模拟设计一个简单的"用户注册"程序.当用户输入用户名和密码时,单击"注 2020 - 9 - 26 TAG : 所有功能均已实现,如有不满意的地方我再修改imp ...

  4. 用Java模拟multipart形式的Http Post请求

    本例通过java模拟了Http的request请求,请求格式为multipart,实现了向服务器同时传递json数据和图片数据. 1 import java.io.ByteArrayOutputStr ...

  5. java 模拟grep_java模拟linux命令grep

    java模拟linux命令grep. 在网上看到matlab模拟linux的grep命令,就想到用java也来模拟下linux命令grep, 算法非常简单,,这里直接上代码: /** * 模拟Unix ...

  6. java模拟单链表环形链表解决约瑟夫问题

    java模拟环形链表解决约瑟夫问题 此文是观看尚硅谷韩老师的数据结构与算法学习视频整理的笔记 约瑟夫问题描述 约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题.在计算机编程的算 ...

  7. java模拟连接超时_Java:使用Toxiproxy模拟各种连接问题

    java模拟连接超时 用Toxiproxy和Java的HttpURLConnection模拟各种连接问题,以查看产生了什么样的错误:连接超时vs.读取超时vs.连接被拒绝-. 结果: 系统:openj ...

  8. curl命令java_上curl java 模拟http请求

    最近,我的项目要求java模拟http请求,获得dns解决 tcp处理过的信息特定的连接. java api提供urlConnection apache提供的httpClient都不能胜任该需求,二次 ...

  9. java 模拟qq源码

    java 模拟qq源码: http://files.cnblogs.com/files/hujunzheng/QQ--hjzgg.zip 转载于:https://www.cnblogs.com/huj ...

最新文章

  1. 参加完Python培训后有哪些就业方向
  2. 20172317 2018-2019-1 《程序设计与数据结构》第6周学习总结
  3. 不同版本Eclipse对JDK版本要求
  4. python3精要(40)-数组与矩阵
  5. IntelliJ IDEA快捷键学习
  6. php get 分页,PHP_codeigniter实现get分页的方法,本文实例讲述了codeigniter实现ge - phpStudy...
  7. Code-First Development with Entity Framework 4
  8. 在线html链接提取工具
  9. C Tricks(十四)—— 余数
  10. 【解题报告】SRM-08
  11. 程序员必备算法——算法相关链接总结
  12. 超声波测距(含报警功能)
  13. 电脑宝马,大量宝马车电脑通病故障检修方法
  14. GWAS生物学相关名词解释
  15. 百度推广怎么调整计算机优先,百度推广oCPC的优化技巧是什么?oCPC常见问题汇总...
  16. Domain Adaptation for Object Detection using SE Adaptors and Center Loss 论文翻译
  17. 我的世界java防火墙_我的世界Java版更新:烟花和自由堡垒!
  18. acr38u PHP调用,ACR38智能卡读写器驱动下载
  19. 检测 Linux VPS 是 Xen、OpenVZ 还是 KVM 架构的方法
  20. ASP.Net中实现Ajax的几种实现方法之AjaxPro的使用(一) [AjaxPro.AjaxMethod]

热门文章

  1. 淘宝难做,不会英语也可以做亚马逊
  2. Java float转int
  3. nginx 报 accept4() failed (24: Too many open files)
  4. vue动态路由传参的几种方式
  5. sql查询所有课程成绩大于80的学生的姓名
  6. ASP.NET Core(.NET Core)中使用HtmlDecode和HtmlEncode方法
  7. 中国建设银行网上支付接口以及自动对账
  8. android游戏开发 深度解析利用位图绘制rpg地图
  9. Skype -申请解除封禁帐号
  10. http api设计规范