湘潭大学软件设计实践副本.docx
《湘潭大学软件设计实践副本.docx》由会员分享,可在线阅读,更多相关《湘潭大学软件设计实践副本.docx(44页珍藏版)》请在冰豆网上搜索。
![湘潭大学软件设计实践副本.docx](https://file1.bdocx.com/fileroot1/2023-6/10/553745f7-3108-4601-b919-61dca66dec19/553745f7-3108-4601-b919-61dca66dec191.gif)
湘潭大学软件设计实践副本
软件设计实践报告
单位:
信息工程学院
班级:
计算机二班
学号:
姓名:
韩林波
任课教师:
周维
湘潭大学
2016年9月
软件设计实践
项目名称:
俄罗斯方块
一、项目概述
1、概述
作为家喻户晓的游戏,俄罗斯方块可谓是大名鼎鼎。
不过,尽管它看起来比较简单,实际上对于我们新手而言确实是一个具有挑战性的项目。
我们准备先简单的理解下俄罗斯游戏开发的大概算法和需要的知识,然后把这些知识组合开发俄罗斯方块。
基本上实现俄罗斯方块游戏的控制和操作。
并使用windowsIDE搭建一个完整的windows应用程序。
通过这个项目,提高自身的动手能力。
2、目的和用途
我们在实际动手过程中,将C++课程中所学的概念、理论和方法加以运用,按照C++程序设计的基本步骤,设计出了一个适当规模的程序来实现设计课程内容中的全部功能;设计了主控模块程序.对给出的程序源代码给出了各部分的详细注释.自己根据能力及需要添加相应功能模块,增强模拟系统功能。
完整的项目内容也增强了我在课堂中的理论学习,为实习工作打下了基础。
3、需求说明
利用MicrosoftVisualstdio2010编写一个windows窗口应用程序下的俄罗斯方块游戏。
要求:
(1)利用面向对象的方法编写。
(2)能够记录游戏得分。
(3)俄罗斯方块的多种类和旋转操作
(4)信息提示时显示颜色变化。
(5)暂停和重新开始
4、环境要求
本程序采用MicrosoftVisualstdio2010的专业版本进行编译。
MicrosoftVisualstdio2010是Microsoft公司推出的基于Windows操作系统的可视化C++编程工具,尽管Microsoft公司推出了.NET平台的集成开发环境,但由于其良好的界面和可操作性,加上支持标准C/C++规范,有相当多的编程人员使用MicrosoftVisualstdio2010进行应用系统的开发。
关于稳定性,经测试,本程序可以在windows操作系统中稳定运行,较为稳定。
VC++是由Microsoft公司制作,基于WINDOWS环境的一款编程软件。
由于WINDOWS操作系统比起MS-DOS操作系统优越了许多。
作为与之相搭配的编程软件自然也是功能非常强大,其最大的特点也就是可视化。
不过在提供可视化的编程方式的同时,它采用了面向对象的程序设计方法,同传统的结构化程序设计方法相比,缩短了软件开发的周期,提高了软件的开发效率,使程序员可以更好地理解和管理庞大且复杂的程序。
VC++中还集成了大量的最新技术,如ActiveX,COM等技术适合开发大型工程,这是相对于VB的一个优势。
它的兼容性较好,还为用户提供了极为丰富的文档和范例。
关于VC的参考资料也非常多,程序开发人员可以紧紧地把握住软件开发技术发展的方向,开发出功能强大的应用程序。
二、系统分析与设计
1、系统分析
根据分析,俄罗斯方块这个程序一共要实现如下几个功能,开始游戏、游戏的暂停\继续、游戏控制和退出游戏。
其中游戏控制最为主要和重要,它控制着整个游戏的画面和有关数据的操作,是游戏的核心部分。
暂停和退出功能做成一体,在退出的提示下不做任何操作即可实现暂停的功能。
程序结构如图。
2、系统设计
根据分析后的程序结构图设计出相应的流程图。
俄罗斯方块的内容主要包括游戏开始,画背景和边框,显示分数等级和下一个方块的预览图;根据速度没隔一定时间方块自动下落,当有按键操作时,根据相应按键执行动作,每次动作前要判断是否动作可以执行。
下落方块满一行时,消去该行,根据消去行数得到相应分数。
分数达到一定程度,等级提升,速度加快。
同时可以响应Esc按键,提示是否退出程序。
如图所示。
3、模块/函数设计
根据程序的结构,将俄罗斯方块需要实现的功能细化为相应的类成员函数。
程序有三个类,一个Block类,作为程序的元素块组成其他元素。
一个MyMap类,用于整个俄罗斯方块的地图相关操作。
一个Manage类,用于整个游戏的相关操作。
----------------------------------------------------------------------------
Block类设计声明
classCBlock
{
public:
CBlock(void);
~CBlock(void);
voidinitBlock();
void_initNextBlock();//初始化下一个方块
voidSetBlockMove(boolisLeft);//方块移动
voidSetBlockDown();
voidSetBlockChange();//方块坐标变化
public:
BLOCK_POS*GetBlockHead(){returnm_blockDate;}
intGetBlockType(){returnm_blockType;}
intGetNextBlockType(){returnm_NextblockType;}
intGetBlockChangeType(){returnm_blockChangeType;}
BLOCK_POS*GetNextBlockHead(){returnm_NextblockDate;}
private:
BLOCK_POSm_blockDate[BLOCK_NUM];
intm_blockType;
intm_blockChangeType;
BLOCK_POSm_NextblockDate[BLOCK_NUM];
intm_NextblockType;
intm_NextblockChangeType;
};
-------------------------------------------------------------------------------
MAP类设计声明(MyMap类)
classCMyMap
{
public:
CMyMap(void);
~CMyMap(void);
voidinitMap();//初始化地图
voidDrawMap(HDChdc);//绘制窗口地图
voidSetMapVal(introw,intcol,intval);
voidSetMinMapVal(introw,intcol,intval);
intGetMapVal(introw,intcol){returnm_mapDate[row][col];}//地图大小行列
intGetNum();
boolIsOver();//游戏是否结束
voidSetBlockColor(inttype);//地图块颜色
voidSetNextBlockColor(inttype);//下一个板块颜色
private:
intm_mapDate[MAP_ROW][MAP_COL];
intm_NextMapDate[BLOCK_NUM][BLOCK_NUM];
private:
RECTm_FillRect;
HBRUSHm_BlockHr;
HBRUSHm_FrameHr;
HBRUSHm_RunBlockHr;
HBRUSHm_MapHr;
HBRUSHm_NextBlockHr;
};
------------------------------------------------------------------------------
Manager类设计声明(Manager类)
classCManage
{
public:
CManage(HDChdc);
~CManage(void);
voidinitGame();//初始化游戏
voidUpdateGame();//更新重新绘制游戏
voidDrawGame(HDChdc);//绘制游戏
voidMyHandleMessage(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam);
voidaddGameSpeed();//增加游戏速度
intgetPause();//是否暂停游戏
voidsetPause(intn);//暂停游戏
intgetplayNum();//获取游戏分数
voidupdateScoreList(ints);//更新游戏分数
private:
HDCm_BuffDc;
HBITMAPm_BuffBitmap;
private:
CMyMap*m_pMap;
CBlock*m_pBlock;
floatm_GameSpeed;
charm_Key;
intm_PlayNum;
intpause;//暂停标志
};
三、系统实现
1、关键模块/函数的实现
A游戏界面
俄罗斯方块的游戏界面包括游戏区域边框、下落方块绘制、右部计分和预览图显示等。
游戏区域边框的绘制比较简单,循环中确定光标的位置输出特定字符,即可完成边框绘制。
游戏区方块的绘制,循环从数据数组中依次读出数据,根据读到的数据显示“□”,最后组成方块的形状,完成方块的绘制。
计分和预览图部分先画出一个矩形区域,然后控制光标在其中显示分数、等级、预览图和提示信息。
具体实现:
#include"StdAfx.h"
#include"MyMap.h"
CMyMap:
:
CMyMap(void)
{
for(inti=0;i{
for(intj=0;j{
m_mapDate[i][j]=MAP_NULL;
}
}
memset(m_NextMapDate,0,sizeof(int)*BLOCK_NUM*BLOCK_NUM);
m_FillRect.top=0;
m_FillRect.bottom=0;
m_FillRect.left=0;
m_FillRect.right=0;
m_BlockHr=NULL;
m_FrameHr=NULL;
m_RunBlockHr=NULL;
m_MapHr=NULL;
m_NextBlockHr=NULL;
}
CMyMap:
:
~CMyMap(void)
{
if(m_BlockHr)
DeleteObject(m_BlockHr);
if(m_FrameHr)
DeleteObject(m_FrameHr);
if(m_RunBlockHr)
DeleteObject(m_RunBlockHr);
if(m_MapHr)
DeleteObject(m_MapHr);
if(m_NextBlockHr)
DeleteObject(m_NextBlockHr);
}
voidCMyMap:
:
initMap()
{
for(inti=0;i{
for(intj=0;j{
if(i==0||i==MAP_ROW-1||j==0||j==MAP_COL-1)
m_mapDate[i][j]=MAP_FRAME;
else
m_mapDate[i][j]=MAP_NULL;
}
}
memset(m_NextMapDate,0,sizeof(int)*BLOCK_NUM*BLOCK_NUM);
m_FrameHr=CreateSolidBrush(RGB(127,127,127));
m_BlockHr=CreateSolidBrush(0x373737);
m_MapHr=CreateSolidBrush(RGB(0,64,128));
}
voidCMyMap:
:
DrawMap(HDChdc)
{
for(inti=0;i{
for(intj=0;j{
switch(m_mapDate[i][j])
{
caseMAP_RUNBLOCK:
{
SetRect(&m_FillRect,200+j*MAP_SIZE,15+i*MAP_SIZE,
200+(j+1)*MAP_SIZE,15+(i+1)*MAP_SIZE);
FillRect(hdc,&m_FillRect,m_RunBlockHr);
FrameRect(hdc,&m_FillRect,m_FrameHr);
}
break;
caseMAP_BLOCK:
{
SetRect(&m_FillRect,200+j*MAP_SIZE,15+i*MAP_SIZE,
200+(j+1)*MAP_SIZE,15+(i+1)*MAP_SIZE);
FillRect(hdc,&m_FillRect,m_BlockHr);
FrameRect(hdc,&m_FillRect,m_FrameHr);
}
break;
caseMAP_FRAME:
{
SetRect(&m_FillRect,200+j*MAP_SIZE,15+i*MAP_SIZE,
200+(j+1)*MAP_SIZE,15+(i+1)*MAP_SIZE);
FillRect(hdc,&m_FillRect,m_MapHr);
FrameRect(hdc,&m_FillRect,m_FrameHr);
}
break;
}
}
}
for(inti=0;i{
for(intj=0;j{
switch(m_NextMapDate[i][j])
{
caseMAP_BLOCK:
{
SetRect(&m_FillRect,510+j*MAP_SIZE,15+i*MAP_SIZE,
510+(j+1)*MAP_SIZE,15+(i+1)*MAP_SIZE);
FillRect(hdc,&m_FillRect,m_NextBlockHr);
FrameRect(hdc,&m_FillRect,m_FrameHr);
}
break;
}
}
}
}
voidCMyMap:
:
SetMapVal(introw,intcol,intval)
{
m_mapDate[row][col]=val;
}
intCMyMap:
:
GetNum()
{
intnum=0;
for(inti=MAP_ROW-2;i>4;--i)
{
boolisClear=true;
for(intj=1;j{
if(m_mapDate[i][j]==0)
{
isClear=false;
break;
}
}
if(isClear)
{
num++;
for(intm=i;m>4;--m)
{
for(intn=1;n{
m_mapDate[m][n]=m_mapDate[m-1][n];
}
}
i++;
}
}
returnnum;
}
voidCMyMap:
:
SetMinMapVal(introw,intcol,intval)
{
m_NextMapDate[row][col]=val;
}
boolCMyMap:
:
IsOver()
{
boolisOver=false;
for(intm=1;m{
if(m_mapDate[4][m]!
=MAP_NULL)
returntrue;
}
returnisOver;
}
voidCMyMap:
:
SetBlockColor(inttype)
{
if(m_RunBlockHr)
DeleteObject(m_RunBlockHr);
switch(type)
{
case0:
m_RunBlockHr=CreateSolidBrush(RGB(255,0,0));
break;
case1:
m_RunBlockHr=CreateSolidBrush(RGB(0,255,0));
break;
case2:
m_RunBlockHr=CreateSolidBrush(RGB(0,0,255));
break;
case3:
m_RunBlockHr=CreateSolidBrush(RGB(255,255,0));
break;
case4:
m_RunBlockHr=CreateSolidBrush(RGB(255,0,255));
break;
case5:
m_RunBlockHr=CreateSolidBrush(RGB(0,255,255));
break;
case6:
m_RunBlockHr=CreateSolidBrush(RGB(255,0,128));
break;
}
}
voidCMyMap:
:
SetNextBlockColor(inttype)
{
if(m_NextBlockHr)
DeleteObject(m_NextBlockHr);
switch(type)
{
case0:
m_NextBlockHr=CreateSolidBrush(RGB(255,0,0));
break;
case1:
m_NextBlockHr=CreateSolidBrush(RGB(0,255,0));
break;
case2:
m_NextBlockHr=CreateSolidBrush(RGB(0,0,255));
break;
case3:
m_NextBlockHr=CreateSolidBrush(RGB(255,255,0));
break;
case4:
m_NextBlockHr=CreateSolidBrush(RGB(255,0,255));
break;
case5:
m_NextBlockHr=CreateSolidBrush(RGB(0,255,255));
break;
case6:
m_NextBlockHr=CreateSolidBrush(RGB(255,0,128));
break;
}
}
B生成方块
本程序中生成的方块有六种形状,每一种方块以shapeindex标记,在程序运行生成方块时,调用shapeindex=rand()%5+1;语句,确定当前要显示的是哪一个方块形状。
而在实际运行中,第一次需要调用两次生成方块函数make(),将先产生的赋给游戏当前方块,第二个赋给预览图方块。
以后每次产生一个方块,把预览方块赋给当前方块,把新产生的赋给预览方块。
具体如图所示。
具体实现:
voidCBlock:
:
_initNextBlock()
{
m_NextblockType=rand()%7;
switch(m_NextblockType)
{
case0:
m_NextblockChangeType=rand()%2;
switch(m_NextblockChangeType)
{
case0:
m_NextblockDate[0].row=2;
m_NextblockDate[0].col=0;
m_NextblockDate[1].row=2;
m_NextblockDate[1].col=1;
m_NextblockDate[2].row=2;
m_NextblockDate[2].col=2;
m_NextblockDate[3].row=2;
m_NextblockDate[3].col=3;
break;
case1:
m_NextblockDate[0].row=3;
m_NextblockDate[0].col=1;
m_NextblockDate[1].row=2;
m_NextblockDate[1].col=1;
m_NextblockDate[2].row=1;
m_NextblockDate[2].col=1;
m_NextblockDate[3].row=0;
m_NextblockDate[3].col=1;
break;
}
break;
case1:
m_NextblockDate[0].row=1;
m_NextblockDate[0].col=1;
m_NextblockDate[1].row=1;
m_NextblockDate[1].col=2;
m_NextblockDate[2].row=2;
m_NextblockDate[2].col=1;
m_NextblockDate[3].row=2;
m_NextblockDate[3].col=2;
break;
case2:
m_NextblockChangeType=rand()%4;
switch(m_Nex