美文网首页
C++ MFC实现俄罗斯方块

C++ MFC实现俄罗斯方块

作者: HughDong | 来源:发表于2018-05-13 22:59 被阅读0次

致谢

感谢博客园用户@Ghost_zhao
因为是应对学校课程设计的要求,所以在他的代码基础上进行了解读
十分感谢! 传送门

项目预览

项目与课程设计实验报告
点击下载,密码ynf1

实现思路

界面数据

在游戏数据操作上使用0和1表示方块情况,0表示没有方块的位置,1表示有方块的位置



游戏主窗口对应15*20的方格,下一个方格窗口对应4*4的方格,在内存中的表示情况


定时机制

围绕计时器为核心的俄罗斯方块,所以将单步下落执行操作写在OnTimer()中覆盖父类的方法,每次触发计时器则进行单步下落。
暂停与游戏结束的区别在于是否重置得分/等级/方块信息,在触发暂停按钮时通过杀死计时器但不重置数据来实现暂停,再次点击暂停按钮时重新建立计时器



开始游戏并建立计时器

void CBoxDlg::OnBnClickedButtonStart()
{
    game->Start();
    CString sData; // 显示级别和得分
    sData.Format(_T("%d"), game->Level);
    GetDlgItem(IDC_STATIC_LEVEL)->SetWindowText(sData);
    sData.Format(_T("%d"), game->Score);
    GetDlgItem(IDC_STATIC_Score)->SetWindowText(sData);
    SetTimer(1,game->TIME_STEP,NULL);
}

暂停/继续操作

void CBoxDlg::OnBnClickedButtonHalt()
{
    game->HaltOrContinue();
    if(game->GetState()==HALT)
        KillTimer(1);
    if(game->GetState()==GO)
        SetTimer(1,game->TIME_STEP,NULL);
}

计时器触发操作

void CBoxDlg::OnTimer(UINT_PTR nIDEvent)
{
    if(!game->Go())
    {
        KillTimer(1);
        TCHAR *msg = _T("Game Over!");
        MessageBox(msg);
    }
    CString sLevel,sScore; // 显示级别和得分
    sLevel.Format(_T("%d"), game->Level);
    GetDlgItem(IDC_STATIC_LEVEL)->SetWindowText(sLevel);
    sScore.Format(_T("%d"), game->Score);
    GetDlgItem(IDC_STATIC_Score)->SetWindowText(sScore);
    Invalidate(true);// 重绘画面
}

定时处理

MFC官方提供了OnTimer方法的处理操作,在这里自定义OnTimer方法覆盖父类方法
在OnTimer方法中操作Go()方块单步下落,并判定是否到达底端等
单步下落后判定是否死亡,死亡则杀死计时器并弹框提示Game Over
未死亡则更新分数和等级并重新绘制画面进入新的循环



定时处理操作

void CBoxDlg::OnTimer(UINT_PTR nIDEvent)
{
    if(!game->Go()) // 执行处理函数
    {
        KillTimer(1);
        TCHAR *msg = _T("Game Over!");
        MessageBox(msg);
    }
    CString sLevel,sScore; // 显示级别和得分
    sLevel.Format(_T("%d"), game->Level);
    GetDlgItem(IDC_STATIC_LEVEL)->SetWindowText(sLevel);
    sScore.Format(_T("%d"), game->Score);
    GetDlgItem(IDC_STATIC_Score)->SetWindowText(sScore);
    Invalidate(true);// 重绘画面
}

单步下落操作

bool Game::Go()
{
    if(CanMoveDown())
    {
        MoveDown();
        return true;
    }
    else
    {
        AddTool(this->BigNet);
        RemoveLines();
        if(IsDead())
        {
            state = STOP;
            return false;
        }
        else
        {
            NextTool();
            return true;
        }
    }   
}

旋转操作

因为方块定义的时4*4的二维数组,在进行旋转操作时需要先进行转置操作,再进行水平对置,能够保证所有的形状不会变形且稳定旋转。
一字型旋转操作



田字形旋转操作



L型旋转操作

反L型旋转操作

Z型旋转操作



反Z型旋转操作

边界检测

下落方块的边界检测是游戏最核心的功能之一,由于时间原因没有将图详细画出来
思路是在边界检测函数中模拟该操作执行后的情况
例如:判断是否可以继续下落CanMoveDown()
先统计当前情况下大窗口内1的个数(正在下落的方块4+已落到底部成型的块数)
获得大窗口数据的拷贝副本
对副本进行模拟下落操作,如果下落后会产生碰撞(方块重合或越界)则1的总数发生变化,此时则不能继续执行

相关文章

网友评论

      本文标题:C++ MFC实现俄罗斯方块

      本文链接:https://www.haomeiwen.com/subject/iburdftx.html