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

来源:互联网 发布:php exec 不执行 编辑:程序博客网 时间:2024/06/01 07:48
------- android培训、java培训、期待与您交流! ----------


交通灯管理系统的项目需求

 

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

1. 异步随机生成按照各个路线

   例如 

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

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

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

。。。。

2. 型号灯忽略黄灯,只考虑红灯和绿灯

3. 应该考虑左转车辆控制信号灯,右转车辆不受信号灯的控制

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

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

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

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

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



面向对象的分析和设计

1. 每条路线上都会出现多辆车,路线上要随机增加新的车,在绿灯期间还要每分钟减少一辆车

   1. 设计一个Road类来表示路线,每个Road对象代表一条路线,总共有12条路线,即系统中总共要产生12Road实例对象。

   2.每条路线上随机增加新的车辆,增加一个到集合中

   3. 每条路线每隔一秒都会检查控制本路线的灯是否为绿灯,则将本路线保存的车的集合中的第一个车辆移除,即表示车穿过了了路口

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

   1. 设计一个Lamp类表示一个交通灯,每个交通灯都维护一个状态,亮(绿)或不亮(),每个交通灯要有变亮和变黑的方法,并且能返回自己的亮黑状态。

Ø   3. 除了右拐弯方向的其他8条路线的灯,他们是两辆成对的,可以归为四组所以,在编程处理时,只要从这4组中各取出一个灯,对这4个灯依次轮询变亮,与这4个灯方向对应的灯则随之一同变化,因此Lamp类中要有一个变量来记住自己相反方向的灯,在一个Lamp对象的变亮和变黑方法中,将对应方向的灯也变亮和变黑。每个灯变黑时,都伴随者下一个灯的变亮,Lamp类中还用一个变量来记住自己的下一个灯。

Ø   无论在程序的什么地方去获得某个方向的灯时,每次获得的都是同一个实例对象,所以Lamp类改用枚举来做显然具有很大的方便性,永远都只有代表12个方向的灯的实例对象。

Ø   设计一个LampController类,它定时让当前的绿灯变红。

 

 

我们初步设想一下有哪些对象:红绿灯,红绿灯的控制系统,汽车,路,汽车看到自己所在的路线对应的灯绿了就穿过

口么?不是,我们还需要看前面是否有车,看前面是否有车,该问那个对象呢?该问路,路中存储着车辆的集合,显然路上就应该有增加车辆和减少的方法了,再看题目,我们这里并不要体现车辆的移动的过程,只是扑捉车辆穿过路口的过程,也就是扑捉路上减少一辆车的过程,所以,这个车并不需要单独设计设计成为一个对象,用一个字符串来表示就可以了

面向对象设计把握一个重要的经验,谁拥有数据,谁就对外听歌操作这些数据的方法,再牢牢掌握几个典型的案例就可以了:人在黑板画圆,列车司机紧急刹车,售货员统计收获小票的金额,你把门关上了等

     学员的两个面向对象的面试题,用面向对象的方式设计了如下情景。

     “两块石头磨成一把石刀,石刀可以看树,砍成木材,木材做成椅子

     “球从一根线的一段移动和到了另外一段

 

理清思路

Road类的编写:

 

1. 每个Road对象都有一个name成员变量来代表方向,有一个vehicles成员变量来代表方向上的车辆集合。

 

2. Road对象的构造方法中启动一个线程每隔一个随机的时间向vechiicles集合中增加一辆车(用一个路线名_id”形式的字符串表示)

3. Road对象的构造发方法中启动一个定时器,每隔一秒检查该方向上的灯是否为绿,是则打印车辆集合和集合中的第一辆车移除


灯的控制器

 

package com.isoftstone.interview;  import java.util.*;import java.util.concurrent.*; public class Road{   List<String> vechicles=new ArrayList<String>();    private String name=null;    public Road(String name)//路线的名称         {             this.name=name;             //等效线程池             ExecutorService pool=Executors.newSingleThreadExecutor();             pool.execute(newRunnable()                   {                            @Override                            public voidrun()                            {                                     for(inti=1;i<1000;i++)                                     {                                               try                                               {                                                        Thread.sleep((new Random().nextInt(10)+1)*1000);                                               }                                               catch (InterruptedException e)                                               {                                                        e.printStackTrace();                                               }//随机产生一辆车                                                                                             //那条路的车                                               vechicles.add(Road.this.name+" "+i);                                               //访问外部类的成员变量 外部类名.this.变量名                                     }                            }                   });   //让线程池执行一个线程                               //定时器            ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);                    //固定频率            timer.scheduleAtFixedRate(                                                   new Runnable()                                                                                    {                                                                                                                                                                                         @Override                                                                                             public voidrun()                                                                                             {                                                                                                       //把集合的第一辆车移走                                                                                                       if(vechicles.size()>0)                                                                                                       {                                                                                                                //假如灯是绿的                                                                                                                boolean lighted=Lamp.valueOf(Road.this.name).isLighted();                                                                                                                if(lighted)                                                                                                                {                                                                                                                         System.out.println(vechicles.remove(0)+"  istravering");                                                                                                                }                                                                                                                                                                                                                               }                                                                                                                                                                                                   }                                                                                    },                                                                                    1,                                                                                    1,                                                                                    TimeUnit.SECONDS);             }  } 

Lamp类的编写:

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

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

3.增加让Lamp变亮和变黑的方法:light和blackOut,对于S2N、S2W、E2W、E2N这四个方向上的Lamp对象,这两个方法内部要让相反方向的灯随之变亮和变黑,blackOut方法还要让下一个灯变亮。
除了S2N、S2W、E2W、E2N这四个方向上的Lamp对象之外,其他方向上的Lamp对象的nextLamp和opposite属性设置为null即可,并且S2N、S2W、E2W、E2N这四个方向上的Lamp对象的nextLamp和oppositee属性必须设置为null,以便防止light和blackOut进入死循环。

package com.isoftstone.interview; //S2N,S2W,E2W,E2S,N2S,N2E,W2E,W2N,S2E,E2N,N2W,W2Spublic 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 Lamp(String opposite,String next ,boolean lighted)  {           this.opposite=opposite;           this.next=next;           this.lighted=lighted;  }  private Lamp()  {            }  private booleanlighted;  private String opposite;//对应的灯的名字  private String next;//定义下一个  public booleanisLighted()  {           returnlighted;  }  //灯变亮  public voidlight()  {           this.lighted=true;           if(opposite!=null)                      Lamp.valueOf(opposite).light();           System.out.println(name()+" lamp is green! 下面总共有六个方向能看到汽车通过");  }  //灯变熄  public Lamp blackOut()  {           this.lighted=false;           if(opposite!=null)           {                      Lamp.valueOf(opposite).blackOut();           }           Lamp nextLamp=null;           if(next!=null)           {                     nextLamp=Lamp.valueOf(next);                     nextLamp.light();                     System.out.println("绿灯从"+name()+"------->切换为"+next);           }           returnnextLamp;  }}

LampController类的编写:

1.整个系统中只能有一套交通灯控制系统,所以,LampController类最好是“单例设计模式的”。

2.LampController构造方法中要设定第一个为绿的灯。

3.LampController对象的start方法中将当前路灯变绿,然后启动一个定时器,每隔10秒将当前灯变红和将下一个灯变绿。


package com.isoftstone.interview; 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(                                       newRunnable()                                                        {                                                                 @Override                                                                 public voidrun()                                                                 {                                                                           //指向新变绿的灯                                                                           currentLamp=currentLamp.blackOut();                                                                 }                                                        },                                      10,                                      10,                                      TimeUnit.SECONDS);         }}

MainClass类的编写:用for循环创建出代表12条路线的对象。

接着再获得LampController对象并调用其start方法。

package com.isoftstone.interview; public class MainClass{         public staticvoid main(String[] args)         {                   //S2N,S2W,E2W,E2S,N2S,N2E,W2E,W2N,S2E,E2N,N2W,W2S                   String[]directions=new String[]{"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"};                   for(inti=0;i<directions.length;i++)                   {                            new Road(directions[i]);                   }                   new LampController();         } } 

//打印结果

N2S lamp is green! 下面总共有六个方向能看到汽车通过

S2N lamp is green! 下面总共有六个方向能看到汽车通过

N2W 1is travering

N2W 2is travering

W2S 1is travering

S2N 1is travering

S2E 1is travering

E2N 1is travering

E2N 2is travering

N2E lamp is green! 下面总共有六个方向能看到汽车通过

S2W lamp is green! 下面总共有六个方向能看到汽车通过

绿灯从S2N------->切换为S2W

S2W 1is travering

N2E 1is travering

W2S 2is travering

S2W 2is travering

N2E 2is travering

S2E 2is travering

N2W 3is travering

S2E 3is travering

E2N 3is travering

N2E 3is travering

W2S 3is travering

S2W 3is travering

N2E 4is travering

S2E 4is travering

W2S 4is travering



0 0
原创粉丝点击