前陣子想用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畫到窗口上。
寫本程序的時候參考了一下icebird的程序,附上鏈接:
http://www.cnblogs.com/Icebird/archive/2006/06/21/CSharpMine.html
這個實現比較完善,我的程序只實現了最基本的功能。不過自認為結構更清晰一些,歡迎大家拍磚~
本文配套源碼