面试题二


交通灯管理系统

   

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



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

例如:



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



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



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



       。。。



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

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

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

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



每辆车通过路口时间为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); 
    其实,上面还可以组合成八方向,有左转,八方向,右转灯常亮,三岔路口等,代码类似,这里就不做介绍了。到这里, 基本上交通管理系统完成了,其结构如下:
路口控制器--->组控制器---->交通灯
如果考虑路口车辆的通过,这个就不属于交通灯控制的范畴了,有兴趣的可以自己开一个线程生成汽车,然后判断当前方向的灯是否亮(人工智能模拟?)

你可能感兴趣的:(设计模式,面试,生活,交通,LINQ)