谣言传播模拟

受到该项目启发,病毒传播和谣言传播有些相似,就修改了该项目的代码,变成了谣言传播的程序(参数设置都没有科学性)
项目地址:https://github.com/alastbing/VirusBroadcastController

main.java

package rumour;

import javax.swing.*;
import java.util.List;
import java.util.Random;

public class Main {
	public static void main(String[] args) {
		initPanel();
		initInfected();
	}

	// 初始化画布
	private static void initPanel() {
		MyPanel p = new MyPanel();
		Thread panelThread = new Thread(p);
		JFrame frame = new JFrame();
		frame.add(p);
		frame.setSize(Parameter.CITY_WIDTH, Parameter.CITY_HEIGHT);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
		frame.setTitle("谣言传播模拟");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		panelThread.start();// 开启画布线程
	}

	// 产生谣言
	private static void initInfected() {
		List<Person> people = PersonPool.getInstance().getPersonList();// 获取所有的市民
		Person person;
		person = people.get(new Random().nextInt(people.size() - 1));// 随机挑选一个市民
		person.beInfected();// 让这个市民成为谣言产生者
	}

}

MyPanel.java

package rumour;

import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class MyPanel extends JPanel implements Runnable {

	public MyPanel() {
		super();
		this.setBackground(new Color(0x444444));
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		// 绘制代表人类的圆点
		List<Person> people = PersonPool.getInstance().getPersonList();
		if (people == null) {
			return;
		}
		for (Person person : people) {

			switch (person.getState()) {
			case Person.State.NORMAL: {
				// 正常人
				// 政府
				if (person.getRank() == 2) {
					g.setColor(new Color(0xe22018));
					break;
				}
				// 媒体社区
				else if (person.getRank() == 1) {
					g.setColor(new Color(0x21a3f1));
					break;
				}
				// 普通人
				else {
					g.setColor(new Color(0xdddddd));
					break;
				}
				// System.out.print(person.getRank());

			}
			case Person.State.OK: {
				// 辟谣者
				g.setColor(new Color(0x80c342));
				break;
			}
			case Person.State.SHADOW: {
				// 传谣者
				g.setColor(new Color(0xffee00));
				break;
			}
			}

			person.update();// 对各种状态的市民进行不同的处理
			g.fillOval(person.getX(), person.getY(), 4, 4);

		}

		int captionStartOffsetX = 700;
		int captionStartOffsetY = 40;
		int captionSize = 24;

		// 显示数据信息
		g.setColor(Color.WHITE);
		g.drawString("城市总人数:" + PersonPool.getInstance().getPeopleSize(-1), captionStartOffsetX, captionStartOffsetY);
		g.setColor(new Color(0xdddddd));
		g.drawString("正常者人数:" + PersonPool.getInstance().getPeopleSize(Person.State.NORMAL), captionStartOffsetX,
				captionStartOffsetY + captionSize);
		g.setColor(new Color(0xffee00));
		g.drawString("传谣者人数:" + PersonPool.getInstance().getPeopleSize(Person.State.SHADOW), captionStartOffsetX,
				captionStartOffsetY + 2 * captionSize);
		g.setColor(new Color(0x80c342));
		g.drawString("辟谣者人数:" + PersonPool.getInstance().getPeopleSize(Person.State.OK), captionStartOffsetX,
				captionStartOffsetY + 3 * captionSize);
		g.setColor(new Color(0xffffff));
		g.drawString("世界时间(天):" + (int) (worldTime / 10.0), captionStartOffsetX, captionStartOffsetY + 8 * captionSize);

	}

	public static int worldTime = 0;// 世界时间
	public Timer timer = new Timer();

	class MyTimerTask extends TimerTask {
		@Override
		public void run() {
			MyPanel.this.repaint();
			worldTime++;
		}

	}

	@Override
	public void run() {
		timer.schedule(new MyTimerTask(), 0, 100);// 启动世界计时器,时间开始流动
	}
}

MathUtil.java

package rumour;

import java.util.Random;

public class MathUtil {

	// 产生正态分布随机值
	private static final Random randomGen = new Random();

	public static double stdGaussian(double sigma, double u) {
		double X = randomGen.nextGaussian();
		return sigma * X + u;
	}

}

City.java

package rumour;

public class City {
    private int centerX;
    private int centerY;

    public City(int centerX, int centerY) {
        this.centerX = centerX;
        this.centerY = centerY;
    }

    public int getCenterX() {
        return centerX;
    }

	public void setCenterX(int centerX) {
        this.centerX = centerX;
    }

    public int getCenterY() {
        return centerY;
    }

    public void setCenterY(int centerY) {
        this.centerY = centerY;
    }
}


Person.java

package rumour;

import java.util.List;
import java.util.Random;

public class Person extends Point {
	private City city;
	double targetXU;// x方向的均值
	double targetYU;// y方向的均值

	// 市民的状态
	public interface State {
		int NORMAL = 0;// 正常人
		int SHADOW = 1;// 相信谣言,开始传谣
		int OK = 2;// 相信辟谣,开始辟谣
	}

	public Person(City city, int x, int y, int rank) {
		super(x, y);
		this.city = city;
		// 对市民的初始位置进行N(x,100)的正态分布随机
		targetXU = MathUtil.stdGaussian(100, x);
		targetYU = MathUtil.stdGaussian(100, y);
		Rank = rank;

	}

