黑馬程序員_【總結】_ Pa_交通燈管理系統

交通燈管理系統


---------- android培訓 java培訓 、期待與您交流! ---------- 

---------------------------------------------------------------------------------------------------------------------------------------------
項目名稱:
 
                     【【【交通燈管理系統】】】
模擬實現十字路口的交通燈管理系統邏輯,具體需求如下


1、異步隨機生成按照各個顯露行駛的車輛
例如:
由南而來去往北的車輛--- 直行車輛
由西而來去往南的車輛--- 右轉車輛
由懂而來去往南的車輛--- 左轉這兩
。。。
2、信號燈忽略 黃燈,只考慮紅燈和綠燈


3、應考慮左轉車輛控制信號燈,右轉車輛不受信號燈控制


4、具體信號燈控制邏輯與現實生活中的交通燈控制邏輯相同
不考慮特殊情況下的控制邏輯
注:南北車輛與東南車輛交替放心,
同方向等待車輛應放行直行車輛而後放行左轉車輛


5、每輛車通過路口時間爲1秒(提示:可通過線程sleep的方式模擬)


6、隨機生成車輛時間建個以及紅綠等叫特時間建個自定,可以設置


7、不要求實現GUI,只考慮系統邏輯實現,可通過LOG方式展現程序運行結果
----
個人感覺
1、找出關鍵對象
2、實現單個對象相關功能
3、改進相互間需要的部分功能
4、進行測試、調節 
----
配圖


分析:

1、 該項目涉及到:燈、車、路、控制器。
2、該十字路口,每個方向的車輛會有3種可能的行駛方向,得出合計有12條路線、同時也是12只燈
3、由此可見,設計到了:紅綠燈(題目不要求黃燈)、燈的變頻控制器、交通工具、路線。
由於本項目只考慮系統邏輯實現,不要求實現交通工具運行移動的過程,只捕捉交通工具穿過路口的過程
同時,交通工具運行到某一條路線上,需要觀察該路線上的紅綠燈,
並且需要知道該自己在路線是否助於第一位置,才能決定是否通過。
由此可見,交通工具在本項目中,只是充當路線上的一個元素,
1、路線讓第一個通過馬路(依次),
2、路線隨機生成後來的交通工具
3、本項目有 12條路線

4、如此:本項目設計到的(對象) 功能類:1、路線 2、紅綠燈、3、控制器   4測試類
5、燈,邏輯上有12只紅綠燈,聯繫實際生活中,假設右轉的4只燈爲常綠
並且直線上的紅綠燈會兩兩對立(這組燈同時變綠燈--另外組則同時變紅燈)--與生活中一致了。
如此一來,就只剩下4只燈(--對應4只燈--4只常綠燈)
在這種設計思維下,編寫類的時候,應該初始化:
1、對面的燈
2、下一個燈
3、燈的狀態
6、控制器,讓燈在規定的時間一到,就變色。應該用一個變頻定時器來完成
1、默認控制一個燈
2、變頻定時器 定時變燈
7、測試類 
1、創建 12條路線 
2、創建 控制器,開啓功能
---
思路
1、class Road 路線
1、路線應該初始化時就指定名稱
2、路線隨機時間add 一輛車
構造函數不能直接創建線程--調用Thread.sleep();
1、使用線程池,創建線程池對象
2、創建線程
1、設定 隨機睡眠時間時間
2、add 新車
3、移除車輛--通過十字路口
1、需要用線程池對象
2、創建一個定時器-按頻率移除
1、移除時要進行判斷--路線上是否有車
1、判斷紅綠燈的狀態--綠燈才移除

2、enum Lamp 紅綠燈
1、創建時記得是 enum
2、創建12只燈  分三組
3、3個關鍵成員變量:
1、當前等的對面的燈
2、當前燈的下一個燈
3、當前燈的狀態
4、根據成員變量生成相關的方法
1、返回對面燈的方法
2、返回下一個燈的方法
3、返回當前燈狀態的方法
4、表示等狀態的方法
1、亮狀態    >>對應- 綠
1、當前等亮的時候--對面的等同步變亮
2、黑狀態          >> 對應- 紅
1、當前等黑的時候--對面的等同步變黑
2、當前等變黑--同步下一組燈  變亮
5、由此得出 構造方法時,需要初始化3個關鍵元素。

