专栏名称: 养码场
养码场,一个技术人职场社交平台。 现有“养码人”80000+,覆盖JAVA/PHP/iOS/测试/运维等领域。80%级别在P6及以上,含P9技术大咖30人,技术总监和CTO 500余人。
目录
相关文章推荐
钱江晚报  ·  “我举报我自己!”网友:后怕 ·  11 小时前  
算法爱好者  ·  他借助 ChatGPT 杀疯了!做了 3 ... ·  13 小时前  
钱江晚报  ·  巨头宣布:永不合作! ·  2 天前  
51好读  ›  专栏  ›  养码场

程序员用代码告诉你,千万别出门!

养码场  · 公众号  ·  · 2020-02-08 16:32

正文

前些天,一个视频火了起来。


事情是这样的,B 站 UP 主 @ele实验室,用了一夜的时间,写了一个简单的疫情传播仿真程序,告诉大家在家待着的重要性,视频如下:

点击查看视频

来自B站up主“Ele实验室”,版权属于原作者


现在,作者已经将代码开源到 GitHub 上,场主特此 download 下来分享给大家。
GitHub 地址如下:
https://github.com/KikiLetGo/VirusBroadcast

此后,有人解析了VirusBroadcast的程序代码,下面我们就来看看它是如何一步步实现的吧!

这个程序主要利用“高斯分布”算法,简单的模拟病毒传播的场景。它由以下程序片段构成

1、病毒对象

2、床位【隔离对象】

3、主要参数【初始状态】,假设没有隔离,潜伏期为一天

