【黑马程序员】7k面试题之交通灯

来源:互联网 发布:万能视频修复软件 编辑:程序博客网 时间:2024/05/21 16:41

------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------

 交通灯项目需求:

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

 

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

例如:

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

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

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

       。。。

 

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

 

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

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

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

 

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

 

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

 

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

交通灯项目需求分析思路:

项目为模拟现实生活中的交通信号灯,为方便业务逻辑分析我们先来画图分析。

项目分为三大主体:路,交通灯,车。

上图所示,根据需求我们得知一共有12条路线。南---->北,北.---->南,南---->西,北---->东,东---->西,西---->东,东---->南,西---->北,南---->东,北---->西,东---->北,西---->南。

每条路有自己的车,车为路的数据,所以根据面向对象设计模式 ,设计Road类,封装road类。 

Road类应该具有的方法和属性。

name:路的方向。

vechicles:存储车辆的集合。

public Road(String name):

构造方法,在创建路对象的时候,因该给路一个名字,然后用这个名字的信号灯来控制此的可行与否。

应该不断有车上路并排队过信号灯,所以创建Road对象时,应该加一个线程,每过若干时间为这条路上增加一辆车。

定时器:路应该每过1秒来判断一下此路是否可通行(是否为绿灯),然后让车队里的每一辆车从第一辆开始过路口。

package com.isoftstone.interview.traffic;import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class Road {private List<String> vechicles = new ArrayList<String>();//车辆集合private String name=null;//名字方向。public Road(){//无参构造方法}public Road(String name){this.name=name;//路的方向ExecutorService pool= Executors.newSingleThreadExecutor();pool.execute(new Runnable(){public void run(){for(int i=0;i<1000;i++){try {Thread.sleep((new Random().nextInt(10)+1)*1000);//随机(1-10)秒后给本路添加一辆汽车} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}vechicles.add(Road.this.name+"_"+i);//随机(1-10)秒后给本路添加一辆汽车}}});ScheduledExecutorService timer= Executors.newScheduledThreadPool(1);timer.scheduleWithFixedDelay(new Runnable(){public void run(){if(vechicles.size()>0){boolean lighted=Lamp.valueOf(Road.this.name).isLighted();//得到当前路灯的可行状态//如果可行,则每秒过一辆车if(lighted){System.out.println(vechicles.remove(0)+"is traversing!");}}}}, 1, 1, TimeUnit.SECONDS);}}

上图所示,根据需求我们得知一共有12条路线。南---->北(S2N),北.---->南(N2S),南---->西(S2W),北---->东(N2E),东---->西(E2W),西---->东(W2E),东---->南(E2S),西---->北(W2N),南---->东(S2E),北---->西(N2W),东---->北(E2N),西---->南(W2S)。

12条路线因该由12个信号灯来指挥当前哪条线路可行驶。

信号灯应该具备的属性:

相对的灯:opposite;//相对的灯的可行状态始终和this一样。例:南往北为绿灯,北往南也为绿灯。

接下来变绿的灯;next;

当前灯可行状态:lighted;

方法:

构造方法:Lamp(String opposite,String next ,boolean lighted);//为灯设置属性。

得到灯的可行状态:isLighted();

设置等的可行状态为true:light();

变灯(把当前所有绿灯关闭,开启接下来路线绿灯):blackOut();

需求“:

右转车辆不受信号灯控制

车辆行驶顺序,假如南北先为绿灯:

1. 南---->北   北.---->南

10秒后,南北绿灯变为红灯,南---->北   北.---->南不可行。换为左拐:

2. 南---->西   北.---->

10秒后,南西左拐绿灯变为红灯,南---->西   北.---->东不可行。换为东西直行

3. 东---->西   西---->东

10秒后,东西绿灯变为红灯东---->西   西---->东不可行。换为东西左拐:

4.东---->南   西---->

10秒后。。。第四步跳回第一步,依次循环变灯。



了解需求后,我们来写这个类,因为这12个灯为固定不变,所以这里我用枚举。

package com.isoftstone.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),S2E(null,null,true),//下面四个为左拐,一直通行不做控制。E2N(null,null,true),N2W(null,null,true),W2S(null,null,true);private String opposite;//当前绿灯的方向private String next;//下一个绿灯的方向private boolean lighted;//private Lamp(){};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();}}//把当前灯和当前灯对面的灯设置为红灯,并把接下来应该转为绿灯的灯和他的对面灯转为绿灯。public Lamp blackOut(){this.lighted=false;if (opposite!=null){Lamp.valueOf(opposite).blackOut();}//Lamp nextLamp=Lamp.valueOf(next);Lamp nextLamp = null;if (next!=null){//nextLamp=Lamp.valueOf(next);Lamp.valueOf(next).light();System.out.println("绿灯从"+name()+"------------>切换为"+next);}return nextLamp;}}

写到这里灯的设计和代码都写出来,这里还差一个控制灯的一个控制器,让灯每过10秒按照需求变化。

package com.isoftstone.interview.traffic;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 timer=Executors.newScheduledThreadPool(1);timer.scheduleAtFixedRate(new Runnable(){public void run(){System.out.println(currentLamp.name());currentLamp=currentLamp.blackOut();if(currentLamp==null){System.out.println("null");}}}, 10, 10, TimeUnit.SECONDS);}}
最后一步:创建一个灯控制器和12个方向的路,路会自动增加车辆,灯会每个一段时间自动变换。绿灯的路会让车辆一辆一辆通过。

package com.isoftstone.interview.traffic;class MainClass {/** * @param args */public static void main(String[] args) {Lamp nextLamp=Lamp.valueOf("dfdfdf");// TODO Auto-generated method stubString [] directions=new String[]{"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","E2W","W2S"};for(int i = 0 ;i<directions.length;i++){new Road(directions[i]);}new LampController();}}

项目感言

交通灯在现实生活中是一个实实在在的项目,虽然我们现在写的这个小程序只是实现了一些个简单的逻辑,但是这个小项目他培养的是编程设计的思维,拿到一个项目首先得会分析需求,然后实现需求。写程序之前学好基础固然重要,但是也一定得会设计程序。一个好的程序员必须要有好的基础和好的思维。这个小项目如果写得出来,我相信我将来可以实现更复杂的逻辑。非常感谢张老师!

------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------

原创粉丝点击