3、class LampContorller 變頻控制器
1、默認控制一組燈
2、構造方法初始化這隻燈爲   4組燈的某一個(不能是其他燈)
3、構造方法初始化這隻燈狀態 爲   1、亮  2、黑
4、繼續構建一個變頻定時器,進行燈的狀態的切換
1、其實很簡單,就是設定一個時間         時間-->變黑-->時間-->變亮      無限循環
2、記住用Executors 線程池  的對象和方法來完成 

4、class MainClass 啓動功能測試類
1、new 出12條線路
2、new 控制器-->  開啓 交通燈測試
3、可以把12只燈 放入一個數組--方便new 出12條線路
----------
具體代碼:
--
【】交通燈項目-1------Road 路線

public class Road {
	//R-1 首先是一個集合 表示每條路線上的車輛
	private List<String> vehicles = new ArrayList<String>();
	//R-2 每條路     應該有個名字
	private String roadName = null;
	//R-2-1 通過構造函數,使每創建一條路線的時候,就指定一個名字
	public Road(String roadName){
		this.roadName = roadName;
		
		
		//r-3 不能在構造方法中直接Thread.sleep();所以new一個線程池
		ExecutorService pool = Executors.newSingleThreadExecutor();
		//r-3-1 execute執行 new Runnable 這個內部類
		pool.execute(new Runnable(){
			@Override//r-3-2 覆蓋 run方法
			public void run() {
				//r-3-2-1 假設每條路上最多999輛車
				for(int i=1 ;i<1000 ;i++ ){
					
					try {
				//r-3-2-3 隨機生成一個1-10的數組*1000 就是秒  在這個時間裏後 完成添加
						Thread.sleep((new Random().nextInt(10)+1)*1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					//r-3-2-2 添加 交通工具 到集合
					vehicles.add(Road.this.roadName + "_" + i);
					//內部類訪問外部類:1 外部類用final 修飾變量 2、重名時候 用類名.this.變量名
				}
			}
		});//command>>   Runnable 線程    
		// pool.execute>>>end
		//r-4 定時器
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
			//r-4 定時器 執行一次,或者循環執行:
			//timer.schedule(command, delay, unit)  只執行一次 下面這個是按頻率執行
			//timer.scheduleAtFixedRate(command, initialDelay, period, unit)
			//4個參數分別是;任務、循環頻率、多久執行一次、前2者的度量單位(秒、分、時等)
		timer.scheduleAtFixedRate(
		//r-4-1  4個參數分別是:1功能代碼、2、1 ,3、1、  4設定前2者爲秒
				new Runnable(){
					@Override// 功能代碼:
					public void run() {
						//r-4-2表示有車輛
						if(vehicles.size()>0){
							//r-4-3 假如 是綠燈
							//boolean lighted = true;
							//【】RL-1   Lamp.valueOf(name) 獲取到當前路線的燈 並 調用isLighted 判斷黑亮狀態
							boolean lighted = Lamp.valueOf(Road.this.roadName).isLighted();
							if(lighted){
								//r-4-4是綠燈就 讓第一輛車通行--就是移除 remove 會返回被移除的元素
								System.out.println("this car:"+vehicles.remove(0)+"---  is traversing ---");;
							}
						}
					}}, 
				1, 
				1, 
				TimeUnit.SECONDS); // end
	}
}
//【】RL-1     代表Road 完成並且 Lamp 完成 後
//Road  end



【】交通燈項目-2----Lamp  紅綠燈

public enum Lamp {
	//              N
	//          W         E 
	// 		S 


	//L-1   12個枚舉值
//	S2N,S2W,E2W,E2S,//A 正面 - 主功能
//	N2S,N2E,W2E,W2N,//b 對面
//	S2E,W2S,N2W,E2N;//c  常綠燈	
	
	//[L-14]&&[L-12]&&[L-9]&& [L-1]     12個枚舉值
	S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),//A
		//L-2  僅僅是建立枚舉值》》S2N
		//L-9 僅僅是設定 對面燈》》S2N("N2S")
		//L-12 設定燈的 [下一個燈]和  [默認黑亮狀態]、》》S2N("N2S","S2W",false)
		//[L-14]把所有等都設置完畢--三個參數,右拐常綠
	N2S(null,null,false),N2E(null,null,false),W2E(null,null,false),W2N(null,null,false),//b
	S2E(null,null,true),E2N(null,null,true),N2W(null,null,true),W2S(null,null,true);//c
	//L-10  構造方法   獲取對面的燈
		//L-12 給構造方法添加  下一個燈、默認黑亮參數
	//Lamp(String oppsite){   //傳遞Lamp oppsite 要報錯   通過傳遞String 表示名字來解決
	private Lamp(String oppsite,String next,boolean lighted){ //參數:對應燈、下一個燈、默認黑亮狀態
		this.oppsite = oppsite;
		this.next = next;
		this.lighted = lighted;
	}// L-10、L-12   end
	
	//L-2  交通燈就應該有一個[燈的狀態]----表示是亮黑是黑(亮綠,黑紅)
	private boolean lighted;
	//L-6 A [對面的燈]  的名字
	private String oppsite;
	//L-13 定義[下一個燈]的名字
	private String next;
	 
	
	//L-8 判斷這個燈的狀態  ,是亮黑是黑?
	public boolean isLighted(){
		return lighted;
	}
	//L-3 知道是黑是亮後 對面的燈需要同步變化、:
		//L-4  亮狀態
	public void light(){
			// this.lighted=true;
			//L-7  的A中的燈亮,則對面的燈同步變亮
			oppsite.light();
			//這裏很容易形成死循環,應該通過構造方法設計爲,A對應B, B沒有對應的,不形成循環。


		this.lighted = true;
		if(oppsite != null){ //A有對應的燈  才亮, 着時候B 沒有對應的,就不會亮
			//L-11 構造方法獲取到名字以後給枚舉,枚舉就能返回枚舉值對象,再調用亮燈
			Lamp.valueOf(oppsite).light();
			//oppsite.light();
		}
		System.out.println("this Lamp "+name() +"------>> to Green   共有6發方向可以通行" );
	}
		//L-5  黑 狀態
	public Lamp blackOut(){
		this.lighted=false;
		//L-15 同//L-7 正面的燈變黑,對面的也變黑。
		if(oppsite != null){ 
			Lamp.valueOf(oppsite).blackOut();
		}
			//L-16 這個燈變黑,則下一個燈 則 變亮--變綠
	//			if(next != null){ 
	//				Lamp.valueOf(next).light();//Lamp end
	//			}
		//LC-1 控制器改進代碼
		Lamp nextLamp = null ;
		if(next != null){ 			
			nextLamp = Lamp.valueOf(next);
			System.out.println("【this Green Lamp  :"+name() +"------>>  to :    " +next+"】");
			nextLamp.light();//Lamp end
		}
		//LC-2 讓該方法 在同步變黑的時候,返回下一個燈
		return nextLamp;
	}
}
//Lamp end




 
 【】交通燈項目-3---------LampController 燈的控制器

public class LampController {
	//1、 燈的控制器,肯定要控制一個燈
	private Lamp currentLamp;
	public LampController(){
		//2、初始化當前燈線路、狀態
		currentLamp = Lamp.S2N;
		currentLamp.light();
		//3、燈是按照規律來變化的,所以要設計一個 頻率定時器
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		//3-1 4參數 設定頻率爲10秒,Run功能10運行一次
		timer.scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						//3-2 應該設計這個燈變黑後,下個等變綠,並且再次調用的時候,是把綠變黑。
						//3-3修改 Lamp 類L-16 爲:LC-2  currentLamp 具有記憶功能 
							// blackOut 變黑,並返回下一個燈 所以currentLamp 是下一個的, 這樣就循環起來了。
						System.out.println("10秒一次來了");
						currentLamp = currentLamp.blackOut();
					}
				}, 
				10, 
				10, 
				TimeUnit.SECONDS);
	}
}
//LampController  end