	// 等级,0普通人,1媒体社交,2政府
	public int Rank = 0;

	public int getRank() {
		return Rank;
	}

	private int state = State.NORMAL;

	public int getState() {
		return state;
	}

	// 传谣函数
	public void beInfected() {
		state = State.SHADOW;
	}

	// 辟谣函数
	public void refute() {
		state = State.OK;
	}

	// 计算两点之间的直线距离
	public double distance(Person person) {
		return Math.sqrt(Math.pow(getX() - person.getX(), 2) + Math.pow(getY() - person.getY(), 2));
	}

	// 对各种状态的人进行不同的处理,更新市民状态
	public void update() {
		List<Person> people = PersonPool.getInstance().personList;
		// 通过一个随机幸运值和安全距离决定传播给其他人
		for (Person person : people) {
			if (person.getRank() == 2) {// 政府辟谣
				float random = new Random().nextFloat();
				if (random < Parameter.govRate &&(int) (MyPanel.worldTime / 10.0) >= Parameter.Time) {
					if (distance(person) < Parameter.govInfluence) {
						this.refute();
						break;
					}
				}
			} else if (person.getRank() == 1) {// 媒体传谣辟谣
				if (person.getState() == State.OK) {
					float random = new Random().nextFloat();
					if (random < Parameter.mediaRate2 && distance(person) < Parameter.mediaInfluence) {
						this.refute();
						break;
					}
				}
				if (person.getState() == State.SHADOW) {
					if (this.state != State.SHADOW) {
						float random = new Random().nextFloat();
						if (random < Parameter.mediaRate1 && distance(person) < Parameter.mediaInfluence
								&& this.getState() != State.OK) {
							this.beInfected();
						}
					}
				}

			} else {// 普通人传谣辟谣
				if (person.getState() == State.OK) {
					float random = new Random().nextFloat();
					if (random < Parameter.perRate2 && distance(person) < Parameter.perInfluence) {
						this.refute();
						break;
					}
				}
				if (person.getState() == State.SHADOW) {
					if (this.state != State.SHADOW) {
						float random = new Random().nextFloat();
						if (random < Parameter.perRate1 && distance(person) < Parameter.perInfluence
								&& this.getState() != State.OK) {
							this.beInfected();
						}
					}

				}

			}
		}

	}
}

PersonPool.java

package rumour;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class PersonPool {
	private static PersonPool personPool = new PersonPool();

	public static PersonPool getInstance() {
		return personPool;
	}

	List<Person> personList = new ArrayList<Person>();

	public List<Person> getPersonList() {
		return personList;
	}

	// 得到各状态市民的数量
	public int getPeopleSize(int state) {
		if (state == -1) {
			return personList.size();
		}
		int i = 0;
		for (Person person : personList) {
			if (person.getState() == state) {
				i++;
			}
		}
		return i;
	}

	private PersonPool() {
		City city = new City(400, 400);// 设置城市中心为坐标
		// 添加城市居民
		Random random = new Random();
		int x;
		int y;
		
		for (int i = 0; i < Parameter.MEDIA_PERSON_SIZE; i++) {
			// 产生N(a,b)的数:Math.sqrt(b)*random.nextGaussian()+a
			x = (int) (100 * random.nextGaussian() + city.getCenterX());
			y = (int) (100 * random.nextGaussian() + city.getCenterY());
			personList.add(new Person(city, x, y, 1));
		}

		personList.add(new Person(city, city.getCenterX(), city.getCenterY(), 2));

		for (int i = 0; i < Parameter.CITY_PERSON_SIZE; i++) {
			// 产生N(a,b)的数:Math.sqrt(b)*random.nextGaussian()+a
			x = (int) (100 * random.nextGaussian() + city.getCenterX());
			y = (int) (100 * random.nextGaussian() + city.getCenterY());
			if (x > 700) {
				x = 700;
			}
			personList.add(new Person(city, x, y, 0));
		}

	}
}

Point.java

package rumour;

public class Point {
	 private int x;
	    private int y;

	    public Point(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;
	    }
}

Parameter.java

package rumour;

//模拟参数
public class Parameter {
   
    public static int CITY_PERSON_SIZE = 10000;//城市总人口数量
    public static int MEDIA_PERSON_SIZE = 5;//媒体数量
    public static int Time = 5;//政府反应时间
    
    public static int govInfluence = 50;//政府影响力
    public static int mediaInfluence = 40;//社交媒体影响力
    public static int perInfluence = 10;//普通人影响力
    
    public static float govRate = 0.8f;//政府辟谣传播率
    public static float mediaRate1 = 0.8f;//媒体谣言传播率
    public static float mediaRate2 = 0.4f;//媒体辟谣传播率
    public static float perRate2 = 0.4f;//普通人辟谣传播率
    public static float perRate1 = 0.5f;//普通人谣言传播率
    
    //城市大小即窗口边界,限制不允许出城
    public static final int CITY_WIDTH = 1000;
    public static final int CITY_HEIGHT = 1000;
}

posted @ 2020-07-15 11:57  启林O_o  阅读(345)  评论(0编辑  收藏  举报