湘潭大学软件设计实践 - 副本

更新时间:2024-05-14 07:53:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

软件设计实践报告

单位:信息工程学院 班级:计算机二班 学 号: 姓名:韩林波 任课教师:周维

湘潭大学 2016年9月

软件设计实践 项目名称:俄罗斯方块

一、 项目概述

1、

概述

作为家喻户晓的游戏,俄罗斯方块可谓是大名鼎鼎。不过,尽管它看起来比较简单,实际上对于我们新手而言确实是一个具有挑战性的项目。 我们准备先简单的理解下俄罗斯游戏开发的大概算法和需要的知识,然后把这些知识组合开发俄罗斯方块。基本上实现俄罗斯方块游戏的控制和操作。并使用windows IDE搭建一个完整的windows应用程序。通过这个项目,提高自身的动手能力。

2、 目的和用途

我们在实际动手过程中,将C++课程中所学的概念、理论和方法加以运用,按照C++程序设计的基本步骤,设计出了一个适当规模的程序来实现设计课程内容中的全部功能;设计了主控模块程序.对给出的程序源代码给出了各部分的详细注释.自己根据能力及需要添加相应功能模块,增强模拟系统功能。完整的项目内容也增强了我在课堂中的理论学习,为实习工作打下了基础。

3、

需求说明

利用Microsoft Visual stdio 2010编写一个windows窗口应用程序下的俄罗斯方块游戏。

要求:

(1)利用面向对象的方法编写。 (2)能够记录游戏得分。

(3)俄罗斯方块的多种类和旋转操作 (4)信息提示时显示颜色变化。 (5)暂停和重新开始

4、 环境要求

本程序采用Microsoft Visual stdio 2010的专业版本进行编译。Microsoft Visual stdio 2010是Microsoft公司推出的基于Windows操作系统的可视化C++编程工具,尽管Microsoft公司推出了.NET平台的集成开发环境,但由于其良好的界面和可操作性,加上支持标准C/C++规范,有相当多的编程人员使用Microsoft Visual stdio 2010进行应用系统的开发。

关于稳定性,经测试,本程序可以在windows操作系统中稳定运行,较为稳定。

VC++是由Microsoft公司制作,基于WINDOWS环境的一款编程软件。由于WINDOWS操作系统比起MS-DOS操作系统优越了许多。作为与之相搭配的编程软件自然也是功能非常强大,其最大的特点也就是可视化。不过在提供可视化的编程方式的同时,它采用了面向对象的程序设计方法,同传统的结构化程序设计方法相比,缩短了软件开发的周期,提高了软件的开发效率,使程序员可以更好地理解和管理庞大且复杂的程序。

VC++中还集成了大量的最新技术,如ActiveX,COM等技术适合开发大型

工程,这是相对于VB的一个优势。它的兼容性较好,还为用户提供了极为丰富的文档和范例。关于VC的参考资料也非常多,程序开发人员可以紧紧地把握住软件开发技术发展的方向,开发出功能强大的应用程序。

二、 系统分析与设计

1、

系统分析

根据分析,俄罗斯方块这个程序一共要实现如下几个功能,开始游戏、游戏的暂停\\继续、游戏控制和退出游戏。其中游戏控制最为主要和重要,它控制着整个游戏的画面和有关数据的操作,是游戏的核心部分。暂停和退出功能做成一体,在退出的提示下不做任何操作即可实现暂停的功能。程序结构如图。

2、

系统设计

根据分析后的程序结构图设计出相应的流程图。俄罗斯方块的内容主要包括游戏开始,画背景和边框,显示分数等级和下一个方块的预览图;根据速度没隔一定时间方块自动下落,当有按键操作时,根据相应按键执行动作,每次动作前要判断是否动作可以执行。下落方块满一行时,消去该行,根据消去行数得到相应分数。分数达到一定程度,等级提升,速度加快。同时可以响应Esc按键,提示是否退出程序。如图所示。

3、 模块/函数设计

根据程序的结构,将俄罗斯方块需要实现的功能细化为相应的类成员函数。程序有三个类,一个Block类,作为程序的元素块组成其他元素。一个MyMap类,用于整个俄罗斯方块的地图相关操作。一个Manage类,用于整个游戏的相关操作。