【】交通燈項目-4 ------MainClass 測試類
public class MainClass {
	public static void main(String[] args) {
		//1、new 出12 條路線 
		//2、new出控制器
		//1-1
		String [] directions = new String[]{
			"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"
		};
		
		for(int i=0;i<directions.length;i++){
			new Road(directions[i]);
			//new Test_R(directions[i]); 
		}
		//模擬交通燈 runing:
		new LampController();
	}
}//MainClass  end

----------
細節問題:
---
1、concurrent 包,對線程和線程池的使用
以前沒學過,目前瞭解來說
構造方法中不能直接創建線程,通過concurrent 裏的對象能夠達到相同目的
Executor: 併發      執行已提交的 Runnable 任務的對象  的接口
Executors:  多線程
static ExecutorService newSingleThreadExecutor():
創建單個線程
static ExecutorService newFixedThreadPool(int nThreads) :
創建線程池
static ScheduledExecutorService newScheduledThreadPool(): 
創建一個線程池,它可安排在給定延遲後運行命令或者定期地執行。
ScheduledExecutorService:可安排在給定的延遲後運行或定期執行的命令   的接口
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) :
創建並執行在給定延遲後啓用的一次性操作。

 ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit
創建並執行一個在給定初始延遲後首次啓用的定期操作,後續操作具有給定的週期; 


