一 需求分析
1.1 设计内容:
设计一个俄罗斯方块游戏,根据实际游戏的规则完成设计。
游戏设计方案:
在一个图形绘制区域的正上方随机产生四种不同方块中的任意一种的初始位置,并使其向下运动
定义键盘,游戏玩家用键盘上定义的键控制方块的翻转、左右移动、加速和暂停等
当某行被填满则该行消除,1次消除1行加10分,1次消除2行加30分,1次消除3行加50分,1次消除4行加100分
当未被消除的行达到绘图区域的最大行数时,则游戏结束,给出游戏最终得分
1.2 要解决的问题怎么在VC++6.0中画出各种图形、填充各种颜色
怎么样根据坐标画出方块
怎么随机产生不同形状、颜色和旋转状态的方块
怎么控制方块的移动、旋转等操作
1.3 如何做在 www.easyx.com 网站中下载Easyx插件,使VC++6.0实现图形化界面
查看easyx的帮助,解决easyx.h和graphics.h库中需要用到的绘图函数。从而会出各种形状、颜色的方块
利用kbhit()函数获取玩家键盘输入,在编写不同输入对应的函数,从而实现对方块的控制
利用time.h库中srand()函数来根据时间产生随机数,从而在游戏中实现随机产生不同形状、颜色和旋转状态的方块
二 算法设计
2.1 总体设计
游戏流程图如下所示:
2.2 关键数据结构和主要算法for(i=0;i<16;i++,b<<=1)
if(b&0x8000)
{
x=block.x+i%4;
y=block.y-i/4;
if(y
DrawUnit(x,y,Blocks[block.id].color);
}
b是一个十六进制数,和0x8000做“与”运算是为了测试最高位是否为1,从而将b的二进制等值数中的1的坐标记录下来,从而准确的画出各种形状的方块。
while(true)
{
new_time=GetTickCount();
// 不控制,默认自动下落一格
if(new_time-old_time>500)
{
old_time=new_time;
returnDOWN;
}
// 如果有按键,返回按键对应的功能
if(kbhit())
{
switch(getch())
{
case72:
cmd=ROTATE;
returncmd;
case80:
cmd=DOWN;
returncmd;
case75:
cmd=LEFT;
returncmd;
case77:
cmd=RIGHT;
returncmd;
case27://ESC键
cmd=QUIT;
returncmd;
case' ':
cmd=SINK;
returncmd;
}
}
}
通过GetTickCount()函数获取时间,计算出时间差,大于规定的时间差,则默认方块下落,通过改变时间差的大小可以控制下落的速度,从而控制游戏难度。在通过kbhit()函数接受键盘输入,不同的按钮相应不同的函数,从而有效的控制的方块的位置和旋转状态。
2.3 主要函数main()函数:是程序的入口,通过调用各个函数来启动游戏
Init()函数:通过rectangle()、line()、outtextxy()函数在黑窗口内画出矩形、线和文字,通过控制它们的位置和大小来画出游戏启动画面
NewGame()函数:先清空游戏区(为下次继续游戏做准备)、初始化分数,在创建新的方块和预备方块
CreatBlock()函数:通过rand()函数随机初始化不同形状、旋转状态和大小的方块。初始化后通过调用DrawBlock()函数来画出方块。创建方块的同时,通过GetTickCount()函数设置计时器,用于判断自动下落
DrawBlock()函数:通过一些算法,将初始化的十六进制数转换为等值二进制,将16位的二进制看成4*4的矩阵,将矩阵中的1用坐标(x, y)记录下来,在将方块的每个单元坐标(x, y)和颜色发送给DrawUnit()函数处理
DrawUnit()函数:将DrawBlock()函数发送过来的坐标和颜色信息,在游戏区内画出来。从而使玩家看到有形有色的方块
ClearBlock()函数、ClearUnit()函数:原理和DrawBlock()函数、DrawUnit()函数一样,只是用BLACK背景色“画”出方块,从而实现擦掉方块的效果
GetCommand()函数:通过GetTickCount()函数获取新的时间,计算出时间差,大于规定的时间差,则默认方块下落,通过改变时间差的大小可以控制下落的速度,从而控制游戏难度。再通过kbhit()函数接受键盘输入,将输入信息发送给SendCommand()函数,从而实现对玩家的输入做出准确的响应
SendCommand()函数:将GetCommand()函数发送过来的输入信息,通过switch()分别调用不同的函数,从而实现玩家对方块的有效控制
CheckBlock()函数:对方块执行左、右、下移和旋转时执行该函数,目的是检验方块目前的位置和旋转状态是否满足执行下一步的条件,起到判断的作用
Go_Down()函数:先检查是否满足下移的条件,如果满足,改变方块的坐标,使方块实现下移,否则,调用Go_Sink()函数,执行沉淀操作
Go_Left()函数:先检查是否满足左移的条件,如果满足,改变方块的坐标,使方块实现左移。否则,不执行任何操作
Go_Right()函数:先检查是否满足右移的条件,如果满足,改变方块的坐标,使方块实现右移。否则,不执行任何操作
Go_Rotate()函数:先检查是否满足旋转的条件,如果满足,改变方块的旋转状态,使方块实现旋转。否则,不断改变方块的条件,使方块满足旋转的条件,使方块完成旋转操作
Go_Sink()函数:先不断的改变方块的坐标,使方块下移,直到不满足下移条件时,记录方块的坐标,画出固定方块。如果此时方块累加的高度大于游戏区的高度,调用GameOver()函数,游戏结束。否则用二维数组FixBlock[x][y]记录方块的位置,表示固定方块区。在判断固定方块区是否有满行方块,如果没有,不做处理,继续固定。如果有满行,就消掉该行,并将所有固定方块区的纵坐标下移。并且累加刷新分数。再调用CreatBlock()函数,创建新的方块
GameOver()函数:弹出对话框,提示玩家是否继续游戏。继续就调用NewName()函数,否则执行Quit()函数
Quit()函数:关闭游戏窗口
三 程序实现
3.1 实现说明
主要实现的功能如下:
在一个图形绘制区域的正上方随机产生四种不同方块中的任意一种的初始位置,并使其向下运动
定义键盘,游戏玩家用键盘上定义的键控制方块的翻转、左右移动、加速和暂停等
当某行被填满则该行消除,1次消除1行加10分,1次消除2行加30分,1次消除3行加50分,1次消除4行加100分
当未被消除的行达到绘图区域的最大行数时,则游戏结束,给出游戏最终得分
采用图形化界面实现
在一个图形绘制区域的正上方随机产生七种不同方块中的任意一种的初始位置
七种方块有七种不同的颜色,并且颜色是随机出现在七种方块中的
在消除方块时产生过渡动画的效果
给游戏设置难度等级,难度由玩家开始游戏之前选择,分为“简单”、“正常”、“困难”
随着玩家分数的提高,游戏难度和等级自动提高,即方块下落的速度加快
进入游戏前和游戏结束后为游戏添加多读动画,使游戏运行更自然
四 程序运行
4.1 游戏手册
进入游戏时,游戏区的上方会自动下落方块,游戏窗口的右上方会显示方块的形状、颜色和旋转状态,使玩家产生心理准备。游戏窗口的右方显示玩家的分数。游戏窗口的右下方是游戏的操作说明。玩家键盘输入左、右、下分别是控制方块的位置,使方块根据玩家的控制移动起来。键盘输入上是改变方块的旋转状态,使方块旋转。按Esc键是退出游戏。按空格键是使方块直接沉底。当方块的高度大于游戏区的高度时,游戏结束。友情提示:当某行被填满则该行消除,1次消除1行加10分,1次消除2行加30分,1次消除3行加50分,1次消除4行加100分。所以想要拿高分,需要一次消多行。
4.2 运行实例
如下图所示:
五 参考资料
[1] Stephen Prata编著 C primer plus[M].北京:人民邮电出版社,2012
[2] 合肥学院计算机科学与技术系编著《C语言程序设计》讲义[M].合肥学院计科系,2016-2-28