黑马程序员_交通灯管理系统

------- android培训java培训、期待与您交流! ----------

一、项目需求

模拟实现十字路口的交通管理系统逻辑,具体需求如下:

1)、异步随机生成按照各个路线行驶的车辆。如:

由南向而来去往北向的车辆---->直行车辆

由西向而来去往南向的车辆---->右行车辆

由东向而来去往南向的车辆---->左行车辆

......

2)、信号灯忽略黄灯,只考虑红灯和绿灯;

3)、只需考虑左转车辆控制信号灯,右转车辆控制信号不需考虑;

4)、具体信号控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑;

        注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放直行车辆,而后方左转车辆。

5)、每辆车通过路口时间为1s(提示:可通过线程sleep方式模拟);

6)、随机生成车辆时间间隔以及红绿灯交换时间间隔;

7)、不考虑实现GUI,只考虑系统逻辑实现,可通过log方式展现程序运行结果。

二、交通灯模型分析

1)、交通灯模拟图


注:S2N:表示由南向北去的车辆,2是to的意思。其他依次相同。

通过对交通图的分析知:该十字路口共有12条路线。我们这里以南为起点参考方向,这十二条路线分别为:S2N, S2W, E2W, E2S, N2S, N2E, W2E, W2N, S2E, E2N, N2W, W2S。 

 再进一步联系实际分析,我们可以知道该线路可以进一步优化减少考虑一部分线路。在这里,我们以东南为参考方向,当车辆由南向西行驶时,由西往南的车辆同样在直行,互补干扰。当车辆由南向西行驶时,在由北向东行驶的车辆也同样不受干扰。同理,车辆由东向西行驶是,由西向东行驶的车辆不受干扰;由东向南行驶时,由西向北的车辆也不受干扰。由于我国交通向右行驶时不受交通灯影响,所以由南向东,由东向北,由北向西,由西向南的都不用考虑。综上分析,我们重点考虑的只有四条线路,即:S2N, S2W, E2W, E2S。在现实生活中向右行驶没有灯,但在模型中我们假设向右行驶都有灯,这灯是常亮的,所以就可以统一模型了。

2)、模型分析

通过分析,我们知道该系统中有3个对象:车,路,灯。再通过具体分析,我们并不需要体现车移动的过程,只是捕捉车辆穿过路口的过程,也就是捕捉路上减少一辆车的过程,所以车就不需要单独设计成为一个对象,用一个字符串表示就可以。但是灯还需要一个控制器控制它,所以我们还得创建一个灯控制器对象。所以总共就需要设计三个对象:路,路灯,路灯控制器。

注:面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法。

3)、分析并创建对象

A、Road类

设计一个Road类来表示路线。该路线上创建一个集合,通过集合来存储路上的车辆,并且每隔一段时间就来一辆车,来一辆车就往集合里面存储。路还要每隔一秒中检查一下控制该路线的灯是否为绿灯,如果是绿灯,则将集合中的第一辆车移除,即表示该辆车穿过了路口。所以还要创建一个定时器来记录时间。

代码体现:

package com.itheima.traffic;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Road {
	/*使用List集合时为了面向对象编程*/
	List<String> vechicles = new ArrayList<String>();
	private String name = null;
	public Road(String name){
		this.name = name;
		
		//使用一个线程池来控制进入车辆的时间;
		ExecutorService pool = Executors.newSingleThreadExecutor();
		pool.execute(new Runnable(){
			public void run() {
				for(int i=1; i<1000; i++){
					try {
						Thread.sleep((new Random().nextInt(10)+1)*1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					vechicles.add(Road.this.name+"_"+i);
				}			
			}
		});
		
		//定义定时器来监控灯的状态并做处理;
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(
				new Runnable(){
					public void run() {
						if(vechicles.size()>0){
							boolean lighted = Lamp.valueOf(Road.this.name).islighted();
							if(lighted){
								System.out.println(vechicles.remove(0) + " is traversing!!!");
								//此处的remove是将集合中的车辆移除,remove返回的是移除的那个元素;
							}
						}
					}
				}, 
				1, 
				1, 
				TimeUnit.SECONDS);
	}

}

B、Lamp类

由于该系统涉及到12个路灯,所有我们可以采用枚举方法列举出每个灯的状态。该类中需要定义一个变量来表示灯的状态,还需要定义该灯与之对应灯和下一个灯。还需要定义方法记录各灯的状态。当参考灯为绿时,与之对应的灯也的是绿色,而它的下一个灯则为红灯(注意:参考灯有与之对应的灯,则与参考灯对应的灯就不存在对应的灯了);增加让Lamp变亮和变黑的方法:lightblackOut对于S2NS2WE2WE2N这四个方向上的Lamp对象,,这两个方法内部要让相反方向的灯随之变亮和变黑,blackOut方法还要让下一个灯变亮。

代码体现:

package com.itheima.traffic;

public enum Lamp {
	S2N("N2S","S2W",false), S2W("N2E","E2W",false), E2W("W2E","E2S",false), E2S("W2N","S2N",false),
	N2S(null,null,false),   N2E(null,null,false),   W2E(null,null,false),   W2N(null,null,false),
	S2E(null,null,true),    E2N(null,null,true),    N2W(null,null,true),    W2S(null,null,true);
	
	private Lamp(String opposite,String next, boolean lighted){
		this.opposite = opposite;
		this.next = next;
		this.lighted = lighted;
	}
	
	private Boolean lighted ;
	private String opposite;
	//此处的opposite用字符串表示可以避免上面使用与参考灯对应的灯对象时,出现先定义后使用时的错误情况;
	private String next;
	
	public Boolean islighted(){
		return lighted;
		
	}
	
	public void light(){
		this.lighted = true;
		if(opposite != null){
			//如果该灯有与之对应的灯,则与之对应的灯也将变亮;此处如果不做判断则会出现死循环;
			
			Lamp.valueOf(opposite).light();
			//valueOf方法可以返回名字为opposite的对象;
		}
		System.out.println(name()+" lamp is green,下面共有6个方向可以看到汽车穿过!");
	}
	
	public Lamp blackOut(){
		this.lighted = false;
		if(opposite != null){
			Lamp.valueOf(opposite).blackOut();
		}
		
		Lamp nextLamp = null;
		if(next != null){
			nextLamp =Lamp.valueOf(next);
			System.out.println("绿灯将从 " + name() + " 切换到-----> " + next);
			nextLamp.light();
		}
		return nextLamp;
	}
	
}

C、LampController类

该类中需要定义一个当前的灯,我们假设E2N的灯为当前灯。当灯控制器对象一创建时就有当前灯,并设定其状态为绿灯,让后定义一个定时器,每隔10s就当前灯变红,则下一个灯变绿。

代码体现:

package com.itheima.traffic;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class LampController {
	
	private Lamp currentLamp;
	public LampController(){
		currentLamp = Lamp.S2N;
		currentLamp.light();
		
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(
				new Runnable(){
					public void run() {
						currentLamp = currentLamp.blackOut();
					}
				}, 
				10, 
				10, 
				TimeUnit.SECONDS);
	}
}



D、MainClass测试类

该类中我们需要创建12条线路的12个对象,所以可以选用数组遍历的方法来翻遍创建,然后调用LampController对象使系统运行起来;

代码体现:

package com.itheima.traffic;

public class MainClass {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String[] directions = new String[]{
				"S2N","S2W", "E2W", "E2S", "N2S", "N2E", "W2E", "W2N", "S2E", "E2N", "N2W", "W2S"
		};
		
		for(int i=0; i<directions.length; i++){
			new Road(directions[i]);
		}
		new LampController();
	}

}


------- android培训java培训、期待与您交流! ----------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值