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

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

一、交通灯交通灯管理系统题目

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

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

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

    由西向而来去往南向的车辆 ---- 右转车辆
    由东向而来去往南向的车辆 ---- 左转车辆
    ... ...
2.信号灯忽略黄灯,只考虑红灯和绿灯。
3.应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
4.具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
5.每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
6.随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
7.不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。

二、交通灯交通灯管理系统分析设计

1.每条路线上都会出现多辆车,路线上要随机增加新的车,在灯绿期间还要每秒钟减少一辆车。

设计一个Road类来表示路线,每个Road对象代表一条路线,总共有12条路线,即系统中总共要产生12个Road实例对象。
每条路线上随机增加新的车辆,增加到一个集合中保存。
每条路线每隔一秒都会检查控制本路线的灯是否为绿,是则将本路线保存车的集合中的第一辆车移除,即表示车穿过了路口。

2.每条路线每隔一秒都会检查控制本路线的灯是否为绿,一个灯由绿变红时,应该将下一个方向的灯变绿。

设计一个Lamp类来表示一个交通灯,每个交通灯都维护一个状态:亮(绿)或不亮(红),每个交通灯要有变亮和变黑的方法,并且能返回自己的亮黑状态。
总共有12条路线,所以,系统中总共要产生12个交通灯。右拐弯的路线本来不受灯的控制,但是为了让程序采用统一的处理方式,故假设出有四个右拐弯的灯,只是这些灯为常亮状态,即永远不变黑。
除了右拐弯方向的其他8条路线的灯,它们是两两成对的,可以归为4组,所以,在编程处理时,只要从这4组中各取出一个灯,对这4个灯依次轮询变亮,与这4个灯方向对应的灯则随之一同变化,因此Lamp类中要有一个变量来记住自己相反方向的灯,在一个Lamp对象的变亮和变黑方法中,将对应方向的灯也变亮和变黑。每个灯变黑时,都伴随者下一个灯的变亮,Lamp类中还用一个变量来记住自己的下一个灯。
无论在程序的什么地方去获得某个方向的灯时,每次获得的都是同一个实例对象,所以Lamp类改用枚举来做显然具有很大的方便性,永远都只有代表12个方向的灯的实例对象。
设计一个LampController类,它定时让当前的绿灯变红。

3.Road类

每个Road对象都有一个name成员变量来代表方向,有一个vehicles成员变量来代表方向上的车辆集合。

在Road对象的构造方法中启动一个线程每隔一个随机的时间向vehicles集合中增加一辆车(用一个“路线名_id”形式的字符串进行表示)。

在Road对象的构造方法中启动一个定时器,每隔一秒检查该方向上的灯是否为绿,是则打印车辆集合和将集合中的第一辆车移除掉。

4.Lamp类

系统中有12个方向上的灯,在程序的其他地方要根据灯的名称就可以获得对应的灯的实例对象,综合这些因素,将Lamp类用java5中的枚举形式定义更为简单。

每个Lamp对象中的亮黑状态用lighted变量表示,选用S2N、S2W、E2W、E2N这四个方向上的Lamp对象依次轮询变亮,Lamp对象中还要有一个oppositeLampName变量来表示它们相反方向的灯,再用一个nextLampName变量来表示此灯变亮后的下一个变亮的灯。这三个变量用构造方法的形式进行赋值,因为枚举元素必须在定义之后引用,所以无法再构造方法中彼此相互引用,所以,相反方向和下一个方向的灯用字符串形式表示。 
增加让Lamp变亮和变黑的方法:light和blackOut,对于S2N、S2W、E2W、E2N这四个方向上的Lamp对象,这两个方法内部要让相反方向的灯随之变亮和变黑,blackOut方法还要让下一个灯变亮。
除了S2N、S2W、E2W、E2N这四个方向上的Lamp对象之外,其他方向上的Lamp对象的nextLampName和oppositeLampName属性设置为null即可,并且S2N、S2W、E2W、E2N这四个方向上的Lamp对象的nextLampName和oppositeLampName属性必须设置为null,以便防止light和blackOut进入死循环。

5.LampController类

整个系统中只能有一套交通灯控制系统,所以,LampController类最好是设计成单例。
LampController构造方法中要设定第一个为绿的灯。
LampController对象的start方法中将当前灯变绿,然后启动一个定时器,每隔10秒将当前灯变红和将下一个灯变绿。


三、代码实现

1.Lamp枚举类

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 boolean isGreen;
	private String opposite;
	private String next;
	private String info;
	
	public String getInfo() {
		return info;
	}
	
	public boolean isGreen() {
		return isGreen;
	}
	
	Lamp(String opposite,String next,boolean isGreen,String info){
		this.opposite = opposite;
		this.next = next;
		this.isGreen = isGreen;
		this.info = info;
	}

	public void ligthGreen(){
		this.isGreen = true;
		if(this.opposite != null){
			Lamp.valueOf(opposite).ligthGreen();
		}
		System.out.println(this.getInfo() + "的绿灯亮了!允许通行。");
	}
	
	public Lamp ligthRed(){
		this.isGreen = false;
		if(this.opposite != null){
			Lamp.valueOf(opposite).ligthRed();
		}
		Lamp nextLamp = null;
		if(this.next != null){
			nextLamp = Lamp.valueOf(next);
			nextLamp.ligthGreen();
		}
		System.out.println(this.getInfo() + "的红灯亮了!禁止通行。");
		return nextLamp;
	}
}

2.LampController类

public class LampController {
	private Lamp currentLamp = null;
	
	public LampController(){
		currentLamp = Lamp.S2N;
		currentLamp.ligthGreen();
		
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(
				new Runnable(){
					public void run() {
						currentLamp = currentLamp.ligthRed();
					}
				}, 
				15, 
				15, 
				TimeUnit.SECONDS);
	}
}

3.Road类

public class Road {
	private List<String> vehicles = new ArrayList<String>();
	private String name;
	
	public Road(String name){
		this.name = name;
		
		ExecutorService pool = Executors.newSingleThreadExecutor();
		pool.execute(new Runnable() {
			public void run() {
				int i = 1;
				while(i < 10000){
					try {
						Thread.sleep((new Random().nextInt(10) + 1) * 1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					vehicles.add(Lamp.valueOf(Road.this.name).getInfo() + "的第" + i + "辆车子");
					i++;
				}
			}
		});
		
		
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(
				new Runnable(){
					public void run() {
						if(vehicles.size() > 0){
							if(Lamp.valueOf(Road.this.name).isGreen()){
								System.out.println(vehicles.remove(0) + "走了!");
							}
						}
					}
				}, 
				1, 
				1, 
				TimeUnit.SECONDS);
		
		
	}
}

4.主方法

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

}

5.运行结果

由北向南的绿灯亮了!允许通行。

由南向北的绿灯亮了!允许通行。
由南向东的第1辆车子走了!
由南向北的第1辆车子走了!
由东向北的第1辆车子走了!
由南向东的第2辆车子走了!
由北向西的第1辆车子走了!
由西向南的第1辆车子走了!
由北向南的第1辆车子走了!
由东向北的第2辆车子走了!
由南向东的第3辆车子走了!
由东向北的第3辆车子走了!
由北向南的红灯亮了!禁止通行。
由北向东的绿灯亮了!允许通行。
由南向西的绿灯亮了!允许通行。
由南向北的红灯亮了!禁止通行。
由南向西的第1辆车子走了!
由北向东的第1辆车子走了!
由北向西的第2辆车子走了!
由南向西的第2辆车子走了!
由北向东的第2辆车子走了!
由东向北的第4辆车子走了!
由西向南的第2辆车子走了!
由南向西的第3辆车子走了!
由东向北的第5辆车子走了!
由南向西的第3辆车子走了!
由南向东的第4辆车子走了!
由西向南的第3辆车子走了!
由北向西的第3辆车子走了!
由北向东的第3辆车子走了!
由东向北的第6辆车子走了!
由南向西的第5辆车子走了!
由北向西的第4辆车子走了!
由南向东的第5辆车子走了!
由西向南的第4辆车子走了!
由东向北的第7辆车子走了!
由北向东的红灯亮了!禁止通行。
由西向东的绿灯亮了!允许通行。
由东向西的绿灯亮了!允许通行。
由南向西的红灯亮了!禁止通行。


测试正常...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值