Java-----面试题之交通灯的实现

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

         交通灯管理系统的实现,主要用到的技术呢,是枚举和线程,用这些技术可以很好的实现一些功能,比如用线程来实现定时器的功能,用枚举来实现灯这样是因为灯就是那几个,已经确定了的所以用这个枚举是比较好的,而且在枚举中可以加入构造方法成员变量和一些操作,感觉这个枚举就是类了吗。对于这个系统,要求是模拟出来在十字路口的交通灯的变化情况和在这种情况下,各个方向的车的运行状况。向右转方向的车可以忽略,就是不用管。
        对于这个我们首先要弄明白的是,有几个对象,对象中都有什么操作以及对象之间的关系。从实际中抽出的有:车----路-----路灯,这样是不是正确呢,视频中老师讲解了好几个关于面向对象怎么来找对象的方法,并且有一句自己总结的话,谁的数据,谁就必须拥有操作该数据的方法。这句话很好理解,比如说路灯吧,它拥有亮这个变量,那么它就必须拥有对这个变量进行操作的方法,让它变量或者变暗。然后就是车,对于车来说我们现在关心的是这条路上的车,在灯的指示下,车穿过路,整个过程中车都是以一个整体的形式出现在路上它并没有什么操作,它走可以认为是路让它走的,因此车就不能是一个类了。而路呢,就是了,它有车这个属性,然后就是添加车和删除车,都是它所要的操作。然后就是我们的灯自己能不能控制自己呢,我觉得是不能了,比如我想在多长时间内循环四个路口的灯,这个时候我们的灯就不知道该怎么办了,那么我们就要有个控制器,用来对灯进行总体上的控制。这样的话我们设计的时候就这3个类了。
         对于这个方向,应该是12个方向,都是成对出现的。然后我们把路的方向和灯结合在一块来看,每一个方向都有一盏灯来告诉该路上的车是该行呢还是停呢。并且题中是忽略了右转的情况,那么现在就只有8个方向让我们来处理了,这8个方向也是成对出现的,就是每一对的灯应该是同亮或者同暗。左转的方向的比如:南->西 和 北->东,东->南 和 西->北是两对。如此的话我们设计的时候就只有只需要把这四组中的一个拿出来设计,另外一个方向就跟随这个进行变化就可以了。即:东-西,东-南,南-北,南-西;在灯的枚举中设置它的一个成员变量是与之相对的灯以及灯的亮或者暗的属性。在灯中,我们有个可以使得灯变暗的操作,这个灯变暗了,那么我们就要指定下来那盏灯要变亮才可以的,所以在变暗的同时把下盏灯变亮,至于这个下盏灯,也要通过构造方法来传递的。具体代码:

public enum Lamp {
 /*
  * 这个交通灯利用枚举来实现,直接会有12盏灯,就只有这12个灯的实例
  * 从每一个灯表示的是不同的方向,在这里右转弯的常亮,亮(绿),暗(红);
  * 每一个方向上都有与其相对的方向,这两个方向具有相同的灯的指示
  * 转弯的灯同样有与之相对应的如:南->西和北->东具有相同的指示灯情况
  * 
  * 这样的话,我们就只要考虑两个相邻的大方向的灯的情况就可以,如此我们在
  * 对灯进行控制的时候就考虑这两个方向的就可以了
  * 
  * 设计上,每盏灯都应该存在,然后对于每盏的所具有属性:
  *                 ①是否亮用一个boolean量来表示;
  *                 ②这个方向的上,还有与之相对的一盏灯和它有相同的动作用Lamp来表示;
  *                 ③最后我们还要有这个灯之后的一个灯,好进行亮之间的转换用nextLamp表示
  *                 至于每盏灯应该具有的操作:
  *                 ①应该具有可以变亮的操作;
  *                 ②应该具有变暗的操作;
  * */
	
	//在这里我们选择的主要的两个方向是东和南,这两个方向上的灯循环切换的进行变亮或者变暗
	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 nextLamp;
	
	private Lamp(String opposite,String nextLamp,boolean lighted){
		//枚举的构造方法必须是私有的,要不然会报错
		this.opposite = opposite;
		this.nextLamp = nextLamp;
		this.lighted = lighted;
	}
	
	public boolean isLighted(){
		return lighted;
	}
	
	public void lighted(){
		lighted = true;
		if(opposite != null)
		//在上面的枚举实例中只有东和南两个方向上有对应的灯,而另外的两个方向就不存在与之对应的所以应该判断
			Lamp.valueOf(opposite).lighted();
		System.out.println(name() +"灯变绿,6个方向有车穿过");
	}
	public Lamp backOut(){
		lighted = false;
		if(opposite != null)
			Lamp.valueOf(opposite).backOut();
		Lamp currentLamp = null ;
		//该灯变暗的同时会有下一盏灯变亮,目前的灯变暗的同时把下一盏变量的灯返回给灯的控制器
		if(nextLamp!=null){
			System.out.println("绿灯从" + name() +"方向--->" + nextLamp);
			currentLamp = Lamp.valueOf(nextLamp);
			currentLamp.lighted();
			}
		return currentLamp;
	}
}

         然后再看我们的灯的控制器,灯的控制器就比较简单了,首先我们要获得第一盏灯并且要给它一个方向。这样才能开始,然后我们要的操作就是10秒后,把这盏灯变暗。每个10秒都要进行这个操作,这个功能就相当是一个定时器,所以用到线程来实现:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class LampController {
	private Lamp currentLamp;
	public LampController(){
		currentLamp = Lamp.S2N;
		currentLamp.lighted();
				ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		  timer.scheduleAtFixedRate(
				  new Runnable(){
					  public void run(){
						  currentLamp = currentLamp.backOut();
					  }
				  }, 
				  10, 
				  10, 
				  TimeUnit.SECONDS
				  );
	}
}

        在看路,路的设计其实也是很简单的首先就是有一个放车的集合,我们就用ArrayList来盛放。再者就是要给这个集合中添加车辆,然后再灯亮的时候我们要每隔1秒删除掉第一个车辆。在这我们同样也使用到了线程,具体代码如下:

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 {
  private List<String> vehicles = new ArrayList<String>();
  private String name;
  
  public Road(String name){
	  this.name = name;
	  
	  ExecutorService pool = Executors.newSingleThreadExecutor();
	  pool.execute(new Runnable(){
		  public void run(){
			  for(int i=1;i<1000;i++){
				  try {
					Thread.sleep((new Random().nextInt(10)+1)*1000);
					//随机的睡1-10秒,醒来后添加汽车
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				  vehicles.add(Road.this.name + "_" + i);
			  }
		  }
	  });
	  
	  ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
//生成一个线程池
	  timer.scheduleAtFixedRate(//按照给定的时间,进行循环执行。定时器
			  new Runnable(){
				  public void run(){
					  if(vehicles.size()>0){
						  System.out.println("-------"+Road.this.name + ":" + vehicles.size());
						  boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
						  if(lighted){
							  System.out.println(vehicles.remove(0) + "从" + Road.this.name +"穿过");
						  }
					 }else
						 System.out.println("xxxxxxx");
				  }
			  }, 
			  1, 
			  1, 
			  TimeUnit.SECONDS);}}

          这部分视频看一遍还真不知道是怎么来实现的,所以我是认真的看了两遍,然后自己顺着老师的思路编了一遍代码,才感觉有点明白了。看来还要继续在看几遍,在顺顺思路,继续加油。。。。。。。


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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值