---------------------------------------------------------------------------- Block类设计声明

class CBlock { public: };

------------------------------------------------------------------------------- MAP类设计声明(MyMap类) class CMyMap { public:

BLOCK_POS int int

m_NextblockDate[BLOCK_NUM]; m_NextblockType; m_NextblockChangeType;

CBlock(void); ~CBlock(void); void initBlock();

void _initNextBlock(); //初始化下一个方块 void SetBlockMove(bool isLeft); //方块移动 void SetBlockDown();

void SetBlockChange(); //方块坐标变化

BLOCK_POS * GetBlockHead() {return m_blockDate;} int GetBlockType() {return m_blockType;}

int GetNextBlockType() {return m_NextblockType;} int GetBlockChangeType() {return m_blockChangeType;} BLOCK_POS * GetNextBlockHead() {return m_NextblockDate;} BLOCK_POS int int

m_blockDate[BLOCK_NUM]; m_blockType; m_blockChangeType;

public:

private:

};

CMyMap(void); ~CMyMap(void);

void initMap(); //初始化地图 void DrawMap(HDC hdc);

//绘制窗口地图

void SetMapVal(int row,int col,int val); void SetMinMapVal(int row,int col,int val);

int GetMapVal(int row,int col) {return m_mapDate[row][col];} int GetNum();

bool IsOver();//游戏是否结束

void SetBlockColor(int type); //地图块颜色 void SetNextBlockColor(int type);//下一个板块颜色 int int RECT

m_mapDate[MAP_ROW][MAP_COL];

m_NextMapDate[BLOCK_NUM][BLOCK_NUM]; m_FillRect;

//地图大小行列

private:

private:

HBRUSH m_BlockHr; HBRUSH m_FrameHr; HBRUSH m_RunBlockHr; HBRUSH m_MapHr; HBRUSH m_NextBlockHr;

------------------------------------------------------------------------------ Manager类设计声明(Manager类) class CManage { public:

CManage(HDC hdc); ~CManage(void); void initGame();

//初始化游戏 //更新重新绘制游戏

void UpdateGame();

void DrawGame(HDC hdc); //绘制游戏

void MyHandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); void addGameSpeed(); //增加游戏速度 int getPause();

//是否暂停游戏

//暂停游戏 //获取游戏分数

void setPause(int n); int getplayNum();

void updateScoreList(int s); //更新游戏分数 HDC

m_BuffDc; m_BuffBitmap; *m_pMap; *m_pBlock;

private:

HBITMAP CMyMap CBlock

private:

};

float char int int

m_GameSpeed; m_Key;

m_PlayNum; pause; //暂停标志

三、 系统实现

1、

关键模块/函数的实现

A游戏界面

俄罗斯方块的游戏界面包括游戏区域边框、下落方块绘制、右部计分和预览图显示等。

游戏区域边框的绘制比较简单,循环中确定光标的位置输出特定字符,即可完成边框绘制。游戏区方块的绘制,循环从数据数组中依次读出数据,根据读到的数据显示“□”,最后组成方块的形状,完成方块的绘制。计分和预览图部分先画出一个矩形区域,然后控制光标在其中显示分数、等级、预览图和提示信息。

具体实现:

#include \#include \

CMyMap::CMyMap(void) {

memset(m_NextMapDate,0,sizeof(int) * BLOCK_NUM * BLOCK_NUM); m_FillRect.top = 0;

for(int i = 0; i < MAP_ROW; i++) { }

for(int j = 0; j < MAP_COL; j++) { }

m_mapDate[i][j] = MAP_NULL;

}

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) { }

void CMyMap::initMap() { }

void CMyMap::DrawMap(HDC hdc)

for(int i = 0; i < MAP_ROW; i++) { }

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));

for(int j = 0; j < MAP_COL; j++) { }

if(i == 0 || i == MAP_ROW - 1 || j == 0 || j == MAP_COL - 1) else

m_mapDate[i][j] = MAP_NULL; m_mapDate[i][j] = MAP_FRAME;

