• 基于C#—WPF的扫雷游戏


      自学教材:《C#入门经典(第六版)》,1月28日购入,1月29日到2月9日学习了前十六章,由于有C语言基础,在语法阶段学习起来比较轻松,不过在接触到面向对象的时候遇到了一些困难,对于一些概念的理解着实费了一些功夫,不过最后还是成功的理解了。整个程序的设计从2月10日开始,在2月12日程序基本完成。2月13日将已知的BUG都清除完毕。

      扫雷很简单。一个程序的核心就是数据结构与算法,我选择的数据结构是二维数组,算法也很简单,就是很简单的利用bool属性做标记以及翻牌的递归。

      首先是雷块类的实现,因为翻开雷块是利用单击,所以我在雷块类中继承了Button基类,使它具有Button类的所有特性。同时定义了几个bool属性,分别表示是不是雷(IsMine),有没有被翻开(IsOpened),有没有被标记(IsFlagged)。还有int属性代表周围雷数(MineAround),最大的行列数(MaxRow、MaxColumn),不是雷的个数(MaxNoMineNum),以及翻开之后显示的图片背景back,代码如下:

    class Pane :Button
        {
            public Image back = new Image();
            public int MaxNoMineNum
            { get; set; }
            public int MaxRow
            { get; set; }
            public int MaxColumn
            { get; set; }
            public bool IsMine
            { get; set; }
            public int MineAround
            { get; set; }
            public bool IsFlagged
            { get; set; }
            public bool IsOpened
            { get; set; }
            public Pane(bool isMine)
            {
                IsMine = isMine;
                
            }
            
        }
    Pane Class

      另外一个非常重要的类就是雷区类,为了方便,我将雷区做成了一个窗口,并根据用户选择难度的不同,向里面的Canvas控件动态加载我的雷块“Button”,同时在上面实现了计时器和重新开始按钮。

      根据难度不同,在初始化函数里定义了int形参Level,传递参数0为初级,1为中级,2为高级,分别按不同的雷数以及雷区大小初始化。初始化函数比较简单故不将代码列出。

      最重要的是单击事件,每次单击至少翻开一个雷块,如果该雷块周围没有雷(MineAround==0),则翻开他周围的雷块。这就要用到递归。同时应注意,一旦该雷块被翻开之后就不应该再次翻开他。否则就会无限递归下去直到栈溢出抛出StackOverFlow异常。所以应该在单击的事件处理程序中加入一个条件判断,在没有翻开(IsFlagged==false)的时候才执行。同时应注意边界上的雷块递归的处理,不能让数组越界。具体代码见下:

      1 private void PaneField_Click(object sender, RoutedEventArgs e)
      2         {
      3             if(IsTimerStart==false)
      4             {
      5                 IsTimerStart = true;
      6                 myTimer.Start();
      7             }
      8             if(IsWining()&&WiningJudge==true&&IsGameOver==false)
      9             {
     10                 IsGameOver = true;
     11                 WiningJudge = false;
     12                 for (int i = 0; i < paneField[0,0].MaxRow; i++)
     13                     for (int j = 0; j < paneField[0,0].MaxColumn; j++)
     14                     {
     15                         PaneField_Click(paneField[i, j], e);
     16                     }
     17                 System.Threading.Thread.Sleep(2000);
     18                 Wining w = new Wining();
     19                 w.Show();
     20                 System.Threading.Thread.Sleep(3000);
     21                 this.Close();
     22             }
     23              if (!Field.Children.Contains((sender as Pane).back))
     24             {
     25                 int Row, Column;
     26                 Pane t = (sender as Pane);
     27                 (sender as Pane).IsOpened = true;
     28                 Field.Children.Remove((UIElement)sender);
     29                 Field.Children.Add((sender as Pane).back);
     30                 if(t.IsMine==true && LosingJudge==true&&IsGameOver==false)
     31                 {
     32                     IsGameOver = true;
     33                     LosingJudge = false;
     34                     for(int i=0;i<t.MaxRow;i++)
     35                         for(int j=0;j<t.MaxColumn;j++)
     36                         {
     37                             
     38                             PaneField_Click(paneField[i, j], e);
     39                         }
     40                     Losing l = new Losing();
     41                     l.Show();
     42                     Thread.Sleep(3000);
     43                     this.Close();
     44                 }
     45                 //递归
     46                 if (t.MineAround == 0)
     47                 {
     48                     GetRowAndColumn(t, out Row, out Column, t.MaxRow, t.MaxColumn);
     49                     #region 四个角
     50                     if (Row == 0 && Column == 0 && t.IsMine == false) //左上角
     51                     {
     52                         PaneField_Click(paneField[0, 1], e);
     53                         PaneField_Click(paneField[1, 0], e);
     54                         PaneField_Click(paneField[1, 1], e);
     55                     }
     56                     else if (Row == 0 && Column == t.MaxColumn - 1 && t.IsMine == false) //右上角
     57                     {
     58                         PaneField_Click(paneField[0, t.MaxColumn - 2], e);
     59                         PaneField_Click(paneField[1, t.MaxColumn - 2], e);
     60                         PaneField_Click(paneField[1, t.MaxColumn - 1], e);
     61                     }
     62                     else if (Row == t.MaxRow - 1 && Column == 0 && t.IsMine == false) //左下角
     63                     {
     64                         PaneField_Click(paneField[t.MaxRow - 2, 0], e);
     65                         PaneField_Click(paneField[t.MaxRow - 2, 1], e);
     66                         PaneField_Click(paneField[t.MaxRow - 1, 1], e);
     67                     }
     68                     else if (Row == t.MaxRow - 1 && Column == t.MaxColumn - 1 && t.IsMine == false) //右下角
     69                     {
     70                         PaneField_Click(paneField[t.MaxRow - 2, t.MaxColumn - 2], e);
     71                         PaneField_Click(paneField[t.MaxRow - 2, t.MaxColumn - 1], e);
     72                         PaneField_Click(paneField[t.MaxRow - 1, t.MaxColumn - 2], e);
     73                     }
     74                     #endregion
     75                     #region 四条边
     76                     else if (Row == 0 && Column != 0 && Column != t.MaxColumn - 1 && t.IsMine == false) //上边
     77                     {
     78                         for (int p = Row; p <= Row + 1; p++)
     79                             for (int q = Column - 1; q <= Column + 1; q++)
     80                             {
     81                                 bool b = Field.Children.Contains(paneField[p, q].back);
     82                                 if (!(p == Row && q == Column) && b == false)
     83                                     PaneField_Click(paneField[p, q], e);
     84                             }
     85                     }
     86                     else if (Row == t.MaxRow - 1 && Column != 0 && Column != t.MaxColumn - 1 && t.IsMine == false) //下边
     87                     {
     88                         for (int p = Row - 1; p <= Row; p++)
     89                             for (int q = Column - 1; q <= Column + 1; q++)
     90                             {
     91                                 bool b = Field.Children.Contains(paneField[p, q].back);
     92                                 if (!(p == Row && q == Column) && b == false)
     93                                     PaneField_Click(paneField[p, q], e);
     94                             }
     95                     }
     96                     else if (Column == 0 && Row != t.MaxRow - 1 && Row != 0 && t.IsMine == false) //左边
     97                     {
     98                         for (int p = Row - 1; p <= Row + 1; p++)
     99                             for (int q = Column; q <= Column + 1; q++)
    100                             {
    101                                 bool b = Field.Children.Contains(paneField[p, q].back);
    102                                 if (!(p == Row && q == Column) && b == false)
    103                                     PaneField_Click(paneField[p, q], e);
    104                             }
    105                     }
    106                     else if (Column == t.MaxColumn - 1 && Row != t.MaxRow - 1 && Row != 0 && t.IsMine == false) //右边
    107                     {
    108                         for (int p = Row - 1; p <= Row + 1; p++)
    109                             for (int q = Column - 1; q <= Column; q++)
    110                             {
    111                                 bool b = Field.Children.Contains(paneField[p, q].back);
    112                                 if (!(p == Row && q == Column) && b == false)
    113                                     PaneField_Click(paneField[p, q], e);
    114                             }
    115                     }
    116                     #endregion
    117                     #region 其他位置
    118                     else if (t.IsMine == false)
    119                         for (int p = Row - 1; p <= Row + 1; p++)
    120                             for (int q = Column - 1; q <= Column + 1; q++)
    121                             {
    122                                 bool b = Field.Children.Contains(paneField[p, q].back);
    123                                 if (!(p == Row && q == Column) && b == false)
    124                                     PaneField_Click(paneField[p, q], e);
    125                             }
    126                     #endregion
    127                 }
    128             }
    129         }
    PaneField_Click

      其中的GetRowAndColumn方法在PaneField中定义,通过Pane对象的Equals方法来得到该元素在二维数组中的下标并利用out形参返回。IsWining方法也在类中定义为私有方法,通过统计翻开数与不是雷的个数是否相等来判断是否胜利。
      至此,扫雷中比较复杂和重要的两个类就介绍完毕了。其他的类or窗口(难度选择,输赢提示)都非常简单,故不再赘述。通过编写这个程序,让我很好的应用了这十几天学习的.Net知识,自己的编程功夫也有了一些长进。希望开学之后能够继续进步,取得更大的成就!

  • 相关阅读:
    CSS中expression使用简介
    过滤Html标签代码
    ASP.NET上传图片时显示预览
    30分钟搞定.net正则表达式
    DataFormatString格式化
    Js事件大全
    Hibernate关联映射
    动态给下拉框添加选项
    python模块整理文章导航
    python学习笔记文章导航
  • 原文地址:https://www.cnblogs.com/mxy2014/p/4296591.html
Copyright © 2020-2023  润新知