VC++课程设计报告俄罗斯方块.docx

上传人:b****8 文档编号:9578814 上传时间:2023-02-05 格式:DOCX 页数:27 大小:199.75KB
下载 相关 举报
VC++课程设计报告俄罗斯方块.docx_第1页
第1页 / 共27页
VC++课程设计报告俄罗斯方块.docx_第2页
第2页 / 共27页
VC++课程设计报告俄罗斯方块.docx_第3页
第3页 / 共27页
VC++课程设计报告俄罗斯方块.docx_第4页
第4页 / 共27页
VC++课程设计报告俄罗斯方块.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

VC++课程设计报告俄罗斯方块.docx

《VC++课程设计报告俄罗斯方块.docx》由会员分享,可在线阅读,更多相关《VC++课程设计报告俄罗斯方块.docx(27页珍藏版)》请在冰豆网上搜索。

VC++课程设计报告俄罗斯方块.docx

VC++课程设计报告俄罗斯方块

 

课程设计报告

(2008--2009年度第1学期)

 

名称:

专业综合训练课程设计

题目:

VC++

专业:

06软件技术

班级:

2班

学号:

07

学生姓名:

常聪

指导教师:

邢煜

设计学时:

60

 

成绩:

日期:

2009年1月3日

目录

一、课程设计的目的与要求3

1.1课程设计的目的3

1.2课程设计的要求3

二、设计正文3

2.1需求分析3

2.1.1游戏需求3

2.2.2游戏界面需求:

3

2.1.3游戏形状(方块)需求:

3

2.2算法分析4

2.2.1程序流程图4

2.2.2定义方块的数据结构6

2.2.3游戏设计分析7

三系统设计8

3.1创建界面的主框架8

3.2正常流程的设计8

3.2.1定时制机制8

3.2.2定时处理9

4.1底部到达的判断与销行的实现10

4.2中断操作流程的实现13

4.3变形的实现14

4.4游戏区域绘图的实现15

4.5功能的完善15

4.6游戏演示16

4.7主程序源程序清单17

六、参考文献32

用VC++实现俄罗斯方块的程序设计

一、课程设计的目的与要求

1.1课程设计的目的

综合运用所学知识,熟练掌握VC++程序设计的编码与MFC框架结构。

1.2课程设计的要求

要求用VC++设计与实现俄罗斯方块游戏。

要求包括系统的需求分析;系统总框图及每个模块的设计分析;MFC应用程序架构;框架的扩展;算法的设计与实现;游戏的内部实现;游戏区域绘图的实现;系统存在的问题及错误处理;列出所有定义的函数及说明;附上程序源代码。

二、设计正文

2.1需求分析

2.1.1游戏需求

随机给出不同的形状(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型)下落填充给定的区域,若填满一条便消掉,记分,当达到一定的分数时,过关,设置六关,每关方块下落的速度不同,若在游戏中各形状填满了给定区域,为输者。

游戏功能要求如下:

2.2.2游戏界面需求:

良好的用户界面,有关数显示和分数显示。

让方块在一定的区域内运动和变形,该区域用一种颜色表明,既用一种颜色作为背景,最好设为黑色。

还需用另一种颜色把黑色围起来,宽度适中,要实现美感。

2.1.3游戏形状(方块)需求:

良好的方块形状设计,绘制七种常见的基本图形(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型),各个方块要能实现它的变形,可设为顺时针或逆时针变形,一般为逆时针。

2.2算法分析

2.2.1程序流程图

 

 

图2.2.3程序运行调用图

2.2.2定义方块的数据结构

对于方块在某一瞬间的位置标识,我们采用一个4×2的小数组标识出来,即用4个存储单位空间存储当前下坠物的每一子块的位置,也就是说,用4个存储单位空间存储当前下坠物的每一子块的位置来对整个下坠物件的位置进行标识,而每个存储空间的大小就是一个典的坐标值(x,y),而每个方块按照从左到右的方式进行编号,并且在编号过程中对于同一列的方块实行从上到下进行编号[2]。

0

