交通灯管理系统思路总结


一.思路明确

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

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

例如:

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

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

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

       。。。

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

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

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

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

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

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

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

难点:

1.如何理清思路?

2.如何建立具体对象?

3.如何想到线程问题?

一.应该对生活有很深的体验,和熟练的编程思路,此时画图法帮助很大。

总共有12条路线,为了统一编程模型,可以假设每条路线都有一个红绿灯对其进行控制,右转弯的4条路线的控制灯可以假设称为常绿状态,另外,其他的8条线路是两两成对的,可以归为4组,所以,程序只需考虑1S2N 2S2W 3E2W 4E2S 这4条路线的控制灯的切换顺序,这4条路线相反方向的路线的控制灯跟随这4条路线切换,不必额外考虑。


找到突破口很重要!尽量优化条件。

二.建立具体对象

谁拥有数据,谁就对外提供操作这些数据的方法。

开始构思一下有哪些对象:路线-->车,  红绿灯--->红绿灯的控制系统

汽车看到自己所在路线对应的灯绿了就穿过路口吗?不是,还需要看前面是否有车,看前面是否有车,该问哪个对象呢?该问路,路中存储着车辆的集合,显然路上就应该有增加车辆和减少车辆的方法了。(面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法。)再看题目,我们这里并不要体现车辆移动的过程,只是捕捉出车辆穿过路口的过程,也就是捕捉路上减少一辆车的过程,所以,这个车并不需要单独设计成为一个对象,用一个字符串表示就可以了。在1中初步设想的对象就减少了一个。这个项目只需要3个对象即可。

在这个十字路口,有且仅有12盏红绿灯,因此红绿灯可以用枚举来实现。其中右转的四盏灯常绿,剩下的八盏灯可以分为4组。因此只需要考虑4盏灯的红绿变化。


  • 路线(Road) 
        |-- 路线 (12条)
        |-- 随机生成车辆
        |-- 减少车辆 (每辆车通过路口时间为1秒)
  • 红绿灯 (Lamp)
        |-- 12条路线 (相应12盏红绿灯) -->应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。-->优化-->4盏灯的红绿变化  (用到枚举)
        |--灯亮的方法
        |--灯灭的方法
  • 红绿灯的控制系统  (LampController)
     |--控制灯变化的方法
Road 类:
public class Road  
{  
 private List<String> vehicles = new ArrayList<String>(); //用这个List来保存这条路上的车   
 private String name = null;      //这条路线和灯的名字
 public Road(String name) //构造方法,每创建一条路时都必须为它命名  
 {  
  this.name = name;  
    
  //启动一个线程,不停地向这条路上增加车辆 
  ExecutorService pool = Executors.newSingleThreadExecutor();  //线程池的作用
  pool.execute(new Runnable()  
  {  
   @Override  
   public void run()  
   {  
    for (int i = 0; i < 1000; i++)  
    {  
     try  
     {  
      Thread.sleep((new Random().nextInt(10)+1) * 1000);  //每1到10秒内.nextInt(10) 10以内,不包括10
     } catch (InterruptedException e)  
     {  
      e.printStackTrace();  
     }  
//     vehicles.add(name + "_" + i);这样写编译会报错,因为这里访问的是这个构造方法里的局部变量。在匿名内部类里访问局部变量,这个局部变量必须用final修饰符修饰 所以这里有两种改法:1.加final修饰符,2.在这里访问外部类的成员变量。  
     vehicles.add(Road.this.name + "_" + i);  //访问外部类的成员变量。  
    }  
   }  
  });  
    
  //启动一个定时器 ,这是<span style="font-family: 宋体; ">ScheduledExecutorService 里面的定时方法</span>
  ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);  
  timer.scheduleAtFixedRate(   //这个方法需要四个参数  
    new Runnable()          //如果是绿灯,并且路上有车,就移走一辆车  
  
    {  
     @Override  
     public void run()  
     {  
      if (vehicles.size()>0)  
      {  
       boolean lighted = Lamp.valueOf(Road.this.name).isLighted();  
//       if (true == lighted) 低能的表现啊。 
       if (lighted)  
       {  
        System.out.println(vehicles.remove(0) + "is traversing ! ");  
       }  
      }  
     }  
    },                      
    1,                   //参数2:多少时间后开始执行任务  
    1,                   //参数3:每隔多少时间执行一次任务  
    TimeUnit.SECONDS     //参数4:前面这两个时间的单位  
    );  
 }  
}
Lamp类:
难点:
1.S2NS2WE2WE2N这四个方向上的Lamp对象依次轮询变亮
2.灯绿,相反方向的灯要变绿,灯变红,对应方向的灯也要变红,并且下一个方向的灯要变绿
package com.isoftstone.interview.traffic;  
  
