Hands on WPF: a simple implementation of mine clearing games (2)

VIII. Random mine laying

/// <summary>
/// Random mine deployment
/// </summary>
/// <param name="mineNum">Number of Mines</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;        // Set as mine
                }
            }
        }
    }
}
This method is not very familiar. We have used it in 2048 games. We will not talk about it here.


IX. set the mine value marked in the grid next to the mine
The principle is to read the position of the mine, and then respectively give the grid value + 1 which is not a mine.
/// <summary>
/// Set the number of grid mines around mines
/// </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)       // When encountering a mine, the surrounding area is divided into 8 spaces+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]++;
            }
        }
    }
}

 

X. set the picture group in the background area

Read the background area data circularly, and set the corresponding image source according to the value.

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]);
        }
    }
}

 

Xi. Start game preparation

According to the level of the game, we call random mine laying, set the numerical method of mine edge, and add the background image array to the background area of the game.

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

    SetRndMine(_gameLevel._mineNum);
    SetCellMineNumber();
    SetBackCellImage();
}

Add this method to the start game menu and the timer opens.

private void MenuGameStart_Click(object sender, RoutedEventArgs e)
{
    ResetGame();
    _gameState = GameState.START;

    //  Start timing
    _stopWatchGame.Start();
    _timerSetTimeText.Start();
}

Click the start menu repeatedly to see the effect.

 

12. Adjust game level

Sets the menu selection status based on the current level value of the menu setting.

/// <summary>
/// Set level menu status
/// </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>
/// Primary level menu
/// </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("The game will be reset with the new difficulty level. Are you sure you want to continue?", "warning", MessageBoxButton.YesNo, MessageBoxImage.Asterisk)
        == MessageBoxResult.Yes)
    {
        _level = Level.SIMPLE;
        SetMenuLevelState(_level);

        ResetGame();
    }
}

/// <summary>
/// Intermediate menu
/// </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("The game will be reset with the new difficulty level. Are you sure you want to continue?", "warning", MessageBoxButton.YesNo, MessageBoxImage.Asterisk)
        == MessageBoxResult.Yes)
    {
        _level = Level.NORMAL;
        SetMenuLevelState(_level);
        ResetGame();
    }
}

/// <summary>
/// Advanced level menu
/// </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("The game will be reset with the new difficulty level. Are you sure you want to continue?", "warning", MessageBoxButton.YesNo, MessageBoxImage.Asterisk)
        == MessageBoxResult.Yes)
    {
        _level = Level.HARD;
        SetMenuLevelState(_level);
        ResetGame();
    }
}

 

XIII. Set up picture group of front scenic spot

/// <summary>
/// Set foreground picture array
/// </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]);
            }
        }
    }
}

Add a call to the ResetGame() method at the last location.
Run the program to see the effect.

Tags: PHP Asterisk

Posted on Sat, 02 Nov 2019 15:27:43 -0700 by y.t.