黑马程序员-交通灯系统
2014-06-07 19:03 黑马程序员* 阅读(280) 评论(0) 编辑 收藏 举报要求:
异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ---- 直行车辆
由西向而来去往南向的车辆 ---- 右转车辆
由东向而来去往南向的车辆 ---- 左转车辆
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
Ø每辆车通过路口时间为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(); } }