if(m_BlockHr)

DeleteObject(m_BlockHr); DeleteObject(m_FrameHr); DeleteObject(m_RunBlockHr); DeleteObject(m_MapHr); DeleteObject(m_NextBlockHr); if(m_FrameHr) if(m_RunBlockHr) if(m_MapHr) if(m_NextBlockHr)

{

for(int i = 0; i < BLOCK_NUM; ++i) {

for(int j = 0; j < BLOCK_NUM; ++j) {

switch(m_NextMapDate[i][j]) {

case MAP_BLOCK:

{

SetRect(&m_FillRect,510 + j * MAP_SIZE,15 + i * MAP_SIZE,

for(int i = 0; i < MAP_ROW; ++i) { }

for(int j = 0; j < MAP_COL; ++j) { }

switch(m_mapDate[i][j]) {

case MAP_RUNBLOCK: }

{ } break; { } break; { } break;

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);

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);

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);

case MAP_BLOCK:

case MAP_FRAME:

}

}

}

}

}

510 + (j + 1) * MAP_SIZE,15 + (i + 1) * MAP_SIZE);

FillRect(hdc,&m_FillRect,m_NextBlockHr); FrameRect(hdc,&m_FillRect,m_FrameHr);

break;

void CMyMap::SetMapVal( int row,int col,int val ) { }

int CMyMap::GetNum() { }

int num = 0;

for(int i = MAP_ROW - 2; i > 4; --i) { }

return num;

bool isClear = true;

for(int j = 1; j < MAP_COL - 1; ++j) { }

if(isClear) { }

num++;

for(int m = i; m > 4; --m) { } i++;

for(int n = 1; n < MAP_COL - 1; ++n) { }

m_mapDate[m][n] = m_mapDate[m - 1][n];

if(m_mapDate[i][j] == 0) { }

isClear = false; break;

m_mapDate[row][col] = val;

void CMyMap::SetMinMapVal( int row,int col,int val ) { }

bool CMyMap::IsOver() { }

void CMyMap::SetBlockColor( int type ) {

if(m_RunBlockHr) { case 0:

m_RunBlockHr = CreateSolidBrush(RGB(255,0,0)); break;

m_RunBlockHr = CreateSolidBrush(RGB(0,255,0)); break;

m_RunBlockHr = CreateSolidBrush(RGB(0,0,255)); break;

m_RunBlockHr = CreateSolidBrush(RGB(255,255,0)); break;

m_RunBlockHr = CreateSolidBrush(RGB(255,0,255)); break;

m_RunBlockHr = CreateSolidBrush(RGB(0,255,255)); break;

m_RunBlockHr = CreateSolidBrush(RGB(255,0,128)); break;

DeleteObject(m_RunBlockHr); switch(type) bool isOver = false;

for(int m = 1; m < MAP_COL - 1; ++m) { }

return isOver;

if(m_mapDate[4][m] != MAP_NULL)

return true;

m_NextMapDate[row][col] = val;

case 1:

case 2:

case 3:

case 4:

case 5:

case 6:

}

}

void CMyMap::SetNextBlockColor( int type ) { }

if(m_NextBlockHr) { case 0: }

m_NextBlockHr = CreateSolidBrush(RGB(255,0,0)); break;

m_NextBlockHr = CreateSolidBrush(RGB(0,255,0)); break;

m_NextBlockHr = CreateSolidBrush(RGB(0,0,255)); break;

m_NextBlockHr = CreateSolidBrush(RGB(255,255,0)); break;

m_NextBlockHr = CreateSolidBrush(RGB(255,0,255)); break;

m_NextBlockHr = CreateSolidBrush(RGB(0,255,255)); break;

m_NextBlockHr = CreateSolidBrush(RGB(255,0,128)); break;

DeleteObject(m_NextBlockHr); switch(type)

case 1:

case 2:

case 3:

case 4:

case 5:

case 6:

B生成方块

