Comment utiliser C# pour créer des didacticiels de code graphique pour le jeu Minesweeper

黄舟
Libérer: 2017-06-18 10:20:31
original
3165 Les gens l'ont consulté

Cet article présente principalement l'explication détaillée de partir de zéro --- créer un jeu de démineur avec C#, ce qui est très pratique. Les amis qui en ont besoin peuvent s'y référer

La raison de l'apprentissage du C# est en fait. assez simple, car j'ai toujours été très intéressé par les jeux, et j'ai vérifié que le principal langage de développement du moteur de jeu populaire Unity est C#, j'ai donc décidé de commencer par C# et d'apprendre l'orienté objet méthodes de programmation.

Dans le passé, je faisais essentiellement du développement embarqué. Après avoir longtemps fait du développement embarqué, je n'utilisais essentiellement que le langage C. Les caractéristiques orientées processus du langage C sont extrêmement populaires. dans les ressources de programmation embarquées. Elle est en effet très avantageuse dans des situations limitées, mais cette méthode est difficile à mettre en œuvre face au développement de logiciels à grande échelle. Le modèle de programmation est en fait une sorte d'habitude de réflexion. Après y avoir été habitué pendant longtemps, c'est en effet un processus difficile à changer...

En parlant de C#, je l'ai en fait étudié pendant un moment. semestre à l'université, ce qui est embarrassant à dire. À cette époque, je ne le considérais pas comme un langage orienté objet (en fait, je ne savais pas ce qu'était l'orienté objet à cette époque). Il n'y avait qu'une petite différence de syntaxe avec le langage C. Toutes les utilisations ont été classées comme différences de syntaxe, ce qui est étonnant, cette méthode peut également être programmée. A la fin du semestre, j'ai remis un jeu de démineur développé avec Winform, ce qui a mis fin à mon apprentissage du C#. Après cela, je n'ai plus jamais touché au C#.

Maintenant, je suis de retour en C# Afin d'éviter des interférences inutiles, je n'ai pas étudié directement sur Unity, mais j'ai quand même étudié en VS, mais cette fois j'ai choisi le relativement nouveau WPF au lieu de WInform pour apprendre, la première tâche est de créer un jeu de dragueur de mines comme avant.

Écrit au début : cet article partage principalement le processus d'analyse du programme. La méthode de mise en œuvre spécifique n'est pas au centre de cet article. Les amis qui ont des problèmes avec la mise en œuvre peuvent laisser un message dans la zone de commentaire pour demander le. code source ou posez des questions ^_^.

1. Analyse

1. Analyse du jeu

Maintenant, venons-en au fait, comment le terminer ce jeu. Laissant de côté les détails (comme le timing, l'affichage du nombre de mines restantes, la barre de menus, etc.), parlons simplement de la partie principale du jeu : la zone de déminage.

Avant le début du jeu, il n'y avait en fait qu'une seule chose dans la zone du dragueur de mines, et c'était le bloc...

Ignorez la lumière et l'ombre effets (Oui, je l'ai encore ignoré...), tous les blocs sont de la même couleur et répondent aux mêmes événements, qui sont des clics gauche et droit. Faites un clic gauche pour ouvrir le bloc et cliquez avec le bouton droit pour marquer le bloc comme mine. En poursuivant l’analyse, il existe différents types de blocs. Après avoir cliqué sur certains blocs, un grand bloc de blocs s'ouvrira autour d'eux. Il y a des mines sous certains blocs, cliquez dessus pour GameOver. Il y a aussi des chiffres sous les carrés, qui représentent le nombre de mines autour. (Effectivement, j'ai ignoré la fonction d'appuyer sur deux boutons de la souris en même temps pour ouvrir automatiquement la grille environnante et le deuxième clic droit pour afficher les points d'interrogation... Mais en fait, je découvrirai plus tard que cette fonction est en réalité très simple à ajouter).

Alors, résumons d'abord l'implémentation de base du jeu Démineur :

  1. Les blocs répondront aux événements de la souris (clic gauche, clic gauche, clic droit , Souris dedans, souris dehors).

  2. Il y a trois effets après avoir cliqué sur un bloc (bombe, numéro, vide). Lorsqu'il est vide, tous les blocs environnants seront automatiquement développés.

  3. Le bloc ne peut être ouvert qu'une seule fois et ne répondra plus aux événements clés.

  4. Lorsque le nombre de cases avec des drapeaux est égal au nombre de mines et que chaque case contenant des mines a un drapeau, la partie est gagnée.

  5. Lorsque le bloc contenant la mine est ouvert, le jeu échoue.

2. Analyse technique de mise en œuvre

Après analyse, avez-vous trouvé que le gameplay de Minesweeper est en réalité très simple, et la technologie à mettre en œuvre ce n'est pas difficile. Tout est statique, sans animation.

Le carré se comporte comme un bouton sur lequel on ne peut appuyer qu'une seule fois (en fait, j'ai directement hérité du contrôle des boutons lorsque j'étais à l'université).

