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

交通灯管理系统

 

   

 

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

 

 

 

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

 

例如:

 

 

 

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

 

 

 

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

 

 

 

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

 

 

 

       。。。

 

 

 

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

 

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

 

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

 

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

 

 

 

每辆车通过路口时间为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();  

     }  

 

 } 

这里,LightLightControlC 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); 

    其实,上面还可以组合成八方向,有左转,八方向,右转灯常亮,三岔路口等,代码类似,这里就不做介绍了。到这里, 基本上交通管理系统完成了,其结构如下:

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

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值