zoukankan      html  css  js  c++  java
  • 谣言传播模拟

    受到该项目启发,病毒传播和谣言传播有些相似,就修改了该项目的代码,变成了谣言传播的程序(参数设置都没有科学性)
    项目地址: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;
    }
    
    
  • 相关阅读:
    使用正则表达式实现(加减乘除)计算器(C#实现)
    asp.net core中间件工作原理
    WPF
    WPF
    WPF
    WPF
    WPF 3D Cube及点击交互
    WPF 3D足球导览
    WPF 3D 球面导览
    WPF 3D球及进阶玩法
  • 原文地址:https://www.cnblogs.com/Qi-Lin/p/13207338.html
Copyright © 2011-2022 走看看