程序设计实践
设计报告
课题名称:俄罗斯方块(MFC版)
学生姓名:
班 级:
班内序号:27
学 号:
日 期:20##.6.1
1. 实验概述
1.1 课题目标和主要内容。
本课题的主要内容是用MFC实现经典游戏俄罗斯方块的编写。目标是能够正常运行,并且无过于严重的问题。使用的平台为MFC(基于对话框)。
1.2
采用计分升级制来进行游戏。当一次消去一行时,得一分,一次两行得4分,一次3行,得9分,一次4行,得16分。每50分为一个等级,得分足够则升级并重新开始游戏。
2. 程序设计
2.1 系统总体框架
用一个4维数组DiamondStruct[7][4][4][4]来表示所有的方块,用一个POINT类型的DiamondPos来表示方块当前的位置,然后通过一个二维数组BlockPanel[][],来表示整个游戏界面,同时进行障碍的添加。游戏过程中,通过改变DiamondPos来进行方块的下降以及左右移动,通过DiamondStruct[7][4][4][4]中第二个参数的改变来进行方块的变换。
2.2系统详细设计
【1】模块划分图及描述
【2】类关系图及描述
CWinApp与CDialog为基类。其它为添加的类。
【3】程序流程图及描述
【4】存储结构,内存分配
主要存储结构为数组。同时分配内存的有,画笔,Diamond类的指针,Panel类的指针,Block类的指针,Mill类的指针,Manager类的指针。
2.3 关键算法分析
【1】
bool Diamond::FullLine()
{
bool IsFull,Full=false;
pManager->SeriesLine=0;
for(int iy=0;iy<=pPanel->nVGridNum;iy++)
{
IsFull=true;
for(int ix=0;ix<=pPanel->nHGridNum;ix++)
{
if(!pBlock->BlockPanel[ix][iy]) IsFull=false;
}
if(IsFull)
{
Full=true;
pManager->SeriesLine++;
for(int jy=iy;jy>0;jy--)
{ Sleep(10);
for(int jx=0;jx<=pPanel->nHGridNum;jx++)
{
pBlock->BlockPanel[jx][jy]=pBlock->BlockPanel[jx][jy-1];
}
}
}
}
pManager->LineNumber+=pManager->SeriesLine;
pManager->Result+=pManager->SeriesLine*pManager->SeriesLine;
if(Full)
return true;
else return false;
}
该算法实现的功能为,判断是否已经满行,并且若是满行,进行消行,加分的操作。该算法的时间复杂度为O(n)= 【(nVGridNum)^2*nHGridNum.】/2
【2】
bool Diamond::overlap()
{
bool bTuFa=false;
POINT TexPos;
for(int iy=3;iy>=0;iy--)
{
for(int ix=0;ix<4;ix++)
{
if(DiamondStruct[DiamondType][DiamondState][ix][iy])
{
TexPos.x=ix+DiamondPos.x;
TexPos.y=iy+DiamondPos.y;
pPanel->PanelPosToPos(TexPos);
TexPos.y+=pPanel->GridSize.cy;
if(TexPos.xPanelRect.left ||
TexPos.x>pPanel->PanelRect.right||
TexPos.y>pPanel->PanelRect.bottom)
bTuFa=true;
if(pBlock->BlockPanel[DiamondPos.x+ix][DiamondPos.y+iy]) bTuFa=true;
}
}
}
if(bTuFa) return true;
return 0;
}
该算法的功能为实现判断方块是否与边界或者已有障碍重叠,若是重叠,则返回值0,若没有重叠,返回值1。算法的时间复杂度为O(1)
【3】
void Block::AddBlock()
{
for(int iy=0;iy<4;iy++)
for(int ix=0;ix<4;ix++)
{
if(pDiamond->DiamondStruct[pDiamond->DiamondType][pDiamond->DiamondState][ix][iy])
BlockPanel[pDiamond->DiamondPos.x+ix][pDiamond->DiamondPos.y+iy]=true;
}
}
该算法的功能为添加障碍,即当方块已经下降到不能下降的时候,将方块转化为障碍。该算法的时间复杂度为O(1)。
【4】
void Mill::MadeDiamond()
{
pDiamond->DiamondType=PreDiamondType;
pDiamond->DiamondState=PreDiamondState;
pDiamond->DiamondPos.x=5;
pDiamond->DiamondPos.y=0;
int nmax=rand()%25;
if((nmax>=0)&(nmax<=3)){
PreDiamondType=DIAMONDCAKE;
}
else if((nmax>=4)&(nmax<=7)){
PreDiamondType=DIAMONDHOOK;
}
else if((nmax>=8)&(nmax<=11)){
PreDiamondType=DIAMONDSEVEN;
}
else if((nmax>=12)&(nmax<=15)){
PreDiamondType=DIAMONDHEAVE;
}
else if(nmax==16){
PreDiamondType=DIAMONDBAR;
}
else if((nmax>=17)&(nmax<=20))
{
PreDiamondType=DIAMONDTWO;
}
else if((nmax>=21)&(nmax<=24)){
PreDiamondType=DIAMONDSPADE;
}
}
该算法的功能为生成新的方块,同时根据值的取值范围不同,确定每一种方块出现的概率。该算法的时间复杂度为O(1)。
【5】
void Manager::InitGame(int level)
{
srand( (unsigned)time( NULL ) ) ;
GetClientRect(theApp.m_pMainWnd->m_hWnd,&ClientRect);
Result=0;
LineNumber=0;
Level=level;
pPanel=new Panel;
pPanel->PanelRect.top =int(ClientRect.bottom*0.1f);
pPanel->PanelRect.bottom=int(ClientRect.bottom*0.9f);
pPanel->PanelRect.left =int(ClientRect.right *0.1f);
pPanel->PanelRect.right =int(ClientRect.right *0.6f);
pPanel->nHGridNum =14;
pPanel->nVGridNum =25;
pPanel->GridSize.cx =(pPanel->PanelRect.right-pPanel->PanelRect.left)/pPanel->nHGridNum;
pPanel->GridSize.cy =(pPanel->PanelRect.bottom-pPanel->PanelRect.top)/pPanel->nVGridNum;
pPanel->PanelColor =RGB(200,200,200);
pPanel->TextRect.SetRect(int(ClientRect.right *0.7f),int(ClientRect.bottom*0.5f),int(ClientRect.right *0.95f),int(ClientRect.bottom *0.9f));
pMill=new Mill;
pMill->MillRect.top =int(ClientRect.bottom*0.1f);
pMill->MillRect.bottom =int(ClientRect.bottom*0.2f);
pMill->MillRect.left =int(ClientRect.right *0.7f);
pMill->MillRect.right =int(ClientRect.right *0.8f);
pMill->GridSize.cx =(pMill->MillRect.right-pMill->MillRect.left)/4;
pMill->GridSize.cy =(pMill->MillRect.bottom-pMill->MillRect.top)/4;
pMill->MillColor =RGB(200,200,250);
pMill->PreColor =RGB(255,0,0);
pDiamond=new Diamond;
pDiamond->DiamondColor=RGB(100,100,255);
pMill->MadeDiamond();
pBlock=new Block;
pBlock->BlockColor=RGB(255,255,100);
Timer1=50;
Timer2=350-Level*40;
FallTimer=30;
SetTimer(theApp.m_pMainWnd->m_hWnd,1,Timer1,NULL);
SetTimer(theApp.m_pMainWnd->m_hWnd,2,Timer2,NULL);
}
该算法的功能为初始化游戏的数据,数据有页面的分配数据,各个部分的颜色数据以及定时器的数据。在这个函数里面,可以通过改变值来进行改变开始游戏时,游戏的初始设定。
该算法的时间复杂度为O(1)。
【6】
bool Manager::WhetherLoss()
{
for(int ix=0;ix<=pPanel->nHGridNum;ix++)
{
if(pBlock->BlockPanel[ix][0])
{
SetFree();
Sleep(2000);
InitGame(1);
}
}
return false;
}
该算法的功能为判断是否已经输了,如果最上面一行出现方块的话, 则判断为输。算法复杂度为O(N)= nHGridNum。
【7】
void Manager::OnTimer(UINT &nIDEvent)
{
if(nIDEvent==1)
{
if(KeyLeft)
{
pDiamond->MoveDiamondLeft();
DrawScene();
}
if(KeyRight)
{
pDiamond->MoveDiamondRight();
DrawScene();
}
}
else if(nIDEvent==2)
{
if(!pDiamond->MoveDiamondDown())
{
pBlock->AddBlock();
pDiamond->FullLine();
pMill->MadeDiamond();
WhetherLoss();
if(Result>=Level*50) PassLevel();
}
DrawScene();
}
}
该算法实现的功能为定时器所要实现的作用,定时器1用来控制方块左右移动时的界面的刷新,定时器2用来实现方块下降时界面的刷新。
时间复杂度为O(n)=1。
【8】
void Manager::OnKeyDown(UINT &nChar)
{
switch (nChar)
{
case VK_LEFT:
KeyLeft=true;
break;
case VK_DOWN:
SetTimer(theApp.m_pMainWnd->m_hWnd,2,FallTimer,NULL);
KeyDown=true;
break;
case VK_RIGHT:
KeyRight=true;
break;
case VK_UP:
case VK_SPACE:
pDiamond->RollDiamond();
DrawScene();
break;
}
}
该算法的功能为按下一个按键后,所实现的功能。
时间复杂度为O(1)。
【9】
void Manager::OnKeyUp(UINT &nChar)
{
switch (nChar)
{
case VK_LEFT:
KeyLeft=false;
break;
case VK_DOWN:
SetTimer(theApp.m_pMainWnd->m_hWnd,2,Timer2,NULL);
KeyDown=false;
break;
case VK_RIGHT:
KeyRight=false;
break;
case VK_UP:
case VK_SPACE:
KeySpace=false;
break;
}
}
该算法实现的功能为,当松开一个按键时,所实现的功能。
时间复杂度为O(1)。
【10】
void CMyDlg::OnPause()
{
KillTimer(1);
KillTimer(2);
MessageBox("已°?暂Y停ª¡ê\n要°a开a始º?请?点Ì?击¡Â确¨¡¤定¡§","暂Y停ª¡ê",MB_OK);
SetTimer(1,pManager->Timer1,NULL);
SetTimer(2,pManager->Timer2,NULL);
}
该算法所实现的功能为,当暂停游戏时,所发生的事件。
算法的时间复杂度为O(1)。
3. 程序运行结果分析
主要的数据输入为键盘的按键输入。输出的显示方式为对话框中方块的移动以及变换。控制左右移动时画面显示的定时器的时间为50ms,控制下降的定时器的时间为350-level*40。整个运行过程并没有内存泄露,较为令人满意。
4.总结
4.1课题的难点及关键点。
本课题的难点主要还是对MFC的不了解,怎样让方块显示在屏幕上,又是怎么样显示方块的移动,怎么样用位图作为对话框的背景等等。
不过,最后通过查找资料以及网上的介绍,还是将这些问题一一的解决了。
本课题的关键点还是在于总体思路的把握。因为对于一个游戏来说,内部的联系是非常复杂与错乱的。如果不能很好的把握住总体的思路,最终将导致自己思路的混乱。
4.2 本课题的评价
对于本次课题的评价,我感觉还是很不错的,本次课题,无论是从综合性还是新颖度,都比较令人满意。而对于自己的评价,并不是特别的满意,由于第一次编写综合性程序,所以,刚开始时,并没有调整好思路,就直接开始编写,结果导致浪费了很多的时间以及精力,后来经过补救,才完成了实验。
4.3 心得体会
对于本次实验,心得与体会还是比较多的。
1.难度非常大。此次实验,是自己所编写的第一个游戏,跟以往不同,游戏的综合性以及代码长度等等,都提升了此次编程的难度,编写之后才知道并不是想象中的那么容易。
2.提升了自己的信心。这一次俄罗斯方块程序的完成,无疑大大加强了我的信心。在编写程序之前,从来没有想到过自己能编写出俄罗斯方块这样的游戏,因为在自己的理念中,自己的水平仍然是在较为基础的一段代码的编写,而此次的实验,让自己重新定位了自己的编写程序的水平以及高度,大大加强了自己的信心。
3.非常有成就感。当运行成功游戏之后,心里的成就感是非常强烈的,对于这个程序,花费了不少的时间,最终的完成,算是给了自己一个完美的交代,看着运行成功的游戏,也是自己所编写的第一个游戏,心里的成就感非常强烈。
4.提升了自己的兴趣。通过此次的编写成功,大大提升了自己对于编程的兴趣。既然我可以编写出俄罗斯方块这样的游戏,我也可以编写出其它的游戏,打算在暑假进一步的提升自己在编程游戏方面的能力。
5.参考文献
书本---------------------------C++高级语言程序设计
程序代码----------------------《俄罗斯方块1.0》
《软件工程与开发实践1》软件设计报告题目:俄罗斯方块学院:计算机学院专业:计算机科学与技术一、软件设计概述(目的、任务、开发环境、…
C语言之游戏俄罗斯方块课程设计报告专业学生姓名指导教师完成时间1目录一需求分析错误未定义书签二概要设计错误未定义书签三详细设计错误…
程序设计实践报告20xx20xx学年第2学期题目专学生姓班级学指导教指导单日俄罗斯方块游戏设计业名号师位软件工程系期20xx032…
数字电路与逻辑设计实验报告基于VHDL的简易俄罗斯方块实验名称姓名班级简易俄罗斯方块电信工程学院04107班辅导老师日期高英20x…
程序设计综合实验设计文档惠州学院HUIZHOUUNIVERSITY课程名称程序设计综合实验姓名实验名称俄罗斯方块学号任课教师专业班…
20xx年计算机实习报告计算机实习报告姓名刘天班级20xx211114学号10210417小班序号14指导老师丘广晖题目俄罗斯方块…
目录1.系统概述12.设计说明书43.系统操作界面64.源程序编码75.测试计划366.改进意见397.课程设计心得体会408.参…
课程设计报告题目基于VC++的俄罗斯方块游戏课程名称学生创新实践院部名称XX学院专业计算机科学与技术班级M08(嵌入式)学生姓名X…
蚌埠学院本科毕业设计论文开题报告计算机科学与技术系20xx届10级计算机科学与技术1班注开题报告由学生在毕业设计论文工作前期内完成…
湖南工学院本科毕业设计论文开题报告20xx届20xx年3月1日说明开题报告作为毕业设计论文答辩委员会对学生答辩资格审查的依据材料之…
C程序设计设计性实验C程序设计设计性实验报告实验项目名称高级计算器设计与开发专业班级姓名学号实验起止日期起于年月日止于年月日实验目…