前面的博文中介紹了如何從“掃雷”游戲中獲取數據、並輸出數據,現在就來講解數據的分析:如何在程序中實現雷塊的判定。從前言中可知,“掃雷”游戲的分析,可分為四種模型,這里介紹前面三種模型的分析。
數據要比編程邏輯更容易駕馭。在此,先介紹“自動掃雷”所定義的有關數據結構。
Blog類表示游戲場景中的一個小方塊。其類圖如下所示:
m_isHide表示其是否隱藏;m_aroundMineCount表示m_isHide為false時(即方塊顯示出來時),方塊上顯示的數字;m_mineState表示m_isHide為true時,程序判斷出這個塊是雷、還是非雷(剛開始掃雷時都為UnKown)。
用TwoDimesionArray<Block> m_blocks表示由Block組成的兩維游戲場景。
由上面的數據即可對付第一、二種模型。在utility.h中分別提供兩個函數calMine(),calHide(),分別用來求某個塊周圍已經判斷出雷的數目,以及某個塊周圍未顯示的塊。如果周圍有雷的個數等於m_aroundMineCount則其它未判斷的塊就都不是雷;如果周圍未顯示的個數等於雷數,則這些就都是雷。
下面介紹第三種模型的分析:
先來簡單回顧下——(詳細先見前言)
如果出現以下的情況:
可以得出下面的數學式子:
a+b=1 (1)
d+e=1 (2)
a+b+c+d+e=2 (3)
在程序中,為了表示這個的式子,本人定義了ProbableMine類,其類圖如下:
points表示所以可能出現雷塊的坐標,mineCount表示在這個塊中雷的總數。上面三個式子得用三個ProbableMine對象表示,其mineCount分別為1,1,2。points分別為a,b;d,e ;a,b,c,d,e的坐標。
SurAnalyse負責第三種模型算法的實現。類圖如下:
其中probables為所有的可能情況,m_notMines,m_Mines用來記錄分析過程中的結果。
在分析時,兩兩比較每個ProbableMine對象,如果其中一個points是另一個的子集,則可由它們差集生成另一個ProbableMine對象。如果這個新ProbableMine對象中的mineCount==0,則可以判斷其points都不是雷;而如果mineCount==points.size(),則可以判斷其points都是雷;如果兩種情況都不滿足則加入到probables中,參加下一輪的運算。直到數據都不再變化為止。
至此,前三種模型的分析都已結束,可以看出算法並不復雜。最有挑戰的還是在第四種模型的分析,本系列的下一篇將會仔細分析(不過最近在研究第四種情況時,發現了這么一個數學題,有興趣的朋友可以思考下,一個排列組合題)。
現在將C++項目源碼公開出來: http://files.cnblogs.com/xiangism/mineTerminator_src.rar ,現在只實現前三種模型,第四種模型的代碼還不完善。 (再次強調,為了專注,本人只研究XP系統下的自動掃雷。如果是WIN7系統,則需要拷貝XP下掃雷游戲,下面提供其下載地址)
32位XP系統下的掃雷游戲:winmine_32cn
自動掃雷的EXE下載地址為:http://files.cnblogs.com/xiangism/mineTerminator.rar
下面是本人用自動掃雷完成的游戲界面