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

原文:练手WPF(三)——扫雷小游戏的简易实现(中)

八、随机布雷

/// <summary>
/// 随机布地雷
/// </summary>
/// <param name="mineNum">地雷数</param>
private void SetRndMine(int mineNum)
{
    for (int k = 0; k < mineNum; k++)
    {
        int nullnum = 0;

        for (int j = 0; j < _gameLevel._colGrid; j++)
        {
            for (int i = 0; i < _gameLevel._rowGrid; i++)
            {
                if (_backData[j, i] == (int)BackState.BLANK)
                    nullnum++;
            }
        }

        if (nullnum < 1)
            return;

        int index = rnd.Next(1, nullnum);
        nullnum = 0;
        for (int j = 0; j < _gameLevel._colGrid; j++)
        {
            for (int i = 0; i < _gameLevel._rowGrid; i++)
            {
                if (_backData[j, i] == 0)
                {
                    nullnum++;
                    if (nullnum != index)
                        continue;

                    _backData[j, i] = (int)BackState.MINE;        // 设置为地雷
                }
            }
        }
    }
}
这个方法是不是很熟悉,我们在2048游戏中用到过,这里就不再多说了。

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

                if (y - 1 > -1 && _backData[y - 1, x] != (int)BackState.MINE)
                    _backData[y - 1, x]++;

                if (y - 1 > -1 && x + 1 < _gameLevel._rowGrid && _backData[y - 1, x + 1] != (int)BackState.MINE)
                    _backData[y - 1, x + 1]++;

                if (x - 1 > -1 && _backData[y, x - 1] != (int)BackState.MINE)
                    _backData[y, x - 1]++;

                if (x + 1 < _gameLevel._rowGrid && _backData[y, x + 1] != (int)BackState.MINE)
                    _backData[y, x + 1]++;

                if (y + 1 < _gameLevel._colGrid && x - 1 > -1 && _backData[y + 1, x - 1] != (int)BackState.MINE)
                    _backData[y + 1, x - 1]++;

                if (y + 1 < _gameLevel._colGrid && _backData[y + 1, x] != (int)BackState.MINE)
                    _backData[y + 1, x]++;

                if (y + 1 < _gameLevel._colGrid && x + 1 < _gameLevel._rowGrid && _backData[y + 1, x + 1] != (int)BackState.MINE)
                    _backData[y + 1, x + 1]++;
            }
        }
    }
}

十、设置背景区图片组

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

private void SetBackCellImage()
{
    BackCanvas.Children.Clear();

    for (int y=0; y<_gameLevel._colGrid; y++)
    {
        for (int x=0; 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(0, 0, _cellSize.Width, _cellSize.Height));
            }
            else if (_backData[y, x] == (int)BackState.MINE)
            {
                _backImage[y, x].Source = ImageHelper.CutImage(_bmpMine, new Int32Rect(0, 0, _cellSize.Width, _cellSize.Height));
            }
            else
            {
                for (int i = 0; i < 8; i++)
                {
                    if (_backData[y, x] == (i+1))
                    {
                        _backImage[y, x].Source = ImageHelper.CutImage(
                            _bmpNum1_8, new Int32Rect(i * _cellSize.Width, 0, _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 = 0; y < _gameLevel._colGrid; y++)
    {
        for (int x = 0; 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(0, 0, _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()方法最后位置加入对该方法的调用。
 运行程序,看看效果。

原文地址:https://www.cnblogs.com/lonelyxmas/p/10946799.html

时间: 2024-11-01 23:29:46

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

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

接上一节,游戏控制首先要解决的就是碰撞检测了 这里用到了学习笔记(三)射线检测的内容了 以鸟为射线原点,向前.上.下分别发射3个射线,射线的长度较短大概为10~30. 根据上一节场景的建设,我把y轴设为前进方向,z轴设为高度~ 如果射线返回有结果,那么说明鸟遇到了障碍物.代码如下: var raycaster1 = new THREE.Raycaster(birdmesh.position, new THREE.Vector3(0, 1, 0), 0, 30) var raycaster2 =

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

一.创建项目1.创建WPF项目,设置初始化窗口大小(初级难度):高x宽为430x350.2.添加文件夹Images,并添加相关图片. 3.xaml中引入图片资源. <Window.Resources> <BitmapImage x:Key="ImgSpace" UriSource="/Images/space.bmp"/> <BitmapImage x:Key="ImgMine" UriSource="/I

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

十四.响应鼠标点击事件    (1)设置对应坐标位置为相应的前景状态 /// <summary> /// 设置单元格图样 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="state"></param> private vo

Oracle SQL 经典查询练手第三篇

Oracle SQL 经典查询练手第三篇 本文分享的是Oracle SQL的经典查询第三篇,仅仅是作者自己的见解,如有问题,希望您给出建议或者方法.同时,欢迎广大读者们补充,如果您有经典的查询方式也可以拿出来我们共同分享,共同成长,共同进步. 本计算机上使用的是Oracle 11.2.0版本,使用scott用户登陆.使用的是系统自带的表. 表结构: describe employees; describe departments; describe locations; select *from

一款JavaScript开发的扫雷小游戏

<style><!-- #FLM_main { margin:50px auto; padding:20px; background:#EEE; zoom:1; width:650px; } #FLM_main table { border-collapse:collapse; background:#EEE; float:left; } #FLM_main table td { border:1px solid #CCC; font-size:20px; width:38px; hei

结对博客(扫雷小游戏)

结对题目:基于一款课下娱乐的小游戏—扫雷 一.需求分析: 1.背景:在现在社会,人们的工作和学习压力不断增大,空余时间时间日益减少,一些大型的娱乐游戏又耗费大量的娱乐时间, 又不一定对身体有益,因此不耗费大量时间的小游戏,方便有趣,是大势所趋. 2.目的:编译此系统是为了在工作和学习之余得到适当的放松,既不浪费大量时间,又可以锻炼自己的思维,缓解疲劳. 3.应用人群:本游戏是基于windows下的小游戏,对人基本没有害处,因此能接触computer的人都可以玩这款游戏. 4.设计概述: 本游戏界

2017.12.16 扫雷小游戏未完成

package saolei; /* * 设计一个二维数组,用于存放雷和周围八个格子雷的个数, * 再定义两个一维数组分别存放雷的X和Y坐标, * 布雷,记录周围八个格子雷的个数. */ import java.util.Random; public class Block { protected int[][] Array;//用于存放雷和周围雷的个数 protected int[] ArrayTestX;//用于存放雷的X坐标 protected int[] ArrayTestY;//用于存

扫雷小游戏

1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 6 #define ROW 9 7 #define COL 9 8 #define MINE_COUNT 10 9 10 int Menu() 11 { 12 printf("=======================\n"); 13 printf(&q

C语言写扫雷小游戏2

这是下午写的,这次的修改增加了鼠标的事件,需要的是windows的消息机制,WinAPI函数,以下是新添加的定义 struct { int num;//格子当前状态,1表示有雷,0表示无雷或已经显示数字 int roundnum;//统计格子周围的雷数 int flag;//右键按下显示红旗标志,0表示没有,1表示有 }Mine[10][10]; POINT Mouse;//定义鼠标事件 int MouseX, MouseY;//鼠标的x,y坐标 int mineNUM;//统计处理过的格子数