1、项目内容及性能
我们“0error”小组的项目选题是“俄罗斯方块”。至今仍风靡全球的俄罗斯方块无疑是史上最经典的益智小游戏之一,目前流行版本多种多样,简单易行,老少皆宜。
本项目主要实现以下功能。
1>主界面有选择游戏难度功能
2>能够查看玩家得分排名的选项。
3>开始游戏,游戏界面有下一个出现的方块样式的提醒,并显示本次难度及当前得分。
4>进入游戏界面后,有背景音乐。
5>可在txt文件中作简单修改改变各方块样式。
2.项目方案
2.1 结构和算法设计
1>程序构架
首先,展示此次俄罗斯方块的程序构架图
接下来,将从程序底层到程序顶层依次介绍。
首先最底层的是俄罗斯方块的数据层。在TetrisFile类中,封装了对方块样式和排行榜两个配置文件的操作。将完成方块样式的读取,以及玩家信息的读取和保存。
再往上一层,就是俄罗斯方块的数据处理层了。在这整个层次中,全部都由Tetris类给予完成。在这个类中,能够从TetrisFile类中轻松的获取数据。同时,该类封装了绘方块图,方块的控制,消行,随机产生方块,游戏结束等操作。并且,能够提供一个画方块图接口,提供一个方块控制的接口,将这两个接口传递给顶层窗口。
最上层,则为窗口层。在窗口层中将完成人机交互。在PlayForm窗口中,会显示砖块的移动,得分,下一个方块图案。同时,用户可以按键操作方块的移动,旋转。在RankForm中,可以显示用户得分的排行。在LevelForm中,用户可以调节游戏难度。在窗口与窗口之间,可以跟据接口进行访问重要的数据。
2>程序算法
在俄罗斯方块游戏设计中,最核心的就是数据结构和方块样式的移动和旋转的操作了。
首先,介绍本游戏主要的数据结构。采用的大方块的数据结构为
public class TetrisBrick
{
private Point[] tetrisBrickPoint;
private int x;
private int y;
private BrickType tetrisBrickType;
}
方块类型的数据结构为
public enum BrickType
{
NoBrick = 0,
Line = 1,
Field = 2,
Soil = 3,
Z = 4,
L = 5,
OtherForm = 6
}
操作类型的数据结构为
public enum TetrisOperateType
{
MoveLeft = 0,
MoveRight = 1,
MoveDown = 2,
MoveBottom = 3,
SpinLeft = 4,
SpinRight = 5
}
在TetrisBrick中的数据成员依次用来表示该大方块中包含小方块的相当坐标,大方块的中心坐标,和方块类型。不同的类型可以用不同的图片进行显示,使界面更美观。BrickType是大方块类型的枚举,TetrisOperateType是操作类型的枚举。
本程序设计的最重要算法之一就是对大方块的控制。控制分为左移、右移、下移、顺时针旋转、逆时针旋转五大类。左移、右移和下移相当简单,只需要大方块的中心坐标的横坐标减一、横坐标加一、纵坐标加一。而对于旋转,则要用到旋转矩阵
取 θ 为90度,则为顺时针旋转90度,-90度则为逆时针旋转90度.(x,y)为变化前的坐标,(x’,y’)为变化后的坐标。只需对大方块的每一个小方块进行坐标变换,就可以对整个大方块进行旋转变换了。
坐标变换后,是否可以进行相应的操作是有限制的。例如变化后的方块是否会越界,是否会碰到其它方块。处理的方法就是对每个变化后的坐标进行判断,如果不会越界,则进行相应操作,否则,不进行移动。
此程序的一大亮点就是不需要更改源码就可以产生各式各样的大方块类型,只需要在配置文件TetrisTemplateFile.txt中增加方块样式就可以了。而能够支持这种功能的原因就是数据结构的兼容性良好。在文件读取时采用泛型算法,能够将方块样式读入TetrisBrick的tetrisBrickPoint数组中。
2.2 用户界面设计
事实上,在C#中进行界面设计是非常便捷的。C#中提供强大功能支持的控件,同时使用起来也非常便捷。
在此次的俄罗斯方块设计中,除了运用C#中提供基本的一些控件之外,就是加载了大量的图片。方块、背景、图标等都是采用我们小组成员PS美化的图片,使得界面能够漂亮美观。在文字上面,我们采用特殊的样式,并以特殊的颜色进行显示。从而在整体上增加了这款游戏的可视性。
2.3 用户使用方法
1. 点击主界面中央的“PLAY”按键,进入游戏界面。用键盘“↑”“↓”“←”“→”键控制掉落方块的定向旋转,下降速率,向左移动和向右移动,来达到填满一行实现消除进而得分的目的。游戏界面右上角显示的是下一个掉落的方块形状,右下部分则显示本次难度(level)和玩家当前得分(score)。消除一行即得10分。方块堆叠满框时游戏结束,弹窗提示输入玩家名称。关闭游戏界面会回到主界面。
2. 点击主界面右下角“LEVEL”按键,可进入难度选择界面难度从1到10,依次提升,具体体现在方块掉落速度变快。关闭难度选择界面会回到主界面。
3. 点击主界面右下角“RANK”按键,可进入排行榜查看界面。排行榜可显示所有分数大于10分的玩家名称及得分。关闭排行榜查看界面会回到主界面。
4.点击主界面右下角“QUIT”按键,退出程序。
2.4 设计难点
在本次的俄罗斯方块游戏的设计中,主要有以下3个难点:
1、 程序的总体框架
一开始我们对于程序的整体把握不够了解,只是想着怎样把要求的功能都实现了,没有框架,像是一盘散沙,设计出来的程序没有可维护性。后来经过老师的指导以及我们小组的讨论,我们整理出了程序的大致框架:顶层窗口,中间控制层,底层数据。有了这三个大致的框架,我们接下来就将他们更加细化,明确其中的类以及他们的关系。
2、 类的提取以及类和类的关系
在整个俄罗斯方块游戏中,结构并不是那么的鲜明,我们没办法像做报表那样,找出各个类以及他们的关系,所以我们在设计类上花了大部分的时间。我们小组初步定为playform类、program类、Tetris类、TetrisBrick类以及两个枚举BrickType和TetrisOperateType。可是他们之间的关系并不清晰,分工也不够明确,按照这样设计出来的程序,只能够实现俄罗斯方块这个游戏,并不能真正意义上满足程序设计的代码重用的功能,也就是当我们想增加新的功能,比如要改变小方块的个数、大方块的形状等,都必须要重新修改、甚至要重写代码,然后重新编译。如此一来,就违背了面向对象的原则,所以经过我们小组的讨论,对我们的类以及他们之间的关系做出了修改。
我们首先从顶层窗口类来说,我们设计了GuardForm类、InputNameForm类、LevelForm类、PlayForm类、Program类、RankForm类。其中增加了难度选择和排行榜的功能,来提高我们游戏的完整性。然后是我们的中间部分,Tetris类和TetrisFile类,分别用来产生方块、组合方块、控制方块以及消除方块。最后,是我们的数据结构MenuType枚举、BrickType枚举、TetrisOperateType枚举以及winner结构。这样一来,我们的程序就清晰明了了。
3、 功能的扩展
当功能扩展时,要尽可能少地修改代码,最好不要编译。这就要跳出我们以前做C++项目的惯有思路,就是先实现功能,再修改代码。我们现在的难点是,要尽可能地考虑到所有功能上的改变,而在设计时就要适应这些改变,以减少以后的修改,提高复用性。
因此,经过我们的讨论,采用TetrisFile类来保存数据,实现了不用编译,就可以改变小方块的个数以及组合方式,做到功能的扩展。
2.5 实验结果与分析
经过测试,我们所设计的俄罗斯方块游戏,可以满足经典俄罗斯方块的功能,包括变换形状、消行、难度选择、得分输入排行榜以及背景音乐等功能。其中难度选择是以时间快慢来控制的,难度等级越高,方块下落的越快。在此基础上,我们新增的改变方块个数以及形状的功能可以在Debug文件中找到TetrisTemplateFile文件,直接修改其中的0和1(1代表小方块),就可以实现多个小方块的任意组合,打破传统的俄罗斯方块形式,增加俄罗斯方块的趣味性。但我们程序还欠缺多人游戏的功能,希望在下次设计时加以改善,让我们的程序更加完美。