zoukankan      html  css  js  c++  java
  • 练手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()方法最后位置加入对该方法的调用。
     运行程序,看看效果。

  • 相关阅读:
    金额格式化vue组件实现
    微信小程序scroll-view滚动到最底部
    腾讯云点播开发引入mui.js 导致播放控件点击事件多次触发
    nodejs中使用crypto-js先HmacSha1加密后转Base64
    vue filters中使用data中数据
    移动web开发中input等输入框问题
    d3-tip中show在自己调用时需要改变this值
    js函数式编程curry与compose实现
    mui中confirm在苹果出现bug,confirm点击确定跳转页面再返回后,页面被遮罩盖住无法使用
    mui上拉加载会影响页面中的某些点击事件
  • 原文地址:https://www.cnblogs.com/moonblogcore/p/10944619.html
Copyright © 2011-2022 走看看