1.遊戲規則
掃雷是玩法極其簡單的小遊戲,點擊玩家認為不存在雷的區域,標記出全部地雷所在的區域,即可獲得勝利。當點擊不包含雷的塊的時候,可能它底下存在壹個數,也可能是壹個空白塊。當點擊中有數字的塊時,遊戲會展現當前點擊塊所包含的數字。當點擊空白塊時,地圖會展開,形成壹個大小和形狀不規則的圖形,該圖形的邊界時數字塊,也可以想成展開的是壹個被數字包圍著的不規則圖形。
1.1? 數字生成規則
掃雷遊戲中是通過數字來判斷雷的位置的,那麽,數字的生成規則是什麽呢?假設遊戲中只有壹個雷,那麽,他的將被1這個數字包圍著,如果遇到邊界就忽略。如圖:
1
1
1
1
雷
1
1
1
1
雷
1
1
1
可見,遊戲是先生成雷然後再根據雷的位置生成數字的,我們再看下面的圖:
1
1
1
1
雷
2
1
2
雷
1
1
1
在上圖中,塊中有兩個數字為2的塊,它是數字疊加的結果,圍繞著雷的區域重合了,重合的區域塊的數字相加,該塊的數字就會變成相加後的數字。
1.2? 本博文的例子掃雷的規則
玩家需要把所有的空白塊點開,留下玩家認為有雷的塊,當所剩余的塊數和雷的數量相等時,玩家勝利。如果在此之前,點到有雷的方塊,玩家失敗。
2. 遊戲的算法和數據結構
2.1? 空白塊展開算法
空白塊的展開幾乎是掃雷遊戲的核心了。上面說到,掃雷遊戲時,點中空白塊,遊戲的地圖塊就會展開,我們可以觀察到:空白塊是壹層壹層展開的,所以,地圖展開算法我們就用廣度優先搜索。也許有人會問:可以用深度優先搜索算法嗎?答案是可以的,但是如果在這裏用的話,效率會比廣度優先搜索算法效率低。
2.2 掃雷的數據結構
(1)方向數組
int[][] dir={
{-1,1},//左上角
{0,1},//正上
{1,1},//右上角
{-1,0},//正左
{1,0},//正右
{-1,-1},//左下角
{0,-1},//正下
{1,-1}//右下角
};
方向數組在展開空白塊的時候回用到,因為廣度優先遍歷就是在地圖中朝各個方向走。
(2)Tile類
該類表示遊戲中的“塊”,我們給它聲明三個成員。
short? value;
boolean flag;
boolean open;
value存儲該塊的值。-1表示雷塊;0表示空白塊;>0代表數字塊。
flag存儲該雷是否被玩家標記(在本例子中無作用,保留,方便擴展)。
open存儲該塊是否被用戶點開過。
(3)Tile數組
Tile數組代表塊的集合,及遊戲的地圖,存儲著遊戲的主要數據。
(3)Point類
Point類代表“位置”,聲明Point類方便我們在地圖中生成隨機位置的雷。Point類還要重寫hashCode和equals方法,為了比較位置與位置是否相同。
(4)Mine類
對上面的數據結構的封裝。
Mine構造函數:對遊戲地圖的參數設置,比如繪制的位置,繪制的大小,塊的大小,生成的雷數等。
init()方法:清空並初始化遊戲地圖。
create(Point p)方法:在地圖中隨機生成雷的位置,並產生數字。參數p是不產生雷的位置,p點可以傳入用戶第壹次點擊時的位置。生成隨機位置的雷比較快速的辦法是:先把地圖中除p位置外所有的位置加入到鏈表中,然後生成0到鏈表大小-1之間的隨機數,根據生成的隨機數在鏈表中取元素,取完元素就把該位置從鏈表中移除,並把Tile數組中該位置的Tile的value設為-1。重復執行以上操作,直到生成的雷個數滿足要求。產生數字的辦法:遍歷Tile數組,遇到雷就將他身邊的八個的位置的value值加1,如果八個位置中有雷,或者該位置不存在,不執行任何操作。
open(Point p,boolean isFirst)方法:p代表點開某個位置的塊,即Tile數組的索引。isFirst傳入是否是第壹次點擊屏幕。該方法要對是不是第壹次點擊而作不同的操作,當玩家第壹次點擊塊時,調用create函數生成地圖。否則就進行展開地圖等操作。
(5)MainView類
視圖類,負責繪圖和操作Mine對象。
3. 代碼示例
Mine.java
詳細