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

------- android培训java培训、期待与您交流! ----------

交通灯管理系统的项目需求

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

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

例如:

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

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

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

。。。

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

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

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

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

每辆车通过路口时间为一秒(可通过线程sleep的方式模拟)

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

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

需求分析

画图有助于对问题的理解和分析,所以分析问题最的办法是画图


由图分析可知

java设计是面向对象的,在在考虑问题时应该将事物以对象的思想来考虑。根据面向对象的程序设计思想,确定程序的对象有:汽车,路线交通灯,交通灯控制系统,汽车在根据自己所在的路上的红绿灯的变化确定是否穿过路口之前,先要判断前方是否有车,由路判断车的前方是否有车,路是存储车辆的集合, 路上就应该有增加车辆和减少车辆的方法。题目中不是体现车的移动过程,而是捕捉车辆穿过路口的过程,也就是路上车辆减少的过程,所以车不必设计成单独的对象,而是由字符串表示。

图中一总共有12条线路,根据实际生活中十字路口交通灯对比上图可知,向右行驶的4条线路(S2E,E2N,N2W,W2S)不受交通灯的控制,除了这四条线路,其余的8条线路中相对的两条线路由交通灯控制的通行状态是一致的,为了统一变成模型,可以假设每条线路都有一个红绿灯控制,右转弯的4条线路可以假设为常绿状态,另外其他的8条线路是两两成对的,可以归为四组,所以程序只考虑标注数字号的4条线路的控制灯的切换顺序,这四条线的反方向路线的控制灯跟随4条路线切换不必额外考虑。


程序设计

Road 类

Road类来表示路线,每个Road对象代表一条路线,总共有12条路线,即系统中总共要产生12个Road实例对象。
每条路线上随机增加新的车辆,增加到一个集合中保存。
每条路线每隔一秒都会检查控制本路线的灯是否为绿,是则将本路线保存车的集合中的第一辆车移除,即表示车穿过了路口。

public class Road {
	//创建存放车辆的集合,相当于路List 接口
	List<String> vehicles=new ArrayList<String>();
	//构造函数
	private String name;//路名
	
