當前位置:
首頁 > 最新 > 從零開始-用C#製作掃雷遊戲

從零開始-用C#製作掃雷遊戲

從零開始用C#製作掃雷遊戲

學C#的原因其實挺簡單的,因為一直對遊戲挺感興趣,查了下比較流行的遊戲引擎Unity的主要開發語言是C#,所以就決定從C#入手,學學面向對象的編程方法。

以前基本都做的是嵌入式開發,做嵌入式久了,基本上只用C語言,C語言面向過程的特性在嵌入式編程這種資源極度受限的情況確實十分有利,但這種方式在面對大型軟體的開發的時候就很難勝任了。編程的模式其實是一種思維習慣,習慣久了以後,想改變確實是一個艱難的過程···

說起C#,其實在大學的時候學過一個學期,說來慚愧那時候倒也沒把它當一門面向對象的語言(其實是當時根本不知道面向對象是啥),感覺跟C語言也就一點語法差異,把所有的用法全部歸為語法不同,說來也神奇,這種方法倒也能編程。最終學期結束的時候交上去一份用Winform開發的掃雷遊戲結束了我的C#學習,在那之後就再也沒碰過C#。

現在重拾C#,為了免除掉不必要的干擾,並沒有直接在Unity上學習,而是仍然在VS中學習,但這次選擇了比較新的WPF,而不是WInform,作為學習,第一個任務還是跟以前一樣做一個掃雷遊戲。

寫在不怎麼前面的前面:本文主要分享下程序分析過程,具體的實現方法不是本文重點,對實現有問題的朋友可以自行評論區留言索要源碼或者提問^_^。

一、分析

1.遊戲分析

那進入正題,應該如何完成這個遊戲。忽略細枝末節的部分(如計時,顯示剩餘雷數,菜單欄等)不說,就單說這個遊戲的主體:掃雷區。

在遊戲沒開始的時候,掃雷區放眼望去其實只有一個東西,那就是方塊...

忽略光影效果不談(是的,我又忽略了···),所有方塊的顏色都一樣,都響應相同的事件,那就是左鍵和右鍵。左鍵點開方塊,右鍵給方塊做個標記,認定為地雷。再繼續分析,方塊具有不同的種類。有的方塊點開之後周圍會有一大片方塊一起打開。有的方塊下面是地雷,點開就GameOver。還有方塊下面是數字,代表著周圍有多少個地雷。(果然,我又忽略了滑鼠兩個鍵同時按自動打開周圍格子和第二次右鍵可以顯示問號的功能···但其實之後會發現這個功能其實要增加也會很簡單)。

所以,先來總結下掃雷遊戲實現的核心:

方塊會響應滑鼠事件(左鍵按下,左鍵單擊,右鍵按下,滑鼠移入,滑鼠移出)。

方塊被點開後的效果有三種(炸彈,數字,空),其中為空的時候會自動展開周圍所有的方塊。

方塊只能被打開一次,之後不再響應按鍵事件。

當插旗的方塊數和地雷數相等,並且每個包含地雷的方塊都被插了旗,則遊戲勝利。

當包含地雷的方塊被打開,則遊戲失敗。

2.實現技術分析

經過分析,是不是發現掃雷的的玩法其實很簡單,實現的技術也不難,全是靜態的沒有動畫的存在。

方塊的表現很像一個只能按一次的按鈕(事實上,在大學的時候我就是直接繼承的按鈕控制項)。

但這一次為了能使用到更多C#相關的東西我使用了更加麻煩的自定義控制項的方式。

方塊有三種表現形式,為特殊性,但很顯然也具有共性,所以在設計的時候,我把按鈕共性抽離出來,設計成了一個抽象的基類Cube。方塊有三種類型,但因為我懶,所以把其中的兩種(空白和數字)合并為了NumCube類,包含地雷的為BombCube類,這兩個類分別繼承了Cube。

Cube的實現:

Cube類中擁有以下欄位:

ImageSource cubeNormalPic ImageSource cubeOnPic ImageSource cubeDownPic ImageSource cubeDisablePic ImageSource cubeFlagPic

這5個欄位是用來設置Cube在各個狀態所顯示的圖片的(普通,滑鼠進入,左鍵按下,失能,標記)

Bool isEnable Bool isFlag

這兩個欄位就是標記Cube是否被使能和Flag

Image cubeImageHigh Image cubeImageLow

這2個是兩個image控制項,作用是用來顯示圖片,之所以要2個圖片是因為旗子圖片被設計為一個疊加在Cube上的圖片。

下面再來重點講下下面2個東西:

displayCube mouseEvent

在設計中,這是兩個介面,分別用來處理滑鼠事件和方塊的展開。不同於直接在內部直接實現介面,將兩個介面設計為Cube屬性是為了能動態的修改這兩個介面的實現方式,不至於每次修改都需要對Cube內的代碼進行修改,且可以實現每個不同的Cube都使用不同的代碼而不需要使用重寫,這種方式在設計模式中也叫「策略模式」。

Cube只擁有一個方法,那就是Open,但這個方法其實也是有display介面代理實現。

public void Open() { if (displayCube != null) { displayCube.Open(this); } }

displayCube.Open(this)之所以要把自身傳入,是因為Open方法要用到Cube自己的參數和方法。

BombCube繼承自Cube

只添加了一個欄位:

ImageSource bombPic

用來存儲地雷圖片.

NumCube 繼承自Cube

Int bombNum

用來記錄方塊周圍有多少個BombCube,當其為0的時候,NumCube就是顯示為空的方塊。

添加了一個組件lable用來顯示數字Text。

interface的實現