TimeUnit unit :是代表long delay或者long initialDelay 的時間單位的 是一個枚舉 值是:天、時、分、秒等




2、本項目中細節代碼
1、
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);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					vehicles.add(Road.this.roadName + "_" + i);
				}
			}
		});

1、拿到線程池的對象
2、調用execute 來創建線程
3、execute方法的參數 採用內部類完成
1、線程 Runnable必須覆蓋 run 方法
1、Thread.sleep((new Random().nextInt(10)+1)*1000); 生成隨機睡眠時間
2、vehicles.add(Road.this.roadName+ "_" + i); 添加了一個新的交通工具
2、
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(
				new Runnable(){
					public void run() {
						if(vehicles.size()>0){
							//boolean lighted = true;
							boolean lighted = Lamp.valueOf(Road.this.roadName).isLighted();
							if(lighted){
								System.out.println("this car:"+vehicles.remove(0)+"---  is traversing ---");;
							}
						}
					}}, 
				1, 
				1, 
				TimeUnit.SECONDS); // end


1、拿到定時器對象
2、通過對象 的scheduleAtFixedRate 方法實現 頻率定時器
3、參數爲 線程、頻率時、功能運行時、前2者世間單位
1、線程 Runnable必須覆蓋 run 方法
1、判斷當前路線的交通工具是否有車
1、判斷當前等的狀態-是黑還是亮
1、移除集合第一個元素--達到第一輛車通過十字路口。
3、
public void light(){
		this.lighted = true;
		if(oppsite != null){ 
			Lamp.valueOf(oppsite).light();
		}
		System.out.println("this Lamp "+name() +"------>> to Green   共有6發方向可以通行" );
	}


1、設定 狀態    lighted 爲 true  表示亮
2、有對面關係,則讓對面同亮--枚舉設定只有單對面(A>>>>b  , b>>>> null)
4、
public Lamp blackOut(){
		this.lighted=false;
		if(oppsite != null){ 
			Lamp.valueOf(oppsite).blackOut();
		}
		Lamp nextLamp = null ;
		if(next != null){ 			
			nextLamp = Lamp.valueOf(next);
			System.out.println("【this Green Lamp  :"+name() +"------>>  to :    " +next+"】");
			nextLamp.light();//Lamp end
		}
		return nextLamp;
	}	


1、當前燈爲黑--對面等同步爲黑
2、當前燈爲黑--下一組燈同步爲亮
3、把下一組等提取到判斷外

5、
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);

1、12組燈  分三組
1組:主實現功能
1、包含3個參數
1、下一組燈
2、對面的燈
3、等的狀態
2組:1組對面燈
3組:常綠燈
6 對應5
private Lamp(String oppsite,String next,boolean lighted){   
		this.oppsite = oppsite;
		this.next = next;
		this.lighted = lighted;
	}	

1、構造函數進行初始化狀態
2、初始化 參數:對面燈、下一個燈、黑亮狀態  



3、其他需要注意的方法

Thread.sleep(1000): 線程方法睡眠1000毫秒
(new Random().nextInt(10)+1): 隨機生成1-10的數字


4、用到的生詞
Road: 路 
Lamp: 燈
isoftstone: 軟通動力 官網
Interview: 面試 
traffic: 燈 
Vehicles: 交通
execute 執行 
lighted 點亮、亮
oppsite 對應的  
controller 控制器
current 當前的
direction 方向   
light
blackOut


-------
運行結果:




設定的第一個燈是S2N   
運行到這裏,  已經是一個輪迴了。

無限循環執行。

上述代碼和上述圖片結果有輕微不同。 不影響功能的演示。







---------------------------------------------------------------------------------------------------------------------------------------------
---------- android培訓、 java培訓 、期待與您交流!----------


----------------------------------------------
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章