欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-08-10 15:42:46
八、随机布雷 十、设置背景区图片组 循环读取背景区数据,根据数值设置对应的图片源。 十一、开始游戏准备 根据游戏级别分别调用随机布雷、设置雷边数值方法,同时添加背景图片数组到游戏背景区。 将该方法添加到开始游戏菜单中,并计时器打开。 重复点击开始菜单,看看效果。 十二、调整游戏级别 根据菜单设置的当 ......

八、随机布雷

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

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

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

 

十二、调整游戏级别

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

/// <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()方法最后位置加入对该方法的调用。
 运行程序,看看效果。

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