1

2

3

(x0,y0)

(x1,y1)

(x2,y2)

(x3,y3)

2

3

0

1

(x0,y0)

(x1,y1)

(x2,y2)

(x3,y3)

 

图3.1方块编号

ActiveStatus[0][0]和ActiveStatus[0][1]则是第0号方块的横坐标x和纵坐标y;ActiveStatus[2][0]和ActiveStatus[2][1]则是第2号方块的横坐标x和纵坐标y。

2.2.3游戏设计分析

有前面的功能描述可知,我先虚拟出俄罗斯方块游戏的类对象,并抽象出核心的数据属性和操作方法等,然后再作细化,最后将整个虚拟类的外壳脱掉,再移植到视图类中去,其实现如下:

CRectGameView:

publicCView

{

//内部存取数据结构

intm_stateMap[MAX_ROW][MAX_COL];

//初始化操作

GameInitnal();//游戏的初始化

//用于判断数据相关状态的操作

IsLeftLimit();//下坠物件是否可向左移动

IsRightLitmit();//

IsBottom();//是否已经到达了底部

IsGameEnd();//是否游戏已经结束

//方块物件下坠过程中的操作

RectChange();//下坠物件变形

RectDown();//下坠物件正常下落

RectArrow();//下坠物件方向移动(左,右,下加速)

//状态控制操作

GameStart();//游戏开始

GamePause();//游戏暂停

GameEnd();//游戏结束

}

通过上面的代码可以看出,在虚拟类中抽象出了核心的内部数据和一些基本的操作函数。

对于操作函数,可以把它们分为内部实现的基本核心操作(如判断操作)以及明显提供给外部使用的整体模块外部操作(如状态控制操作)。

而内部的基本操作又可以分为判断操作和执行操作这样两种类型[3]。

三系统设计

3.1创建界面的主框架

首先建立一个项目工程,名为skyblue_Rect,并在AppWizard的架构选择过程中选择单文档方式,其他保持默认选项。

其项目的架构类视图信息如图所示:

在构架类视图中是MFC基本架构组合:

App(应用程序)类、Document(文档)类、View(视图)类、Frame(框架)类和用于提示关于作者的对话框CAboutDlg类,至于COptionDlg类是用作俄罗斯方块参数选择的对话框类对象。

 

3.2正常流程的设计

3.2.1定时制机制

从分析游戏的特性可以知道,定时器的产生与生效应该在游戏开始的时候,而在游戏暂停或者游戏结束时则将已经设定的定时器失效/销亡(对于暂停的情况,使它销亡,当游戏从暂停状态又进入游戏状态时候,则重新创建一个定时器并激活它的运作),所以分别在游戏的开始函数、暂停函数已经结束函数中实现定时器的激活与去激活工作。

这里,先在资源编辑器菜单资源里面添加三个菜单选项,分别是游戏的“开始”、“暂停”、和“结束”,然后利用ClassWizard直接在视图类对象Cskyblue_RectView中为它们添加空白的处理函数,具体如表2所示。

3.2.1菜单选项功能对应表

菜单选项名称

快捷键

资源ID

响应处理函数

开始游戏

&S

ID_GAME_STAT

OnGameStart()

暂停游戏

&P

ID_GAME_PAISH

OnGamePaush()

结束游戏

&E

ID_GAME_END

OnGameEnd()

3.2.2定时处理

经过定时器的设置后,这里通过利用ClassWizard跳到定时器到时候的处理函数OnTimer()去实现,当固定时间片间隔到达后,先检测当前下坠物是否已经到达了底部,不是则进行RectDown()下坠物向下移动一个单位的操作,是则到底后产生一个新的“下一个下坠物”,并代替旧的,将原先旧的“下一个下坠物”用作当前激活状态下正在使用的下坠物,并对使用后的一些状态进行检测:

是否马上到达底部,使则进行销行操作

;是否在到达底部的同时到达游戏区域的顶部,从而判定游戏是否因违规而结束。

图3.2.2装载方块

