八、随机布雷

/// <summary>
/// 随机布地雷
/// </summary>
/// <param name="mineNum">地雷数</param>
private void SetRndMine(int mineNum)
{
for (int k = ; k < mineNum; k++)
{
int nullnum = ; for (int j = ; j < _gameLevel._colGrid; j++)
{
for (int i = ; i < _gameLevel._rowGrid; i++)
{
if (_backData[j, i] == (int)BackState.BLANK)
nullnum++;
}
} if (nullnum < )
return; int index = rnd.Next(, nullnum);
nullnum = ;
for (int j = ; j < _gameLevel._colGrid; j++)
{
for (int i = ; i < _gameLevel._rowGrid; i++)
{
if (_backData[j, i] == )
{
nullnum++;
if (nullnum != index)
continue; _backData[j, i] = (int)BackState.MINE; // 设置为地雷
}
}
}
}
}
这个方法是不是很熟悉,我们在2048游戏中用到过,这里就不再多说了。

九、设置地雷旁边的格子标注的地雷数值
原理就是读取地雷位置,然后分别给不是地雷的格子数值+1。
/// <summary>
/// 设置地雷周围格子雷数
/// </summary>
private void SetCellMineNumber()
{
for (int y = ; y < _gameLevel._colGrid; y++)
{
for (int x = ; x < _gameLevel._rowGrid; x++)
{
if (_backData[y, x] == (int)BackState.MINE) // 遇到地雷则周围8格分别+1
{
if (x - > - && y - > - && _backData[y - , x - ] != (int)BackState.MINE)
_backData[y - , x - ]++; if (y - > - && _backData[y - , x] != (int)BackState.MINE)
_backData[y - , x]++; if (y - > - && x + < _gameLevel._rowGrid && _backData[y - , x + ] != (int)BackState.MINE)
_backData[y - , x + ]++; if (x - > - && _backData[y, x - ] != (int)BackState.MINE)
_backData[y, x - ]++; if (x + < _gameLevel._rowGrid && _backData[y, x + ] != (int)BackState.MINE)
_backData[y, x + ]++; if (y + < _gameLevel._colGrid && x - > - && _backData[y + , x - ] != (int)BackState.MINE)
_backData[y + , x - ]++; if (y + < _gameLevel._colGrid && _backData[y + , x] != (int)BackState.MINE)
_backData[y + , x]++; if (y + < _gameLevel._colGrid && x + < _gameLevel._rowGrid && _backData[y + , x + ] != (int)BackState.MINE)
_backData[y + , x + ]++;
}
}
}
}

十、设置背景区图片组

循环读取背景区数据,根据数值设置对应的图片源。

private void SetBackCellImage()
{
BackCanvas.Children.Clear(); for (int y=; y<_gameLevel._colGrid; y++)
{
for (int x=; x<_gameLevel._rowGrid; x++)
{
_backImage[y, x] = new Image();
if (_backData[y, x] == (int)BackState.BLANK)
{
_backImage[y, x].Source = ImageHelper.CutImage(_bmpSpace, new Int32Rect(, , _cellSize.Width, _cellSize.Height));
}
else if (_backData[y, x] == (int)BackState.MINE)
{
_backImage[y, x].Source = ImageHelper.CutImage(_bmpMine, new Int32Rect(, , _cellSize.Width, _cellSize.Height));
}
else
{
for (int i = ; i < ; i++)
{
if (_backData[y, x] == (i+))
{
_backImage[y, x].Source = ImageHelper.CutImage(
_bmpNum1_8, new Int32Rect(i * _cellSize.Width, , _cellSize.Width, _cellSize.Height));
break;
}
}
} _backImage[y, x].SetValue(Canvas.LeftProperty, x * (double)_cellSize.Width);
_backImage[y, x].SetValue(Canvas.TopProperty, y * (double)_cellSize.Height);
BackCanvas.Children.Add(_backImage[y, x]);
}
}
}

十一、开始游戏准备

根据游戏级别分别调用随机布雷、设置雷边数值方法,同时添加背景图片数组到游戏背景区。

private void ResetGame()
{
InitialGameState();
InitGameData(_level);
textBlockMineNum.Text = _gameLevel._mineNum.ToString(); SetRndMine(_gameLevel._mineNum);
SetCellMineNumber();
SetBackCellImage();
}

将该方法添加到开始游戏菜单中,并计时器打开。

