練手WPF(三)——掃雷小遊戲的簡易實現(中)

8、隨機佈雷數組

/// <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遊戲中用到過,這裏就再也不多說了。


9、設置地雷旁邊的格子標註的地雷數值
原理就是讀取地雷位置,而後分別給不是地雷的格子數值+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]++;
            }
        }
    }
}

 

10、設置背景區圖片組spa

循環讀取背景區數據,根據數值設置對應的圖片源。code

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

 

11、開始遊戲準備blog

根據遊戲級別分別調用隨機佈雷、設置雷邊數值方法,同時添加背景圖片數組到遊戲背景區。遊戲

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

重複點擊開始菜單,看看效果。it

 

12、調整遊戲級別class

根據菜單設置的當前級別值設置菜單選擇狀態。原理

/// <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();
    }
}

 

十3、設置前景區圖片組object

/// <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()方法最後位置加入對該方法的調用。
 運行程序,看看效果。

相關文章
相關標籤/搜索