一、整体思路

该程序实现了最简单的一个行人疏散模型,程序模拟行人从一个带有出口的封闭房间疏散,墙壁上有疏散方向标志,行人先移动到墙底,然后按照疏散方向往出口移动。

创建一个矩阵,空位设置为0,行人设置为1,墙壁设置为100,出口设置为1000,墙壁和出口的位置手工设置,本程序墙壁为于场地四周,出口位于上方墙壁的中点。行人的位置由随机产生或者手工设定。

具体规则如下:

1、  房间长m,宽n,行人密度p。

2、  行人在墙壁之外的无法看到出口,只能看到墙。

3、  行人会向离自己最近的墙面移动。

4、  墙面上有疏散方向。

5、  如果2人的下一点位置重合,各有50%的几率占据位置,另一个人则原地等待一步。

6、  行人到达出口时从系统移除。

二、具体程序

(一)、绘图类img.java

在绘图类的构造方法,完成界面的初始化,窗口的大小,关闭按钮的作用,将JPanel作为与矩阵相对应的场地。

    
public Img (){//构造方法jf = new JFrame("CA");jp = new JPanel[m] [n];jf.setLayout(new GridLayout(m,n,5,5));//mn 5 5 长m宽n 行间距5 列间距5for (int i=0;i<m;i++){for (intj=0;j<n;j++){jp[i][j]=new JPanel();jp[i][j].setBackground(Color.black);//布置背景色jf.add(jp[i][j]);//将jp添加到jf}}jf.setSize(500,500); //窗口大小jf.setVisible(true);//显示窗口jf.addWindowListener(newWindowAdapter() {//关闭按钮的作用public voidwindowClosing(WindowEvent e) {System.exit(0);}});}



然后是创建行人位置的方法,也就是在矩阵中产生行人、墙壁、出口的方法。产生行人可以用随机方法creatRomNum,也可以用指定方法creatRegNum。
    
    
public int [][] creatRegNum(inta[][]){//手工 创建矩阵for(int i=0;i<m;i++){for (intj=0;j<n;j++){a[0][j]=100;//设置边缘  墙的值为100a[i][0]=100;a[i][m-1]=100;a[n-1][j]=100;}}for(int i=1;i<m-1;i++){for(int j=1;j<n-1;j++){a[i][i]=0;}}a[3][2]=1;//a[3][2]=1;//a[5][5]=1;a[data.CX][data.CY]=1000;//出口returna;}public int [][] creatRomNum(inta[][]){//随机创造矩阵for (inti=0;i<m;i++){for (intj=0;j<n;j++){a[0][j]=100;//设置边缘  墙的值为100a[i][0]=100;a[i][m-1]=100;a[n-1][j]=100;}}for (inti=1;i<m-1;i++){for (intj=1;j<n-1;j++){if(Math.random()>p){a [i][j]=1;//行人代表1}else{a [i][j]=0;//空位代表0}  }}a[data.CX][data.CY]=1000;//设置出口 值为1000return a;}




最后时绘图方法onColor,根据矩阵不同的数值设为不同的颜色。
public void onColor(inta[][]){//绘图方法for(int i=0;i<data.m;i++){for(int j=0;j<data.n;j++){switch(a[i][j]){//对应矩阵的值添加不同的颜色case 0: //空地为0  白色jp[i][j].setBackground(Color.white);break;case 1: //人为1  红色jp[i][j].setBackground(Color.red);break;case 100: //墙为100 蓝色jp[i][j].setBackground(Color.blue);break;case 1000: //出口为1000 黄色jp[i][j].setBackground(Color.yellow);break;default: //其他为黑色  一般用不到jp[i][j].setBackground(Color.black);}}}}

(二)、行人类Peo.java

行人类包含移动方法peoMove,行人具体移动方法peoMoveDirection,判断下一点是否有人方法peoMoveDirectionDecect和行人到达出口方法peoMoveExit。
行人类中最为重要的就是移动方法peoMove。在此方法中,用到了3个数组:a[][],c[][]和d[][]。其中a是由绘图类产生并传进来的,用作判断。C是a的复制,采用循环赋值,在做出移动判断后将更改c的值。在移动之前,首先要判断:获取下一点移动的方向,下一点是否为墙或者人,下一点如果墙的话如何处理。最后交给具体移动方法peoMoveDirection来实现。
public int [][] peoMove(inta [][]){int c[][]=new int [data.m][data.n];int fr;//判断下一点为墙int f;//移动方向boolean moveOk;for (int i=0;i<data.m;i++){ //循环赋值for (int j=0;j<data.n;j++){c[i][j]=a[i][j];}}for (int i=1;i<data.m-1;i++){for(int j=1;j<data.n-1;j++){//在进行移动之前先判断下一点是否能走//用d的值来判断f=rule.calRange(i, j, data.m, data.n,data.r);//判断方向if(a[i][j]==1){fr=rule.stopChange(a, i, j);if(fr==2){//判断墙f=rule.calRangeDouble(i,j);moveOk=peoMoveDirectionDecect(f,i, j, c);if(moveOk){c=peoMoveDirection(f,i, j, c);}else{c=peoMoveDirection(5,i, j, c);}}else{c=peoMoveDirection(f,i, j, c);}}}}return c;}

行人具体移动方法peoMoveDirection和判断下一点是否有人方法peoMoveDirectionDecect大概差不多。peoMoveDirection方法是将下一点设置为1,将原来的点设置为0;peoMoveDirectionDecect是判断下一点是否为1,如果是,则返回false。
public int[][] peoMoveDirection(intf,int i,int j,int c [][]){//行人移动  传入方向f 改变下一点的值switch(f){case 1:c[i-1][j-1]=1;c[i][j]=0;break;case 2:c[i-1][j]=1;                 c[i][j]=0;break;case 3:c[i-1][j+1]=1;c[i][j]=0;break;case 4:c[i][j-1]=1;c[i][j]=0;break;case 5:c[i][j]=1;break;case 6:c[i][j+1]=1;c[i][j]=0;break;case 7:c[i+1][j-1]=1;c[i][j]=0;break;case 8:c[i+1][j]=1;c[i][j]=0;break;case 9:c[i+1][j+1]=1;c[i][j]=0;break;}return c;}public booleanpeoMoveDirectionDecect(int f,int i,int j,int c[][]){//判断行人下一点移动  传入方向f 如果下一点数值为1flag为falseboolean flag=true;switch(f){case 1:if(c[i-1][j-1]==1){flag=false;}break;case 2:if(c[i-1][j]==1){flag=false;}break;case 3:if(c[i-1][j+1]==1){flag=false;}break;case 4:if(c[i][j-1]==1){flag=false;}break;case 5:c[i][j]=1;break;case 6:if(c[i][j+1]==1){flag=false;}break;case 7:if(c[i+1][j-1]==1){flag=false;}break;case 8:if(c[i+1][j]==1){flag=false;}break;case 9:if(c[i+1][j+1]==1){flag=false;}break;}return flag;}

行人到达出口方法peoMoveExit,如果检测到行人在出口,则将行人移除系统。(这里为什么不整合到移动方法中呢?在主方法中,所有步骤运行后会有个赋值语句,将此次的结果覆盖原来的矩阵。如果写到移动方法中,会使出口方法失效)
public int [][] peoMoveExit(inta[][]){//行人到达出口方法如果出去  设为0boolean exitOk=false;int c[][]=new int [data.m][data.n];for (int i=0;i<data.m;i++){ //循环赋值for (int j=0;j<data.n;j++){c[i][j]=a[i][j];}}for(int i=0;i<data.m;i++){for(int j=0;j<data.n;j++){if(a[i][j]==1){exitOk=rule.exitDose(a, i, j);if(exitOk){c[i][j]=0;System.out.println("跑出去一个");}}}}return c;}

(三)、规则类Rule.Java

规则类包含方向判断方法calRange,遇到墙壁的方向判断calRangeDouble,判断墙壁方法stopChange和判断出口方法exitDose。
判断方法calRange,将行人距离四周墙壁的长度存入array中,然后用sort方法排序,取出第一个值,于4个方向的值相比较完成赋值。
public int calRange(int i,intj,int m,int n,int R){//判断方向的方法//将计算[i][j]与四周墙的距离 存入数组  使用sort方法进行排序//首先判断距离出口长度//其此将数组的最小值分别与4个值比较  得到具体方向int f=5;int north=i;int east=m-j;int south=n-i;int west=j;int ran[]=newint[4];ran[0]=north;ran[1]=east;ran[2]=south;ran[3]=west;Arrays.sort(ran);if(ran[0]==north){f=2;}else if(ran[0]==east){f=6;}else if(ran[0]==south){f=8;}else if(ran[0]==west){f=4;}return f;}

遇到墙如何走方法calRangeDouble,根据位置不同,直接指定方法。
public int calRangeDouble(inti,int j){//沿着墙走时  判断遇到拐角的方法intf=0;//输出方向if(i==1){//如果行人在最上面if(j==1){//如果在在左边f=6;//方向向右}elseif(j==data.n-2){//如果在最右边f=4;}else{if(j>=data.n/2){//如果在右半部分f=4;}else{//左半边f=6;}}}if(i==data.m-2){//在最下面if(j==1){//最左边f=2;}elseif(j==data.n-2){//最右边f=2;}else{if(j>=data.m/2){//右半部分f=6;}else{//左边部分f=4;}}}if(j==1){//在左边if(i==1){//左上角f=6;}else{f=2;}}if(j==data.n-2){//在右边if(i==1){//有上交f=4;}else{f=2;}}returnf;}

判断墙的方法stopChange,遇到墙壁返回2。
public int stopChange(inta[][],int i,int j){//判断墙intfr=0; //fr 为判断下一步是否为墙if(i==1||j==1||i==data.n-2|| j==data.m-2 ){fr=2;//fr=2 表示下一点为墙}returnfr;}

判断出口方法exitDose,遇到出口返回TRUE。
public boolean exitDose(inta[][],int i,int j){//判断是否到达出口  如果到达出口 flag改为TRUEbooleanflag=false;intexitId=data.n/2;if(i==1){if(j==exitId){flag=true;}if(j==exitId+1){flag=true;}if(j==exitId-1){flag=true;}}returnflag;}

(四)、主方法
  public class RunMain {public static voidmain(String[] args) {Data data=new Data();Img img=new Img();Peo peo=new Peo();int a[][]=new int[data.m][data.n];int c[][]=new int[data.m][data.n];int d[][]=new int[data.m][data.n];a=img.creatRomNum(data.a);img.onColor(a);try {Thread.sleep(15000);} catch (Exception e) {e.printStackTrace();}for (int h=0;h<data.h;h++){c=peo.peoMove(a);d=peo.peoMoveExit(c);img.onColor(d);for (int i=0;i<data.m;i++){for (int j=0;j<data.n;j++){a[i][j]=d[i][j];}}try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}System.out.println("第"+h+"次");}}
}

三、总结

经过这次编程,我又重新拾起快遗忘的Java。相对于matlab来说,Java最大的优势就是面向对象,各种方法有机结合。但是对新手不友好,需要先学一大堆Java知识,而matlab入手简单,简单学习就可以使用。
本程序离预定目标还差不少,最关键的是对于行人碰撞的解决不太可行。在房间中间的视野盲区,行人应该按随机方向行走,于是就有可能有2人的下一点在同一位置上,此时2人占据这点的概率应该是50%,但是程序是通过遍历数组来完成绘图的。这就导致位于前面的人就可以优先选择。虽然也可以通过将行人的一下步存到数组f中,然后在对其进行标识,从而产生50%的概率,但是这样做有点麻烦,因此在我想不使用矩阵,直接通过坐标将图绘出来,采用多线程,希望可以解决这个问题。

												

简单行人疏散 Java版相关推荐

  1. 菜鸟学Java(六)——简单验证码生成(Java版)

    转载自  菜鸟学Java(六)--简单验证码生成(Java版) 验证码大家都知道,它的作用也不用我多说了吧.如果不太清楚请参见百度百科中的解释,一般验证码的生成就是随机产生字符(数字.字母或者汉字等) ...

  2. 菜鸟学Java——简单验证码生成(Java版)

    验证码大家都知道,它的作用也不用我多说了吧.如果不太清楚请参见百度百科中的解释,一般验证码的生成就是随机产生字符(数字.字母或者汉字等),然后将这些生成的字符绘制成一张图片,再在图片上加上一些干扰元素 ...

  3. 简单聊天室(java版)

    这是本人从其他地方学习到的关于聊天室的一个模本,我从中截取了一部分关于客户端和服务端通信的Socket的内容.希望对大家对socket有个了解,我写的这些代码可以实现两人或多人在多台电脑上实现简单的对 ...

  4. Java版DBHelper【简单】(MySQL数据库)

    http://www.cnblogs.com/xia520pi/archive/2012/05/22/2513920.html Java版DBHelper[简单](MySQL数据库) 1.测试数据库 ...

  5. java版银联8583协议解析,超简单超直观的实现及示例(全互联网最简单)

    一直以来做嵌入式软件开发,跟银联8583协议通信打交道太多了. 最近有需要把8383协议的解析用到android上,但是搜遍了整个互联网,没发现有哪个简单好用点的java版8583解析库.就自己动手自 ...

  6. 【原】简单的鼠标切换左右键(java版)

    简单的鼠标切换左右键(java版) 0. 写在最前面 客户需要一个能切换左右键的小功能满足使用需要. 具体需要如下: 我需要一个独立运行的窗口,在其中输入数字x,按下"转换"按钮后 ...

  7. 简单工厂模式,工厂方法模式,抽象工厂模式总结-java版

    文章目录 LOG:更新日志 一.简单工厂模式,工厂方法模式,抽象工厂模式定义 二.三种工厂模式的优缺点以及适用场景 三.名词解释 四.简单工厂模式.工厂方法模式与抽象工厂模式之间的区别 五.抽象工厂模 ...

  8. JAVA版StarDict星际译王简单实现

    由胡正开发的星际译王是Linux平台上很强大的一个开源的翻译软件(也有Windows版本的)支持多种词库.多种语言版本.尤其词库设计比较合理.之前看到一篇博文<星际译王词库应用-自制英汉词典&g ...

  9. 我的世界java版gamemode指令_我的世界(电脑Java版)简单又好玩指令教程

    注:该教程基于Java V1.16.3 通常可以兼容1.13+的版本 1.9-1.12可能会有不兼容 已知的不兼容会在文章中标出并给出旧版本指令 如果发现其他不兼容指令可以在评论区提问 指令是< ...

  10. [全网首发!超级简单!] iOS开Minecraft:Java版服务端

    iOS开Minecraft:Java版服务器 写在前面 材料准备 一.环境准备 配置环境 1.安装opensssh 2.添加软件源 3.安装Java Runtime Environment 3.寻找J ...

最新文章

  1. 建立与ftp服务器的连接——完成版(java)
  2. 使用Git工具生成公钥与私钥
  3. IT人分类,你属于哪个级别?
  4. mySql配置在nodejs中使用
  5. 基于python的性能测试工具–locust
  6. Linux debian安装Typora教程
  7. 玻尔兹曼分布涨落_科学网—高分子统计物理漫谈-涨落耗散定理-2 - 苗兵的博文...
  8. java server faces
  9. 部署Nginx+Keepalived
  10. mysql 基础面试_面试必问之mysql基础
  11. bzoj 5281: [Usaco2018 Open]Talent Show【dp】
  12. 03.SpringBoot入门案例及详解
  13. 双线性对在密码学中的应用(上)
  14. VirtualBox安装Ubuntu教程
  15. 华为荣耀8C安装Google play store的记录
  16. 【Uplift】模拟数据篇
  17. 2018-11-15-mqtt-mosquitto系列11之配置基于ca证书的桥接
  18. Alpha 冲刺(7/10)
  19. 【Linux后端开发必问】操作系统系列(Linux常用命令、文件权限修改、静态与动态库的制作)
  20. Knowledge 1命题逻辑语义蕴含

热门文章

  1. 学习《医学三字经白话解》之咳嗽+疟疾+痢证
  2. stata基础--异方差检验和处理
  3. 抖音怎么上热门?这样发视频点赞过万!
  4. Java开发-使用Java语言实现刷微信跳一跳小游戏的分数
  5. 【量化笔记】时间序列--ARCH模型及GARCH模型
  6. 云服务器功能检验方法
  7. 外包公司能去吗?进了外包如何翻盘?
  8. 移动支付新趋势:短信支付「Pay by Text」
  9. 为啥E进制计算机的效率最高?
  10. 关于打开CMD窗口一闪而退的解决方法