private void MenuGameStart_Click(object sender, RoutedEventArgs e)
{
ResetGame();
_gameState = GameState.START; // 开始计时
_stopWatchGame.Start();
_timerSetTimeText.Start();
}

重复点击开始菜单,看看效果。

十二、调整游戏级别

根据菜单设置的当前级别值设置菜单选择状态。

/// <summary>
/// 设置级别菜单状态
/// </summary>
/// <param name="level"></param>
private void SetMenuLevelState(Level level)
{
switch (level)
{
case Level.SIMPLE:
MenuLowLevel.IsChecked = true;
MenuMiddleLevel.IsChecked = false;
MenuHighLevel.IsChecked = false;
break;
case Level.NORMAL:
MenuLowLevel.IsChecked = false;
MenuMiddleLevel.IsChecked = true;
MenuHighLevel.IsChecked = false;
break;
case Level.HARD:
MenuLowLevel.IsChecked = false;
MenuMiddleLevel.IsChecked = false;
MenuHighLevel.IsChecked = true;
break;
}
}
/// <summary>
/// 初级级别菜单
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MenuLowLevel_Click(object sender, RoutedEventArgs e)
{
if (_level == Level.SIMPLE)
return; if (MessageBox.Show("将用新难度级别重置游戏,确认要继续吗?", "警告", MessageBoxButton.YesNo, MessageBoxImage.Asterisk)
== MessageBoxResult.Yes)
{
_level = Level.SIMPLE;
SetMenuLevelState(_level); ResetGame();
}
} /// <summary>
/// 中级级别菜单
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MenuMiddleLevel_Click(object sender, RoutedEventArgs e)
{
if (_level == Level.NORMAL)
return; if (MessageBox.Show("将用新难度级别重置游戏,确认要继续吗?", "警告", MessageBoxButton.YesNo, MessageBoxImage.Asterisk)
== MessageBoxResult.Yes)
{
_level = Level.NORMAL;
SetMenuLevelState(_level);
ResetGame();
}
} /// <summary>
/// 高级级别菜单
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MenuHighLevel_Click(object sender, RoutedEventArgs e)
{
if (_level == Level.HARD)
return; if (MessageBox.Show("将用新难度级别重置游戏,确认要继续吗?", "警告", MessageBoxButton.YesNo, MessageBoxImage.Asterisk)
== MessageBoxResult.Yes)
{
_level = Level.HARD;
SetMenuLevelState(_level);
ResetGame();
}
}

十三、设置前景区图片组

/// <summary>
/// 设置前景图片数组
/// </summary>
private void SetForeCellImages()
{
ForeCanvas.Children.Clear(); for (int y = ; y < _gameLevel._colGrid; y++)
{
for (int x = ; x < _gameLevel._rowGrid; x++)
{
if (_foreData[y, x] > (int)ForeState.NONE)
{
_foreImage[y, x] = new Image();
_foreImage[y, x].Source = ImageHelper.CutImage(_bmpForeground, new Int32Rect(, , _cellSize.Width, _cellSize.Height)); _foreImage[y, x].SetValue(Canvas.LeftProperty, x * (double)_cellSize.Width);
_foreImage[y, x].SetValue(Canvas.TopProperty, y * (double)_cellSize.Height);
ForeCanvas.Children.Add(_foreImage[y, x]);
}
}
}
}

在ResetGame()方法最后位置加入对该方法的调用。
 运行程序,看看效果。

