摘 要:Matlab是國際上使用最為廣泛的科學與工程計算軟件工具。與VC等其他編程語言相比,Matlab 的GUI(Graphics User Interface,圖形用戶接口)設計同樣采用了面向對象的技術,但Matlab具有強大、豐富的內置函數和工具箱,界面設計時更加簡潔、快捷與直觀。在簡要介紹掃雷游戲核心算法的基礎上,給出一種基于Matlab GUI的能安裝且能獨立運行的掃雷游戲的設計與實現方法,并在Matlab 7.1和Windows XP SP2操作系統下成功實現,經過實驗測試,結果正確,各項功能達到游戲要求。該實現方法對其他基于Matlab的游戲開發起到拋磚引玉的作用,同時對各專業人員借助Matlab語言快速開發出具備強大計算功能的專業應用軟件具有重要的意義。
關鍵詞:Matlab;掃雷;游戲開發;圖形用戶接口;Stand-Alone
中圖分類號:TP18文獻標識碼:B
文章編號:1004-373X(2008)24-085-04
Design and Realization of a Game of Mine-sweeping Based on Matlab GUI
CHEN Ziwei
(Chengdu University of Information Technology,Chengdu,610225,China)
Abstract:Matlab is the most popular scientific and engineering computation tool.Comparing to other programming language,Matlab GUI is also object-oriented,but it has powerful built-in functions and toolbox.It is more simple,faster and intuitive when interface design using Matlab GUI.Core algorithm of mine-sweeping games,design and realization method of installable and stand-alone mine-sweeping games based on Matlab GUI is presented.This game is realized on the Matlab 7.1 and Windows XP SP2.It proves that results are correct and all functions satisfy game requirements.This realization method contributes to other game developing based on Matlab,and it is valuable to help the professionals develop applications software possessing high-performance for computing based on Matlab quickly.
Keywords:Matlab;mine-sweeping;game developing;graphics user interface;Stand-Alone
1 引 言
最初以訓練鼠標操作為目的而設計的掃雷游戲是一款經久不衰的Windows平臺休閑益智游戲。盡管Windows操作系統歷經數次換代,變得越來越龐大、復雜,但這個可愛的小游戲在任何版本的Windows操作系統里卻依然保持著原貌,幾乎每個電腦使用者都接觸過它。
Matlab是美國MathWorks公司研制開發的軟件產品,它是當今世界上使用最為廣泛的科學計算軟件之一,Matlab具有強大、豐富的內置函數和工具箱,以及高度靈活的可編程性,Matlab特別適用于科學計算、圖形圖像處理、數據的擬合和可視化等,還具有動畫處理、Fourier變換、有限差分和有限元的處理等高級功能[1]。由于采用了面向對象的技術并且以矩陣運算為基礎,它的數據處理效率是其他軟件很難相比的。與VC相比,兩者在圖形界面之間有很大的相似性,但Matlab實現更簡單,特別是對于有大量數值運算和圖形圖像處理的程序,Matlab具有很大優勢。
本文將經典的掃雷游戲和Matlab相結合,研究利用Matlab的GUI工具開發類似Windows 掃雷游戲的方法。
2 掃雷游戲的算法分析
2.1 隨機布雷
掃雷游戲要求在X行、Y列的游戲區內隨機地布上nummines個雷(要求nummines
掃雷游戲還要求在沒有雷的地方被點擊后就會顯示一個數字表示它周圍有幾個雷,這里可以分析實現這個功能的算法。把整個游戲區看成一個二維數組minefield[i,j]:

要知道minefield [2,6]周圍有幾個雷,只需要去檢測如下8個網格是否布置了雷即可。
minefield[1,5],minefield[1,6],minefield[1,7]
minefield[2,5],minefield[2,7]
minefield[3,5],minefield[3,6],minefield[3,7]
將上面的8個網格的位置關系與minefield [2,6]進行比較,不難發現它們之間存在一定的數學關系,抽象出來就是:minefield[i,j]周圍雷的個數是由如下8個位置處的雷的總和決定的。
minefield[i-1,j-1],minefield[i-1,j],minefield[i-1,j+1]
minefield[i,j-1],minefield[i,j+1]
minefield[i+1,j-1],minefield[i+1,j],minefield[i+1,j+1]
上面幾個位置可能超出了邊界,因此需要根據實際情況給變量i與j設置范圍。
2.2 自動展開非雷區
掃雷程序還要求自動展開已確定沒有雷的網格(即非雷區)。如果minefield [2,6]周圍雷數為1,且minefield[3,7]已被標示為地雷,則minefield[1,5],minefield[1,6],minefield[1,7],minefield[2,5],minefield[2,7],minefield[3,5],minefield[3,6]將被展開。同理,minefield[1,5]周圍的非雷區網格也將被展開,以此類推,一直波及到有雷的網格(即雷區)為止。這也是實現本游戲的關鍵[2]。事實上這就是一種遞歸過程,通過遞歸算法可以實現。把數組的元素設定為一個類對象,它們所屬的類設定這樣的一個事件:在被展開時,檢查周圍的雷數是否與周圍標示出來的雷數相等, 如果相等則展開周圍未標示的網格。這樣新的網格展開又觸發這個事件,就這樣遞歸下去,一直蔓延到不可展開的網格為止。
3 系統設計及實現
3.1 游戲主界面設計
游戲主界面由菜單、游戲區、按鈕區、信息顯示區等幾部分構成,如圖1所示。Matlab提供了一套完整的GUI庫,能夠完成基本的Windows窗體應用程序,因此可以簡單地為掃雷程序制作出界面。圖1主要通過Matlab 的GUI控件,建立Figure對象、Axes對象、Uimenu對象、Uicontrol對象的Text類型、Uicontrol對象的Pushbutton類型等。Matlab還提供了定時器,能夠完成游戲的計時。

3.2 初始化
3.2.1 雷區/非雷區的產生
底圖的大小為N=X×Y,其中X表示底圖的行數,Y表示底圖的列數,因此申請一個X×Y的矩陣空間minefield存儲雷區與非雷區。為了隨機的產生地雷,需要產生N個隨機數并對這N個隨機數按照增序排列。這對Matlab來說很容易實現。由于需要產生nummines個地雷(可由玩家根據不同難度級別選取或自定義不同的行數、列數以及雷數,并事先賦給rows,cols,nummines等變量),所以只要找出最小的nummines個隨機數所在位置即可。可以以索引值為nummines的隨機數為設定值,并用該設定值與所有隨機數比較,小于或等于設定值的地方為邏輯1,即為雷區;大于設定值的地方為邏輯0,即為非雷區。
%隨機產生雷區和非雷區
minefield = rand(rows,cols);
[temp,index] = sort(minefield(:));
minefield = (minefield <= minefield(index(nummines)));
3.2.2 鄰接雷數的計算
掃描整個底圖,按照左、右、上、下、左上、右上、左下、右下的順序檢測每個網格周圍8格的地雷數,并把這些數字累加后賦給minefield矩陣的相應位置。
east = (2:cols); west = (1:cols-1); north = (1:rows-1); south = (2:rows);
cntmines = zeros(rows,cols);
cntmines(:,west) = cntmines(:,west) + minefield(:,east);
cntmines(:,east) = cntmines(:,east) + minefield(:,west);
cntmines(north,:) = cntmines(north,:) + minefield(south,:);
cntmines(south,:) = cntmines(south,:) + minefield(north,:);
cntmines(north,west) = cntmines(north,west) + minefield(south,east);
cntmines(north,east) = cntmines(north,east) + minefield(south,west);
cntmines(south,west) = cntmines(south,west) + minefield(north,east);
cntmines(south,east) = cntmines(south,east) + minefield(north,west);
3.3 對鼠標事件的處理
3.3.1 鼠標右鍵標記的實現
單擊鼠標右鍵標記為雷的功能是先通過判斷Figure對象中的SelectionType屬性是否為Alt,從而判斷右鍵是否按下。再確定到底哪一個網格被點擊,若點擊的網格已被標記為雷,則去掉標記,否則調用Matlab函數image來標記為雷。鼠標右鍵操作是在窗口點擊事件里處理的。
%如果計時器沒有啟動,則啟動
if strcmp(get(handle,′Running′),′off′)
start(handle);
end
axes(findobj(gcf,′Tag′,′MainAxes′));
%如果點擊了鼠標右鍵,那么Figure的SelectionType會被設置為alt
if strcmp(get(gcf,′SelectionType′),′alt′)
pt = get(gca,′CurrentPoint′);%獲取點擊的網格坐標
m = rows - (floor(pt(1,2) / HEIGHT) + 1) + 1;
n = floor(pt(1,1) / WIDTH) + 1;
if 1 <= m m <= rows 1 <= n n <= cols%如果點擊的是網格
if hflag(m,n) ~= 0%如果點擊的網格已被標記為雷,則去掉標記
set(h(m,n),′Visible′,′on′);
delete(hflag(m,n));
hflag(m,n) = 0;
remaining = remaining + 1;
set(textHndl,′String′,num2str(remaining));
else%如果點擊的網格未做操作,則標記為雷
hflag(m,n) = image([(n-1)*WIDTH+4,(n-1)*WIDTH+2+BWIDTH-5],…[(rows-m)*HEIGHT+4,(rows-m)*HEIGHT+2+BHEIGHT-5],flag);
set(h(m,n),′Visible′,′off′);
remaining = remaining - 1;
set(textHndl,′String′,num2str(remaining));
end
end
CheckWin();%檢查游戲是否勝利
drawnow;
end
3.3.2 蔓延處理
如果點了一個網格,則查看周圍的7個,那7個繼續計算周圍鄰接的網格,只要有1個不是空白(有雷),此次遞歸結束。根據這個原理可編寫一個遞歸函數xpbombs(′uncover′,m,n),該函數先對網格(m,n)周圍的地雷總數c進行判斷,如果c不大于1,則根據遞歸算法進行蔓延處理;如果c大于1(即周圍有地雷),則此次遞歸結束,在該網格處用不同顏色標明c的數值大小。
if m>1
if n>1
xpbombs(′uncover′,m-1,n-1),
end;
xpbombs(′uncover′,m-1,n);
if n < cols,
xpbombs(′uncover′,m-1,n+1),
end;
end
if n>1,
xpbombs(′uncover′,m,n-1),
end;
if n xpbombs(′uncover′,m,n+1), end; if m if n > 1, xpbombs(′uncover′,m+1,n-1), end; xpbombs(′uncover′,m+1,n); if n < cols, xpbombs(′uncover′,m+1,n+1), end; end 3.4 Matlab內置式GUI對話框設置 Matlab提供了多種內置的GUI對話框,用戶可以借助該對話框進行GUI的設置、輸入等動作,使GUI的設計更為方便,同時也可以使開發的GUI界面更富有人性化,在操作上更富有彈性。 在游戲的過程中,需要使用信息對話框給用戶反饋提示信息,這可以通過Matlab的msgbox函數來實現。由于Matlab內置式GUI對話框也是GUI的一部分,因而也可以通過set與get函數進行屬性的存取。如果無法預知有哪些屬性可以使用時,也可以由get(hm)去查看msgbox有哪些屬性可以設置,其中hm是msgbox對話框的句柄。下面的函數給出了如圖2所示的“關于”對話框的實現方法: function aboutbox_Callback(src,evnt) [IconData,IconCmap]=imread(′cuit.gif′); tips=[{′Version: 2.0′},{sprintf([′\\\Copyright 2008-2010 dsplab.cuit \\\Author: Chen Ziwei \\\ email:czw@cuit.edu.cn′])}]; hm=msgbox(tips,′About XPbombs′,′custom′,IconData,IconCmap); set(hm,′color′,′w′); th=findall(hm,′type′,′text′); set(th,′color′,′r′,′fontsize′,11); 4 將GUI制作成可安裝程序 4.1 Matlab Compiler文件編譯 Matlab可以使用C或C++編譯器進行文件編譯的操作[3],從而可以將Matlab中function格式的M文件編譯成獨立運行的可執行文件(即*.exe文件)。在編譯前,需要執行mbuild-setup進行一次編譯器安裝操作,其中setup除了可以設置當前的編譯器外,還可以用以更改setup系統信息選項文件。若僅需要使用當前Matlab Compiler所默認的Lcc編譯器,則無需執行mbuild-setup這個步驟。編譯是由“mcc-m M文件名”語句實現的。編譯成功后所產生的獨立執行文件可以直接在MS-DOS下執行。 4.2 DOS窗口的消去 在Windows平臺下如果直接運行編譯生成的可執行文件,則在運行的過程中會產生一個黑色背景的DOS窗口。這個DOS窗口是一個控制臺界面,主要用來顯示一些有用的信息,例如程序運行時產生的一些錯誤信息,或者程序運行過程中的輸出信息 (用disp( )函數輸出的信息)。如果程序不會產生這些信息或者用戶不關心這些信息,則可以直接將該DOS窗口消去。消去DOS窗口的方法有很多[4],可以采用MathWorks公司網站提供的免費工具NSIS[5]來實現。該方法首先用文本編輯工具(例如寫字板)編寫suppress.ini文件,其內容只有2行,即為: [LoadProgram] Name=XPbombs.exe 其中\"XPbombs.exe\"就是Matlab Compiler編譯所產生的可執行文件的名稱。接著直接運行所提供的工具軟件\"suppress.exe\"即可。并且\"suppress.exe\"的文件名是可以更改的,但要求\"suppress.exe\",\"suppress.ini\"和所要執行的EXE文件必須處于同一文件夾下。 4.3 可安裝程序的制作 由Matlab生成的代碼不能脫離Matlab環境獨立運行,但通過安裝Matlab自帶的MCRInstaller.exe文件就可以在沒有安裝Matlab的系統上,獨立運行由Matlab編譯后所生成的可執行文件(XPbombs.exe)[6]。因此可以利用安裝制作軟件(例如 Inno Setup),將GUI程序與MCRInstaller.exe文件一起打包。安裝制作軟件能快速制作出標準Windows風格的安裝界面,并且能將全部文件打包成一個EXE文件。執行該EXE文件程序即會解包并安裝,程序安裝后會在桌面和程序組生成程序運行的快捷方式。運行該快捷方式即可啟動程序,而不必由用戶手動啟動Matlab然后運行M文件。 5 結 語 該掃雷游戲在Matlab 7.1 和Windows XP SP2操作系統上成功實現,能在Windows平臺下安裝和獨立運行。除能實現基本的左鍵打開、右鍵標記的掃雷功能以外,還能實現計時、剩余雷數顯示、自定義游戲難度、快捷鍵操作、點擊空白網格打開一大片、作弊、語音提示等擴展功能。經過實驗測試,界面美觀,結果正確,各項功能達到游戲要求。該實現方法可對其他基于Matlab的游戲開發起到拋磚引玉的作用,其中的鍵盤、鼠標等功能的實現方法可用于其他Matlab編程,同時對各專業人員借助Matlab語言快速開發出具備強大計算功能的專業應用軟件具有重要的意義。 參考文獻 [1]何大維.Matlab循序漸進[M].北京:科學出版社,2002. [2]薇蘋.掃雷思想解析[J].電腦知識與技術,2003(34):45. [3]李顯宏.Matlab 7.x界面設計與編譯技巧[M].北京:電子工業出版社,2006. [4]Vihang.Hiding the DOS Window in a Stand-alone Application[EB/OL].http://groups.google.com/group/comp.soft-sys.matlab/browse-thread/thread/0527d566c3b72873,2007. [5]The MathWorks,Inc.Suppress Command Window[CP/OL].http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=3909,2006. [6]施曉紅,周佳.精通GUI圖形界面編程[M].北京:北京大學出版社,2003. [7]蘇金明,王永利.Matlab圖形圖像[M].北京:電子工業出版社,2005. [8]徐勇.利用VB開發掃雷游戲[J].電腦編程技巧與維護,2006(3):75-77. [9]詹國梁.用C語言進行游戲編程掃雷游戲簡介[J].廣東商學院學報,2002(S2):103-106. [10]薛年喜.Matlab在數字信號處理中的應用[M].北京:清華大學出版社,2003. [11]張建強,張秀梅.掃雷游戲策略初探[J].數學教學,2004(6):32-33. 作者簡介 陳子為 男,1978年出生,湖北漢川人,講師,碩士。主要研究方向為雷達信號處理、高速DSP系統、Matlab應用。