交通燈管理系統





交通燈管理系統

1.模擬實現十字路口的交通燈管理系統邏輯,具體需求如下:

    1.1異步隨機生成按照各個路線行駛的車輛:

          例如:

          1.1.1.由南向而來去往北向的車輛---- 直行車輛。

          1.1.2.由西向而來去往南向的車輛---- 右轉車輛。

          1.1.3.由東向而來去往南向的車輛---- 左轉車輛。

          1.1.4.信號燈忽略黃燈,只考慮紅燈和綠燈。

          1.1.5.應考慮左轉車輛控制信號燈,右轉車輛不受信號燈控制。

          1.1.6.具體信號燈控制邏輯與現實生活中普通交通燈控制邏輯相同,不考慮特殊情況下的控制邏輯。

如圖:


2.思考:車子由什麼產生?產生的車子存儲在什麼裏面?怎麼產生車?

       2.1.信號燈忽略黃燈,只考慮紅燈和綠燈。

       2.2.應考慮左轉車輛控制信號燈,右轉車輛不受信號燈控制。


3.思路:考慮右轉的燈都爲長綠燈,表示車隨時可以右轉

       3.1.具體信號燈控制邏輯與現實生活中普通交通燈控制邏輯相同,不考慮特殊情況下的控制邏輯。

       3.2.注:南北向車輛與東西向車輛交替放行,同方向等待車輛應先放行直行車輛而後放行左轉車輛。

       3.3. 每輛車通過路口時間爲1秒(提示:可通過線程Sleep的方式模擬)。


4.思考:車開過路口這個操作怎麼實現?在哪裏實現?

      4.1.  隨機生成車輛時間間隔以及紅綠燈交換時間間隔自定,可以設置。

      4.2.不要求實現GUI,只考慮系統邏輯實現,可通過Log方式展現程序運行結果。


5. 邏輯中的12個方向的燈:

      5.1.S2N(南到北),S2W(南到西),E2W(東到西),E2S(東到南)//主要的需要操作的四個燈,它控制通往四個方向的車。

      5.2.N2S(北到南),N2E(北到東),W2E(西到東),W2N(西到北)//前面四個燈對應的反向燈,讓它們依託於前面四個燈來運作。

      5.3.S2E(南到東),N2W(北到西),E2N(東到北),W2S(西到南)//四個右轉燈,它們長亮。


6. 排除4個長亮燈,我們需要處理的燈有8個燈,不過,每一個燈都有反向的燈。比如S2N(南到北)和N2S(北到南)。這樣的        話,就表示,S2N綠燈的話,那麼N2S也是綠燈。這樣的話,也就是說,剩下的8個燈中,有四個燈可以依託於它的反向        燈的運作來進行相同的運作,即它的反向燈綠,那麼它綠,它的反向燈紅,那麼它紅。


7.   在這裏車子可以用一個String來表示,根據不同的燈對應的路線,產生這條路線上的車。可以考慮用12個線程來產生相           對應的車。創建一個Road類,該類在構造函數中接受一個表示路線的StringroadName,

      比如:

               this.roadName=roadName; 然後根據傳入的路線,來創建這條路線上的車,並把String表示的車存入這條路線上的                  ArrayList中。通過它的remove方法來移除這條路線上的車子。不過再移除的時候,需要先判斷當前路線上的燈是否                爲綠燈,綠燈才能移。車子移除出去,就表示車子開過路口了。這個操作可以通過定時器完成。


8. 燈控制器用於操作燈變化的時間,多長時間換下一個燈綠等等。


9. 一共需要創建三個類:燈(用枚舉),路,燈控制器。


        類的編碼實現:

       9.1.Road類

                 9.1.1.每個Road對象都有一個name成員變量來代表方向,有一個vehicles成員變量來代表方向上的車輛集合。

                 9.1.2.在Road對象的構造方法中啓動一個線程每隔一個隨機的時間向vehicles集合中增加一輛車(用一個“路線名                                _id”形式的字符串進行表示)。

                 9.1.3.在Road對象的構造方法中啓動一個定時器,每隔一秒檢查該方向上的燈是否爲綠,是則打印車輛集合和將集                             閤中的第一輛車移除掉。

代碼如下:
package com.manage.system.taffic;

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;
/**
 * 每個Road對象代表一條路,一共有12個路的Road實例對象 
 * 每條路線上隨機增加新的車輛,增加到一個集合中
 * 每條路每隔一秒就會檢測這條路上的燈是否爲綠色,是則將本路線中的集合中的車移除一輛
 */

//路的對象,控制路上的車在規定時間間隔內讓車隨機通過
public class Road {
	private List<String> vechicles = new ArrayList<String>();//將路上的車放入鏈表中
	private String name;//路的名字,路名與燈名應該相同
	