本程序中生成的方块有六种形状,每一种方块以shapeindex标记,在程序运行生成方块时,调用shapeindex=rand()%5+1;语句,确定当前要显示的是哪一个方块形状。而在实际运行中,第一次需要调用两次生成方块函数make(),将先产生的赋给游戏当前方块,第二个赋给预览图方块。以后每次产生一个方块,把预览方块赋给当前方块,把新产生的赋给预览方块。具体如图所示。

具体实现:

void CBlock::_initNextBlock() {

m_NextblockType = rand() % 7; switch(m_NextblockType) { case 0:

m_NextblockChangeType = rand() % 2; switch(m_NextblockChangeType) { case 0:

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;

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;

case 1:

break;

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;

m_NextblockChangeType = rand() % 4; switch(m_NextblockChangeType) { case 0:

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 = 2; m_NextblockDate[3].row = 3; m_NextblockDate[3].col = 2; break;

m_NextblockDate[0].row = 1; m_NextblockDate[0].col = 2; m_NextblockDate[1].row = 2; m_NextblockDate[1].col = 2; m_NextblockDate[2].row = 2; m_NextblockDate[2].col = 1;

case 1:

case 2:

case 1:

}

break;

m_blockDate[0].row = m_blockDate[1].row; m_blockDate[0].col = m_blockDate[1].col - 1; m_blockDate[2].row = m_blockDate[1].row; m_blockDate[2].col = m_blockDate[1].col + 1; m_blockDate[3].row = m_blockDate[1].row; m_blockDate[3].col = m_blockDate[1].col + 2; m_blockChangeType = 0; break;

case 1:

break;

switch(m_blockChangeType) { case 0:

m_blockDate[0].row = m_blockDate[1].row; m_blockDate[0].col = m_blockDate[1].col; m_blockDate[1].row = m_blockDate[0].row + 1; m_blockDate[1].col = m_blockDate[0].col; m_blockDate[2].row = m_blockDate[0].row + 1; m_blockDate[2].col = m_blockDate[0].col - 1; m_blockDate[3].row = m_blockDate[0].row + 1; m_blockDate[3].col = m_blockDate[0].col - 2; m_blockChangeType = 1; break;

m_blockDate[0].row = m_blockDate[1].row; m_blockDate[0].col = m_blockDate[1].col; m_blockDate[1].row = m_blockDate[0].row; m_blockDate[1].col = m_blockDate[0].col - 1; m_blockDate[2].row = m_blockDate[0].row - 1; m_blockDate[2].col = m_blockDate[0].col - 1; m_blockDate[3].row = m_blockDate[0].row - 2; m_blockDate[3].col = m_blockDate[0].col - 1; m_blockChangeType = 2; break;

m_blockDate[0].row = m_blockDate[1].row; m_blockDate[0].col = m_blockDate[1].col; m_blockDate[1].row = m_blockDate[0].row - 1; m_blockDate[1].col = m_blockDate[0].col; m_blockDate[2].row = m_blockDate[0].row - 1; m_blockDate[2].col = m_blockDate[0].col + 1;

case 2:

case 1:

case 2:

}

m_blockDate[3].row = m_blockDate[0].row - 1; m_blockDate[3].col = m_blockDate[0].col + 2; m_blockChangeType = 3; break;

m_blockDate[0].row = m_blockDate[1].row; m_blockDate[0].col = m_blockDate[1].col; m_blockDate[1].row = m_blockDate[0].row; m_blockDate[1].col = m_blockDate[0].col + 1; m_blockDate[2].row = m_blockDate[0].row + 1; m_blockDate[2].col = m_blockDate[0].col + 1; m_blockDate[3].row = m_blockDate[0].row + 2; m_blockDate[3].col = m_blockDate[0].col + 1; m_blockChangeType = 0; break;

case 3:

break;

case 3:

switch(m_blockChangeType) { case 0:

m_blockDate[0].row = m_blockDate[1].row - 1; m_blockDate[0].col = m_blockDate[1].col ; m_blockDate[1].row = m_blockDate[1].row ; m_blockDate[1].col = m_blockDate[1].col ; m_blockDate[2].row = m_blockDate[1].row + 1; m_blockDate[2].col = m_blockDate[1].col ; m_blockDate[3].row = m_blockDate[1].row ; m_blockDate[3].col = m_blockDate[1].col - 1; m_blockChangeType = 1; break;

case 1:

m_blockDate[0].row = m_blockDate[1].row ;

m_blockDate[0].col = m_blockDate[1].col - 1; m_blockDate[1].row = m_blockDate[1].row ; m_blockDate[1].col = m_blockDate[1].col ; m_blockDate[2].row = m_blockDate[1].row ; m_blockDate[2].col = m_blockDate[1].col + 1; m_blockDate[3].row = m_blockDate[1].row - 1; m_blockDate[3].col = m_blockDate[1].col ; m_blockChangeType = 2; break;

m_blockDate[0].row = m_blockDate[1].row - 1;

case 2:

}

m_blockDate[0].col = m_blockDate[1].col ; m_blockDate[1].row = m_blockDate[1].row ; m_blockDate[1].col = m_blockDate[1].col ; m_blockDate[2].row = m_blockDate[1].row + 1; m_blockDate[2].col = m_blockDate[1].col ; m_blockDate[3].row = m_blockDate[1].row ; m_blockDate[3].col = m_blockDate[1].col + 1; m_blockChangeType = 3; break;

m_blockDate[0].row = m_blockDate[1].row ; m_blockDate[0].col = m_blockDate[1].col - 1; m_blockDate[1].row = m_blockDate[1].row ; m_blockDate[1].col = m_blockDate[1].col ; m_blockDate[2].row = m_blockDate[1].row + 1; m_blockDate[2].col = m_blockDate[1].col ; m_blockDate[3].row = m_blockDate[1].row ; m_blockDate[3].col = m_blockDate[1].col + 1; m_blockChangeType = 0; break;

case 3:

break; case 4:

switch(m_blockChangeType) { case 0:

m_blockDate[1].row = m_blockDate[0].row; m_blockDate[1].col = m_blockDate[0].col; m_blockDate[0].row = m_blockDate[1].row + 1; m_blockDate[0].col = m_blockDate[1].col; m_blockDate[2].row = m_blockDate[1].row; m_blockDate[2].col = m_blockDate[1].col - 1; m_blockDate[3].row = m_blockDate[1].row; m_blockDate[3].col = m_blockDate[1].col - 2; m_blockChangeType = 1; break;

m_blockDate[1].row = m_blockDate[0].row; m_blockDate[1].col = m_blockDate[0].col; m_blockDate[0].row = m_blockDate[1].row; m_blockDate[0].col = m_blockDate[1].col - 1; m_blockDate[2].row = m_blockDate[1].row - 1; m_blockDate[2].col = m_blockDate[1].col;

case 1:

m_blockDate[3].row = m_blockDate[1].row - 2; m_blockDate[3].col = m_blockDate[1].col; m_blockChangeType = 2; break;

m_blockDate[1].row = m_blockDate[0].row; m_blockDate[1].col = m_blockDate[0].col; m_blockDate[0].row = m_blockDate[1].row - 1; m_blockDate[0].col = m_blockDate[1].col; m_blockDate[2].row = m_blockDate[1].row; m_blockDate[2].col = m_blockDate[1].col + 1; m_blockDate[3].row = m_blockDate[1].row; m_blockDate[3].col = m_blockDate[1].col + 2; m_blockChangeType = 3; break;

case 2:

case 3:

m_blockDate[1].row = m_blockDate[0].row; } break;

switch(m_blockChangeType) { case 0:

m_blockDate[0].row = m_blockDate[2].row - 1; m_blockDate[0].col = m_blockDate[2].col + 1; m_blockDate[1].row = m_blockDate[2].row - 1; m_blockDate[1].col = m_blockDate[2].col; m_blockDate[2].row = m_blockDate[2].row; m_blockDate[2].col = m_blockDate[2].col; m_blockDate[3].row = m_blockDate[2].row ; m_blockDate[3].col = m_blockDate[2].col - 1; m_blockChangeType = 1; break;

m_blockDate[0].row = m_blockDate[2].row - 1; m_blockDate[1].col = m_blockDate[0].col; m_blockDate[0].row = m_blockDate[1].row; m_blockDate[0].col = m_blockDate[1].col + 1; m_blockDate[2].row = m_blockDate[1].row + 1; m_blockDate[2].col = m_blockDate[1].col; m_blockDate[3].row = m_blockDate[1].row + 2; m_blockDate[3].col = m_blockDate[1].col; m_blockChangeType = 0; break;

case 5:

case 1:

}

}

}

m_blockDate[0].col = m_blockDate[2].col - 1; m_blockDate[1].row = m_blockDate[2].row; m_blockDate[1].col = m_blockDate[2].col - 1; m_blockDate[2].row = m_blockDate[2].row; m_blockDate[2].col = m_blockDate[2].col; m_blockDate[3].row = m_blockDate[2].row + 1; m_blockDate[3].col = m_blockDate[2].col; m_blockChangeType = 0; break;

break;

switch(m_blockChangeType) { case 0: } break;

m_blockDate[0].row = m_blockDate[2].row + 1; m_blockDate[0].col = m_blockDate[2].col + 1; m_blockDate[1].row = m_blockDate[2].row + 1; m_blockDate[1].col = m_blockDate[2].col; m_blockDate[2].row = m_blockDate[2].row; m_blockDate[2].col = m_blockDate[2].col; m_blockDate[3].row = m_blockDate[2].row ; m_blockDate[3].col = m_blockDate[2].col - 1; m_blockChangeType = 1; break;

m_blockDate[0].row = m_blockDate[2].row - 1; m_blockDate[0].col = m_blockDate[2].col + 1; m_blockDate[1].row = m_blockDate[2].row; m_blockDate[1].col = m_blockDate[2].col + 1; m_blockDate[2].row = m_blockDate[2].row; m_blockDate[2].col = m_blockDate[2].col; m_blockDate[3].row = m_blockDate[2].row + 1; m_blockDate[3].col = m_blockDate[2].col; m_blockChangeType = 0; break;

case 6:

case 1:

D方块显示

以上方块的操作都是数据层面的操作,而真正要在游戏窗口中看到数据的变化,还必须把方块不断的绘制出来。这就是draw()函数的作用。把当前运动的方块对应节点存储在一个4*4数组里,变形和生成方块的过程就是更新该数组数据的过程。然后在draw()函数里检测数组的各个值,并控制光标跳到一定位置,画出“□”组成方块。 具体实现:

void CBlock::SetBlockMove(bool isLeft) { }

void CBlock::SetBlockDown() { }

for(int i = 0; i < 4; ++i) { }

m_blockDate[i].row++; if(isLeft) { } else { }

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

m_blockDate[i].col++; for(int i = 0; i < 4; ++i)

m_blockDate[i].col--;

F障碍判断

障碍判断,就是在方块运动中或者变形中判断周围是否有障碍阻碍下落、移位、

变形。当方块下落遇到下面有方块或者到达下边界则应停止下落并记录数据,存入背景数据数组。变形时应判断这个变形是否可以进行,如果有障碍则不能变形。例如当方块达到右边界,而若变形则会越过边界,那么这个变形的命令是不应执行的。所有这些判断都由meet()函数进行,根据是否有障碍返回1或0,再由其他函数接收执行相应操作。 E速度变化

游戏玩家拼满一行后,程序消去满行,并计分。中当一个方块下落停止后,程序检查方块是否充满了游戏区域,如果是结束游戏。不是,则判断是否构成消行条件,从下落方块的最低点依次向上检查是否可以消行,根据消去行数分数增加。分数达到一定程度,速度加快。

void CManage::addGameSpeed() { }

if(m_PlayNum < 100)

m_GameSpeed = 1.0f;

else if(m_PlayNum < 200)

m_GameSpeed = 0.8f;

else if(m_PlayNum < 300) else

m_GameSpeed = 0.1f; m_GameSpeed = 0.3f;

四、 测试分析

1、 测试方案,要求包含系统测试方法、测试用例与测试工具。

测试方法: 1人工断点调试 2 IDE自动判断 3实际代码效果测试

测试用例:

我们主要对以下模块进行调试: 1) 2) 3) 4) 5)

