黑马程序员--------------交通灯管理系统

来源:互联网 发布:linux系统ping命令参数 编辑:程序博客网 时间:2024/06/09 14:56
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

需求

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

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

例如:

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

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

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

       。。。

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

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

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

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

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

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

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


思路

首先明确有多少个方向,以及现实当中红绿灯是怎么运作的。一般情况十字路口有12个方向,直行的有四条南—北两条,东—西两条,右转的有四条,左转的有四条,所以加起来一共12条,具体如下图所示:

首先明确了有多少条路,因为在每一种路上都有三个方向,向左转,直走,向右转,所以一共有十二条路。而现实生活中每个路口右转都是可以直接转的,不需要看是否是红灯或是绿灯。再看其它方向的过程,假设先是从南到北走,首先是直行,当直行灯变红后左转的灯变绿,因这道题不需要考虑黄灯的情况,所以当左转的灯也变红后,由东西方向的灯就变绿,以此进行循环。

分析路:每条路上都会出现随机的出现新的车辆,而用面对对象的思路, 把路看作是一个对象,它最清楚路上有几辆车,所以车辆可以用一个集合来进行存储,而且还有一个优点是可以对集合中存储的对象可以删除动作,也可以看作车辆经过路口的过程。每个Road对象都有一个name成员变量来代表方向,有一个vehicles成员变量来代表方向上的车辆集合。在Road对象的构造方法中启动一个线程每隔一个随机的时间向vehicles集合中增加一辆车(用一个“路线名_id”形式的字符串进行表示)。在Road对象的构造方法中启动一个定时器,每隔一秒检查该方向上的灯是否为绿,是则打印车辆集合和将集合中的第一辆车移除掉。
[java] view plaincopyprint?
  1. package com.isoftstone.interview.traffic;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. import java.util.Random;  
  6. import java.util.concurrent.ExecutorService;  
  7. import java.util.concurrent.Executors;  
  8. import java.util.concurrent.ScheduledExecutorService;  
  9. import java.util.concurrent.TimeUnit;  
  10.   
  11. public class Road {  
  12.     List<String> vecaicles =new ArrayList<String>();  
  13.     private String name=null;  
  14.     public Road(String name)  
  15.     {  
  16.         this.name=name;  
  17.         //模拟车不断的增加,使用线程池中创建单个线程的方法,创建一个线程池。  
  18.         ExecutorService pool=Executors.newSingleThreadExecutor();  
  19.         pool.execute(new Runnable(){  
  20.             public void run()  
  21.             {  
  22.                 for (int i=1;i<1000;i++)  
  23.                     {  
  24.                       try {  
  25.                           //模拟车辆随机的增加  
  26.                         Thread.sleep((new Random().nextInt(10)+1)*1000);  
  27.                     } catch (InterruptedException e) {  
  28.                           
  29.                         e.printStackTrace();  
  30.                     }//车名就是路的名称加上车辆的个数  
  31.                        vecaicles.add(Road.this.name+"_"+i);  
  32.                }  
  33.             }  
  34.         });  
  35.         //用一个这时器,来操作每隔一秒检查对应的灯是否是绿灯,是则放行一辆车  
  36.         ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);  
  37.         timer.scheduleAtFixedRate(  
  38.                 new Runnable()  
  39.                 {  
  40.                     public void run()  
  41.                     {//判断路上是否有车  
  42.                         if(vecaicles.size()>0)  
  43.                         {  
  44.                             boolean lighted =Lamp.valueOf(Road.this.name).isLighted();  
  45.                             if(lighted)  
  46.                             {  
  47.                                 //当灯为绿时,就放行一辆车  
  48.                                 System.out.println(vecaicles.remove(0)+" is traversing ");  
  49.                             }  
  50.                         }  
  51.                 }  
  52.                 },   
  53.                 1//---->间隔多少秒  
  54.                 1//---->再隔多少秒继续做  
  55.                 TimeUnit.SECONDS);//这个是指定前面两个数字的单位  
  56.           
  57.     }  
  58.   
  59. }  
对灯的分析:

系统中有12个方向上的灯,在程序的其他地方要根据灯的名称就可以获得对应的灯的实例对象,综合这些因素,将Lamp类用java5中的枚举形式定义更为简单。

① 每个Lamp对象中的亮黑状态用lighted变量表示,选用S2N、S2W、E2W、E2N这四个方向上的Lamp对象依次轮询变亮,Lamp对象中还要有一个oppositeLampName变量来表示它们相反方向的灯,再用一个nextLampName变量来表示此灯变亮后的下一个变亮的灯。这三个变量用构造方法的形式进行赋值,因为枚举元素必须在定义之后引用,所以无法再构造方法中彼此相互引用,所以,相反方向和下一个方向的灯用字符串形式表示。 

② 增加让Lamp变亮和变黑的方法:light和blackOut,对于S2N、S2W、E2W、E2N这四个方向上的Lamp对象,这两个方法内部要让相反方向的灯随之变亮和变黑,blackOut方法还要让下一个灯变亮。