	//在構造函數中創建線程
	public Road(String name){
		this.name = name;
		
		ExecutorService pool = Executors.newSingleThreadExecutor();//產生一個線程池對象實例
		
		//在類部內中使用線程池隨機創建路上的車輛
		pool.execute(new Runnable() {//在線程池中調用線程實例來產生路上的車			
			@Override
			public void run() {//重寫Run方法
				for(int i=1;i<1000;i++){//產生999輛車
					try {
						Thread.sleep((new Random().nextInt(10)+1) * 1000);//線程每隔1到10秒                                                                                                    之內產生一輛車
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					vechicles.add(Road.this.name+"_"+i);//將產生的車放入鏈表中
				}
			}
		});
		
		//創建定時器,每隔1秒中該路若爲綠燈則通過一輛車
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);//創建一個定時器
		timer.scheduleAtFixedRate(new Runnable() {//創建並執行一個在給定初始延遲後首次啓用的定期操作
			@Override
			public void run() {//操作命令
				if(vechicles.size()>0){
					boolean lighted = Lamp.valueOf(Road.this.name).isLighted();//通過路的名字與燈的名字獲取該條路上的燈的狀態
					if(lighted){//若這條路的燈是綠色則該路上的車每隔1秒通過
						System.out.println(vechicles.remove(0)+" is"+" traversing!");
					}
				}
			}
		}, 
		1, 
		1, 
		TimeUnit.SECONDS);//設置燈改變的時間間隔爲1秒
	}

}


        9.2.Lamp類

                 9.2.1.系統中有12個方向上的燈,在程序的其他地方要根據燈的名稱就可以獲得對應的燈的實例對象,綜合這些因                             素,將Lamp類用java5中的枚舉形式定義更爲簡單。

                 9.2.2.每個Lamp對象中的亮黑狀態用lighted變量表示,選用S2N、S2W、E2W、E2N這四個方向上的Lamp對象依                             次輪詢變亮,Lamp對象中還要有一個oppositeLampName變量來表示它們相反方向的燈,再用一個                                             nextLampName變量來表示此燈變亮後的下一個變亮的燈。這三個變量用構造方法的形式進行賦值,因爲枚舉                           元素必須在定義之後引用,所以無法再構造方法中彼此相互引用,所以,相反方向和下一個方向的燈用字符串                           形式表示。

                 9.2.3.增加讓Lamp變亮和變黑的方法:light和blackOut,對於S2N、S2W、E2W、E2N這四個方向上的Lamp對象,                            這兩 個方法內部要讓相反方向的燈隨之變亮和變黑,blackOut方法還要讓下一個燈變亮。

                 9.2.4.除了S2N、S2W、E2W、E2N這四個方向上的Lamp對象之外,其他方向上的Lamp對象的nextLampName和                              oppositeLampName屬性設置爲null即可,並且S2N、S2W、E2W、E2N這四個方向上的Lamp對象的                                          nextLampName和oppositeLampName屬性必須設置爲null,以便防止light和blackOut進入死循環。

代碼如下:

package com.manage.system.taffic;

//用枚舉來創建燈對象,一共有12盞燈
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;//表示燈的狀態,false爲紅燈,true爲綠燈
	private String opposite;//表示對面方向的燈
	private String next;//表示下一個方向的燈
	
	private Lamp(){		
	}
	
	private Lamp(String opposite , String next,boolean lighted){
		this.lighted = lighted;
		this.next = next;
		this.opposite = opposite;
	}
	
	public boolean isLighted(){//檢測該燈的狀態
		return lighted;
	}
	public void light(){//將該燈變爲綠色
		this.lighted = true;
		if(opposite!=null){
			Lamp.valueOf(opposite).light();
		}
		System.out.println(name()+" lamp is green:此時應該有六個方向的路有車通過。");
	}
	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("綠燈從"+name()+"-------------->切換爲"+next);
		}		
		return nextLamp;
	}
}


        9.3.LampController類

                 9.3.1.整個系統中只能有一套交通燈控制系統,所以,LampController類最好是設計成單例。

                 9.3.2.LampController構造方法中要設定第一個爲綠的燈。 

                 9.3.3.LampController對象的start方法中將當前燈變綠,然後啓動一個定時器,每隔10秒將當前燈變紅和將下一個                              燈變綠。

代碼如下:

package com.manage.system.taffic;

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;//初始化第一個燈爲S2N
		currentLamp.light();//將該燈變綠		
		
		//創建一個定時器,定時器中只有一個線程,每隔10秒改變當前燈與下一個燈的狀態,
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(
				new Runnable() {
				@Override
					public void run() {
						currentLamp = currentLamp.blackOut();//將該燈變紅並且得到下一個燈
					}
				},
				10,
				10,
				TimeUnit.SECONDS);
	}
}


         9.4.MainClass類

                 9.4.1.用for循環創建出代表12條路線的對象。

                 9.4.2.接着創建出LampController對象。

代碼如下:
package com.manage.system.taffic;

public class MainClass {
	public static void main(String[] args) {
		String[] directions = {"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 LampController();
	}

}



總結:
         用面向對象的思想將交通燈的情況模擬的非常清楚,先設計可以抽象出的類,再設計方法來控制類中的數據,
不得不說張老師這功底真牛,我學到了怎樣設計一個真實的項目。


發佈了46 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章