	public Road(String name)
	{
		this.name=name;
		//1-10秒钟随机种来一辆车,线程完成
		//创建线程池Executors
		
	ExecutorService pool=	Executors.newSingleThreadExecutor();
	//调用执行execute方法,方法的参数为runnable 的匿名内部类
	pool.execute(new Runnable(){
		public void run()
		{
			for(int i=1;i<1000;i++)
			{
				try {
					//线程阻塞 ,随机1-10秒
					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.newScheduledThreadPool(1);//线程池size为1,即中有一个线程

	timer.scheduleAtFixedRate(new Runnable(){
		public void run()
		{
			
			if(vehicles.size()>0)//集合不为空
			{
				
				//boolean lighted=true;//灯的状态
				boolean lighted=
					 Lamp.valueOf(Road.this.name).islighted();
				if(lighted)
				{
					//vehicles.remove(0);//移走第一辆车(出错的代码!!!)
					
					System.out.println(vehicles.remove(0)+"is traveling");//返回被移走的那辆车
				}
			}
		}
	},
			1,//最初延迟时间
			1,//期间间隔
			TimeUnit.SECONDS);//单位
	
	
	}
	
	
}
Lamp类

12条线路上,每一条线路上都有一个交通灯来控制,这样就有12个交通灯,无论在程序的什么地方去获得某个方向的灯时,每次获得的都是同一个实例对象,所以Lamp类用枚举来实现,永远都只有代表12个方向的灯的实例对象。

用lighted变量表示交通灯的红绿状态,绿为true ,红为false ,向右行驶的4条线路S2E,E2N,N2W,W2S不受交通灯的控制,默认为灯的状态为true ,除了这四条线路,用S2N、S2W、E2W、E2N这四个方向上的Lamp对象依次轮询变亮,Lamp对象中还要有一个oppositeLampName变量来表示它们相反方向的灯,反方向的灯的明亮状态和四个对象的状态一致,再用一个nextLampName变量来表示此灯变亮后的下一个变亮的灯。这三个变量用构造方法的形式进行赋值,因为枚举元素必须在定义之后引用,所以无法再构造方法中彼此相互引用,所以,相反方向和下一个方向的灯用字符串形式表示。 

public enum Lamp {
	//枚举出12个灯
	
	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);
	//枚举的构造方法都是私有的
	//定义有参数的构造方法,参数传递对面的灯,下一个灯,当前灯的状态
	//因为构造当前灯对面的灯可能没有创建,so传递对面灯的字符串名字
	private Lamp(String opposite,String next,boolean lighted)
	{
		this.opposite=opposite;
		this.next=next;
		this.lighted=lighted;
		
	}
	//定义无参数的构造方法
	private  Lamp(){
		
	}
	
	
	//定义当前的灯状态
	private boolean lighted;
	//判断灯状态
	private String opposite;//对面灯的字符串名字
	private String next;  
	public boolean islighted()
	{
		return lighted;
	}
	//lighted 为true 时为绿灯
	public void greenlight()
	{
		this.lighted=true;
		
		if(opposite!=null)//有对面的灯时对面的灯为绿
		{
			// valueOf()返回对象
			Lamp.valueOf(opposite).greenlight();
		}
		System.out.println(name()+"这个灯变绿下面看到六个方向汽车穿行");
	}
	//定义lighted为false 时是红灯
	public Lamp redlight()
	{
		this.lighted=false;//当前灯变红
		
		if(opposite!=null)//有对面的灯时对面的灯为红
		{
			// valueOf()返回对象
			Lamp.valueOf(opposite).redlight();
		}
		
		Lamp nextLamp=null;//出现问题的地方!!!
		if(next!=null)
			
		{	
			nextLamp=Lamp.valueOf(next);
			System.out.println("绿灯从"+name()+"切换为"+next);
			nextLamp.greenlight();//下一个灯变为绿灯,并返回nextLamp灯
		}
		return nextLamp;
		
	}
LampController类

整个系统中只能有一套交通灯控制系统,所以,LampController类最好是设计成单例。
LampController构造方法中要设定第一个为绿的灯。
LampController对象的start方法中将当前灯变绿,然后启动一个定时器,每隔10秒将当前灯变红和将下一个灯变绿。

public class LampController {
	
	private Lamp currentLamp;
	public LampController()
	{
		//构造函数中初始化当前的灯为由南向北的灯
		currentLamp=Lamp.valueOf("S2N");
		currentLamp.greenlight();
		
		ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);//创建调度线程池
		timer.scheduleAtFixedRate(new Runnable(){
			public void run()
			{System.out.println("aaa ");
				currentLamp=currentLamp.redlight();
			}
		},
				10,// 十秒后调度线程
				10,//间隔十秒再调度
				TimeUnit.SECONDS);//时间单位秒
		
	}
检验

Main Class

设计main方法,方法中通过for循环创建12个线路的实例对象,并创建LampController 调用start 方法

public static void main(String[] args) {
		String [] directions=new String[]{"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","N2E","E2N","N2W","W2S"};
		for(int i=0;i<directions.length;i++)
		{
			new Road(directions[i]);
		}
		new LampController();
	}
运行结果
N2S这个灯变绿下面看到六个方向汽车穿行
S2N这个灯变绿下面看到六个方向汽车穿行
E2N_1is traveling
S2N_1is traveling
N2W_1is traveling
N2S_1is traveling
E2N_2is traveling
N2S_2is traveling
W2S_1is traveling
N2W_2is traveling
绿灯从S2N切换为S2W
N2E这个灯变绿下面看到六个方向汽车穿行
S2W这个灯变绿下面看到六个方向汽车穿行
S2W_1is traveling
N2E_1is traveling
N2E_1is traveling
W2S_2is traveling




------- android培训java培训、期待与您交流! ----------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值