视图类创建了m_icurrentStatus和m_inextStatus两个成员变量来记录下坠物的类型,共有七种形状,并从7种方块中随机抽取图形。

而m_currentRect除了记录下坠物的类型外,还需记录其当前的变形状态,最多用两位表示,第1位用作类型标识(1~7),第2位用作同种类型的不同表现方式,最多有4种状态(1~4)。

在产生新的下一个下坠物前,需要先将当前状态物的记录和旧的下一个下坠物保存下来,然后用随机函数Random()产生一个最大值不大于指定值的随机正整数,将这个新生成的正整数用作新的“下一个下坠物”的形状值。

四、系统实施

4.1底部到达的判断与销行的实现

图3.2.3处理方块到达图

将新的下坠物放置到游戏区域中去,这时可能出现马上到达底部的情况,因此需要对它进行判断,如果是到达底部,则进行销行处理,并且修改相应的数据状态。

而判断是否已经到达了底部,可以通过当前下坠物件所对应的接触面的方块位置为被占用状态(MAP_STATE_NOT_EMPTY=1)来确定,利用数组InterFace[74][4]记录1~7种下坠物的1~4种形态的接触面信息。

统计分数:

在消行处理里面有一个专门用来统计消行数的变量,然后根据变量的值决定分数的多少,程序统计分数是:

消一行得100分,同时消2行得400分,销掉x行,则分数为:

x*(x*100)。

如果总分数达到过关条件就过关,改变游戏速度,游戏初始化,开启新的一关,然后再加载方块。

没有达到过关分数或者没有满行,则加载下一个方块继续游戏。

4.2中断操作流程的实现

(1)处理键盘事件

关于按键命令消息的响应,可以通过对WM_KEYDOWN消息的处理函数进行截获并重写来实现,下面是对该处理函数OnKeyDown()的重写。

//功能:

处理用户的输入,方块的左,右移,加速及变形

voidCSkyblue_RectView:

:

OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags)

{

switch(nChar)

{

caseVK_LEFT:

RectArrow(LEFT);

break;

caseVK_RIGHT:

RectArrow(RIGHT);

break;

caseVK_UP:

RectChange();

break;

caseVK_DOWN:

RectArrow(DOWN);

break;

}

CView:

:

OnKeyDown(nChar,nRepCnt,nFlags);

}

4.3变形的实现

当按下向上键时,将会执行方块变化事件(change())。

常见的方块有7种(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型),所有图形都是用两个一维数组来统计它的横坐标和纵坐标,每个方块有4种不同的变化形状。

例计算变形后的小方块的坐标和显示的状态值

//变形后位置在数组中的存放顺序仍需遵循先左后右,在同一列中先上后下

xx1=x1;xx2=x2;xx3=x3;xx4=x4;yy1=y1;yy2=y2;yy3=y3;yy4=y4;

switch(m_currentRect)

{

case1:

xx1=x1+1;yy1=y1-1;xx3=x3-1;yy3=y3+1;xx4=x4-2;yy4=y4+2;

m_lscurrentRect=11;

break;

case11:

xx1=x1-1;yy1=y1+1;xx3=x3+1;yy3=y3-1;xx4=x4+2;yy4=y4-2;

m_lscurrentRect=1;

break;

……

//省略部分为同类实现的变形后小方块坐标的计算代码

case73:

xx2=x2+1;yy2=y2-1;xx3=x3+2;yy3=y3-2;xx4=x4-1;yy4=y4-1;

m_lscurrentRect=7;

break;

}

4.4游戏区域绘图的实现

首先将外部位图文件rect.bmp中的位图动态导入(映射)到内存位图里面,根据游戏区域中的二维数组GameStatus[MAX_ROW][MAX_COL]中的内部数据将所有数据状态中为被占用状态MAP_STATE_NOT_EMPTY的小方块区域用指定的小方块图样类型来填充,然后将已经绘制好的游戏区域图像一次性的拷贝到与屏幕关联的设备环境中,从而达到屏幕的显示。

4.5功能的完善