public class Constants {    public static int ORIGINAL_COUNT=50;//初始感染数量    public static float BROAD_RATE = 0.8f;//传播率    public static float SHADOW_TIME = 1;//潜伏时间    public static int HOSPITAL_RECEIVE_TIME=10;//医院收治响应时间    public static int BED_COUNT=0;//医院床位    public static float u=0.99f;//流动意向平均值}

4、医院对象,随机分布,产生床位

public class Hospital {    private int x=800;    private int y=110;
private int width;    private int height=606; public int getWidth() { return width;    } public int getHeight() { return height; }
public int getX() { return x; }
public int getY() { return y; }
private static Hospital hospital = new Hospital(); public static Hospital getInstance(){ return hospital; } private Point point = new Point(800,100); private List beds = new ArrayList<>();
private Hospital() { if(Constants.BED_COUNT==0){ width=0; height=0; } int column = Constants.BED_COUNT/100;        width = column*6;        for(int i=0;i for(int j=10;j<=610;j+=6){ Bed bed = new Bed(point.getX()+i*6,point.getY()+j);                beds.add(bed);            } } }
public Bed pickBed(){ for(Bed bed:beds){ if(bed.isEmpty()){ return bed; } } return null; }

5、流动目的性

public class MoveTarget {    private int x;    private int y;    private boolean arrived=false;
public MoveTarget(int x, int y) { this.x = x; this.y = y; }
public int getX() { return x; }
public void setX(int x) { this.x = x; }
public int getY() { return y; }
public void setY(int y) { this.y = y; }
public boolean isArrived() { return arrived; }
public void setArrived(boolean arrived) { this.arrived = arrived; }}

6、人员【流动及感染】

public




    
 class Person {    private City city;    private int x;    private int y;    private MoveTarget moveTarget;    int sig=1;    double targetXU;    double targetYU;    double targetSig=50;    public interface State{        int NORMAL = 0;        int SUSPECTED = NORMAL+1;        int SHADOW = SUSPECTED+1;        int CONFIRMED = SHADOW+1;        int FREEZE = CONFIRMED+1;        int CURED = FREEZE+1;    }
public Person(City city, int x, int y) { this.city = city; this.x = x; this.y = y; targetXU = 100*new Random().nextGaussian()+x; targetYU = 100*new Random().nextGaussian()+y;
} public boolean wantMove(){ double value = sig*new Random().nextGaussian()+Constants.u; return value>0; }
private int state=State.NORMAL;
public int getState() { return state; }
public void setState(int state) { this.state = state; }
public int getX() { return x; }
public void setX(int x) { this.x = x; }
public int getY() { return y; }
public void setY(int y) { this.y = y; } int infectedTime=0; int confirmedTime=0; public boolean isInfected(){ return state>=State.SHADOW; } public void beInfected(){ state = State.SHADOW; infectedTime=MyPanel.worldTime; }
public double distance(Person person){ return Math.sqrt(Math.pow(x-person.getX(),2)+Math.pow(y-person.getY(),2)); }
private void freezy(){ state = State.FREEZE; } private void moveTo(int x,int y){ this.x+=x; this.y+=y; } private void action(){ if(state==State.FREEZE){ return; } if(!wantMove()){ return; } if(moveTarget==null||moveTarget.isArrived()){
double targetX = targetSig*new Random().nextGaussian()+targetXU; double targetY = targetSig*new Random().nextGaussian()+targetYU; moveTarget = new MoveTarget((int)targetX,(int)targetY);
}

int dX = moveTarget.getX()-x; int dY = moveTarget.getY()-y; double length=Math.sqrt(Math.pow(dX,2)+Math.pow(dY,2));
if(length<1){ moveTarget.setArrived(true); return; } int udX = (int) (dX/length); if(udX==0&&dX!=0){ if(dX>0){ udX=1; }else{ udX=-1; } } int udY = (int) (dY/length); if(udY==0&&udY!=0){ if(dY>0){ udY=1; }else{ udY=-1; } }
if(x>700){ moveTarget=null; if(udX>0){ udX=-udX; } }        moveTo(udX,udY);

}
private float SAFE_DIST = 2f;
public void update(){        if(state>=State.FREEZE){ return; } if(state==State.CONFIRMED&&MyPanel.worldTime-confirmedTime>=Constants.HOSPITAL_RECEIVE_TIME){ Bed bed = Hospital.getInstance().pickBed(); if(bed==null){ System.out.println("隔离区没有空床位"); }else{ state=State.FREEZE; x=bed.getX(); y=bed.getY(); bed.setEmpty(false); } } if(MyPanel.worldTime-infectedTime>Constants.SHADOW_TIME&&state==State.SHADOW){ state=State.CONFIRMED; confirmedTime = MyPanel.worldTime; }
action();
List people = PersonPool.getInstance().personList; if(state>=State.SHADOW){ return; } for(Person person:people){ if(person.getState()== State.NORMAL){ continue; } float random = new Random().nextFloat(); if(random this.beInfected(); } } }}

7、汇总人数

public class PersonPool {    private static PersonPool personPool = new PersonPool();    public static PersonPool getInstance(){        return personPool;    }
List personList = new ArrayList();
public List getPersonList() { return personList; }
private PersonPool() { City city = new City(400,400); for (int i = 0; i < 5000 ; i++) { Random random = new Random(); int x = (int) (100 * random.nextGaussian() + city.getCenterX()); int y = (int) (100 * random.nextGaussian() + city.getCenterY()); if(x>700){ x=700; } Person person = new Person(city,x,y); personList.add(person); } }}

8、分布点

9、显示面板,设置色块【红色:感染   黄色:潜伏  绿色:安全】

public class MyPanel extends JPanel implements Runnable {   private int pIndex=0;    public MyPanel() {        this.setBackground(new Color(0x444444));    }
@Override public void paint(Graphics arg0) { super.paint(arg0); //draw border arg0.setColor(new Color(0x00ff00)); arg0.drawRect(Hospital.getInstance().getX(),Hospital.getInstance().getY(), Hospital.getInstance().getWidth(),Hospital.getInstance().getHeight());        List people = PersonPool.getInstance().getPersonList(); if(people==null){ return; } people.get(pIndex).update(); for(Person person:people){
switch (person.getState()){ case Person.State.NORMAL:{ arg0.setColor(new Color(0xdddddd));
}break; case Person.State.SHADOW:{ arg0.setColor(new Color(0xffee00));
}break; case Person.State.CONFIRMED: case Person.State.FREEZE:{ arg0.setColor(new Color(0xff0000));
}break; } person.update(); arg0.fillOval(person.getX(), person.getY(), 3, 3);
} pIndex++; if(pIndex>=people.size()){ pIndex=0; } }
public static int worldTime=0; @Override public void run() { while (true) {
this.repaint();
try { Thread.sleep(100






请到「今天看啥」查看全文