黑马程序员_张老师的交通管理灯系统

来源:互联网 发布:问卷调查数据库设计 编辑:程序博客网 时间:2024/05/16 06:03

---------------------- <ahref="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<ahref="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------


黑马程序员_张老师的交通管理灯系统

这个是本人尝试做得第一个小项目,有些小收获。1.好的英语基础在做项目时,能使程序的阅读性好很多。2程序可以慢慢的调,但是思路一定等清楚,不然绕绕就把自己绕进去了,而且后期调错的时候就累死了。3面向对象必须掌握好

 

题目:交通灯管理系统

 

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

 

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

例如:

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

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

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

       。。。

 

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

 

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

 

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

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

 

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

 

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

 

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

 

关键所在

思路:拿到这道题目后,才发现一个问题,原来基本天天见的红绿灯我真心不是很清楚运作原理。所以我就拿出本子,在上面开始画了。

       1     路口有四个方向,先拿一个方向来分析,比如说南(S)

坐南朝北的汽车就有三个方向可以行驶(直行往北(S2N),左拐往西(S2W),右拐往东(S2E))

2        也就是每个方向的车有三种选择,那么四个方向的车加起来就有12中选择。看起来貌似头都糊了。但是细想可以每个方向向右拐的车所面向的灯都假设为恒为绿(这个是张老师的假设,我个人认为只要该方向直行或左拐时灯为绿,那么右拐就一直为绿,),这样已处理,那么就只剩8个了,同时只要考虑相邻两个路口的情况,其他的路口都是一样的。因此只需要考虑四组就行了。例如S2N,S2W,E2W,E2S此处用逆时针顺序)

下面借一下张老师画的图:

3        现在分析下我们要的对象,分别有:路,红绿灯,还有汽车。

4        路:但是仔细一分析汽车在本道题中可以不是对象,他可以是由路提供数据,在判断玩红绿灯后,我们还要判断前面有没有车,有车就要等。所以可以把路看成集合里面存储着不定时,不定量的车,其实可以直接用整数代替。同时路上的方向是死的只有12中,不会改变所以这里可以用上枚举。

5        灯:灯(lamp)主要提供红绿两色,我们可以用开通(light)和闭合(blackout)代替。不但如此我们还要设定lamp变色的时间,和变色后维持的时间。同时这个lamp还要有当自己是blackout时让下一个lamp light的方法。而他的相反方向的灯的显示情况要与 它相反

 

经分析这道题 大体情况也就这些,经张老师梳理之后发现也并不复杂!下面来看看代码。

 

先编写Road类

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

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

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

我们在定义包名的时候前面要加上你所面试的那所公司的名称,例如com.isoftstone.interview.traffic    这样可以为自己的应聘增加好感

 

ExecutorServiceExecutor:执行已提交的 Runnable任务的对象。

ScheduledExecutorService:一个 ExecutorService,可安排在给定的延迟后运行或定期执行的命令

 

 

 

 

public class Road {

    //定义一个集合用来装载车辆,此处车辆用vechicle不要用car ,用集合方便添加删减

    private List<String>vechicles = new ArrayList<String>();//这里用ListArrayList好,方便接口

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

     *

     */

    private Stringname = null;

    public Road(String name){

        this.name = name;

   

    ExecutorService pool=Executors.newSingleThreadExecutor();//Executor:执行已提交的 Runnable任务的对象。

    pool.execute(new Runnable(){

        public void run(){

            for(int i=1;i<1000;i++){

                try {

                    Thread.sleep((new Random().nextInt(10) + 1) * 1000);//random获取随09的机数,让线程睡眠不定时间代表下辆车来的等待时间

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

                vechicles.add(Road.this.name +"_" + i);//必须要写上Road.this.name

            }              

        }

       

    });

 

    //每隔一秒检查对应的灯是否为绿,是则放行一辆车   

            ScheduledExecutorService timer=  Executors.newScheduledThreadPool(1);//ScheduledExecutorService:一个 ExecutorService,可安排在给定的延迟后运行或定期执行的命令

            timer.scheduleAtFixedRate(//定时器

                    new Runnable(){

                        publicvoid 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);//时间单位

           

        }

}

 

 

编写lamp的类:

注意事项:

因为lamp的情况就12是不变的,所以这里使用枚举更合适:

这个灯除了自身是否开着还必须能控制对面的和下面的灯并且

某个灯变红时,对应方向的灯也要变红,并且下一个方向的灯要变绿

 下一个要变绿的灯

   

 

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);

这里前两个参数用String类是关键,如果不用String类直接用变量,后面的变量都还没定义就被使用,明显不对。

    private Lamp(String opposite,String next,boolean lighted){

        this.opposite = opposite;

        this.next = next;

        this.lighted = lighted;

    }

 

 

 

    private boolean lighted;

    /*与当前灯同时为绿的对应方向*/ 

    private Stringopposite;

    /*当前灯变红时下一个变绿的灯*/ 

    private Stringnext;

    public boolean isLighted(){

        returnlighted;

    }

   

     // 某个灯变绿时,它对应方向的灯也要变绿

        publicvoid light(){

        this.lighted =true;

        if(opposite !=null){//此处必须判断,否则会溢出

            Lamp.valueOf(opposite).light();

        }

        System.out.println(name() +" lamp is green,下面总共应该有6个方向能看到汽车穿过!");

       

    }

   

    public Lamp blackOut(){

        this.lighted =false;

        if(opposite !=null){

            Lamp.valueOf(opposite).blackOut();

        }      

       

        Lamp nextLamp= null;

        if(next !=null){

            nextLamp = Lamp.valueOf(next);

            System.out.println("绿灯从" + name() +"-------->切换为" +next);        

            nextLamp.light();

        }

        return nextLamp;

    }

}

 

其实编译到这的时候这个项目的主要难点就都在这了,下面只要写个lamp控制器和主函数就行

LampContorller

 

 

整个系统中只能有一套交通灯控制系统,所以,LampController类最好是设计成单例。(这句话很重要,至少我是没想到使用单例,看来还是经验太少了)

LampController对象主要作用就是定义一个定时器,每隔10秒将当前灯变红和将下一个灯变绿

其实这个在lamp里面都定义过一次了

 

ScheduledExecutorService timer =  Executors.newScheduledThreadPool(1);

              timer.scheduleAtFixedRate(

                            newRunnable(){

                                   public  void run(){

                     currentLamp = currentLamp.blackOut();

                            }

                            },

                            10,

                            10,

                            TimeUnit.SECONDS);

为了提高代码的阅读性,我们将参数分行写


---------------------- <ahref="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<ahref="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------


0 0