基于C#—WPF的扫雷游戏

  本人是大一学生,上半学期刚学完C语言。出于自己的兴趣同时也是哥哥的任务,在寒假这几天自学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知识,自己的编程功夫也有了一些长进。希望开学之后能够继续进步,取得更大的成就!

时间: 2024-10-22 01:29:51

基于C#—WPF的扫雷游戏的相关文章

基于c++控制台的扫雷游戏

Screen   类用于与控制台交互 gotoxy(short x, short y)跳转到控制台的指定位置 void Init() 获取控制台 句柄 bool changeColor(WORD color)变更颜色 /* 0 = 黑色 8 = 灰色搜索 1 = 蓝色 9 = 淡蓝色 2 = 绿色 A = 淡绿色 3 = 浅绿色 B = 淡浅绿色 4 = 红色 C = 淡红色 5 = 紫色 D = 淡紫色 6 = 黄色 E = 淡黄色 7 = 白色 F = 亮白色 FOREGROUND_BLUE

wpf版扫雷游戏

近来觉得wpf做出来的界面很拉风,于是就去自学,发现感觉很不错,可是属性N多,太多了,而且质料也少,很多不会用,只会写基本的操作,样式直接百度黏贴在自己改改,于是属于自己的扫雷就出来了,也只能做这等游戏了,用的知识少,代码也不多,还能帮助自己提高熟练度,最后的感言还是多做才是王道啊,码农就是苦逼啊,wpf属性真是多啊,不过还是得学啊,下面也没什么好说的了,贴代码,扫雷也就一个递归而已 XAML 1 <Window x:Class="SweepMineUI.MainWindow"

洛谷P2670 扫雷游戏

题目描述 扫雷游戏是一款十分经典的单机小游戏.在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格).玩家翻开一个非地雷格时,该格将会出现一个数字--提示周围格子中有多少个是地雷格.游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格. 现在给出n行m列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数. 注:一个格子的周围格子包括其上.下.左.右.左上.右上.左下.右下八个方向上与之直接相邻的格子. 输入输出格式 输入格式: 输入文件第一行是用一个

c++ 控制台版 扫雷游戏

白天看了一天书看累了,晚上瞅见扫雷游戏,就自己琢磨着做一个呗.想了一会,也没看别人怎么做的,大概1个多小时完成了这个简单版本的扫雷游戏,由于没怎么学过c#,界面的事情可能迟几天再做,明天要回家啦,哈哈! 先说思路,其实挺简单的. (1) 随机生成10个雷,标记到二维数组里,然后计算八个方向的雷的总数记录下来,这是预处理阶段. (2)输入要翻开的位置的坐标,如果是数字直接显示,是空白的话,这里采用bfs即宽度优先搜索解决,搜到最外层是数字(仅一层)时结束,具体详见代码. // 扫雷程序 #incl

扫雷游戏

扫雷游戏 发布时间: 2017年8月15日 22:17   最后更新: 2017年8月15日 22:21   时间限制: 1000ms   内存限制: 128M 描述 扫雷游戏是一款十分经典的单机小游戏.在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格).玩家翻开一个非地雷格时,该格将会出现一个数字--提示周围格子中有多少个是地雷格.游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格. 现在给出n行m列的雷区中的地雷分布,要求计算出每个非地雷格周围的

很久木来博客园了,今天献上周末撸的扫雷游戏咯~~

下面先上效果图 上图为最终效果,界面没美化,有点丑将就将就,,,,哈哈 不多说,上代码看注释已经注释好多,扫雷主要难度在于计算但前点击周围你的安全区域,我的想法是:递归循环计算当前点击的上.下.左.右4个格子,如果遇到空白则继续,如果遇到周围有雷则停止. 由中心点往外扩散,在扩散中肯定回遇到已经处理过的格子,则跳过continue.... html代码 <!doctype html> <html> <head> <meta charset="UTF-8&

C++实现简单的扫雷游戏(控制台版)

C++新手的代码,请各位多包涵. 用C++写的一个简单的控制台版扫雷游戏.玩家通过输入方块的坐标来翻开方块. 只是一个雏形,能够让玩家执行翻开方块的操作并且判断输赢,还未添加标记方块.游戏菜单.记录游戏时间.重新开一局等等的功能. 玩家输入坐标的方式来翻开方块只适用于小型的“雷区”,若“雷区”大了,用坐标会变得很不方便. 代码片段扫雷V1.1 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

基于Cocos2dx开发卡牌游戏Demo_放开那三国 2.0

PS:下载地址在最下面 1.登录 2.副本选择 3.地图 4. 选择敌人 5. 战斗 6. 战斗结算 7. 地图拓展 8. 武将拓展 9. 下载地址 主程序(包含资源文件):点击打开链接 源代码:正在上传... 基于Cocos2dx开发卡牌游戏Demo_放开那三国 2.0,布布扣,bubuko.com

红包扫雷游戏软件开发

微信红包扫雷游戏开发,微信红包扫雷软件开发,联系微电188-2624-7572. 微信扫雷游戏模式介绍:1.选 择做庄家的粉丝,发红包可设置多少金额,多少红包数,多少红包尾数为雷, 2.发出去红包后其它粉丝可抢,如果抢的红包尾数是庄家设置的尾数那则是中雷,则需把庄家发的红包金额发给庄家.   以上是做庄家发红包,庄家不会亏本的,总会有一个中雷的,每做一次庄平台会送相对应的积分,积分可去换购产品,做庄家稳赚不亏 再说说如果你做为玩家抢红包,首先条件是你余额需有你抢庄家红包对等的钱,打个比方,庄家发