黑马程序员_7K面试题之交通灯系统(一)

2014-11-23 21:35:26 · 作者: · 浏览: 21

交通灯信号模拟系统


一、概述

模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:(需求直接来源于老师的文档)

① 异步随机生成按照各个路线行驶的车辆。

例如:

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

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

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

。。。

② 信号灯忽略黄灯,只考虑红灯和绿灯。

③ 应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。

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

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

⑤ 每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。

⑥ 随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。

⑦ 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。



二、需求分析:

纵观整个系统的需求我们可以得出以下结论:在一个十字路口,涉及到了车、灯以及路,可以把他们之间的关系模拟以下,把路设计成为一个存储车辆的容器,车辆来了,存入容器内,等到车辆将要通过某一条路上的红绿灯亮起,车辆启动,相当于从容器中取出车辆,通过十字路口,下面再仔细地介绍:

\

四面拐弯的设为永远都是绿灯,也就是说四面什么时候都可以转,也就是S--E ,E--N,N--W,W--N,所以我们在下面就不加以考虑了

我们先从S---N看起:假设有S--N的车可以开动了,那么这个时候就有N--S的车也可以开动了,也就是说只要S--N可以通车,那么N--S也可以通车

S--N的绿灯停止了,S--N将不能再通车,同样,N--S也不能通车。

下一个绿灯就是S--W:S--W可以通车,则N--E也可以通车

S--W绿灯停止:下一个绿灯是E--W:E--W可以通车,W--E也可以通车

E--W绿灯停止:下一个绿灯是E--S;E--S可以通车,W--N也可以通车

E--S绿灯停止:下一个绿灯又回到S--N。如此循环。

从上面的分析可以得出,我们只需要四个方向上的交通灯状态就可以控制整个交通系统,因为我们发现他们都是成对出现,比如说我们只要知道S--N是绿灯,那么N--S也应该是绿灯,S--W是绿灯,N--E也应该是绿灯,还有四个角上的拐弯也固定的绿灯,所以我们只需控制四个方向上的四盏等就可以控制整个系统了。


三、面向对象的分析与设计

①每一条路上的车辆在某一时段内可以随机增加车辆,在绿灯到来的时候,要减少该路上的车辆数。当然是在绿灯亮起期间有顺序减少车辆。

某个时刻,可能有任意的车辆到任意的一条路上,这里我们使用到了12盏灯,所有我们要假设有十二条路(实际上只有8条),且每条上某个时刻都有可能有车辆加入该路上等待(或者直接通过,但是得是绿灯且其前面没有车的时候),也就是说我们要为每一盏灯创建一个存储车辆的容器,当某一盏灯亮起的时候,对应容器中的汽车就可以通过了,

②每一条路上在指定时间都回去检查该线路上红绿灯是否为绿。不为绿,不允许车辆通过本线路,在某一条线路上的红绿灯表红的时候,要记得把下一个方向上的红绿灯变绿。

设计一个Lamp类来表示一个交通灯,每个交通灯都维护一个状态:亮(绿)或不亮(红) 总共有12条路线,所以,系统中总共要产生12个交通灯。右拐弯的交通灯为常绿状态,即永远不变红。 无论在程序的什么地方去获得某个方向的灯时,每次获得的都是同一个实例对象,所以Lamp类改用枚举来做显然具有很大的方便性,永远都只有代表12个方向的灯的实例对象。 设计一个枚举类,它定时让当前的绿灯变红。

四 用到的类的编写

①Road类的编写

由于有12条线路,这里开启一个线程池,分配线程池中的线程去为每一条线路增加车辆

同时还要监视红绿灯(以便知道那个线路上的车辆可以启动),那就要开启一个线程去监视该红绿灯的情况,同时在监视中还要得到下一个变绿的灯。

package cn.itcast.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 {
//路就好比是以个容器,在路上面有车
	
	private List
  
    ArrRoad = new ArrayList
   
    (); //面相接口
    编程,提高程序的可扩展性 String name = null; //指定是那条路上的的产生的车辆 public Road(String name ){ this.name = name; //可以产生车辆了 //由于是在某个时刻,每个方向上都有可能产生车辆,所以这里要用到多线程的思想 ExecutorService thread = Executors.newCachedThreadPool(); //创建线程池 thread.execute(new Runnable() {//任务到来时,从线程池中选择一个线程来执行该任务 @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 1000; i++) { //为了达到更加接近实际,这里设置一个随机数,也就是说在某个时间段内随时都有可能有汽车开到路上 try { Thread.sleep((new Random().nextInt(10)+1)*1000);//在1s--10s中有车上路 ArrRoad.add(Road.this.name+(i+1));//指定是那条路上的第几辆车, //这里有个知识点,匿名内部类访问外围类的成员变量的时候,有两种方法,可以将外围类的成员变量设置为final,也也可像这里写的这样 //类名.this.成员变量 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }); //我是这样想的,某条路上有车上来,当遇到路灯的时候,那么这条路上的车就会开走,也就是说这条路上的车会减少 //这里也要单独开启一个线程来执行个监视(监视绿灯) //dispatch(调度) // 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。这里就相当于说是规定什么时候去观察红绿灯的情况 ScheduledExecutorService dispatch= Executors.newScheduledThreadPool(1); //这里的意思是在 创建并执行一个在给定初始延迟1s后首次启用的定期操作,在1s后有执行new Runnable的实现类对象的方法 dispatch.scheduleAtFixedRate( new Runnable() { @Override public void run() { // TODO Auto-generated method stub //先判断判断,name路上的灯是否亮了 boolean light =Lamp.valueOf(Road.this.name).isstate(); //在这里想要知道那条公路上的车该走了,首先得到该路上的车所要走的那条路线上的灯 if(ArrRoad.size() > 0){ if(light){ System.out.println(Road.this.name+"路上的车"+ArrRoad.remove(0)+"飞快通过"); } } } }, 1, 1, TimeUnit.SECONDS ); } } 
   
  

②Lamp类的编写

系统中有12个方向上的灯,在程序的其他地方要根据灯的名称就可以获得对应的灯的实例对象,综合这些因素,将Lamp类用java5中的枚举形式定义更为简单。 每个对象中与当前对象所代表的的灯相对应的灯用correlight表示,该灯是否有下一个灯用next表示,当前灯是否为绿灯用flag表示。
增加了三个方法,也就是开启绿灯,关闭绿灯以及获取当前灯的状态是绿灯还是红灯。
在这里,我设置了Lamp的对象的三个参数的意义分别为:是否有与之对应的灯,为null者表示没有,是否有下一个灯,为null表示没有,当前灯是否为绿,没false表示为红灯。
实现细节在源代码中讲述的很清楚:
package cn.itcast.Traffic;



//使用枚举来描述每个路口路口上的灯
//这里我们先从南到北说起,S,N,E,W代表南、北、东、西,S2N即使南到北
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,nul