ホームページ  >  記事  >  バックエンド開発  >  C# を使用してマインスイーパー ゲームのグラフィック コードを作成する方法のチュートリアル

C# を使用してマインスイーパー ゲームのグラフィック コードを作成する方法のチュートリアル

黄舟
黄舟オリジナル
2017-06-18 10:20:313140ブラウズ

この記事では主に C# を使ってマインスイーパー ゲームをゼロから作る詳細な説明を紹介します。これは非常に実用的です。必要な友達は参考にしてください。私がずっと興味があったからです。調べてみると、人気のゲームエンジン Unity の主な開発言語は C# であるため、C# から始めて

オブジェクト指向

のプログラミング手法を学ぶことにしました。 昔は基本的に組み込み開発をしてきましたが、基本的には

C言語

しか使いませんでした。C言語のプロセス指向の特性は、リソースを必要とする組み込みプログラミングのような場面では確かに非常に有益です。できることは非常に限られていますが、大規模なソフトウェアの開発となるとこの方法は困難です。プログラミングモデルは実際には思考の習慣であり、長い間慣れてしまうと、それを変えるのは確かに難しいプロセスです... C# について言えば、私は実際に大学で 1 学期勉強しました。当時学ばなかったのが恥ずかしくて、オブジェクト指向言語として扱って(実際、当時はオブジェクト指向が何なのか知りませんでした)、ほんの少しの構文しかないような気がします。 C言語との違いはすべて構文の違いとして分類されており、このメソッドもプログラミングできると言えます。学期の終わりに、Winform で開発したマインスイーパー ゲームを提出し、C# の学習は終了しました。それ以来、私は二度と C# に触れることはありませんでした。

今は C# に戻りました。不要な干渉を避けるために、代わりに Unity で直接勉強しましたが、今回は WInform ではなく比較的新しい WPF を選択しました。学習のステップ。最初のタスクは、以前と同様にマインスイーパ ゲームを作成することです。

冒頭に記載: この記事では主にプログラムの解析プロセスについて説明します。具体的な実装方法はこの記事の焦点では​​ありません。実装に問題がある友人は、コメント領域にメッセージを残してソース コードをリクエストするか質問してください。質問^_^。

1. 分析

1. ゲーム分析

では、このゲームをどのようにクリアするかという本題に入りましょう。細かいこと(タイミング、地雷の残り数の表示、メニューバーなど)は無視して、ゲームのメイン部分である地雷除去エリアについてだけ話しましょう。

ゲームが始まる前、掃海艇エリアには実際にはブロックが 1 つだけありました...

光と影の効果を無視して (はい、また無視しました...)、すべてブロック 色はすべて同じで、すべて同じイベント、つまり左ボタンと右ボタンに応答します。左クリックしてブロックを開き、右クリックしてブロックを地雷としてマークします。分析を続けると、さまざまな種類のブロックがあることがわかります。いくつかのブロックをクリックすると、その周囲に大きなブロックのブロックが開きます。いくつかのブロックの下に地雷があるので、クリックするとゲームオーバーになります。四角形の下には、周囲にある地雷の数を表す数字もあります。 (案の定、マウスボタンを2つ同時に押すと周囲のグリッドが自動的に開き、2回目の右クリックで疑問符が表示される機能は無視しました...しかし、実際にはこの機能は後でわかります追加するのは非常に簡単です)。

それでは、まずマインスイーパー ゲームのコア実装を要約しましょう:

    ブロックはマウス イベント (左ボタンを押す、左ボタンをクリックする、右ボタンを押す、マウスを移動する、マウスを移動する) に応答します。
  1. ブロックをクリックすると 3 つの効果 (爆弾、数字、空) があり、空の場合は周囲のすべてのブロックが自動的に展開されます。
  2. ブロックは一度だけ開くことができ、それ以降はキーイベントに応答しなくなります。
  3. 旗のあるマス目の数が地雷の数と等しく、地雷のあるすべてのマス目に旗がある場合、ゲームに勝ちます。
  4. 地雷を含むブロックが開くと、ゲームは失敗します。
2. 実装の技術分析

分析の結果、マインスイーパのゲームプレイは実際には非常にシンプルであり、それを実装するための技術はすべて静的であり、アニメーションがないことがわかりました。

四角は一度しか押せないボタンのように動作します(実際、私は大学時代にボタンコントロールを直接継承しました)。

しかし今回は、C#関連をもっと使うために、より面倒なカスタムコントロールメソッドを使用しました。

Cube には 3 つの表現形式があり、それぞれ具体的ですが、明らかに共通点もあるので、デザインする際にボタンの共通点を抽出し、抽象基本クラス Cube に設計しました。キューブは3種類ありますが、無精なのでそのうちの2つ(空白と数字)をNumCubeクラスにマージし、地雷が入っているのがBombCubeクラスです。 この2つのクラスはそれぞれ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中需要加入如下语句:


< myTypes:Cube x:Class="扫雷.UserControl.NumCube"

xmlns=" http:// schemas.microsoft.com/w infx/2006/xaml/presentation "

xmlns:x=" http:// schemas.microsoft.com/w infx/2006/xaml "

xmlns:mc=" http:// schemas.openxmlformats.org /markup-compatibility/2006 "

xmlns:d=" http:// schemas.microsoft.com/e xpression/blend/2008 "

mc:Ignorable="d"

xmlns:myTypes="clr-namespace:扫雷.UserControl"

d:DesignHeight="18" d:DesignWidth="18">

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个不相同的坐标。本程序的实现方法是创建一个listbd43222e33876353aff11e13a7dc75f6,之后使用随机数在0-sizeX * sizeY - 1之间随机生成一个数,检查list中是否包含该数字,若不包含则添加进list,直到list拥有N个元素停止。


List<int> BombIndexList=new List<int>();
      
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 < BombNum);
IndexList = BombIndexList;

之后根据生成的list来确定坐标上应该是NumCube还是BombCube


for (int y = 0; y < sizeY; y++)     
{
 for (int x = 0; x < sizeX;x++)
 {
  //cube属性设置
  if(bombIndexList.Exists((int temp) => 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中做游戏啦 哈哈。

以上がC# を使用してマインスイーパー ゲームのグラフィック コードを作成する方法のチュートリアルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。