转载请标明是引用于 http://blog.csdn.net/chenyujing1234
例子代码:
http://www.rayfile.com/zh-cn/files/9d09926e-736b-11e1-b9a4-0015c55db73d/
设计思路:
由10*10组成,图案更不相同,为存储游戏画面中的图案方块,采用Block类二维数组blocks[10,10];
在定时器控制下,不停地统计用户的得分,并控制生命进度条,如果生命进度条为0,则游戏结束。
当用户鼠标连续选中两相邻块firstblock2和secondblock2,交换以后调用check()检测是否有符合消去
的方块,如果有被消去的方块则修改要绘制的图案代号rectan2[10,10]数组对应的元素值,不需要绘制为0.
通过按列统计rectan2数组0值,得出每列被消去的方块的个数,并调用fill()从游戏屏幕该列上方重新随机产生新的方块,
依次下移填充被削去方块,重画需要绘制的所有方块,从而看到动态效果。
下面介绍设计过程:
1、新建一C# windows窗体工程。
将Form1.cs改名为Start.cs
在解决方案中添加两个文件平:images sound并把相关图片与声音资源包含进来.
给Start窗体的ICON选择图片小狗.ico
2、窗体Start.cs添加新控件
progressBar记得value值选100
在加载声音pictureBox时为Image属性选择图片
在加入了statusStrip contextMenuStrip timer1后,接下来为statusStrip添加toolStripDropDownButton
方法是右击statusSctrip1右选择编辑项,然后从列表中选择toolStripDropDownButton1然后点添加
3、界面算是画好了,接下来开始进行代码设计.
新建Block.cs文件来定义方块的坐标位置、小方块图案、图案种类代号字段成员及访问相应的属性.
using System; using System.Collections.Generic; using System.Text; using System.Drawing; using SuperPeng.Properties; namespace SuperPeng { /*本类描述的对象是对对碰的每个小方块*/ class Block { private Point location; //小方块坐标 private Bitmap blockImage; //小方块图案 private int imageType; //图片种类 public int ImageType//ImageType属性 { get { return imageType; } } public Point Location//Location属性 { get { return location; } set { location= value; } } public Block(int imageIndex,int x,int y) { location = new Point(x, y); imageType = imageIndex; //初始化小方块图案 switch (imageIndex) { case 1: blockImage = Resources._1; break; case 2: blockImage = Resources._2; break; case 3: blockImage = Resources._3; break; case 4: blockImage = Resources._4; break; case 5: blockImage = Resources._5; break; case 6: blockImage = Resources._6; break; case 7: blockImage = Resources._7; break; case 8: blockImage = Resources._8; break; default: blockImage = Resources._4; imageType = 4; break; } } /*画对象*/ public void Draw(Image img) { Graphics g = Graphics.FromImage(img); Rectangle r = new Rectangle(location, new Size(50, 50)); g.DrawImage(blockImage, r); } public void DrawSelectedBlock(Graphics g) { //画选中方块的示意边框线 Pen myPen = new Pen(Color.Black, 3); Rectangle r = new Rectangle(location, new Size(50, 50)); g.DrawRectangle(myPen, r); } public void ClearSelectedBlock(int x, int y, Graphics g) { //清除选中方块 } } }
Block()构造函数,参数提供了方块图案种类的代号imageIndex 及坐标位置(x,y),该构造函数中Switch(/case根据方块种类代号设置相应的方块图案。
Draw(方法将方块画在Image对象上,而不是游戏面板上,这样便于采用双缓冲技术。
DrawSelectedBlock将方块周围选中的示意边框线,这是直接画在传递过来的游戏面板上,而不是IMage对象上
4、接下来设计GameField.cs。
它是游戏实例,首先定义在游戏面板中存储所有方块的容器 ---- 二维数组 blocks[10,10],记录要绘制方块的图案代号rectan2[10,10]数组
using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Threading; using System.Media; using SuperPeng.Properties; namespace SuperPeng { /* * 场景大小:500×500 * 方块大小:50×50 */ class GameField { public IntPtr winHandle; public Image bufferImage; //双缓存 public Block[,] blocks=new Block[10,10]; //场景中所有的小图片 //存储绘制的方块图案带代号的数组,不需绘制的值为0 private int[,] rectan2 = new int[10, 10]; private int[] empty = new int[10];//每列有多少个可以消去方块 private int RowSames = 1; //检测到同行相同数 private int ColumSames = 1; //检测到同列相同数 private SoundPlayer sound = new SoundPlayer(); public bool soundSwitch = true;//声音开关 true为开
游戏场景类GameField中生成场景中所有的Block方块对象,调用createAll画在游戏面板中
/*生成场景中所有的对象*/ public void createAll() { Random rand = new Random(); for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++) { Block b = new Block(rand.Next(8) + 1, j * 50, i * 50); blocks[i, j] = b; //rectan[i,j] = b.ImageType;//******************7-06 rectan2[i, j] = b.ImageType; } reDraw(); }
reDraw();采用双缓冲技术。先将所有的方块绘制在Image对象bufferImage上,然后将绘制好的bufferImage显示在游戏面板上.
exchange(int x1, int y1, int x2, int y2)交换选中两个相邻的方块
/*交换两个方块,参数x,y为矩阵坐标*/ public void exchange(int x1, int y1, int x2, int y2) { //交换blocks Block temp = blocks[x1, y1]; blocks[x1, y1] = blocks[x2, y2]; blocks[x2, y2] = temp; ////交换rectan //******************7-06 //rectan[x1, y1] = blocks[x1, y1].ImageType; //rectan[x2, y2] = blocks[x2, y2].ImageType; //交换rectan2 rectan2[x1, y1] = blocks[x1, y1].ImageType; rectan2[x2, y2] = blocks[x2, y2].ImageType; //交换坐标 Point tmploc = blocks[x1, y1].Location; blocks[x1, y1].Location = blocks[x2, y2].Location; blocks[x2, y2].Location = tmploc; PlaySound("Exchange"); //重画一下 reDraw(); }
check()完成检测是否有3上以上方块对象有相同的图像并返回可以消除的方块个数。
若有超过3个(含3个)则保存要绘制方块的图案代号的rectan2[10,10]数组对应元素的值为0,通过统计rectan2数组0值,
得出每列被消去方块的个数及所有列被消去方块的总线.
/*对对碰检测,返回可以消除方块对象的个数*/ public int check() { //检测是否同行或列有超过3个一样 for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { //for内开始 //行检测 if (j == 0) RowSames = 1; else { if (blocks[i, j - 1].ImageType == blocks[i, j].ImageType)//图案相同 RowSames++; else { if (RowSames >= 3) { //该位置之前rowsames个格子的物体都要消除 for (int n = 1; n <= RowSames; n++) rectan2[i, j - n] = 0; } RowSames = 1; } if (j==9&&RowSames >= 3) { //该位置之前rowsames个格子的物体都要消除 for (int n = 1; n <= RowSames; n++) rectan2[i, 10 - n] = 0; } } //列检测 if (j == 0) ColumSames = 1; else { if (blocks[j - 1, i].ImageType == blocks[j, i].ImageType)//图案相同 ColumSames++; else { if (ColumSames >= 3) { //该位置之上的columsames个格子的物体要消除 for (int n = 1; n <= ColumSames; n++) rectan2[j - n, i] = 0; } ColumSames = 1; } if (j==9&&ColumSames >= 3) { //该位置之前rowsames个格子的物体都要消除 for (int n = 1; n <= ColumSames; n++) rectan2[10 - n, i] = 0; } } //for内结束 } } RowSames = 1; ColumSames = 1; //检测每列有多少个空格 int temp=0; int result = 0;//总和 for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { if (rectan2[j, i] == 0) temp++; } empty[i] = temp; result += temp; temp = 0; } //reDraw(); return result; }
fill()从游戏屏幕该列上方重新随机产生新的方块,依次下移填充被削去的方块,重画需要绘制的所有方块
/*生成填补*/ public void fill() { Random rand = new Random(); for (int j = 0; j < 10;j++ ) //每列 { if(empty[j] > 0) { for (int i = 0; i < 10; i++) //每行 { while(rectan2[i, j] == 0) { if (i >0) {//空格之后的所有图片向下移一位 for (int n = i-1; n>=0; n--) down(n,j); } //填充最顶上一格方块 Block tb = new Block(rand.Next(8) + 1, j * 50,0 ); blocks[0, j] = tb; //rectan[0, j] = tb.ImageType; rectan2[0, j] = tb.ImageType; } } //本来想在这里重画,不料令游戏速度太慢 } } PlaySound("AddScore"); //重画一下 reDraw(); }