黑马程序员-交通灯系统

时间:2023-02-17 18:10:34

要求:

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

例如:

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

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

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

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

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

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

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

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

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

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

黑马程序员-交通灯系统

分析:
总共有12条线路。直行4条,左转4条,右转4条。

编程模式:每条线路都控制一个交通灯,右转的等是常绿的。南北,东西是对应的。只考虑南—>北,南—>西,东—>西,东—>南,四条线路。

对象和类的设计:总共有三个类

Lamp枚举类:有12个灯,创建对象很麻烦,考虑使用枚举来设计,右转的等设计为常绿,其余八个等设计为4组。每个枚举元素包含oppsite方向的灯,下一个亮的等next(), 灯是否是亮的isLighting()三个属性。

三个方法:

isLighting():灯是否是亮的

lightToGreen():灯变绿,某个灯变绿时,对面的灯也变绿,某个等变红时;

lightToRed():灯变红,对面的等也变红,同时下一个等变绿。

public enum Lamp {

    /**
     * Lamp类:
     * 因为有12个lamp对象,而且需要频繁的被调用,new对象很麻烦,所以使用枚举。
     * 该枚举:两个构造方法,三个方法
     * 三个成员变量:
     *     1.对面的灯:oppositeLamp
     *    2.下一个灯:nextLamp
     *    3.亮灯的标志:flag
     * 两个构造方法:
     *     1.空参数方法
     *    2.三个参数的构造方法,接受上面的三个变量
     *    三个方法:
     *    1.isLighting():用于判断灯的状态,true绿灯,false代表红灯
     *    2.toGreen();灯变绿的方法,同时将对面的灯变绿
     *    3.toRed();灯变红的方法,同时将对面的灯变红,并返回下一个灯(给控制器用)
     *
     */
 
    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),N2W("null","null",true),E2N("null","null",true),W2S("null","null",true);
    private String oppositeLamp;
    private String nextLamp;
    private boolean lighting;
    private Lamp(){}
    private Lamp(String oppositeLamp,String nextLamp,boolean lighting){
        this.oppositeLamp=oppositeLamp;
        this.nextLamp=nextLamp;
        this.lighting=lighting;
    }
    public boolean isLighting(){
        return lighting;
    }
    //灯变绿,同时将对面的等变绿
    public void toGreen(){
        this.lighting=true;
        if(oppositeLamp!=null){
            Lamp.valueOf(oppositeLamp).toGreen();
        }
        
    }    
    //灯变红,将对面的灯变红,同时将下一个灯变绿
    public Lamp toRed(){
        this.lighting=false;
        if(oppositeLamp!=null){
            Lamp.valueOf(oppositeLamp).toRed();
        }
        Lamp next =null;
        if(nextLamp!=null){
             Lamp.valueOf(nextLamp).toGreen();
             next =  Lamp.valueOf(nextLamp);
        }
        return next;
    }
}

 

Road类:

12条路线都有名字。Road查看交通灯,如果是绿灯就放行。车辆vehicles设计成有road来生成。路线的名字就是对应的灯的名字。

在构造函数中创建两个线程:一个控制产生车辆,一个控制放行车辆。

import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.Executors;
public class Road {

    /** road类:
     *  功能:产生车辆,并根据交通灯放行车辆。
     *  注:
     *  1.使用LinkedList模拟车辆产生和放行
     *  2.在构造方法中,创建两个线程。不再创建别的方法,是因为路一旦存在,就让它运行
     *  3.路一初始化就要有名字,同时该名字也是其对应灯名字。在判断灯的红绿时,很方便。
     */
     private String name;
     LinkedList<String> link = new LinkedList<String>();
     Road(String name){
         this.name=name;
         //创建产生的车辆的线程,使用线程工具类,创建一个线程池
         Executors.newScheduledThreadPool(1).execute(new Runnable(){             
            public void run() {
                 for(int x=0;x<1000;x++){
                     link.offerFirst(Road.this.name+x+"号车辆");
                     //每隔1-10秒产生一辆车
                     int randomNum = new Random().nextInt(10)+1;
                     try {
                        Thread.sleep(randomNum*1000);
                    } catch (InterruptedException e) {
                         e.printStackTrace();
                    }
                 }
            }
             
         });
         //创建线程,放行车辆
         Executors.newFixedThreadPool(1).execute(new Runnable(){             
            public void run() {
                //路的名字就是灯的名字
                boolean flag = Lamp.valueOf(Road.this.name).isLighting();
                if(flag==true){
                    link.pollLast();
                }
                 
            }
             
         });
     }
}


 

LampController

成员变量:当前的灯

方法:控制灯的方法。

import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class LmapController {

    /**
     *  该类的功能:每隔10秒让灯变红,注意:只是让它控制变红,不用控制变绿,因为变红的同时Lamp会将下一个等变绿、
     *  有一个成员:currentLamp
     *  一个构造方法:创建改变灯的线程
     */
    private Lamp currentLamp=Lamp.S2N;
    LmapController(){
        currentLamp.toGreen();//默认第一个灯是绿灯
        //创建调度线程,10秒之后变换
        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
                new Runnable(){                     
                    public void run() {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                             e.printStackTrace();
                        }
                        currentLamp=currentLamp.toRed();
                        
                    }
                    
                },
                10,
                10,
                TimeUnit.SECONDS
                ); 
    }
}

 

Main方法:

public class Mian {     
    public static void main(String[] args) {
        String[] directions = {"S2N","S2W","E2W","E2S",
                 "N2S","N2E","W2E",
                 "W2N","S2E","N2W","E2N","W2S"};
        //new12个对象
        for(int x=0;x<12;x++){
            new Road(directions[x]);
        }
        new LampController();
    }

}