黑马程序员-交通灯面试题总结

本文介绍了一个模拟十字路口交通灯管理系统的实现方案,包括灯、路和控制器的设计与代码实现。

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

下面是项目需求:

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

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

例如:

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

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

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

       。。。

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

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

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

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

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

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

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

我刚看到的时候是想啊想,解过想了半天还是好乱,车的转弯行走路线就把我搞乱了,更别提下手写代码了。

所以后来干脆直接看视频,结果真的学到即为重要的一点:当我们感觉事情复杂的时候,不要只用脑袋去想,有时候想破头都没用,

我们可以用笔或记或画,把示意图做出来,在看就简单多了。



一共有12条路线,有4条是不需要我们设计的,还剩下8条,没两条是对应的,也就是只剩下四条,这样我们就能确定我们要做的就是做出12盏灯,有4盏是常绿的,剩下的8盏两两对相,也就是我们只需要控制4盏就好,另外4盏和这4盏对应变就好。
下面我们根据思路来把张老师的代码捋顺一下。
首先写一个灯的类,这个类最好用枚举写,比较简单。

 public enum Lamp {
 //创建12盏灯,把对应的灯和下一盏要亮的灯,和当前等的状态,当作参数传给当前灯。
 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),
 //这四盏是右拐的灯,其实不需要,我们写上并让他一直常亮就可以了,为了便与理解。
 S2E(null,null,true),E2N(null,null,true),N2W(null,null,true),W2S(null,null,true);
 //用3个变量来接收3个参数。
 private boolean lighted;
 private String opposite;
 private String next;
 //创建带3个参数的构造方法
 private Lamp(String opposite,String next,boolean lighted){
  this.opposite=opposite;
  this.lighted=lighted;
  this.next=next;
 }
 //获取当前灯的状态。
 public boolean isLighted(){
  return lighted;
 }
 //让当前灯变量,相当于绿灯,如果对应灯不为null,让对应的灯变亮。
 public void light(){
  this.lighted=true;
  if(opposite!=null){
   Lamp.valueOf(opposite).light();
  }
 }
 //让当前灯变暗,相当于红灯,如果对应灯不为null,让对应灯变暗。如果下一盏灯不为null;让下一盏灯变亮,并返回下一盏灯。
 public Lamp blackOut(){
  this.lighted=false;
  if(opposite!=null){
   Lamp.valueOf(opposite).blackOut();
  }
  Lamp nextLamp=null;
  if(next!=null){
   nextLamp=Lamp.valueOf(opposite);
   nextLamp.light();
  }
  return nextLamp;
 }
}

这时灯的代码就写完了。下面是路的代码,车是行走在路上,我们可以把路看成一个集合,车就是集合中的元素,车是随即添加的,但是只有绿灯的时候才可以每过一小段时间删除一个。模拟现实生活中车走在路上的情景。

import java.util.*;
import java.util.concurrent.*;

public class Load {

 //创建一个集合,用来存放车量。
 private List<String> ches=new ArrayList<String>();
 String name=null;//每个方向的路名,12个方向,单独看成12条马路。
  public Load(String name){
   this.name=name;
   
   ExecutorService pool=Executors.newSingleThreadExecutor();//创建一个单一线程池。每条路需要
   pool.execute(new Runnable() {                            //一个单独的线程控制。
     int count=1;
    public void run() {//用匿名内部类创建一个线程对象并实现run方法。
     while(true){
      try {
       //int i=(int) (Math.random()*10+1);
       int j=(new Random().nextInt(10)+1);//用随机数来模拟,每隔一段时来一两车。
       Thread.sleep(j*1000);
      } catch (InterruptedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
      ches.add(Load.this.name+"_"+count);//将车辆添加到马路上。
      count++;//嘿嘿区分车辆的,看做车牌号吧,不然打印程序的时候不好看输出结果。
     }
     
    }
   });
  ScheduledExecutorService acheduled=Executors.newScheduledThreadPool(1);//创建一个定时器线程池。
  acheduled.scheduleAtFixedRate(new Runnable() {
   //又是匿名内部类,不多说了。
   @Override
   public void run() {
    if(ches.size()>0){//首先判断集合是否为空,即马路上有没有车,
     boolean lighted=Lamp.valueOf(Load.this.name).isLighted();
     if(lighted){//在判断当前灯是否是绿灯,
      System.out.println(ches.remove(0)+"正在通行ing");//是的话就把元素删除,即把车开过去。
     }
    }
   }
  }, 
  1, //定时器第一次的执行时间。
  1,//以后每隔多长时间执行一次。
  TimeUnit.SECONDS);//定时器的时间单位。
  }

}

哎,总算吧路也搞定了。写注释也是一个麻烦的事,但是为了以后程序可以随时看懂,这都是必须要做的事。

马上就要完成了,在写一个路灯控制器,用来给路灯的转换定时的。

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class LampController {
 private Lamp currentLamp;
 public LampController(){
  currentLamp=Lamp.S2N;//给路灯控制器一个初始化的路灯。
  currentLamp.light();//并初始化为绿灯。
  
  ScheduledExecutorService acheduled=Executors.newScheduledThreadPool(1);
  acheduled.scheduleAtFixedRate(new Runnable() {//创建一个定时器,让路灯定时改变。
   
   @Override
   public void run() {
    // TODO Auto-generated method stub
    currentLamp=currentLamp.blackOut();//将等变成红灯。下面就不用说了吧。前面讲过了。
   }
  },
  10,
  10, 
  TimeUnit.SECONDS);
 }


}
哈哈,总算大功告成了,一切都写完了。

马上写个主程序运行一下吧。

public class MainClass {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  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 Load(directions[i]);//初始化12条马路,条数一定弄对啊
  }
  new LampController();//初始化路灯控制器
 }

}
OK了,以上代码在myeclipse8.5运行没有问题,java版本不能低于1.5。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值