黑马程序员——交通灯管理系统学习笔记

来源:互联网 发布:知乎 前苏联军事强大 编辑:程序博客网 时间:2024/05/27 20:27
------- android培训、java培训、期待与您交流! ----------

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

 异步随机生成按照各个路线行驶的车辆。
例如:
       由南向而来去往北向的车辆 ---- 直行车辆
       由西向而来去往南向的车辆 ---- 右转车辆
       由东向而来去往南向的车辆 ---- 左转车辆
       。。。
 信号灯忽略黄灯,只考虑红灯和绿灯。

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

 具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。

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

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

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

          先把题目贴上,刚开始没看张老师讲解这道题目之前是完全摸不着头脑,感觉这个题目非常的复杂,看了视频后发现如果思想对了也没有想象中的复杂,这种功底不是一天两天能够做得到的,而是经过常年累月的积累的沉淀。
1:大概思路:题目要求是要模拟一个十字路口的真实的交通灯,因为路口有东、西、南、北四个方向,而无论你站在那个方向,你前面都会有3条路线可以走(向左,向右,向前),所以总共会有12条路线。
     然后我们可以假设每条路线的前面都有一个灯,如果是绿灯就前进,如果是红灯就停下,但是无乱是哪个路口的右转弯都是不需要红灯的,所以可以把这个方向的灯设置为常绿,所以只有8条路线要进行红绿灯的切换,让我们在思考一下,因为每个灯都有一个相对应的灯,比如说从南向北的灯是绿,那摩从北向南的灯也应该是绿,对面的灯是跟着这边的等切换的,所以这样子以来右将题目简化了许多,只要在4个路线上的灯进行轮流切换就可以了。
假设要切换的灯分别是(S2N,S2W,E2W,E2N),这4盏灯的对面的灯分别是(N2S,N2E,W2E,W2N),常绿的四盏灯分别为(S2E,E2N,N2W,W2S)。
2:既然已经知道了是只要在4盏灯之间进行切换,那切换的顺序是怎么样的呢?因为我们都经常过十字路口,现在假设由南向北跟由北向南的方向变红了,那摩接下来应该是由南向西跟又北向东的车要开始走了,搞清了这点之后就基本上知道这些灯之间的切换了。
      假设这四个方向的灯随便哪一个是绿的,那摩在它变绿时必须也将自己对面的灯变绿,当自己变红时必须将自己对面的灯也变红,另外还要将自己的下一盏灯变绿。
