用C#实现单机版俄罗斯方块

2016-02-05 08:05韦立梅张淑荣
电脑与电信 2016年10期
关键词:子类方块方格

韦立梅 张淑荣

(广东白云学院,广东 广州 510450)

用C#实现单机版俄罗斯方块

韦立梅 张淑荣

(广东白云学院,广东 广州 510450)

俄罗斯方块是一款非常受欢迎的益智游戏。本文介绍了利用C#来实现此游戏的分析设计、主要类及其代码等知识。

俄罗斯方块;C#;类

1 引言

C#是微软公司发布的一种面向对象的、运行于.NET Framework之上的高级程序设计语言,它是由C和C++衍生出来的,具有安全、简单、执行效率高等特点。Microsoft Visual Studio(简称VS)是美国微软公司的开发工具包系列产品,是目前最流行的Windows平台应用程序的集成开发环境。本文将说明使用C#语言实现俄罗斯方块游戏的主要类代码,开发平台使用Visual Studio 2013。

2 设计分析

当用户单击开始游戏命令按钮后,在程序界面的左侧出现游戏面板区域,是由18行、11列方格组成的长方形区域,并设置两个障碍物方格,然后随机给出不同的形状,从正中间一列开始下落,当碰到障碍物后,该形状也变成新的障碍物,若没有,则下落并填充到相应的区域,在下落的过程中可通过键盘上的“↑”按键对形状进行翻转变形,键盘上的“↓”按键控制形状加速下落,键盘上的“←”、“→”按键控制形状进行左右移动,若填满游戏面板中的某一行,便消除该行,剩余的方块向下移动,并记分。当形状填满游戏面板首行时,游戏视为结束。

用户界面的右侧,会显示下一个即将出现的形状、所得分数、等级、形状下落速度等信息。

图1 游戏开始界面

图2 游戏结束界面

3 游戏主要类

游戏主要有三个类:游戏帮助类,形状父类,背游戏控制器类。由于篇幅所限,这里只重点介绍形状父类及其代码。

3.1 游戏帮助类

提供整个程序运行过程中经常要使用的公共变量:游戏面板的行数、列数,默认是18行,11列,小方格的边长,游戏环境的初始化,中间列索引,障碍物的颜色,普通背景方格的颜色,游戏速度的设置,线程锁(玩家分数,玩家等级)。

3.2 形状父类

这个抽象类描述的对象是俄罗斯方块的七种不同的形状,是一个父类,它共有七个子类(ShapeLine、ShapeLLeft、ShapeLRight、ShapeSquare、ShapeT、ShapeZLeft、ShapeZRight)。每个子类的形状都是由四个小正方形组成。这个抽象类需要实现不同形状实体所有的属性和动作。包括:形状的组成,位置,形状左移,右移,下移,旋转等。

类设计:

