路口交通灯控制的模拟实现

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

两个枚举设定

///

/// 交通灯颜色 /// public enum LightState { Green=0, Red=1 } /// /// 控制的方向 /// public enum ControlDirection { /// /// 南北 /// SN, /// /// 北南 /// NS, /// /// 东西 /// EW, /// /// 西东 /// WE, /// /// 南西 /// SW, /// /// 南东,右转 /// SE, /// /// 北东 /// NE, /// /// 北西,右转 /// NW, /// /// 西南,右转 /// WS, /// /// 西北 /// WN, /// /// 东北,右转 /// EN, /// /// 东南 /// ES }

 

对于交通灯,需求中需要考虑的是常亮的灯,比如,大部分路口的右转灯;对于所有的灯,都要有一个状态,控制的方向,以及一个改变状态的方法。

 

///

/// 一个交通灯 /// public class Light { protected LightState state; /// /// 交通灯当前的颜色状态 /// public virtual LightState State { get { return state; } set { state = value; } } public virtual void ChangeState() { //忽略黄灯 State = (LightState)Math.Abs((int)State-1); } /// /// 该交通灯控制的方向 /// public ControlDirection Direction { get; set; } } /// /// 固定常亮的信号灯 /// public class FixLight:Light { public override LightState State { get { return base.State; } set { state = LightState.Green; } } public override void ChangeState() { //什么都不做 } }

一个简单的继承关系。

 

接下来就是麻烦的东西了,交通灯肯定不止一个,在一个路口,需要对一些交通灯的状态进行轮换,而且,各个路口的轮换模式还不一样,有的是南北对开,然后左转、有的是直行和左转同时亮,然后是另外一个方向的直行和左转。归根结底,其实就是把交通灯划分为几组,同组的交通灯状态时相同的,状态变换只需要切换当前的组别就可以了。因此,引入组控制器,每个组控制器之间是一个互斥的状态。

///

/// 一组控制器 /// public class LightControl { Dictionary lights; /// /// 该控制器控制的所有交通灯,这些交通灯有同样的状态 /// public Dictionary Lights { get { return lights; } set { lights=value; foreach (Light light in lights.Values) { light.Control = this; } } } LightState state; /// /// 本组内的状态 /// public LightState State { get { return state; } set { state = value; ChangeState(state); } } public LightControl() { Lights = new Dictionary(); } public void ChangeState() { foreach (Light light in Lights.Values) { light.ChangeState(); } } }

 

不知道有没有人在路口等红灯的时候注意过,如果一个路口的交通灯不会自动变化的话,往往在路口边都会有个大箱子,一个交通协管站在边上,时间差不多了的时候,就伸手在箱子里拨一下,灯就变了,当然,有的时候是交警在路口拿个遥控器按一下,效果是一样的。站在用户接口的角度上,不可能让他们去一组组改变状态,因此,就会有个路口控制器,针对每一组进行轮换控制
///

/// 路口控制器 /// public class CrossRoadControl { /// /// 该路口的交通灯集合,这个集合其实仅在动态改变本路口交通灯分组的时候需要用到 /// public Dictionary Lights { get; set; } List controls; /// /// 该路口的控制器集合 /// public List Controls { get { return controls; } set { controls = value; if (value.Count > 0) { activeIndex = 0; } } } int activeIndex; /// /// 当前激活的控制器序号 /// public int ActiveIndex { get { return activeIndex; } set { activeIndex = value; if (value >=0 && value(); Lights=new Dictionary(); } /// /// 改变所有交通灯到下一组状态 /// public void ChangeState() { //当前这一组变化信号 controls[activeIndex].ChangeState(); activeIndex++; if (activeIndex >= controls.Count) activeIndex = 0; //下一组变化信号 controls[activeIndex].ChangeState(); } }

 

最终的调用,由于路口控制器中使用集合存储组控制器,因此每个路口是三岔还是十字都是可变的,组控制器控制的交通灯也是集合,因此组控制策略就是可变的,当然别设置成东西向和南北向同组了,这样会碰车的

 

最简单的只有四个灯的十字路口如下:

//只有四个方向的灯 Dictionary lights = new Dictionary { {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.NS,lights[ControlDirection.NS]}, {ControlDirection.SN,lights[ControlDirection.SN]}, };//南北,北南是一组 LightControl control2 = new LightControl(); control2.Lights = new Dictionary { {ControlDirection.EW,lights[ControlDirection.EW]}, {ControlDirection.WE,lights[ControlDirection.WE]}, };//东西,西东是一组 List controls = new List(); 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);

至于路口车辆的通过,这个就不属于交通灯控制的范畴了,有兴趣的可以自己开一个线程生成汽车,然后判断当前方向的灯是否亮(人工智能模拟?)

 

这个例子的结构其实这么一看就知道了

 

路口控制器--->组控制器---->交通灯

 

完整源码在这里下载

 

vs2008下通过

你可能感兴趣的:(.net入门)