转载请标明是引用于 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();
}