{public ShapeUnit[]units=new ShapeUnit[4];//声明ShapeU-nit数组,对应每个形状中的4个小方格

public ShapeDirection shapeDirection=ShapeDirection.Up; //形状方向,默认是向上的

protected CellPosition shapeCenter;//形状中心点

public Shape(){……}//构造函数用于初始化units数组,调用SetUnitsPositon()方法。

{for(int i=0;i

{units[i]=new ShapeUnit();}

this.SetUnitsPositon();}

protected abstract void SetUnitsPositon();//虽然每个形状子类对象都是由4个小方格组成,但是每个子类4个小方格(元素)的位置不同,所以定义一个抽象方法,而在每个子类中会重写该方法,设置每个小方格的位置

public void DrawMe(Graphics g)//画出形状的方法

{lock(CommonHelper.lockKey)

{foreach(ShapeUnit u in this.units)//遍历数组中的每一个元素,调用每一个元素的DrawMe方法

u.DrawMe(g);}}

public void WipeMe(Graphics g){……}//擦除形状的方法,与画出形状的方法类似,实际上就是调用每个小方格的WipeMe(g)方法,将小方格自己擦除,可参照上面的DrawMe方法,编写相应代码,在此省略。

public void MoveDown(Graphics g)//形状下落的方法

{this.WipeMe(g);//擦除形状.

for(int i=0;i

{units[i].Position=new CellPosition(){RowIndex=units[i].

Position.RowIndex+1,ColIndex=units[i].Posi

tion.ColIndex};}

shapeCenter.RowIndex++;

this.DrawMe(g);}//根据新的位置重新绘制形状

Interface.IShapeMoveable shapeMoveListener;//形状下落的线程开始

bool isAive=true;//形状存活的标志

public void StartShapeMoveThread(Interface.IShapeMoveable shapeMoveListener)//开启形状移动线程

{this.shapeMoveListener=shapeMoveListener;

Thread shapeMoveThread=new Thread(MoveDownAuto);//声明1个线程对象,并为这个线程指定执行的方法

shapeMoveThread.IsBackground=true;//设置线程为后台线程

shapeMoveThread.Start();//开启线程 } private void MoveDownAuto()//线程执行方法

{while(isAive)

{Thread.Sleep(CommonHelper.GameSpeed);//暂停线程

shapeMoveListener.ShapeMove(this);//移动形状}} public void KillMe(){this.isAive=false;}//结束线程public void MoveToLeft(Graphics g)//向左移动

{this.WipeMe(g);//擦除形状本身

for(int i=0;i

{units[i].Position=new CellPosition(){RowIndex=

units[i].Position.RowIndex,ColIndex=units

[i].Position.ColIndex-1};}

shapeCenter.ColIndex--;

this.DrawMe(g);//重新绘制}形状

public void MoveToRight(Graphics g){……}//向右移动

//可参照向左移动方法,编写向右移动代码,注意向右移动时行坐标不变,列坐标增加

public void MoveToDown(Graphics g){……}//向下移动

//可参照向左移动方法,编写向下移动代码,注意向下移动时列坐标不变,行坐标增加

public abstract void TurnToRight();//形状右旋转,在每个形状子类中,重写该方法

public abstract void TurnToDown();//形状下旋转,在每个形状子类中,重写该方法

public abstract void TurnToLeft();//形状左旋转,在每个形状子类中,重写该方法

public abstract void TurnToUp();//形状上旋转,在每个形状子类中,重写该方法}

左L形状子类实现SetUnitsPositon方法的重写代码如下:

class ShapeLeftL:Shape

{protected override void SetUnitsPositon()

{base.shapeCenter=new CellPosition(1,CommonHelper.MidCol);

base.units[0].Position=new CellPosition(base.shape-Center.RowIndex-1,base.shapeCenter.ColIndex);

base.units[1].Position=new CellPosition(base.shape-Center.RowIndex,base.shapeCenter.ColIndex);

base.units[2].Position=new CellPosition(base.shape-Center.RowIndex+1,base.shapeCenter.ColIndex);

base.units[3].Position=new CellPosition(base.shape-Center.RowIndex+1,base.shapeCenter.ColIndex-1);}

左L形状子类实现TurnToRight方法的重写代码如下:

public override void TurnToRight()

{base.units[0].Position=new CellPosition(base.shapeCenter.RowIndex+1,base.shapeCenter.ColIndex+1);

base.units[1].Position=new CellPosition(base.shapeCenter.RowIndex+1,base.shapeCenter.ColIndex);

base.units[2].Position=new CellPosition(base.shapeCenter.RowIndex+1,base.shapeCenter.ColIndex-1);

base.units[3].Position=new CellPosition(base.shapeCenter.RowIndex,base.shapeCenter.ColIndex-1);}

3.3 游戏引擎类

游戏引擎类就如一个汽车发动机一样,可以让游戏反复地运行。它的主要功能是:当用户单击“开始游戏”按钮后,重新画出游戏背景、初始障碍物、随机产生形状;形状以一定的速度下落的过程中,对键盘事件做出响应,实现左右移动、向下加速、旋转。当形状到达边界时,结束形状的移动,并将形状变成新的障碍物。

4 结束语

在Visual Studio 2013环境下实现的俄罗斯方块游戏,可以让广大编程爱好者更好地学习C#语言的应用,提高实战能力的同时,也激发了学习兴趣,对自己动手编写应用程序的能力会有很大的帮助。

[1]王文举.C#语言开发俄罗斯方块游戏[J].电脑编程与维护,2013(3):7 3-7 9.

[2]付强,丁宁,等编著.C#编程实战宝典[M].北京:清华大学出版社,2014.

【Abstract】Tetris is a very popular puzzle game.This paper describes the design of using C#to achieve the game,the main types of knowledge and code.

class Shape

Using C#to Achieve a Single version of Tetris

Wei Limei Zhang Shurong
(Guangdong Baiyun University,Guangzhou 510450,Guangdong)

Tetris;C#;class

TP311.52

A

1008-6609(2016)10-0055-03

韦立梅(19 77-),女,辽宁凌源人,硕士,讲师,研究方向为图形图象处理、数据库系统开发。

猜你喜欢
子类方块方格
有多少个方块
方格里填数
不一样的方块桥
卷入Hohlov算子的某解析双单叶函数子类的系数估计
方格里填数
谜题方块
分方格
分方格
Java类的继承
面向对象的多版本传感器观测服务模式匹配方法