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

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

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

例如:

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

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

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

       。。。 

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

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

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

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

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

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

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

图如下:

  

总共有12条路线,为了统一编程模型,可以假设每条路线都有一个红绿灯对其进行控制,右转弯的4条路线的控制灯可以假设称为常绿状态,另外,其他的8条线路是两两成对的,可以归为4组,所以,程序只需考虑图中标注了数字号的4条路线的控制灯的切换顺序,这4条路线相反方向的路线的控制灯跟随这4条路线切换,不必额外考虑。(注意:这里的重点是要分清楚路线,我们已经将多条路线给予分开,现在的研究重点已经转向图上标注的四条路线 !)

经过面向对象的分析,这里主要可以分为Lamp(路灯类),LampControl(路灯的控制类),Road(路)。

为了简便编程我们使用枚举来表示路灯类:代码如下:

/**
 * 
 * 类说明:灯方法
 *  作者:test
 *   版本:v1.0 修改历史:
 *   注意:在这里一个灯必须包括 与之相对应的灯(同时暗同时亮)、明暗、下一个要亮的灯
 */

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 opposite;//对应的灯
	private String next;//下一个要亮的灯
	/**
	 * 传入灯的名字
	 * @param opposite 对应的另一个灯
	 * @param next 下一个灯 
	 * @param lighted 灯是否是亮的
	 * 注意:这里只能用string表示下一个将要亮的灯,和对应的灯。
	 * 否则如果直接用Lamp表示的话,不能正确得到相应的Lamp值,因
	 * 为在第一个Lamp初始化时,其他的都没有(Lamp.)得不到响应的
	 * Lamp,只能用String
	 */
	private Lamp(String opposite,String next,boolean lighted){
		this.opposite=opposite;
		this.lighted=lighted;
		this.next=next;
	}
	
	public boolean isLighted() {
		return lighted;
	}

	/**
	 * 灯亮绿灯
	 */
	public void light() {
		this.lighted = true;
		if (opposite != null) {
			Lamp.valueOf(opposite).light();
		}

	}

	/**
	 * 灯变暗,变成红灯
	 */
	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(this.name()+"和"+Lamp.valueOf(opposite).name()
				+"灭了"+"\n"+nextLamp.name()+"和"+Lamp.valueOf(nextLamp.opposite)+"亮了");
		}
		return nextLamp;
	}
}

路灯控制类代码:主要是设置路灯的暗亮,即初始化路灯状态,并新建立线程每隔十秒改变状态。

路类:

public class Road {
	private String name;
	private List<String> vehicles=new ArrayList<String>();
	
	
	public Road(String name){
		this.name=name;
		
		
		/*
		 * 定义一个线程进行初始化车辆
		 */
		ExecutorService service=Executors.newSingleThreadExecutor();
		service.execute(new Runnable(){
			public void run(){
				for(int i=0;i<1000;i++){
					try {
						Thread.sleep((new Random().nextInt(10)+1)*1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					vehicles.add(Road.this.name+"_"+i);
				}
			}
		});
		/*
		 * 定义每隔一定的时间进行检查看是否可以通过车
		 */
		ScheduledExecutorService timer=Executors.newSingleThreadScheduledExecutor();
		timer.scheduleAtFixedRate(new Runnable(){
			public void run(){
				boolean lighted=Lamp.valueOf(Road.this.name).isLighted();
				if(vehicles.size()>0&&lighted){
					System.out.println(vehicles.remove(0)+"is travering !");;		//让道路上第一辆车通过			
				}
			}
		}, 
		1, 1, TimeUnit.SECONDS);
	}
}

路的主要功能:一是增加或减少自己路上的车辆,控制车辆的增加与减少。(通过与名字与相应的灯联系在一起).

测试类代码:

public class ClassMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//初始化路,在路上有灯,灯内部形成一个循环
		String [] s={"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"};
		for(int i=0;i<s.length;i++){
			new Road(s[i]);
		}
		new LampControl();
	}
}

总结:

     首先把老师的一句比较经典的话写下来:谁拥有数据,谁有的提供操作这些数据的方式    !

   问题解决:

            交通灯看似一个比较复杂的问题,经过一步一步的细化分析,最终将题目分解为多个类,每个类设置不同的属性与动作。在这里最难设计的一个类是路灯类。一般人们不会去想到用枚举(一般人思维:枚举就是设置数据常量集合的)。其实不然,枚举也可以自己的构造函数,自己的方法,自己的属性。在这里用枚举来表示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), 

如果出现这个问题:说明你没有看清老师前期的分组,首先需要控制的灯有8个,这8个灯分成四组。关键就在这四组上,四组中每组的成员中有两个,两个中有一个设置上自己的相对路灯即可。也可以这样理解,可以把每组的路灯一个叫做主灯,一个叫做次灯,主灯可以控制次灯(内部有次灯的引用)。

除此还有一个要点不知大家注意了没有:

S2N("N2S","S2W",false), S2W("N2E","E2W",false), E2W("W2E","E2S",false), E2S("W2N","S2N",false),   //这四个形成一个循环

我后面注释上了:这四个形成一个循环。即这四个主灯内部通过设置下一个主灯,来实现循环。即每个灯构造函数第二个参数就是下一个主灯,四组形成一个循环。而相对的灯即次灯通过主灯来设置。

还要强调一点:这里是通过枚举类实现了数据的共享。枚举是静态final的,保证每次通过Lamp得到的等都是同一个灯 !这样就能保证操作的是同一个对象。。

微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码
微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值