前陣子想用C#寫個掃雷,檢驗一下學習一年多C#的功力如何。掃雷的基本實現很簡單,動態產生控制項,然後用Controls.Add添加到視窗中,用隨機數佈雷,處理Mouse事件...最麻煩的事情不過是在點到空白地帶的時候需要實現一個FloodFill演算法。
不過要實現一個十分接近Windows掃雷的版本,還是需要費一些周折的。首先需要找到資源檔,我是在百度知道上搜到的,或者從掃雷的資源檔裡讀取也可以。
其次,控制項上的映像,要用gdi+畫上去,如果使用picture_box去load image的話會很慢,點到大片空白的時候會有閃爍。
設計的時候也有一些技巧,把MineControl控制項和Form的邏輯隔開,每個MineControl記錄自己的狀態,分別為: Initial(初始), Pressed(滑鼠左鍵按住不放), Flag(插上小旗), QuestionMark(標記為問號), Unseal(翻開後) 。同時提供Press(), UnPress(), PutFlag(), Unseal() 這些操作。這樣做的好處是,使原本複雜的判斷變得簡單,在Form中,只需要根據當前的滑鼠事件調用這些操作即可,而這些操作本身會完成MineControl的狀態轉移,並顯示出來。
滑鼠的左右鍵處理也有些小技巧,好像以前在VB裡,可以直接獲得滑鼠左右鍵當前的狀態,用Mouse.Left|Mouse.Right來判斷滑鼠左右鍵同步選取的狀況。但是C#的MouseDown事件中,只能知道當前滑鼠按下的鍵是什麼,因為每個鍵按下總有先後,在C#裡,左右鍵同步選取會觸發兩次MouseDown事件。於是,需要設一個全域變數,記錄滑鼠左右鍵當前的狀態。
最後,重寫MineControl的Paint方法,用gdi+把icon畫到視窗上。
附上源碼
SweepMine.rar
寫本程式的時候參考了一下icebird的程式,附上連結:
http://www.cnblogs.com/Icebird/archive/2006/06/21/CSharpMine.html
這個實現比較完善,我的程式只實現了最基本的功能。不過自認為結構更清晰一些,歡迎大家拍磚~