生成基本元素的initblock()函数 生成地图的initMap()函数 Block旋转的操作,鼠标响应事件 消去一行的实际效果

分数增加的updatescore()函数

测试工具:

采用了visualstdio的debug调试工具,以及我们经常使用的printf打印数据,还有adb命令行调试工具。

2、 测试与调试

俄罗斯方块是一个windows应用,因此我们的测试和调试都是在windows平台下利用现有的visualstdio IDE测试相关功能。

主要测试: 1.界面GUI完整性 2.代码逻辑的正确性 3.程序的健壮性和稳定性 4.异常处理和bug错误 5.游戏的可玩性 6.操作的易行性

3、 测试结果分析

序号 测试用例 预期结果 实测结果 测试状态 错误类型 测试单元:模块名>>子模块1>>功能1 1. Block 2. MyMAP 3. Manager 4. 分数记录 生成基本元素块 与预期结果一致 生成地图 游戏控制 按比例增加 与预期结果一致 与预期结果不一致 与预期结果一致 1 1 0 1 旋转功能失效 测试单元:模块名>>子模块1>>功能2 5. Exit

退出游戏 与预期结果不一致 -1 未正常退出 4、 结论

经过调试和修改,程序完全实现设计要求,成功模拟了俄罗斯方块的运行过程和游戏效果,只是界面略微简陋,但已从程序层面上实现了游戏,达到了这次实训的要求和目的。程序正常生成方块,根据速度值每隔一定时间自动下落,如有操作按键按下,根据按键实现位移和变形。当方块满一行后,可以消除该行,同时记录分数和等级。按下Esc键红色提示信息正常显示,可以响应Y,N键决定是否退出游戏。