3:考虑清楚了路线之间的切换后就要考虑车辆的前行了,如果某辆车它在的路线的灯是绿的,那摩它就可以前行,这里还需要考虑到一个问题就是如果这辆车前面还有车呢,岂不是要跟前面的车相撞了,所有车辆前行的另外一个条件就是它必须是这条路上的第一辆车。
4:既然路上的车会因穿过路口而减少,那摩路上的车也会不断的进行增加,可以在这里设个时间的随机数,因为什么时候来一辆车世间是不确定的,不管这条路上的灯是什么颜色,这条路上的车都必须不断的增加。可以把路看作是一个ArrayList集合,路上的车都是这个集合中的元素,可以把车看做是一个字符串,当车辆穿过路口时,就好比这个集合中少了一个字符串对象,增加一辆车辆时,就往集合中增加一个字符串,因此就不要考虑车这个对象了,又进一步将问题简单化了。用路来控制这些车,路有一个增加车辆和减少车辆的方法。
基本思路搞清楚之后就是代码的具体实现了:
public class Load {
 private String name;
 private List<String> vechicles=new ArrayList<String>();
 Load(String name){
 定义一个Load类,在Load类的构造方法中接收一个name的参数
  this.name=name; 
   ExecutorService pools=Executors.newFixedThreadPool(1);    创建了一个线程池,用这个线程池中的一个线程去每隔一段时间就往集合中添加一辆车。
   pools.execute(new Runnable() {
    public void run() {
     for(int x=0;x<1000;x++)
     {
      try {
       Thread.sleep(((int)(Math.random()*10)+1)*1000);      添加车的时间间隔是个1到10之间的随机数。
      } catch (InterruptedException e) {
       e.printStackTrace();
      }
      vechicles.add(Load.this.name+"..."+x);    添加的车的名字是路的名字加车的编号。    
     }    
    }
   });
ScheduledExecutorService time= Executors.newSingleThreadScheduledExecutor();     创建了一个单线程执行程序,调用一个定时器方法,每隔多长时间会执行要执行的程序。
   time.scheduleAtFixedRate(new Runnable() {      这个方法接收4个参数,第一个参数是Runnable接口,也就是要执行的程序。     
    public void run() {
     if(vechicles.size()>0){
      boolean lighted=true;
      if(lighted)
      {
       System.out.println(vechicles.remove(0) + "车开走了");
      }
     }
    }
   },
   1,                               第二个参数是首次执行的延迟时间

   1,                                第三个参数是连续执行之间的时间周期

   TimeUnit.SECONDS);     第四个参数是这2个时间的类型,是一个枚举类,有秒,时,分等。
上面这段代码用到了一个跟线程有关的类Executors,这个类中的创建线程的方法之前没有接触过,不过好像很有用。

定义一个枚举,枚举的实例对象是12盏灯。
package cn.itcast.interview.traffic;
public enum Lamp {
 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),
 //需要轮流转换的灯的对面4盏灯也没有下一盏灯跟对面的灯,初始化是按的
 S2E(null,null,true),E2N(null,null,true),N2W(null,null,true),W2S(null,null,true);
 //4个右转弯的灯没有下一个灯跟对面的灯,而且一直是绿的
 private Lamp(String opposite,String nextLamp,boolean lighted)
 {
  this.opposite=opposite;
  this.nextLamp=nextLamp;
  this.lighted=lighted;
 }
 private Lamp(){}
 private boolean lighted;
 private String opposite;
 private String nextLamp;
 public boolean isLighted()
 {
  return lighted;
 }
 public void light()
 {
  this.lighted=true;
  if(opposite!=null)
   Lamp.valueOf(opposite).light();
  //在这里需要将灯的字符串作为参数传递给枚举类,枚举类将其转换为枚举的实例对象后在调用将灯变绿的方法。
 }
 public Lamp black()
 {
  this.lighted=false;
  if(opposite!=null)   //这里为什么要判断对面的是否为空呢,因为我们只需要让4盏灯有对应的灯即可。
   //在这里需要将灯的字符串作为参数传递给枚举类,枚举类将其转换为枚举的实例对象后在调用将灯变红的方法。
   Lamp.valueOf(opposite).black();
  Lamp next=Lamp.valueOf(nextLamp);
  if(nextLamp!=null)   //同上
   next.light();
  return next;
 }
}
定义一个控制灯的类
public class LampController {
 private Lamp currentLamp;
 public LampController(){
  currentLamp=Lamp.E2N;       让当前灯为E2N,然后让他变亮。
  currentLamp.light();
  ScheduledExecutorService time=Executors.newSingleThreadScheduledExecutor();
  定义一个定时器每隔10秒钟就切换一次,将当前等变黑,将下一盏灯变绿
  time.scheduleAtFixedRate(new Runnable() {   
   public void run() {
    currentLamp=currentLamp.black();    
   }
  } ,
      10,
  10,
  TimeUnit.SECONDS);
 }
}
在主函数中创建路的实例对象,创建12条路,路的名字跟灯的名字相同,然后启动控制灯的系统,整个交通路口就跑起来了!!
public static void main(String[] args) {
  String[] s={"S2N"," S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"};
  for(String ss:s)
  {
   new Road(ss);
  }
  new LampController();
 }
运行结果正常,以上代码是参照老师的代码自己写的,题目是理解了,但是如果下次换个难度相同的题目的话估计还是很难做出来,
只能慢慢来。

------- android培训、java培训、期待与您交流! ---------- 

 详细请查看:http://edu.csdn.net/heima/

原创粉丝点击