分別為每種Cube設計了一種介面的實現方式,使用這種方式,若後期需要改為動畫顯示,也只需要實現一個動畫的介面,賦值給對應的Cube就可以了。

二、實現

控制項繼承:

Wpf進行控制項繼承的時候需要注意,被繼承的控制項不能有xaml。

在繼承的時候,xaml中需要加入如下語句:

Cube 滑鼠事件的實現:

滑鼠事件主要是在各個事件中實現對Cube圖片的變換,例如滑鼠移出事件

public void MouseLeaveCube(object sender, MouseEventArgs e) { BombCube bombCube = sender as BombCube; if (bombCube.IsEnable) { isClicking = false; bombCube.cubeImageLow.Source = bombCube.cubeNormalPic; } }

關於地雷位置的生成演算法實現:

遊戲很重要的一個方面是,每次地雷的位置應該不同。很容易想到應該用隨機數來產生地雷的位置。這就需要隨機生成N個不相同的坐標。本程序的實現方法是創建一個list,之後使用隨機數在0-sizeX * sizeY - 1之間隨機生成一個數,檢查list中是否包含該數字,若不包含則添加進list,直到list擁有N個元素停止。

List BombIndexList=new List(); Random ran = new Random(); do { int bombIndex = ran.Next(0,sizeX * sizeY - 1); if(!BombIndexList.Contains(bombIndex)) { BombIndexList.Add(bombIndex); } else { continue; } } while (BombIndexList.Count

之後根據生成的list來確定坐標上應該是NumCube還是BombCube

for (int y = 0; y

temp == x + y * cubeX)) { cubexMatrix[x, y] =bombCubeList[bombIndex++]; } else { numCubeList[numIndex].Text =""; cubexMatrix[x, y] =numCubeList[numIndex++]; } cubexMatrix[x, y].IsFlag =false; cubexMatrix[x, y].Margin =new Thickness(x * 18, y * 18, 0, 0); cubexMatrix[x, y].IsEnable = true; SetCubeBombNum(cubexMatrix,cubeX, cubeY); bombGrid.Children.Add(cubexMatrix[x, y]); } }

如何讓空白Cube打開以後會打開周圍的Cube:

因為這種打開方式有點類似於遞歸,需要有傳染性(即若打開的也是空白Cube,則其也應該打開周圍的Cube),所以執行該事件的時候一定要具有周圍Cube的信息(即能獲取到周圍的控制項)。

獲取周圍的Cube的方法有兩種:

1.保存Cube自身的位置,並獲取所有Cube的位置

2.保存周圍Cube的信息

我使用的是第二種方式,之前Cube類中的Cubelist就是用來保存周圍Cube的信息的。通過CubeList找到周圍Cube,並觸發他們的左鍵單擊事件。

public void MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { NumCube numCube = sender as NumCube; if (numCube.IsEnable && numCube.IsFlag == false) { // 完成在控制項上點擊 if (isClicking) { isClicking = false; numCube.IsEnable = false; if (numCube.BombNum != 0) numCube.Text = Convert.ToString(numCube.BombNum); else { foreach (Cube cubeTemp in numCube.CubeList) { MouseButtonEventArgs args = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left); args.RoutedEvent = Cube.MouseLeftButtonDownEvent; cubeTemp.RaiseEvent(args); args.RoutedEvent = Cube.MouseLeftButtonUpEvent; cubeTemp.RaiseEvent(args); } } } } }

一些小技巧:

1.可以把一些圖片的修改放在屬性的set內,例如disable的圖片。

public bool IsEnable { get { return isEnable; } set { isEnable = value; if (isEnable) { if (cubeNormalPic != null) cubeImageLow.Source = cubeNormalPic; } else { if (cubeDisablePic != null) cubeImageLow.Source = cubeDisablePic; } } }

2.Wpf創建控制項較慢,為了提升(修改寬度長度或地雷數量之後)遊戲開始速度,應該預先創建控制項,並把控制項放入list或者arr保存,按照需求取出。

到這掃雷遊戲的製作就沒什麼難度技術上的難度的,只需要通過百度了解一些WPF常用的事件,控制項,xalm相關的知識就能做出一個掃雷遊戲啦。相關源碼就不發在這了,需要的朋友可以評論中找我,這次遊戲製作讓我對面向對象的基本編程方法的了解有了一個很大的提升,下次應該就可以在Unity中做遊戲啦 哈哈。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 推酷 的精彩文章:

Legion:基於Haskell開發的極簡區塊鏈伺服器
超越 GVFS:更多 Git 大存儲庫的優化細節
十年大猿猴生活兩茫茫-30幾歲是不是程序員生涯的一個句號
論吐槽的正確姿勢
深入理解Go的interface

TAG:推酷 |

您可能感興趣

從零開始
從零開始教你成為站在遊戲開發食物鏈頂端的程序員
瑜伽基礎動作,從零開始學起
從零開始玩膠捲
C+從零開始怎麼學?
《從零開始》新作OVA動畫將於10月發售迷你專輯
從零開始了解3D列印
從零開始學虛幻4遊戲開發系列04
從零開始用 Python 打造自己的區塊鏈
《從零開始》雷姆降臨
哈爾濱中軟分享:從零開始使用Python進行深度學習
《從零開始》天使雷姆
從零開始學漫畫
用這4個動作來練腹部,基礎簡單,從零開始練
小白如何從零開始自學DIY裝機:CPU選購篇
如何從零開始用Keras開發一個機器翻譯系統!
如何從零開始學習服裝裁剪製作?
從零開始練瑜伽 減肥瑜伽的入門動作
21步,從零開始學會如何挑選西服和配飾
Python 高手之路:從零開始打造一個Web伺服器