public enum Lamp  
{  
 S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false), //有业务逻辑的4个灯  
 N2S(null,null,false)  ,N2E(null,null,false)  ,W2E(null,null,false)  ,W2N(null,null,false)  , //和上面一一对应的4个灯  
 S2E(null,null,true)   ,E2N(null,null,true)   ,N2W(null,null,true)   ,W2S(null,null,true)   ; //常绿的4个灯  
   
 private boolean lighted; //用来表示灯的状态。true为绿灯,false为红灯  
 private String opposite;//这里要把相对应的Lamp用字符串代替,是因为S2N(N2S)这种写法可能会报错,Cannot reference a field before it is defined.  
 private String next; //当前灯变红时,下一盏应该变绿的灯  
   
 private Lamp(String opposite,String next,boolean lighted)  
 {  
  this.opposite = opposite;  
  this.next = next;  
  this.lighted = lighted;  
 }  
   
 public boolean isLighted() //返回当前灯的状态  
 {  
  return lighted;  
 }  
   
 public void light() // 让当前灯变绿的方法,同时检查当前灯有没有对应灯,若有,需将对应灯也变绿  
 {  
  this.lighted = true;  
    
  if (opposite != null) //这个条件判断很重要,否则就是死循环了  
  {  
   Lamp.valueOf(opposite).light();  
  }  
  System.out.println(name()+" lamp is green ,下面总共应该有6个方向能看到汽车穿过 !"); //这六个方向是指:当前路线,  
  
//当前路线的对应路线,以及4个常绿路线。  
 }  
   
  
// 让当前灯变红的方法,同时检查当前灯有没有对应灯,若有,需将对应灯也变红。然后,将当前灯的下一盏灯变绿。  
  
 public Lamp blackOut()  
 {  
  this.lighted = false;  
  if (opposite != null) //这个条件判断很重要,否则就是死循环了  
  {  
   Lamp.valueOf(opposite).blackOut();  
  }  
  
  Lamp nextLamp = null;  
  if (next != null)  
  {  
   nextLamp = Lamp.valueOf(next);  
   System.out.println("绿灯从 "+name()+" ---------->切换为:"+next);  
   nextLamp.light();  
  }  
    
  return nextLamp;  
 }  
}

LampController
重要:单例,定时器
public class LampController  
{  
 private Lamp currentLamp;  
   
 public LampController()  
 {  
  currentLamp = Lamp.S2N; //最开始设定S2N这个灯是绿的  
  currentLamp.light();  
    
  ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);  
  timer.scheduleAtFixedRate(  
    new Runnable() //每隔10s将当前灯变暗,同时将currentLamp变为下一盏灯。  
    {  
     @Override  
     public void run()  
     {  
      System.out.println("灯控定时器");  
      currentLamp = currentLamp.blackOut();  
     }  
    },  
    2,  
    2,  
    TimeUnit.SECONDS  
    );  
 }  
  
} 

MainClass
产生路线,放进集合中去。
public class MainClass  
{  
 public static void main(String[] args)  
 {  
  //new出12条路线,再加一个灯控制器,就可以模拟一个十字路口了。  
  String[] directions = new String[]{  
    "S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"  
  };  
  for (int i = 0; i < directions.length; i++)  
  {  
   new Road(directions[i]);  
  }  
    
  new LampController();    //红绿灯控制器  
 }  
}  

总结:
1.面试时英语也很重要。
2.思路解题,平时要多练。
3."谁拥有数据,谁就对外提供操作这些数据的方法"



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值