练手WPF(三)——扫雷小游戏的简易实现(中)的更多相关文章

  1. WEBGL学习笔记(七):实践练手1-飞行类小游戏之游戏控制

    接上一节,游戏控制首先要解决的就是碰撞检测了 这里用到了学习笔记(三)射线检测的内容了 以鸟为射线原点,向前.上.下分别发射3个射线,射线的长度较短大概为10~30. 根据上一节场景的建设,我把y轴设 ...

  2. 练手WPF(三)——扫雷小游戏的简易实现(上)

    一.创建项目1.创建WPF项目,设置初始化窗口大小(初级难度):高x宽为430x350.2.添加文件夹Images,并添加相关图片. 3.xaml中引入图片资源. <Window.Resourc ...

  3. 练手WPF(三)——扫雷小游戏的简易实现(下)

    十四.响应鼠标点击事件    (1)设置对应坐标位置为相应的前景状态 /// <summary> /// 设置单元格图样 /// </summary> /// <para ...

  4. Angular4 扫雷小游戏

    扫雷小游戏,可以升级过关,难度随关卡增加.但是有很明显的bug,以后有时间会继续优化! HTML: <div class="mainContent"> <div ...

  5. 扫雷小游戏PyQt5开发【附源代码】

    也没啥可介绍哒,扫雷大家都玩过. 雷的分布算法也很简单,就是在雷地图(map:二维数组)中,随机放雷,然后这个雷的8个方位(上下左右.四个对角)的数字(非雷的标记.加一后不为雷的标记)都加一. 如何判 ...

  6. 练手WPF(二)——2048游戏的简易实现(上)

    1.创建游戏界面编辑MainWindow.xaml,修改代码如下: <Window.Resources> <Style TargetType="Label"> ...

  7. web版扫雷小游戏(一)

    作为一名程序猿,平时的爱好也不多,说起游戏,我不太喜欢大型的网游,因为太耗时间,偶尔玩玩经典的单机小游戏,比如windows下自带的游戏扫雷(秀一下,高级下最高纪录110s). 现阶段正在致力于web ...

  8. 练手WPF(一)——模拟时钟与数字时钟的制作(上)

    一.Visual Studio创建一个WPF项目. 简单调整一下MainWindow.xaml文件.主要使用了两个Canvas控件,分别用于显示模拟和数字时钟,命名为AnalogCanvas.digi ...

  9. C++扫雷小游戏(基于CMD命令行)

    这个小游戏是笔者在大一C语言课程设计的时候写的,基于命令行,为了显得漂亮一些,特别加上了彩色特效~~~ 注意:Win10系统须将命令行调为旧版命令行,否则有可能会显示乱码! 代码示例: #includ ...

随机推荐

  1. layui 使用随记

    layui confir使用 不显示右上角关闭按钮 针对提示框内按钮指定操作 layer.confirm("这里填写提示信息", {closeBtn:0,icon: 0, titl ...

  2. 13. 罗马数字转整数(C#)

    看到这道题,存在键值对,所以先建个泛型字典,把键值填进去. 由于这道题存在两个字符表示一个数字的情况,所以在for循环的时候判断一下,看看当前字符串中循环到的字符是否和下一个字符能够组成存在在字典里的 ...

  3. PlayJava Day009

    今日所学: /* 2019.08.19开始学习,此为补档. */ 1.Date工具类: Date date = new Date() ; //当前时间 SimpleDateFormat sdf = n ...

  4. 使用CAD快速看图如何将图纸打印和预览?

    有相关CAD工作经验的小伙伴们都知道,绘制完CAD图纸后是需要借助CAD看图工具来进行查看图纸的,其实CAD快速看图中不仅能够对图纸进行查看,还能够将CAD图纸进行打印出来.但是有很多的伙伴不知道要怎 ...

  5. Java基础—面向对象的三大特性

    面向对象有三大特性分别是继承.封装和多态. (1)继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法.对象的一个新类可以从现有的类中派生,这个过程称为类继承.新类 ...

  6. TCP三次握手四次分手—简单详解

    关于TCP三次握手四次分手,之前看资料解释的都很笼统,很多地方都不是很明白,所以很难记,前几天看的一个博客豁然开朗,可惜现在找不到了.现在把之前的疑惑总结起来,方便一下大家. 疑问一,上图传递过程中出 ...

  7. MySQL Linux环境的安装配置

    在Kali中已经内置了MySQL(镜像可以从mysql.com/downloads/ 下载安装) 奇怪的是博主我的kali内置的是mariaDB数据库,所以我也懒得弄MySQL了!直接mariaDB吧 ...

  8. QT QNetworkAccessManager 如何支持RESTFul的HTTP Patch方法

    HTTP Patch方法是除了post,get,put,delete之外的一个新方式, 网上查不到的,也算是独家吧: 主要用下面这个方法: QNetworkReply *sendCustomReque ...

  9. web网页利用JavaScript实现对摄像头的调用

    实现效果: 代码如下: <!DOCTYPE html> <html lang="zh"> <head> <meta charset=&qu ...

  10. 查找树ADT--二叉查找树

    二叉树的一个重要应用是它们在查找中的使用. 二叉查找树的性质:对于树中的每个节点X,它的左子树中所有项的值小于X中的项,而它的右子树中所有项的值大于X中的项.这意味着该树所有的元素可以用某种一致的方式 ...