五、 设计体会

1、 设计过程中的问题及其解决方案 1)

如何控制方块的旋转

游戏中的下落的方块是需要玩家操作旋转的,因此,如何做到方块的旋转是增加可玩性的重点。

分析如下,首先,下落的游戏板块都是由4个block块组成,因此,游戏板块本身采用的结构是一个3*3的Mymap结构,像里面填充4个block,具有block的元素块的标志为1,没有的为0,此时,相当于建立了一个关于X,Y的坐标系。可以为每一个block块初始化其x,y坐标值,完成这些后。方块的旋转转化成了坐标的变化问题,这样,当旋转的操作时,记录下各种情况的坐标变换即实现了旋转功能。

2) 如何暂停游戏

暂停游戏需要使用到windows API函数,我采用了信号量机制,当监听到暂停要求时,在地图中将暂停的标志置1,同时调用windows函数 sleep使程序休

眠,当再次监听到游戏继续信号量之后,唤醒程序。

3) 游戏中速度如何控制

游戏中的速度和分数挂钩,使用了一个函数计算速度和分数的关系,大约是100:1的比例,当分数增加100时,加快游戏速度。

游戏速度实现转化成block板块的下标变化程度,初始化的时候下标的变化是每次自增1个单位,当速度增加之后每次增加2个单位,这样便实现了速度的变化。

4) 障碍碰撞检测

游戏中的碰撞检测主要是因为地图的大小是默认值,边框上具有默认板块,当新版块下落的时候便形成了叠加。因此,我们采用的方法是坐标判断法,每一个板块在下落的过程中,每次坐标变化的时候都要判断坐标是否能够变化,需要构造相对应的坐标对应变化表,当变化表对应的时候才可以做变换操作,否则遇到障碍使板块停下。

5) 键盘控制

玩家需要操控键盘实现对游戏的操作,因此,需要用到windows的键盘监听机制,通过查询相关资料,我们发现键盘上的每一个按键都对应了一个windows内部变量值,只需要判断此时触发的键盘事件时候与我们设置的相等,即判断是否触发了对应事件。

2、 设计过程中的错误及其原因分析

1)

旋转功能失效

当运行游戏的时候,板块下落的时候出现了玩家无法操作的情况,即旋转功能

失效。我们分析,玩家操控板块的时候触发键盘监听事件,调用了旋转操作函数,在旋转操作中首先要判断能够做相应的旋转,如果需要旋转的位置已经有板块,旋转操作不能进行。

因此,我们断点调试程序,找到了对应板块中的旋转坐标表中有些地方设置错误,经过修改调试,运行正常。

2) 键盘监听大小写异常

我们需要监听用户的操作,但是游戏过程中会出现监听异常的情况。经过细心排查问题,我们发现,键盘中的事件对应一个常量,但是大小写所对应的值明显是不同的,当用户开启大小写按钮的时候可能无法正常监听到用户操作。因此,我们添加了额外的兼容程序。经过测试,错误得到了改正。

3) 游戏无法正常结束

当游戏结束的时候需要用户手动选择退出或者重新开始,但是我们运行的时候发现无法正常退出游戏。

我们分析,退出操作是windowsAPI中的windows窗体的默认功能,如果无法生效应该是参数的设置错误,因此我们找到windows窗体应用中的退出exit’函数退出部分,找到对应的参数,经过查询相关的API资料设置推出的参数默认值。

经过测试,成功的改正了问题。

3、 体会和收获

1通过真正的实战演练,巩固学校里面所学习的理论知识,并把理论知识更好的和实际○

结合,学会真正的活学活用。

2熟练掌握C++,web的编程技术,通过与企业无缝对接,学会项目中的一整套流程,○

从开始创建到动态模型的建立,加深对实际工作流程的理解。

3开拓计算机专业的眼界,见多识广,对已学的技能树之后的方向起到了很好的指导作○

用,定下了就业的方向。

4与公司中的大牛接触,○学习他人的优点,认识朋友,提升交际能力和信息获取的能力。认识到自己的不足,取长补短,与他人打交道。 5大学生体验职场生活,积累经验,更好的为社会服务。 ○

6团队协作方面,大家一起共同奋斗,相互尊重,解决一些生活中的矛盾,合理分工,○

一起完成任务

7增强了我个人的时间管理,每天按时的计划既保证了学习和休息的平衡,也给了自己○

充足的思考时间,吾日三省吾身,在思考中前进。

8认识到了提高效率的重要性,时间和工作量的比例安排,对今后的个人生活的工作的○

安排规划有显著提高。

六、 附录(配置清单)

1.操作系统

Windows 8 64位,以及windows 10

2.开发环境

微软Visualstdio 2010 pro

3.相关软件

Sublime编辑器,记事本,photoshop

4.技术文档

Api说明,应用大纲

七、 参考文献

1.

WindowsAPI 官方文档

https://msdn.microsoft.com/en-us/library/windows/desktop/ff818516(v=vs.85).aspx

2.MFC开放帮助文档

3.百度百科 俄罗斯方块综述

http://wenku.http://www.wodefanwen.com//link?url=DEaRFyVIAH4kZ7TolplfFhFhmAk3gFaNSOH7XPzfTnCWY4CBfCAKSoCuY_yinRE4QGNIwFUFXWp76O3sfC4c5tJtLdo-BTJwwVhBb9fQiP3

八、 基本信息

1、

项目小组成员

姓名 韩林波 杨轲 樊平 刘宇星 高霖山 陈思比 王梧桐 代家民 学号 2013551417 2013551433 2013551404 2013551425 2013551437 2013551427 2013551305 2013551422 班级 13计算机科学与技术2班 13计算机科学与技术2班 13计算机科学与技术2班 13计算机科学与技术2班 13计算机科学与技术2班 13计算机科学与技术2班 13计算机科学与技术1班 13计算机科学与技术2班 联系电话 电子邮箱

2、 各成员分担的实践内容(要求具体)

开发文档编写:

项目文档设计:樊平 UI设计:王梧桐 项目功能设计:韩林波

代码功能编写:

C++游戏开发方块初始化:高霖山、刘宇星、杨轲 方块的旋转:韩林波,代家民 方块的碰撞:樊平,王梧桐 分数记录:陈思比

应用测试及维护:

韩林波,代家民

3、

设备编号

无编号

4、 实践时间

2016年7月5日---2016年7月15日

5、 报告完成日期

2016年8月30日

本文来源:https://www.bwwdw.com/article/4i97.html

Top