`
yunnick
  • 浏览: 389952 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

一个电梯运行的简单模拟实现

阅读更多

用Java写了一个类似电梯模拟器的一段代码,运行了下,还没有发现大问题,记录如下:

基本思路:

模拟电梯运行(为单一电梯,未考虑达到承载上限,最短等待时间等问题)

基本条件:

1、电梯有三种状态:静止,向上,向下。

2、每层的指示灯有三种状态:向上、向下、到达(只开门)。

3、开门上人1秒,每上或下一层用0.1秒。

 

实现方案:

使用一个队列(可看做时间优先)将所有按钮事件依次入队。

当电梯静止时首先响应队头的按钮事件,并根据按钮楼层和当前楼层的位置确定移动方向; 当向上移动时,将移动到所有亮灯的按钮所在楼层的最高层,当按钮方向和电梯方向一致时或该楼层内部到达按钮亮起时开门;向下移动类似。 当队列中没有按钮事件时,电梯静止。有些类似LOOK算数,但没有按钮事件时不会来回扫描。

使用主线程来控制电梯上下,需要注意同步“设置和获取电梯按钮最高层或按钮最底层数的方法”。

 

主方法用来不断循环监测:

while(true){
			if(!ele.getPushedFloor().isEmpty()){
				int nextFloor = ele.getPushedFloor().peek();
				if(nextFloor > 0){//向上的按钮
					if(ele.getCurFloor() - nextFloor <= 0){
						ele.liftUp();
					}else if(ele.getCurFloor() - nextFloor > 0){
						ele.liftDown();
					}
				}else{//向下的按钮
					if(ele.getCurFloor() + nextFloor < 0){
						ele.liftUp();
					}else if(ele.getCurFloor() + nextFloor >= 0){
						ele.liftDown();
					}
				}
			}else{
				ele.setStat(RunningStat.INIT);
			}
			Thread.sleep(100);
		}

 电梯上升方法:

public void liftUp() throws InterruptedException{
		setStat(RunningStat.UP);
		int floorIdx = curFloor;
		while(floorIdx <= this.getLiftTop()){
			curFloor = floorIdx;
			if(btnMap.get(floorIdx).isUpLightOn()){
				openDoor(floorIdx, true);
				btnMap.get(floorIdx).setUpLightOn(false);
			}else if(btnMap.get(floorIdx).isInnerLightOn()){
				justOpenDoor(floorIdx);
			}
			/**
			 * 模拟电梯上升
			 */
			Thread.sleep(100);
			floorIdx++;
		}
		synchronized (this) {
			//需要注意,若“当前层”达到最高层需重新初始化最高层指示变量
			if(this.getLiftTop() == curFloor){
				this.setLiftTop(bottom - 1);
			}
		}
	}

 定义了一个User线程,模拟用户按下按钮

class User implements Runnable{
		@Override
		public void run() {
			int i = 0;
			while(i < 10){
				i++;
				int floor = RandomUtils.nextInt(top) + 1;
				Button btn = ele.getButton(floor);
				try {
					if(floor == ele.top){
						btn.push(floor, BtnDirec.DOWN);
					}else if(floor % 2 == 0 || floor == ele.bottom){
						btn.push(floor, BtnDirec.UP);
					}else{
						btn.push(floor, BtnDirec.DOWN);
					}
					Thread.sleep(500);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

 

还定义了一个EleStat线程,监测电梯状态并打印的后台,日志类似:

The elevator started
The elevator is no moving, cur:1
5 floor down light on
5 ↓,
The elevator is lift up, cur:1
5 ↓,
The elevator is lift up, cur:2
5 ↓,
The elevator is lift up, cur:3
5 ↓,
The elevator is lift up, cur:4
5 ↓,
The elevator is lift up, cur:5
10 floor up light on
5 ↓,10 ↑,
The elevator is lift up, cur:6
5 ↓,10 ↑,
The elevator is lift up, cur:7
5 ↓,10 ↑,
The elevator is lift up, cur:8
5 ↓,10 ↑,
The elevator is lift up, cur:9
opening door on floor: 10 lift to:20
5 ↓,20 -,
The elevator is lift up, cur:10
12 floor up light on
5 ↓,20 -,12 ↑,
The elevator is lift up, cur:10
5 ↓,20 -,12 ↑,
The elevator is lift up, cur:10
5 ↓,20 -,12 ↑,
The elevator is lift up, cur:10
5 ↓,20 -,12 ↑,
The elevator is lift up, cur:10
5 ↓,20 -,12 ↑,
The elevator is lift up, cur:10
13 floor down light on
5 ↓,20 -,12 ↑,13 ↓,
The elevator is lift up, cur:10
5 ↓,20 -,12 ↑,13 ↓,
The elevator is lift up, cur:10
5 ↓,20 -,12 ↑,13 ↓,
The elevator is lift up, cur:10
5 ↓,20 -,12 ↑,13 ↓,
The elevator is lift up, cur:10
5 ↓,20 -,12 ↑,13 ↓,
The elevator is lift up, cur:10
14 floor up light on
5 ↓,20 -,12 ↑,13 ↓,14 ↑,
The elevator is lift up, cur:11
opening door on floor: 12 lift to:20
5 ↓,20 -,13 ↓,14 ↑,
。。。

 

 具体代码见附件。

 

 ++++++++++++++++++++++++++++++分割线++++++++++++++++++++++++++++++++++++++++

 经 qiuyibo7777 提示,主方法中那种面向过程的写法对专注面向对象的程序员来说有些不堪入目了。

        所以就改写了一个基于“模式”的版本,我选择的是策略模式,不用状态模式,我认为所谓状态模式就是根据事物的上下文状态而采取某种行动,是状态决定了行为;而策略模式为算法决定行为,就比如采用不用的电梯算法(比如平均等待时间最短还是等待时间方差最小)电梯会有不同的行为(上行或下行),相同的状态,不同的算法,可能电梯的行为会不一样。

下面是我改写的主要内容:

UML 类图:

简要说明:

定义了一个总接口ElevatorAction

public interface ElevatorAction {
	public void action();
}

 接口LiftDownAction和LiftUpAction分别继承了ElevatorAction ,TimePriorityLiftDown和TimePriorityLiftUp为具体的实现类。

主方法启动电梯这样写:

Elevator ele = new Elevator();
ele.setTop(top);
ele.init();
ele.start();

 然后主要就是Elevator的star()方法:

public void start(){
		while(true){
			ea = getNextAction(pushedFloor, curFloor);
			ea.action();
		}
	}

 

每次主循环获取下一个行动的方法,根据当前楼层和下一楼层的数值确定:

public ElevatorAction getNextAction(Queue<Integer> floors, int curFloor){
		Integer flag = floors.peek() == null? null : Math.abs(floors.peek()) - curFloor;
		return getBean(flag);
	}

 

然后电梯具体的行为执行类通过ObjectFactory获取: 

public ElevatorAction getBean(Integer flag){
		String beanName = ObjectFactory.getBeanName(flag);
		return ObjectFactory.getBean(beanName);
	}

 通过上述方式就避免了繁琐的面向过程的if-else判断,也更容易理解。

 TimePriorityLiftDown和TimePriorityLiftUp就是具体的策略类,如果有其他算法可以通过IOC进行灵活配置更改。

 

注:所谓模式不一定能解决一切问题,但任何问题都应尝试用模式的思维去解决。我认为这是不错的,但我还认为解决问题还是先要有思路,先打好草稿,再有必要的话进行基于模式的重构;若凡事都将模式挂在嘴边,不免有炫耀之嫌,或者就像一个人为人做事老是在那“端着”,又累又没意思。

1
1
分享到:
评论
3 楼 yunnick 2015-10-21  
qiuyibo7777 写道
看到三层if。尼玛只能呵呵了,状态模式去看看

说的不错,这个情形很适合用状态模式;我觉得策略模式的话应该跟贴切一些,稍后修改一下
2 楼 qiuyibo7777 2015-10-21  
看到三层if。尼玛只能呵呵了,状态模式去看看
1 楼 yunnick 2015-10-20  
关于日志:
The elevator is lift up, cur:5 
10 floor up light on  
5 ↓,10 ↑,  

虽然到达5层,但是电梯运行状态时向上,且正好有10楼按了按钮,所以5楼没有停。

相关推荐

    用java实现的《模拟电梯调度》源代码

    模拟电梯调度:利用JAVA语言编写一个模拟电梯调度程序,要求电梯除最底层、最高层以外每一层外面都有一个上下按钮(第1层只有向上按钮,第6层只有向下按钮),电梯层数为6层,电梯内部有1——6数字按钮和开门按钮,...

    模拟电梯系统程序设计

    将呼叫和目标写入一个正文文件,然后程序读取这些呼叫和目标数据后可以在没有人工干预的情况下模拟电梯运行情况。其中一个呼叫/目标占一行,格式如下: &lt;操作时间&gt;[空格]&lt;呼叫目标&gt;[回车] 操作时间,表示呼叫请求的...

    电梯调度模拟运行程序

    使用C/C++模拟电梯调度运行程序,简单实现电梯上下运行的各种情况

    java实现的电梯模拟系统

    用java实现的电梯模拟系统,课程设计可以用,课设环境eclipse,导入工程即可运行

    利用MFC编写的一个模拟电梯程序

    该程序是利用MFC编写的一个模拟电梯运行的程序,程序功能简单,但基本都实现了

    Java实现 电梯模拟系统(附有开发文档和程序代码 )

    java swing 实现的电梯模拟系统,能够通过界面方式简易模拟电梯的运行,管理员登录,设置等基本功能!附有开发文档,程序代码和界面的一些图片,开发环境为:JCreator,一些功能还未实现,希望给你一点借鉴,并希望你...

    编译原理 电梯模拟程序java版

    编程模拟电梯运行程序,能够通过按钮实现上下楼梯,要求程序简洁,使用简单线程,绘图技术

    用c++模拟三部电梯的运行

    用C++进行简单的模拟三部电梯同时运行的状况,实现不同的楼层之间、不同电梯之间的及时、不冲突的响应。

    电梯调度算法(源代码)

    通过编程模拟实现电梯调度算法,介于只适用于模拟实现阶段,程序比较简单!

    简单的电梯控制系统

    /*C语言简易电梯实现(模拟状态机) /* /*通过定义两个枚举类型和两个结构表征电梯当前状态 /* /*具有如下功能: /*电梯状态初始化(电梯在一楼且电梯门关闭) /*选择电梯是否继续运行 /*控制电梯每次运行时的方向 /*在...

    OOelevator 傻瓜电梯

    OO第二次作业 通过设计一个简单的单部电梯运行控制系统,要求设计者以面向对象程序的 设计方式来实现电梯控制系统的具体功能。

    elevator NuSMV 建模 模型检测 电梯

    资源:一份源代码,一份英文报告。英文报告包括了模拟运行结果(20步随机),还有CTL以及CTL验证结果,最后一些简单说明。

    Elevator-Simulator:Python中的电梯模拟器

    该项目是建筑物中许多电梯的简单模拟器,使您可以通过增加可以处理的人数和范围来对其进行配置。 此外,您可以选择目标,方向并显示当前楼层。 更进一步,停下来上新乘客,然后重新开始,改变方向,或者如果其中一项...

    基于51单片机的16层电梯控制系统(16)原理图、流程图、物料清单、仿真图、源代码

    基于51单片机的16层电梯控制...1、模拟16层电梯工作,实现上下行指示,楼层显示 2、使用矩阵键盘输入要去的楼层 3、电梯进行红外检测,如果红外被遮挡则停止运行。 【说明:按多个楼层以后,LED会出现比较严重的闪烁】

    java源码包---java 源码 大量 实例

    一个简单的CS模式的聊天软件,用socket实现,比较简单。 凯撒加密解密程序 1个目标文件 1、程序结构化,用函数分别实现 2、对文件的加密,解密输出到文件 利用随机函数抽取幸运数字 简单 EJB的真实世界模型(源代码...

    基于51单片机设计的电梯模拟系统.zip(毕设/课设/竞赛/实训/项目开发)

    嵌入式优质项目,资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松copy复刻,拿到资料包后可轻松复现出一样的项目。 本人单片机开发经验充足,深耕嵌入式领域,有任何使用问题欢迎随时与我联系,我会...

    java源码包2

    一个简单的CS模式的聊天软件,用socket实现,比较简单。 凯撒加密解密程序 1个目标文件 1、程序结构化,用函数分别实现 2、对文件的加密,解密输出到文件 利用随机函数抽取幸运数字 简单 EJB的真实世界模型(源...

    java源码包3

    一个简单的CS模式的聊天软件,用socket实现,比较简单。 凯撒加密解密程序 1个目标文件 1、程序结构化,用函数分别实现 2、对文件的加密,解密输出到文件 利用随机函数抽取幸运数字 简单 EJB的真实世界模型(源...

Global site tag (gtag.js) - Google Analytics