③ 除了S2N、S2W、E2W、E2N这四个方向上的Lamp对象之外,其他方向上的Lamp对象的nextLampName和oppositeLampName属性设置为null即可,并且S2N、S2W、E2W、E2N这四个方向上的Lamp对象的nextLampName和oppositeLampName属性必须设置为null,以便防止light和blackOut进入死循环。

[java] view plaincopyprint?
  1. ackage com.isoftstone.interview.traffic;  
  2.   
  3. public enum Lamp {  
  4.     //每一个枚举元素都表示一个方向的控制的灯  
  5.   S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),  
  6.   //下面这四个元素表示与上面四个元素相反的灯,它们的相反相反方向和下一个灯应该忽略不计。  
  7.   N2S(null,null,false),N2E(null,null,false),W2E(null,null,false),W2N(null,null,false),  
  8.   //向右转弯的灯不受红绿类的控制,所以假设它们都是绿灯  
  9.   S2E(null,null,true),E2N(null,null,true),N2W(null,null,true),W2S(null,null,true);  
  10. //Lamp的构造函数中接收的第一个为对应的灯,第二个为下一个灯,第三个为灯是否亮的  
  11.   private Lamp(String opposite,String next,boolean lighted)  
  12.   {  
  13.       this.opposite=opposite;  
  14.       this.next=next;  
  15.       this.lighted=lighted;  
  16.   }  
  17.   private Lamp()  
  18.   {  
  19.         
  20.   }  
  21.   private boolean lighted;//判断灯是不是绿灯  
  22.   private String opposite;//对应的灯  
  23.   private String next;//当前灯变红时下一个变绿的灯  
  24.     
  25.   public boolean isLighted()//判断灯是不是绿灯  
  26.   {  
  27.       return lighted;  
  28.   }  
  29.   //下面这方法是当某个灯变绿时,它对应方向的灯也要变绿  
  30.   public void light()  
  31.   {  
  32.       this.lighted=true;  
  33.       if(opposite !=null)  
  34.       {  
  35.           Lamp.valueOf(opposite).light();  
  36.           
  37.       }  
  38.       System.out.println(name()+" lamp is green ,下面总共应该有6个方向能看到汽车穿过");  
  39.   }  
  40.   //当某个灯变红时,对应方向的灯也要变红,并且下一个方向的灯要变绿  
  41.   public Lamp blackOut()  
  42.   {  
  43.       this.lighted=false;  
  44.       if(opposite !=null)  
  45.       {  
  46.           Lamp.valueOf(opposite).blackOut();  
  47.           
  48.       }  
  49.       Lamp nextLamp =  null;  
  50.       if(next !=null)  
  51.       {  
  52.           nextLamp =  Lamp.valueOf(next);  
  53.           System.out.println("绿灯从"+name()+"------>切换为"+next);   
  54.           nextLamp .light();   
  55.            
  56.           
  57.       }  
  58.       return nextLamp;  
  59.   }  
  60.     
  61. }  

定义一个红绿灯控制系统,然后启动一个定时器,每隔10秒将当前灯变红和将下一个灯变绿
[java] view plaincopyprint?
  1. package com.isoftstone.interview.traffic;  
  2.   
  3. import java.util.concurrent.Executors;  
  4. import java.util.concurrent.ScheduledExecutorService;  
  5. import java.util.concurrent.TimeUnit;  
  6.   
  7. public class LampController {  
  8.     private Lamp currentLamp;//当前的灯  
  9.     public LampController()  
  10.     {  
  11.         currentLamp=Lamp.S2N;//指定第一个灯  
  12.         currentLamp.light();//让第一个灯变绿  
  13.         //每隔10秒将当前为变红,并让下一个方向的灯变绿  
  14.         ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);//1表示返回的是一个线程  
  15.         timer.scheduleAtFixedRate(  
  16.                 new Runnable()  
  17.                 {  
  18.                     public void run()  
  19.                     {  
  20.                         currentLamp = currentLamp.blackOut();  
  21.                     }  
  22.                 },   
  23.                 10,  
  24.                 10,   
  25.                 TimeUnit.SECONDS);  
  26.     }  
  27.   
  28. }  

定义一个类,用来实现每条路的对象的运行。for循环创建出代表12条路线的对象。并调用交通灯的系统。

[java] view plaincopyprint?
  1. package com.isoftstone.interview.traffic;  
  2.   
  3. public class MainClass {  
  4.   
  5.     /** 
  6.      * @param args 
  7.      */  
  8.     //S2N,S2W,E2W,E2S,N2S,N2E,W2E,W2N,S2E,E2N,N2W,W2S  
  9.     public static void main(String[] args) {  
  10.         String[] directions = {"S2N","S2W","E2W","E2S","N2","N2E","W2E","W2N","S2E","E2N","N2W","W2S"};  
  11.         for(int i=0;i<directions.length;i++)  
  12.         {  
  13.             new Road(directions[i]);  
  14.         }   
  15.         new LampController();  
  16.   
  17.     }  
  18.   
  19. }  


---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
0 0
原创粉丝点击