Mais cette fois, afin d'utiliser davantage d'éléments liés au C#, j'ai utilisé une méthode de contrôle personnalisé plus gênante.

Le cube a trois formes d'expression, qui sont spécifiques, mais qui ont évidemment aussi des points communs, donc lors de la conception, j'ai extrait les points communs du bouton et l'ai conçu dans un Cube de classe de base abstrait. Il existe trois types de cubes, mais parce que je suis paresseux, j'en ai fusionné deux (vierge et numéro) dans la classe NumCube, et celle contenant les mines est la classe BombCube. Ces deux classes héritent respectivement de Cube.

Implémentation du cube :

La classe Cube comporte les champs suivants :


ImageSource cubeNormalPic
ImageSource cubeOnPic
ImageSource cubeDownPic
ImageSource cubeDisablePic
ImageSource cubeFlagPic
Copier après la connexion

Ces 5 champs permettent de paramétrer les images affichées par Cube dans différents états (normal, saisie souris, bouton gauche enfoncé, désactivé, marque)


Bool isEnable
Bool isFlag
Copier après la connexion

这两个字段就是标记Cube是否被使能和Flag


Image cubeImageHigh
Image cubeImageLow
Copier après la connexion

这2个是两个image控件,作用是用来显示图片,之所以要2个图片是因为旗子图片被设计为一个叠加在Cube上的图片。

下面再来重点讲下下面2个东西:


displayCube
mouseEvent
Copier après la connexion

在设计中,这是两个接口,分别用来处理鼠标事件和方块的展开。不同于直接在内部直接实现接口,将两个接口设计为Cube属性是为了能动态的修改这两个接口的实现方式,不至于每次修改都需要对Cube内的代码进行修改,且可以实现每个不同的Cube都使用不同的代码而不需要使用重写,这种方式在设计模式中也叫“策略模式”。

Cube只拥有一个方法,那就是Open,但这个方法其实也是有display接口代理实现。


public void Open()   
{    
 if (displayCube != null)    
 {
  displayCube.Open(this);    
 }     
}
Copier après la connexion

displayCube.Open(this)之所以要把自身传入,是因为Open方法要用到Cube自己的参数和方法。

BombCube继承自Cube

只添加了一个字段:


ImageSource bombPic
Copier après la connexion

用来存储地雷图片.

NumCube 继承自Cube


Int bombNum
Copier après la connexion

用来记录方块周围有多少个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">
Copier après la connexion

Cube 鼠标事件的实现:

鼠标事件主要是在各个事件中实现对Cube图片的变换,例如鼠标移出事件


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

关于地雷位置的生成算法实现:

游戏很重要的一个方面是,每次地雷的位置应该不同。很容易想到应该用随机数来产生地雷的位置。这就需要随机生成N个不相同的坐标。本程序的实现方法是创建一个list,之后使用随机数在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;
Copier après la connexion

之后根据生成的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]);         
 }     
}
Copier après la connexion

如何让空白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);
        }
      }
    }
  }
}
Copier après la connexion

一些小技巧:

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;
    }
  }
}
Copier après la connexion

2.Wpf创建控件较慢,为了提升(修改宽度长度或地雷数量之后)游戏开始速度,应该预先创建控件,并把控件放入list或者arr保存,按照需求取出。

到这扫雷游戏的制作就没什么难度技术上的难度的,只需要通过百度了解一些WPF常用的事件,控件,xalm相关的知识就能做出一个扫雷游戏啦。相关源码就不发在这了,需要的朋友可以评论中找我,这次游戏制作让我对面向对象的基本编程方法的了解有了一个很大的提升,下次应该就可以在Unity中做游戏啦 哈哈。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal