您的位置:首页 > 职场人生

面试题 二交通灯管理系统的思考

2010-07-16 20:38 295 查看
交通灯管理系统



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



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

例如:



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



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



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



。。。



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

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

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

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



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

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

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

对于这道题,我想,首先这是一个不是状态模式的一个状态机。根据,张孝祥老师提供的思路,我知道了

每一个交通灯都有它各自的状态,又由于它的状态仅需模拟红、绿两个状态,不像状态模拟一样,需要针对每个状态设计类,那么仅需要一个枚举就可以了,当然,我们还需要一个枚举来设定控制的方向,或者说是路口的方向。

解题步骤:(1)我首先设置两个枚举类型,即是交通灯颜色和控制的方向。源代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TrafficDemo
{
/// <summary>
/// 交通灯颜色
/// </summary>
public enum LightState
{
Green=0,
Red=1
}

/// <summary>
/// 控制的方向
/// </summary>
public enum ControlDirection
{
/// <summary>
/// 南北
/// </summary>
SN,
/// <summary>
/// 北南
/// </summary>
NS,
/// <summary>
/// 东西
/// </summary>
EW,
/// <summary>
/// 西东
/// </summary>
WE,
/// <summary>
/// 南西
/// </summary>
SW,
/// <summary>
/// 南东,右转
/// </summary>
SE,
/// <summary>
/// 北东
/// </summary>
NE,
/// <summary>
/// 北西,右转
/// </summary>
NW,
/// <summary>
/// 西南,右转
/// </summary>
WS,
/// <summary>
/// 西北
/// </summary>
WN,
/// <summary>
/// 东北,右转
/// </summary>
EN,
/// <summary>
/// 东南
/// </summary>
ES
}

/// <summary>
/// 一个交通灯
/// </summary>
public class Light
{
protected LightState state;
/// <summary>
/// 交通灯当前的颜色状态
/// </summary>
public virtual LightState State
{
get { return state; }
set { state = value; }
}

public virtual void ChangeState()
{
//忽略黄灯
State = (LightState)Math.Abs((int)State-1);
}

/// <summary>
/// 该交通灯控制的方向
/// </summary>
public ControlDirection Direction
{
get;
set;
}

LightControl control;

/// <summary>
/// 该交通灯属于哪组控制器
/// </summary>
public LightControl Control
{
get { return control; }
set { control = value; }
}
}
}
其布局的图如下:

