黑马程序员_java(交通灯管理系统)

———–android培训、java培训、java学习型技术博客、期待与您交流!————

1
7K面试题:交通灯管理系统的模拟

题目要求:

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


异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 —- 直行车辆
由西向而来去往南向的车辆 —- 右转车辆
由东向而来去往南向的车辆 —- 左转车辆
。。。

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

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

具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。

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

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

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

具体分析:
首先应该分析,在这个十字路口应该有十二条不同的线路(就是车的走向),向右拐的线路可以一直是绿灯,可以不考虑。这样就剩下八条线路,(直行和向左拐的线路)。有知道,对向的线路应该是对称的,所以可以只考虑四条线路(对向的线路对称)。

灯对象的设计:有十二个方向的路线,就应该有十二个灯来控制,十二个灯可以用枚举类来做。只要有四个灯有逻辑(第一个逻辑:该等本身为绿灯的时候,对应方向的灯也该是绿的,第二个逻辑:该等本身变红后,应该让下一个灯变绿)。

灯的控制系统对象:随机的产生,让不同方向上的灯交替进行变换,要有让灯变绿的方法,和让灯变红的方法。

把路看成一个集合,把车看成集合中的元素。(车通过十字路口的效果是,集合中元素的增删)

Road(类)

package Traffic_system;

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
{
     String name;

    List<String> vechicles=new ArrayList<String>();

    public Road( String name)
    {
        this.name=name;
        //自动开启一个线程,每隔十秒钟向集合中添加一辆车
        //产生一个线程池,
        ExecutorService pool=Executors.newSingleThreadExecutor();
        pool.execute(new Runnable()
        {

            @Override
            public void run()
            {
                for (int i = 0; i <1000; i++)
                {
                    try
                    {
                        Thread.sleep((new Random().nextInt(11))*1000);//休息1——10秒之后,增加一辆车
                    } catch (InterruptedException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    vechicles.add(Road.this.name+"--"+i);
                }

            }
        });//这是增加车


        //下面要怎么让车通过:通过一个定时器。检查对应路上的灯是否为绿,是就减少车辆(还要看这辆前边是否有车,没车才能通过)
        ScheduledExecutorService timer= Executors.newScheduledThreadPool(1);

        timer.scheduleAtFixedRate(
                new Runnable()
                {

                    @Override
                    public void run()
                    {
                        if(vechicles.size()>0)
                        {
                            boolean lamp=Lamp.valueOf(Road.this.name).islightde();//路要检查自己该路线上的灯的状态
                            if(lamp)
                            {
                                System.out.println(vechicles.remove(0)+"--车通过路口!");
                            }
                        }

                    }
                }, 
                1, 
                1, 
                TimeUnit.SECONDS);

    }

}

灯类

package Traffic_system;

import com.itheima.reText;

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 boolean lighted;
    private String  oppsite;//对应方向的灯,应该是Lamp类型,可是为何是String类型,是因为在构造第一个对象的时候,要使用后边还没有的对象,
    private String  next;//所以用String类型,当以后要用到此对象是,可通过valueof()方法,把对应的String类型对象,转换成枚举实例

    private Lamp(String oppsite,String next,boolean lighted)
    {
        this.oppsite=oppsite;
        this.next=next;
        this.lighted=lighted;

    }
    private Lamp()
    {}

    public boolean islightde()//判断是否是绿灯
    {
        return lighted;
    }

    public void light()//让灯变绿,此时要看此灯有没有对应的灯,有,就把对应的灯变绿
    {

        this.lighted=true;
        if(oppsite!=null)
        {//此时要用到对应的灯,可此时oppsite确实String类型,就需要把String类型,变成枚举实例对象
            Lamp.valueOf(oppsite).light();
        }

        System.out.println(name()+"此方向上的灯的绿的,应该有6条可以通行的线路");
    }

    public Lamp unlight()//让灯变红,此灯变红后就要让对应的灯变绿,还要让下一个灯变绿
    {
        this.lighted=false;
        if(oppsite!=null)//此灯变红后就要让对应的灯变红
        {//此时要用到对应的灯,可此时oppsite确实String类型,就需要把String类型,变成枚举实例对象
            Lamp.valueOf(oppsite).unlight();
        }

        Lamp nextLamp=null;
        if(next!=null)//还要让此灯的下一个灯变绿
        {//此时要用到对应的灯,可此时oppsite确实String类型,就需要把String类型,变成枚举实例对象
            nextLamp=Lamp.valueOf(next);
            nextLamp.light();
            System.out.println("绿灯从-"+name()+"方向切换为:"+next+"方向");
        }
        return nextLamp;//让下一个灯变绿,并且返回此绿灯,为的是要在控制器中,能够改变指示当前灯值:
    }

}

灯的控制器类

package Traffic_system;

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

public class lampContraler
{//灯的控制系统
    private Lamp contraller;//指示当前的灯

    public lampContraler()
    {
        contraller=Lamp.S2N;
        contraller.light();//让当前的灯变绿

        //
        ScheduledExecutorService  timer=Executors.newScheduledThreadPool(1);
        timer.scheduleAtFixedRate(
                new Runnable()
                {

                    @Override
                    public void run()
                    {//每隔10秒,就让当前的灯变红,把当前灯变红,就要刷新当前的灯代表的是谁(就是更换当前灯指示的对象,也就要指向先一个灯)

                        contraller=contraller.unlight();//让当前灯变红后,还要从返回值中得到,下一个绿灯时谁;
                    }
                }, 
                10, 
                10,
                TimeUnit.SECONDS);
    }

}

测试类

package Traffic_system;

public class Testmain
{
    public static void main(String[] args)
    {
        //创建12条路的对象

        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 Road(directions[i]);
        }

        //创建灯的控制器
        new lampContraler();
    }


}

———–android培训、java培训、java学习型技术博客、期待与您交流!————

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值