为了使得游戏功能更加健全,另外为用户提供了一些附加功能,如表4.5.1所示。

表4.5.1附加功能描述列表

功能名称

选项

其他描述

游戏等级选择

初级......顶级

对游戏快慢难度的设定

方块图案样式选择

深蓝......条纹

对下坠物的小方块图案样式选择

游戏区域大小选择

小、中、大

对游戏区域的行列数选择

网格的选用

有、无

是否需要在游戏区域绘制网格

背景音乐的选用

有、无

在游戏过程中是否播放背景音乐

先将这些目标功能通过资源编辑器在主菜单条进行添加,将前面已有的菜单选项补全,再通过ClassWizard添加对应的响应处理函数。

其最终效果如图

1

图4..5.2游戏设置

游戏是用来给大家娱乐的,所以要能在使用的过程中给大家带来快乐,消除大家的疲劳,所以我在游戏中添加了漂亮的场景和动听的背景音乐,设置了个性化的工具栏快捷键,激发大家的娱乐激情。

4.6游戏演示

游戏主界面如图所示。

图4..6.1俄罗斯方块游戏运行主界面

4.7主程序源程序清单

CSkyblue_RectView:

:

CSkyblue_RectView()

{

//第一次开始游戏

m_bFistPlay=TRUE;

//缺省为不是游戏暂停状态

m_bGamePaush=FALSE;

//缺省为不插放背景音乐

m_bMusic=FALSE;

//缺省为画网格线

m_bDrawGrid=TRUE;

//总分值清零

m_iPerformance=0;

//测试值:

为12行,10列

m_iRow=12;

m_iCol=10;

//左上角X,Y坐标

m_iStartX=10;

m_iStartY=10;

//缺省级别为3级

m_iLevel=2;

//第一种样式

m_iBlockSytle=0;

//缺省方块大小为m_iLarge个象素

m_iLarge=30;

//缺省游戏是结束的

m_bGameEnd=TRUE;

inti,j;

//赋初值

for(i=0;i<100;i++)

for(j=0;j<100;j++)

GameStatus[i][j]=0;

//各种形状方块的接触面数据,参见设计书的接触面表格,

//5.判断游戏是否已结束:

碰了底,且第1行有小方块

if(m_isBottom)

for(i=0;i

if(GameStatus[0][i])

{

KillTimer

(1);

AfxMessageBox("游戏已结束!

");

for(j=0;j

for(k=0;k

GameStatus[j][k]=0;

Invalidate(FALSE);

m_bGameEnd=TRUE;

break;

}

}

else//当前方块下降

{

RectDown();

}

CView:

:

OnTimer(nIDEvent);

}

//函数:

产生一个最大值不大于指定值的随机正整数(Random)

//参数:

MaxNumber:

随机数的上限

//返回值:

产生的随机数

intCSkyblue_RectView:

:

Random(intMaxNumber)

{

//布下随机种子

srand((unsigned)time(NULL));

//产生随机数

intrandom=rand()%MaxNumber;

//保证非0

if(random==0)random++;

returnrandom;

}

}

}

//内部函数:

刷新当前的区域

voidCSkyblue_RectView:

:

InvalidateCurrent()

{

inti;

for(i=0;i<4;i++)

{

CRectrect(m_iStartX+ActiveStatus[i][1]*m_iLarge,

m_iStartY+ActiveStatus[i][0]*m_iLarge,

m_iStartX+(ActiveStatus[i][1]+1)*m_iLarge+5,

m_iStartY+(ActiveStatus[i][0]+1)*m_iLarge);

//InvalidateRect(&rect);

Invalidate(FALSE);

}

}

//内部函数:

当前方块下降加速,左移,右移

voidCSkyblue_RectView:

:

RectArrow(intm_Type)

{

//获取当前下坠物4个小方块的位置坐标

intx1,x2,x3,x4,y1,y2,y3,y4;

x1=ActiveStatus[0][0];

x2=ActiveStatus[1][0];

x3=ActiveStatus[2][0];

x4=ActiveStatus[3][0];

y1=ActiveStatus[0][1];

y2=ActiveStatus[1][1];

y3=ActiveStatus[2][1];

y4=ActiveStatus[3][1];

//对不同的移动命令指示进行分类实现

switch(m_Type)

{

caseLEFT:

//对每种不同的移动命令指示特性作相应的可移动分析

if((ActiveStatus[0][1]>0)&&IsLeftLimit()&&!

m_isBottom)

{

//清原来的方块

GameStatus[x1][y1]=MAP_STATE_EMPTY;

GameStatus[x2][y2]=MAP_STATE_EMPTY;

GameStatus[x3][y3]=MAP_STATE_EMPTY;

GameStatus[x4][y4]=MAP_STATE_EMPTY;

//添加新的移动后数据状态

ActiveStatus[0][1]-=1;

ActiveStatus[1][1]-=1;

ActiveStatus[2][1]-=1;

ActiveStatus[3][1]-=1;

GameStatus[x1][y1-1]=MAP_STATE_NOT_EMPTY;

GameStatus[x2][y2-1]=MAP_STATE_NOT_EMPTY;

GameStatus[x3][y3-1]=MAP_STATE_NOT_EMPTY;

GameStatus[x4][y4-1]=MAP_STATE_NOT_EMPTY;

InvalidateCurrent();

}

break;

caseRIGHT:

if((ActiveStatus[3][1]

m_isBottom)

{

//清原来的方块

GameStatus[x1][y1]=MAP_STATE_EMPTY;

GameStatus[x2][y2]=MAP_STATE_EMPTY;

GameStatus[x3][y3]=MAP_STATE_EMPTY;

GameStatus[x4][y4]=MAP_STATE_EMPTY;

//添加新的移动后数据状态

ActiveStatus[0][1]+=1;

ActiveStatus[1][1]+=1;

ActiveStatus[2][1]+=1;

ActiveStatus[3][1]+=1;

GameStatus[x1][y1+1]=MAP_STATE_NOT_EMPTY;

GameStatus[x2][y2+1]=MAP_STATE_NOT_EMPTY;

GameStatus[x3][y3+1]=MAP_STATE_NOT_EMPTY;

GameStatus[x4][y4+1]=MAP_STATE_NOT_EMPTY;

InvalidateCurrent();

}

break;

caseDOWN:

RectDown();

break;

}

}

//内部函数:

方块的变形

voidCSkyblue_RectView:

:

RectChange()

{

//先预先变形,然后判断变形后的方块是否有空间,如有足够空间,则进行实际变形,否则不变

intxx1,xx2,xx3,xx4,yy1,yy2,yy3,yy4;

intm_lscurrentRect;

CStringlsStr;

intx1,x2,x3,x4,y1,y2,y3,y4;

x1=ActiveStatus[0][0];

x2=ActiveStatus[1][0];

x3=ActiveStatus[2][0];

x4=ActiveStatus[3][0];

y1=ActiveStatus[0][1];

y2=ActiveStatus[1][1];

y3=ActiveStatus[2][1];

y4=ActiveStatus[3][1];

//变形后位置在数组中的存放顺序仍需遵循先左后右,在同一列中先上后下

xx1=x1;xx2=x2;xx3=x3;xx4=x4;yy1=y1;yy2=y2;yy3=y3;yy4=y4;

switch(m_currentRect)

{

case1:

xx1=x1+1;yy1=y1-1;xx3=x3-1;yy3=y3+1;xx4=x4-2;yy4=y4+2;

m_lscurrentRect=11;

break;

case11:

xx1=x1-1;yy1=y1+1;xx3=x3+1;yy3=y3-1;xx4=x4+2;yy4=y4-2;

m_lscurrentRect=1;

break;

……

//省略部分为同类实现的变形后小方块坐标计算代码

case73:

xx2=x2+1;yy2=y2-1;xx3=x3+2;yy3=y3-2;xx4=x4-1;yy4=y4-1;

m_lscurrentRect=7;

break;

}

//改变形状代码

m_currentRect=m_lscurr

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 文学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1