(2)接着,我们考虑交通灯,这里需求中需要考虑的是常亮的灯,比如,大部分路口的右转灯;对于所有的灯,都要有一个状态,控制的方向,以及一个改变状态的方法。其源代码如下:
/// <summary>
/// 一个交通灯
/// </summary>
public class Light
{
protected LightState state;
/// <summary>
/// 交通灯当前的颜色状态
/// </summary>
public virtual LightState State
{
get { return state; }
set { state = value; }
}

public virtual void ChangeState()
{
//忽略黄灯
State = (LightState)Math.Abs((int)State-1);
}

/// <summary>
/// 该交通灯控制的方向
/// </summary>
public ControlDirection Direction
{
get;
set;
}


/// <summary>
/// 固定常亮的信号灯
/// </summary>
public class FixLight:Light
{
public override LightState State
{
get
{
return base.State;
}
set
{
state = LightState.Green;
}
}
public override void ChangeState()
{
//什么都不做
}
}
这里FixLight继承了Light类。
(3)然后,就是最关键的东西了,考虑交通灯肯定不止一个,在一个路口,需要对一些交通灯的状态进行轮换,而且,各个路口的轮换模式还不一样,有的是南北对开,然后左转、有的是直行和左转同时亮,然后是另外一个方向的直行和左转。归根结底,其实就是把交通灯划分为几组,同组的交通灯状态时相同的,状态变换只需要切换当前的组别就可以了。因此,引入组控制器,每个组控制器之间是一个互斥的状态。
/// <summary>
/// 一组控制器
/// </summary>
public class LightControl
{
Dictionary<ControlDirection, Light> lights;
/// <summary>
/// 该控制器控制的所有交通灯,这些交通灯有同样的状态
/// </summary>
public Dictionary<ControlDirection, Light> Lights
{
get
{
return lights;
}
set
{
lights=value;
foreach (Light light in lights.Values)
{
light.Control = this;
}
}
}

LightState state;

/// <summary>
/// 本组内的状态
/// </summary>
public LightState State
{
get
{
return state;
}
set
{
state = value;
ChangeState(state);
}
}

public LightControl()
{
Lights = new Dictionary<ControlDirection, Light>();
}

public void ChangeState()
{
foreach (Light light in Lights.Values)
{
light.ChangeState();
}
}
}
(4) 另外,在日常生活中,我们还注意到在路口等红灯的时候,如果一个路口的交通灯不会自动变化的话,往往在路口边都会有个大箱子,一个交通协管站在边上,时间差不多了的时候,就伸手在箱子里拨一下,灯就变了,当然,有的时候是交警在路口拿个遥控器按一下,效果是一样的。站在用户接口的角度上,不可能让他们去一组组改变状态,因此,就会有个路口控制器,针对每一组进行轮换控制。因此,这里设置一个路口控制器。
/// <summary>
/// 路口控制器
/// </summary>
public class CrossRoadControl
{

/// <summary>
/// 该路口的交通灯集合,这个集合其实仅在动态改变本路**通灯分组的时候需要用到
/// </summary>
public Dictionary<ControlDirection, Light> Lights
{
get;
set;
}

List<LightControl> controls;
/// <summary>
/// 该路口的控制器集合
/// </summary>
public List<LightControl> Controls
{
get
{
return controls;
}
set
{
controls = value;
if (value.Count > 0)
{
activeIndex = 0;
}
}
}

int activeIndex;

/// <summary>
/// 当前激活的控制器序号
/// </summary>
public int ActiveIndex
{
get
{
return activeIndex;
}
set
{
activeIndex = value;
if (value >=0 && value<controls.Count)
{

foreach (LightControl control in controls)
{
if (controls.IndexOf(control)==activeIndex)
{
control.ChangeState( LightState.Green);
}
else
{
control.ChangeState( LightState.Red);
}

}
}
}
}


public CrossRoadControl()
{
Controls = new List<LightControl>();
Lights=new Dictionary<ControlDirection,Light>();
}

/// <summary>
/// 改变所有交通灯到下一组状态
/// </summary>
public void ChangeState()
{
//当前这一组变化信号
controls[activeIndex].ChangeState();
activeIndex++;
if (activeIndex >= controls.Count)
activeIndex = 0;
//下一组变化信号
controls[activeIndex].ChangeState();
}

}
这里,Light、LightControl和C rossRoadControl三者之间关系如图所示。

(5)最后,就是调用,由于路口控制器中使用集合存储组控制器,因此每个路口是三岔还是十字都是可变的,组控制器控制的交通灯也是集合,因此组控制策略就是可变的,当然别设置成东西向和南北向同组了,这样会碰车的。
这里使用最简单的四个灯的十字路口如下:
//只有四个方向的灯
Dictionary<ControlDirection, Light> lights = new Dictionary<ControlDirection, Light>
{
{ControlDirection.NS,new Light{ Direction=ControlDirection.NS} },
{ControlDirection.SN,new Light{ Direction=ControlDirection.SN} },
{ControlDirection.WE,new Light{ Direction=ControlDirection.WE} },
{ControlDirection.EW,new Light{ Direction=ControlDirection.EW} }
};
#region 分为两组
LightControl control1 = new LightControl();
control1.Lights = new Dictionary<ControlDirection, Light>
{
{ControlDirection.NS,lights[ControlDirection.NS]},
{ControlDirection.SN,lights[ControlDirection.SN]},
};//南北,北南是一组

LightControl control2 = new LightControl();
control2.Lights = new Dictionary<ControlDirection, Light>
{
{ControlDirection.EW,lights[ControlDirection.EW]},
{ControlDirection.WE,lights[ControlDirection.WE]},
};//东西,西东是一组


List<LightControl> controls = new List<LightControl>();
controls.Add(control1);
controls.Add(control2);
#endregion

//该路口控制器只需要控制两组灯即可
CrossRoadControl road = new CrossRoadControl
{
Controls = controls,
Lights = lights
};
road.ActiveIndex = 0;
InitDisplay(road);
RefreshButton();

StopThread();
thd = new Thread(new ParameterizedThreadStart(Begin));
thd.Start(road);
其实,上面还可以组合成八方向,有左转,八方向,右转灯常亮,三岔路口等,代码类似,这里就不做介绍了。到这里, 基本上交通管理系统完成了,其结构如下:
路口控制器--->组控制器---->交通灯
如果考虑路口车辆的通过,这个就不属于交通灯控制的范畴了,有兴趣的可以自己开一个线程生成汽车,然后判断当前方向的灯是否亮(人工智能模拟?)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: