C++俄罗斯方块课程设计Word下载.docx
《C++俄罗斯方块课程设计Word下载.docx》由会员分享,可在线阅读,更多相关《C++俄罗斯方块课程设计Word下载.docx(25页珍藏版)》请在冰豆网上搜索。
1.1课程设计的目的和要求
俄罗斯是家喻户晓的益智小游戏,选择这个题目一是为了将自己的所学知识加以运用,二是俄罗斯方块是我第一个接触到的游戏,它的实现方法也吸引着我。
我希望通过探索实践去实现它,在这次学习中从实践和实际的项目中提高自己的编程能力。
因此我选定了这个题目。
C++课程所学的概念、理论和方法,按照C++程序设计的基本步骤,设计出一个适当规模的程序来实现设计课程内容中的全部功能;
设计主控模块程序.对给出的程序源代码要给出各部分的详细注释.自己根据能力及需要添加相应功能模块,增强模拟系统功能。
1.2课程设计任务内容
利用MicrosoftVisualC++编写一个文本窗口下的俄罗斯方块游戏。
要求:
(1)利用类和多文件编写。
(2)能够记录游戏得分和等级。
(3)可暂停/继续游戏,使玩家在不愿游戏时退出。
(4)信息提示时显示颜色变化。
1.3关于编译软件
本程序采用MicrosoftVisualC++6.0的英文版本进行编译。
VisualC++6.0是Microsoft公司推出的基于Windows操作系统的可视化C++编程工具,尽管Microsoft公司推出了.NET平台的集成开发环境,但由于其良好的界面和可操作性,加上支持标准C/C++规范,但仍有相当多的编程人员使用VisualC++6.0进行应用系统的开发。
关于稳定性,经测试,本程序可以在windows操作系统中稳定运行,较为稳定。
第二章详细设计说明
2.1程序设计
2.1.1主要功能设计
根据分析,俄罗斯方块这个程序一共要实现如下几个功能,开始游戏、游戏的暂停\继续、游戏控制和退出游戏。
其中游戏控制最为主要和重要,它控制着整个游戏的画面和有关数据的操作,是游戏的核心部分。
暂停和退出功能做成一体,在退出的提示下不做任何操作即可实现暂停的功能。
程序结构如图2.1所示。
图2.1
2.1.2程序流程图
根据分析后的程序结构图设计出相应的流程图。
俄罗斯方块的内容主要包括游戏开始,画背景和边框,显示分数等级和下一个方块的预览图;
根据速度没隔一定时间方块自动下落,当有按键操作时,根据相应按键执行动作,每次动作前要判断是否动作可以执行。
下落方块满一行时,消去该行,根据消去行数得到相应分数。
分数达到一定程度,等级提升,速度加快。
同时可以响应Esc按键,提示是否退出程序。
如图2.2所示。
图2.2
2.2参数说明
根据程序的结构,将俄罗斯方块需要实现的功能细化为相应的类成员函数。
程序有两个类,一个view类,用于背景相关操作。
一个squar类,用于方块相关操作。
2.2.1类设计声明(view类)
classview
{
public:
view();
//类的缺省构造函数
intgetbgdata(int,int);
//取得数组x,y点的数据值
voidscoreadd(int);
//得分增加,根据消去行数
voidscorereset();
//得分清零,用于升级后
voidlevelup();
//等级提升,当分数达到规定值后执行
intgameover();
//游戏结束
voidrowdelete();
//消除满行
voidpreviewset(int(*p)[4]);
//设置预览方块的形状数据
voidpreviewreset();
//预览方块数据清零
voidsetdata(int(*)[2]);
//设置主游戏区数据值
voiddatareset();
//主游戏区数据清零
voiddrawpreview();
//显示预览方块
private:
intdata[25][26];
//主游戏区数组
intpreview[4][4];
//预览方块数组
introwsdelete;
//每次消除行数变量
intscore;
//得分变量
intscorelevel;
//升级规定值变量
intlevel;
//等级变量
booloverflag;
//结束标记变量
voidscorelevelup();
//升级规定值提升
};
2.2.2类设计声明(squar类)
classview;
//先向引用声明
classsquar
squar();
squar(squar&
);
//拷贝构造函数
friendvoidcursor(int,int);
//友元函数控制光标位置
voidgetcursor(int&
int&
//取得位置记录坐标
voidmake();
//随机产生一个方块
voidgetmake(int(*p)[4]);
//取得方块数据值
voiddraw();
//显示主方块
voiddrop(view&
//方块下落
voidchange();
//方块变形
intmeet(int);
//判断方块周围是否有障碍
voidtorecord(int(*)[2]);
//传送需要记录的数据
voidreset();
//方块数组清零
intmoveflag;
//方块运动标记变量
voidmove();
//方块运动
intshape[4][4];
//方块形状数据
intx,y;
//坐标
intshapeindex;
//方块形状序号
intchangeindex;
//变形序号变量
intspeed;
//下落速度变量
2.3函数功能说明
2.3.1游戏界面
俄罗斯方块的游戏界面包括游戏区域边框、下落方块绘制、右部计分和预览图显示等。
游戏区域边框的绘制比较简单,循环中确定光标的位置输出特定字符,即可完成边框绘制。
游戏区方块的绘制,循环从数据数组中依次读出数据,根据读到的数据显示“□”,最后组成方块的形状,完成方块的绘制。
计分和预览图部分先画出一个矩形区域,然后控制光标在其中显示分数、等级、预览图和提示信息。
2.3.2生成方块
本程序中生成的方块有六种形状,每一种方块以shapeindex标记,在程序运行生成方块时,调用shapeindex=rand()%5+1;
语句,确定当前要显示的是哪一个方块形状。
而在实际运行中,第一次需要调用两次生成方块函数make(),将先产生的赋给游戏当前方块,第二个赋给预览图方块。
以后每次产生一个方块,把预览方块赋给当前方块,把新产生的赋给预览方块。
具体如图2.3所示。
图2.3
2.3.3方块变形
俄罗斯方块的特点就在于通过方块的变形拼满整行来消去该行方块从而使游戏可以继续下去,很难想象不能变形的俄罗斯方块是什么样子。
而变形的过程就是根据当前方块形状改变方块的相对位置,这样就可以改变方块的形状了。
在程序中每当按下Up键,程序判断可以变形后,根据当前方块的形状序号shapeindex和变化形状序号changeindex调用相应的方块数值赋给draw()函数,通过刷新重画就可以显示变化后的方块了。
具体形状变化如图2.4所示。
2.3.4方块显示
以上方块的操作都是数据层面的操作,而真正要在游戏窗口中看到数据的变化,还必须把方块不断的绘制出来。
这就是draw()函数的作用。
把当前运动的方块对应节点存储在一个4*4数组里,变形和生成方块的过程就是更新该数组数据的过程。
然后在draw()函数里检测数组的各个值,并控制光标跳到一定位置,画出“□”组成方块。
具体方块对应数组数值关系如图2.5所示。
图2.4
2.3.5障碍判断
障碍判断,就是在方块运动中或者变形中判断周围是否有障碍阻碍下落、移位、变形。
当方块下落遇到下面有方块或者到达下边界则应停止下落并记录数据,存入背景数据数组。
变形时应判断这个变形是否可以进行,如果有障碍则不能变形。
例如当方块达到右边界,而若变形则会越过边界,那么这个变形的命令是不应执行的。
所有这些判断都由meet()函数进行,根据是否有障碍返回1或0,再由其他函数接收执行相应操作。
2.3.6消行计分
游戏玩家拼满一行后,程序消去满行,并计分。
中当一个方块下落停止后,程序检查方块是否充满了游戏区域,如果是结束游戏。
不是,则判断是否构成消行条件,从下落方块的最低点依次向上检查是否可以消行,根据消去行数分数增加。
如图2.6所示。
2.3.7暂停退出
游戏的友好性在于能考虑用户的需要,随时可以暂停/继续游戏,在不愿继续游戏时退出游戏。
本程序可以在用户需要的时候响应Esc按键,提示是否退出游戏,如果不做选择即可暂停游戏,等待选择。
界面如图2.7所示。
图2.5
图2.6
图2.7
2.4程序调试
经过调试和修改,程序完全实现设计要求,成功模拟了俄罗斯方块的运行过程和游戏效果,只是界面略微简陋,但已从程序层面上实现了游戏,达到了这次实训的要求和目的。
程序正常生成方块,根据速度值每隔一定时间自动下落,如有操作按键按下,根据按键实现位移和变形。
当方块满一行后,可以消除该行,同时记录分数和等级。
按下Esc键红色提示信息正常显示,可以响应Y,N键决定是否退出游戏。
2.5软件使用说明
打开俄罗斯方块游戏后,通过控制方向区域的“上”、“下”、“左”、“右”来控制,“上”键代表变形转换,“下”、“左”、“右”均代表方向键,而“空格”代表“沉底”,
也可以通过“W”、“S”、“A”、“D”来控制方向;
“esc”代表退出游戏键。
若想暂停游戏,也可通过“esc”键,当初来询问框是,可不做选择,则可达到暂停的效果。
第三章总结与体会
通过这次课程设计,我收获了很多。
首先把所学知识加以利用和巩固,其次在实践中遇到问题去探索和学习,更增加了新知识。
在程序设计编写过程中两个类的数据交换是个比较麻烦的过程,这个类的定义过程中要用到另一个类做参数类型,而在后一个类中亦需要第一个类做参数类型,出现了互相调用的情况。
编译提示未定义,只好在两个类外定义函数负责两个类函数的数据交换。
实践证明达到了预期的目的,积累了经验。
由于程序是用文本窗口模拟的图形,界面比较简陋,如果使用MFC用C++来实现,那么界面将会非常好,只是由于所学知识有限,只有下一步去探索了。
通过这次的学习设计,我发现我还有许许多多的不足的地方,比如c++的程序设计,源代码的书写等等,刚开始我发现我的问题后,十分紧张,感觉很绝望,没有别人的帮助,自己动手设计曾经自己想都没想过的东西,虽然很兴奋,但想想自己无从下手,原来的兴奋劲一下子都没了,很忙然。
但是,通过与王老师的交流,经过老师的耐心讲解,我慢慢感到希望又重生了,于是我通过上网查找资料,进图书馆查找书籍等,终于知道了俄罗斯方块游戏的设计概念,终于知道了设计的方法,于是,渐渐地我的游戏设计理念诞生了。
通过几个礼拜的设计,我的游戏渐渐初见成效了,当我把回车键摁下的一刹那,我十分激动,眼前的既熟悉又陌生的游戏出现在了我的面前,看着自己设计的童年时代经常玩的游戏,我感慨万千。
通过这次设计,我学会了很多东西,例如通过网络资料来寻求帮助,自己改正错误,加强了我自己的自己动手能力,对今后的学习和生活有很大的帮助,有助于以后的课程设计顺利完成。
附录1参考文献
[1]段钢编著加密与解密(第三版).电子工业出版社.2009年8月
[2]赵树升赵韶平.Windows信息安全原理与实现.北京:
清华大学出版社.2004年
[3]杨永国.VisualC++6.0实用教程.北京:
[4]唐俊明.VisualC++6.0编程实例与技巧.北京:
高等教育出版,2002年
[5]潘锦平.软件系统开发技术.西安:
西安电子科技大学出版社,1997年
附录2源程序代码
#include<
graphics.h>
conio.h>
time.h>
/////////////////////////////////////////////
//定义常量、枚举量、结构体、全局变量
#defineWIDTH10//游戏区宽度
#defineHEIGHT22//游戏区高度
#defineSIZE20//每个游戏区单位的实际像素
//定义操作类型
enumCMD
CMD_ROTATE,//方块旋转
CMD_LEFT,CMD_RIGHT,CMD_DOWN,//方块左、右、下移动
CMD_SINK,//方块沉底
CMD_QUIT//退出游戏
//定义绘制方块的方法
enumDRAW
SHOW,//显示方块
HIDE,//隐藏方块
FIX//固定方块
//定义七种俄罗斯方块
structBLOCK
WORDdir[4];
//方块的四个旋转状态
COLORREFcolor;
//方块的颜色
}g_Blocks[7]={{0x0F00,0x4444,0x0F00,0x4444,RED},//I
{0x0660,0x0660,0x0660,0x0660,BLUE},//口
{0x4460,0x02E0,0x0622,0x0740,MAGENTA},//L
{0x2260,0x0E20,0x0644,0x0470,YELLOW},//反L
{0x0C60,0x2640,0x0C60,0x2640,CYAN},//Z
{0x0360,0x4620,0x0360,0x4620,GREEN},//反Z
{0x4E00,0x4C40,0x0E40,0x4640,BROWN}};
//T
//定义当前方块、下一个方块的信息
structBLOCKINFO
byteid;
//方块ID
charx,y;
//方块在游戏区中的坐标
bytedir:
2;
//方向
}g_CurBlock,g_NextBlock;
//定义游戏区
BYTEg_World[WIDTH][HEIGHT]={0};
//函数声明
voidInit();
//初始化游戏
voidQuit();
//退出游戏
voidNewGame();
//开始新游戏
voidGameOver();
//结束游戏
CMDGetCmd();
//获取控制命令
voidDispatchCmd(CMD_cmd);
//分发控制命令
voidNewBlock();
//生成新的方块
boolCheckBlock(BLOCKINFO_block);
//检测指定方块是否可以放下
voidDrawBlock(BLOCKINFO_block,DRAW_draw=SHOW);
//画方块
voidOnRotate();
//旋转方块
voidOnLeft();
//左移方块
voidOnRight();
//右移方块
voidOnDown();
//下移方块
voidOnSink();
//沉底方块
//函数定义
//主函数
voidmain()
Init();
CMDc;
while(true)
{
c=GetCmd();
DispatchCmd(c);
//按退出时,显示对话框咨询用户是否退出
if(c==CMD_QUIT)
HWNDwnd=GetHWnd();
if(MessageBox(wnd,_T("
您要退出游戏吗?
"
),_T("
提醒"
),MB_OKCANCEL|MB_ICONQUESTION)==IDOK)
Quit();
}
}
//初始化游戏
voidInit()
initgraph(640,480);
srand((unsigned)time(NULL));
//显示操作说明
setfont(14,0,_T("
宋体"
));
outtextxy(20,330,_T("
操作说明"
outtextxy(20,350,_T("
上:
旋转"
outtextxy(20,370,_T("
左:
左移"
outtextxy(20,390,_T("
右:
右移"
outtextxy(20,410,_T("
下:
下移"
outtextxy(20,430,_T("
空格:
沉底"
outtextxy(20,450,_T("
ESC:
退出"
//设置坐标原点
setorigin(220,20);
//绘制游戏区边界
rectangle(-1,-1,WIDTH*SIZE,HEIGHT*SIZE);
rectangle((WIDTH+1)*SIZE-1,-1,(WIDTH+5)*SIZE,4*SIZE);
NewGame();
//退出游戏
voidQuit()
closegraph();
exit(0);
//开始新游戏
voidNewGame()
//清空游戏区
setfillstyle(BLACK);
bar(0,0,WIDTH*SIZE-1,HEIGHT*SIZE-1);
ZeroMemory(g_World,WIDTH*HEIGHT);
/生成下一个方块
g_NextBlock.id=rand()%7;
g_NextBlock.dir=rand()%4;
g_NextBlock.x=WIDTH+1;
g_NextBlock.y=HEIGHT-1;
//获取新方块
NewBlock();
//结束游戏
voidGameOver()
游戏结束。
\n您想重新来一局吗?
游戏结束"
),MB_YESNO|MB_IC