交通灯系统的实现与代码

来源:互联网 发布:0信誉淘宝店铺 在哪买 编辑:程序博客网 时间:2024/06/08 10:34

交通灯管理系统的项目需求
模拟实现十字路口的交通灯管理系统罗技,具体需求如下:
*异步随即生成按照各个路线行驶的车辆。
例如:
 由南向而来去往北向的车辆 ----直行车辆
 由西向而来去往南向的车辆 ----右转车辆
 由东向而来去往南向的车辆 ----左行车辆
  
*信号灯忽略黄灯,只考虑红灯和绿灯。
*应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
*具体信号灯控制罗技与现实生活中普通交通灯控制罗技相同,不考虑特殊情况下的控制逻辑。
注意:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。

*每辆车通过路口时间为1秒(提示:可以通过线程SLEEP的方式模拟)。
*随即生成车辆时间间隔以及红绿灯交换时间间隔自定义,可以设置。
*不要求实现GUI,只考虑系统逻辑实现,可以通过LOG方式展现程序运行结果。

--------------------------------------------------------------------------
面向对象的分析与设计
*每条路线上都会出现多辆车,路线上要随即增加新的车,在灯绿期间还要每秒钟减少一辆车。

*每条路线每个一秒都会检查控制本路线的灯是否为绿,一个灯由绿变红时,应该将下一个方向的灯变绿。

面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法。在牢牢掌握几个典型的案例就可以了:人在黑板上画圈,列车司机学院的两个面向对象的面试题,用面向对象的方式设计如下场景。
“两块石头磨成一把石刀,石刀可以砍树,砍成木材,木材做成椅子”,
“球从一个绳子的一段移动到了另一端”

===========================================================================
Road类的编写
*每条Road(路)对象都应该有一个name成员变量来代表方向,有一个vehicles(交通工具)成员变量来代表方向上的车辆集合。
*在Road对象的构造方法中启动一个线程每隔一个随即的时间向vehicles集合中增加一辆车(用一个"路线名_id"形式的字符串进行表示)。
*在 Road对象的构造方法中启动一个定时器,每隔一秒检查方向的


 List<String> vechicles = new ArrayList<String>();
 private String name = null;
 public Road(String name){
  this.name = name;
  ExecutorService pool = Executors.newSingleThreadExecutor(); //创建一个单独的线程池,哪个闲着调用哪个
  //向一个线程池中添加一项任务,然后线程池中会随即抽取一个线程来工作。
  pool.execute(new Runnable(){
   public void run(){ // 此处不可以直接new Runnable()接口,如果加{}就是一个Runnable()的内部实现对象
    try {
     Thread.sleep((new Random().nextInt(10))*1000);//随即添加1秒到九秒之间会来一辆车
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    for(int i=0;i<3;i++){
     vechicles.add(Road.this.name+"_"+i+"--------going"); //当内部类的变量名与全局变量名发生冲突时:this.变量名是内部类中的, 类名.this.变量名才是成员变量名
    }
   }
  });
  ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);//使用一个调度池(某个阶段做某事)   
  // 这个代码不够全面,需要用另外一个方法更能实现业务需求
  /*timer.schedule(//创建一个定时器 
    new Runnable(){
     
    },// 创建一个任务
    1, //多久之后执行上面任务
    TimeUnit.SECONDS);//时间计量器,计算上面数字是秒还是分.*/
  
  timer.scheduleAtFixedRate(
    new Runnable(){// 创建一个任务
     public void run(){
      if(vechicles.size()>0){ //如果公路上有车在做处理
       //得到该名字的路线路灯是否为绿
       boolean light = Lemp.valueOf(Road.this.name).isLighted();
       if(light){
        System.out.println(vechicles.remove(0));//remove方法返回的是正被删除的对象
       }
      }
     }
    },
    1, //多久之后执行上面任务
    1, //再过多久继续执行一次
    TimeUnit.SECONDS);//时间计量器,计算上面数字是秒还是分。 
  
  
  
 
 }
=========================================================================================
Lemp类的编写

public enum Lemp {

 
 S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),
 N2S(null,null,false),N2E(null,null,false),W2E(null,null,false),W2N(null,null,false),
 S2E(null,null,true),E2N(null,null,true),N2W(null,null,true),W2S(null,null,true);
 private boolean lighted ;//是否绿灯
 private String opposite; //对应的灯
 private String next ;//下一个灯
 public boolean isLighted(){
  return lighted;
 }
 private Lemp(String opp,String next,boolean lighted){ //参数1对应的灯,2下一个灯,3开始时是否绿
  /**S2N(N2S)如果不加双引号会报错,因为编译器在编译时会先声明后编译,但是先生成的要调用
  后生成的是无法通过的,我们可以用一个字符串来接收,然后再用枚举的方法valueof()中放入对象名
  就会返回对象名的那个类
  */
  this.opposite = opp;
  this.next = next;
  this.lighted = lighted;
  
 }
 private Lemp(){
  
 }
 public void light(){
  this.lighted = true; //这里是否为true有何作用。
  if(opposite!=null){//判断之后为何就不会死循环。
  Lemp.valueOf(opposite).light();//通过枚举名类获得对象中的方法。
  }
  System.out.println(name()+"是绿灯,应该有6条路线可以通过");
 }
 public Lemp blackOut(){ //当前的灯变黑方法
  this.lighted =  false;
  if(opposite!=null){
   Lemp.valueOf(opposite).blackOut(); //通过枚举名类获得对象中的方法。
  }
  Lemp nextLamp = null;
  if(next!=null){
   nextLamp = Lemp.valueOf(next); // 得到下一个灯
   nextLamp.light(); //在关闭当前灯时使下一个灯变绿
  }
  System.out.println("绿灯从"+name()+"转变到"+next);
  return nextLamp; //返回下一个交通灯
  
 }
}


============================================================================================
LempController类的编写


public class Lempcontroller {
 Lemp currentLemp;
 public Lempcontroller() {
  currentLemp = Lemp.S2N;
  currentLemp.light(); //当前的灯为绿
  ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);//在线程池i中使用一个线程的定时器
  timer.scheduleAtFixedRate(
     new Runnable(){//每隔10秒就给当前的灯变黑、
     public void run(){
      System.out.println("变灯");
      currentLemp = currentLemp.blackOut(); // 将当前灯变黑时执行下一个灯变绿并且返回下一个灯对象
      
     }
    },
    10,
    10,
    TimeUnit.SECONDS);
 }
 

==========================================================================================
测试方法:
public static void main(String[] args) {
  // TODO Auto-generated method stub

  String[] Lemps = new String[]{
  "S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S" //将12条路线放到一个数组中方便处理。
  };
  for(int i =0;i<Lemps.length;i++){
   Road road = new Road(Lemps[i]);
  }
  new Lempcontroller();
 }

原创粉丝点击