关 键 词:
俄罗斯
基本实现了大部分功能 没有加时钟控件,所以方块不能自行下降.没有计分器
主要精力放在功能实现及结构上 希望有高手能指点下不足之下.
全部源码如下
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
namespace WindowsApplication2
{
public class MainRun
{
public static void Main()
{
Form1 f=new Form1();
f.Width=309;
f.Height=485;
Application.Run(f);
}
}
public partial class Form1 : Form
{
public Form1()
{
Csh(); //程序初始化
}
TxPaint tx; //自定义图形绘制类
void Csh()
{
this.BackColor = Color.AliceBlue;
tx = new TxPaint(new txfactory(),this.BackColor); //初始化 图形工厂
tx.CreateTx();
}
protected override void OnPaint(PaintEventArgs e)
{
tx.Paint(CreateGraphics());
}
protected override void OnKeyDown(KeyEventArgs e)
{
Rectangle re = new Rectangle(0, 0, this.Width, this.Height);
tx.KeyEvent(e,re);
//tx.Paint(this.CreateGraphics());
}
}
/// <summary>
/// 抽象图形类
/// </summary>
public abstract class TxClass
{
public Rectangle[] r; //储存图形
public SolidBrush blueBrush; //储存颜色
/// <summary>
/// 图形绘制
/// </summary>
/// <param name="gg">传入需绘制的Graphics</param>
public void paint(Graphics gg)
{
Pen rPen = new Pen(Color.Black);
Graphics g = gg;
g.DrawRectangles(rPen, r);
for (int i = 0; i < r.Length; i++)
{
r[i].Inflate(-1, -1);
}
g.FillRectangles(blueBrush, r);
for (int i = 0; i < r.Length; i++)
{
r[i].Inflate(1, 1);
}
}
/// <summary>
/// 键盘点击事件
/// </summary>
/// <param name="e">键盘点击值</param>
/// <param name="MoveRe">积木图形移动范围</param>
public void KeyEvent(KeyEventArgs e,Rectangle MoveRe)
{
#region 键盘的 上 下 左 右 点击事件
int intkey = e.KeyValue;
// 下
if (intkey == 83 || intkey == 40)
{
//if (GetMax_Y() + 90 < MoveRe.Height) //将往下移动限制范围取消,以便于落底时 左右移动的判断
//{
for (int i = 0; i < r.Length; i++)
{
r[i].Offset(0, 30);
}
//}
}
//// 上
if (intkey == 87 || intkey == 38)
{
for (int i = 0; i < r.Length; i++)
{
r[i].Offset(0, -30);
}
}
// 左
if (intkey == 65 || intkey == 37)
{
if (GetMix_X() - 30 > 0 || GetMix_X() - 30 == 0)
{
for (int i = 0; i < r.Length; i++)
{
r[i].Offset(-30, 0);
}
}
}
//右
if (intkey == 68 || intkey == 39)
{
if (GetMax_X() + 60 < MoveRe.Width)
{
for (int i = 0; i < r.Length; i++)
{
r[i].Offset(30, 0);
}
}
}
#endregion
if (intkey == 74 || intkey == 97)
{
BX(MoveRe);
}
}
/// <summary>
/// 变形
/// </summary>
public abstract void BX(Rectangle re);
/// <summary>
/// 获取最大X坐标
/// </summary>
/// <returns></returns>
public int GetMax_X()
{
int itemp = r[0].X;
for (int i = 0; i < r.Length - 1 ; i++)
{
if (itemp < r[i + 1].X)
{
itemp = r[i + 1].X;
}
}
return itemp;
}
/// <summary>
/// 获取最小X坐标
/// </summary>
/// <returns></returns>
public int GetMix_X()
{
int itemp = r[0].X;
for (int i = 0; i < r.Length - 1; i++)
{
if (itemp > r[i + 1].X)
{
itemp = r[i + 1].X;
}
}
return itemp;
}
/// <summary>
/// 获取最大Y坐标
/// </summary>
/// <returns></returns>
public int GetMax_Y()
{
int itemp = r[0].Y;
for (int i = 0; i < r.Length - 1; i++)
{
if (itemp < r[i + 1].Y)
{
itemp = r[i + 1].Y;
}
}
return itemp;
}
/// <summary>
/// 克隆
/// </summary>
/// <param name="T">传入对象数据类型</param>
/// <returns></returns>
public TxClass Clone(Type T)
{
TxClass TempTxClass = (TxClass)Activator.CreateInstance(T);
for (int i = 0; i < r.Length; i++)
{
//TempTxClass.r[i].Height = r[i].Height;
//TempTxClass.r[i].Width = r[i].Width;
//TempTxClass.r[i].X = r[i].X;
//TempTxClass.r[i].Y = r[i].Y;
TempTxClass.r[i] = r[i]; // Rectangle 为结构 值类型
}
TempTxClass.blueBrush = blueBrush;
return TempTxClass;
}
}
/// <summary>
/// 派生类
/// </summary>
public class TxLong : TxClass
{
public TxLong()
{
Size s = new Size(30, 30);
Point po = new Point(120, -120);
Rectangle re0 = new Rectangle(po, s);
po.Y = -90;
Rectangle re1 = new Rectangle(po, s);
po.Y = -60;
Rectangle re2 = new Rectangle(po, s);
po.Y = -30;
Rectangle re3 = new Rectangle(po, s);
po.Y = 0;
Rectangle re4 = new Rectangle(po, s);
r = new Rectangle[] { re0, re1, re2, re3, re4 };
blueBrush = new SolidBrush(Color.Yellow);
}
public override void BX(Rectangle re)
{
if (r[0].X == r[1].X && r[1].Y > 0)
{
if (r[0].X - 30 > 0 && r[4].X + 90 < re.Width)
{
r[0].Location = new Point(r[2].X - 60, r[2].Y);
r[1].Location = new Point(r[2].X - 30, r[2].Y);
r[2].Location = new Point(r[2].X, r[2].Y);
r[3].Location = new Point(r[2].X + 30, r[2].Y);
r[4].Location = new Point(r[2].X + 60, r[2].Y);
}
}
else
{
if (r[4].Y + 120 < re.Height)
{
r[0].Location = new Point(r[2].X, r[2].Y - 60);
r[1].Location = new Point(r[2].X, r[2].Y - 30);
r[2].Location = new Point(r[2].X, r[2].Y);
r[3].Location = new Point(r[2].X, r[2].Y + 30);
r[4].Location = new Point(r[2].X, r[2].Y + 60);
//MessageBox.Show(string.Format("{0} {1}", r[4].Y, re.Height));
}
}
}
}
/// <summary>
/// 派生类 long
/// </summary>
public class TxBox : TxClass
{
public TxBox()
{
Size s = new Size(30, 30);
Point po = new Point(90, -30);
Rectangle re0 = new Rectangle(po, s);
po.X = 120;
Rectangle re1 = new Rectangle(po, s);
po.X = 90;
po.Y = 0;
Rectangle re2 = new Rectangle(po, s);
po.X = 120;
Rectangle re3 = new Rectangle(po, s);
r = new Rectangle[] { re0, re1, re2, re3 };
blueBrush = new SolidBrush(Color.Moccasin);
}
public override void BX(Rectangle re)
{
}
}
/// <summary>
/// 派生类 Z
/// </summary>
public class TxZ : TxClass
{
public TxZ()
{
Size s = new Size(30, 30);
Point po = new Point(90, -30);
Rectangle re0 = new Rectangle(po, s);
po.X = 120;
Rectangle re1 = new Rectangle(po, s);
po.Y = 0;
Rectangle re2 = new Rectangle(po, s);
po.X = 150;
Rectangle re3 = new Rectangle(po, s);
r = new Rectangle[] { re0, re1, re2, re3 };
blueBrush = new SolidBrush(Color.PaleGoldenrod);
}
public override void BX(Rectangle re)
{
if (r[2].Y == r[3].Y)
{
//if (r[0].X + 30 > 0)
//{
r[2].Location = new Point(r[2].X - 30, r[2].Y);
r[3].Location = new Point(r[3].X - 30, r[3].Y - 60);
//}
}
else
{
if (r[0].X + 90 < re.Width)
{
r[2].Location = new Point(r[2].X + 30, r[2].Y);
r[3].Location = new Point(r[3].X + 30, r[3].Y + 60);
}
}
}
}
/// <summary>
/// 派生类 S
/// </summary>
public class TxS : TxClass
{
public TxS()
{
Size s = new Size(30, 30);
Point po = new Point(120, -30);
Rectangle re0 = new Rectangle(po, s);
po.X = 150;
Rectangle re1 = new Rectangle(po, s);
po.Y = 0;
po.X = 90;
Rectangle re2 = new Rectangle(po, s);
po.X = 120;
Rectangle re3 = new Rectangle(po, s);
r = new Rectangle[] { re0, re1, re2, re3 };
blueBrush = new SolidBrush(Color.Aqua);
}
public override void BX(Rectangle re)
{
if (r[2].Y == r[3].Y)
{
//if (r[0].X + 30 > 0)
//{
r[2].Location = new Point(r[2].X + 30, r[2].Y - 60);
r[3].Location = new Point(r[3].X + 30, r[3].Y);
//}
}
else
{
if (r[2].X - 30 > 0 || r[2].X - 30 == 0)
{
r[2].Location = new Point(r[2].X - 30, r[2].Y + 60);
r[3].Location = new Point(r[3].X - 30, r[3].Y);
}
}
}
}
/// <summary>
/// 派生类 L
/// </summary>
public class TxL : TxClass
{
public TxL()
{
Size s = new Size(30, 30);
Point po = new Point(120, -30);
Rectangle re0 = new Rectangle(po, s);
po.Y = 0;
Rectangle re1 = new Rectangle(po, s);
po.X = 150;
Rectangle re2 = new Rectangle(po, s);
po.X = 180;
Rectangle re3 = new Rectangle(po, s);
po.X = 210;
Rectangle re4 = new Rectangle(po, s);
r = new Rectangle[] { re0, re1, re2, re3, re4 };
blueBrush = new SolidBrush(Color.BurlyWood);
}
public override void BX(Rectangle re)
{
if (r[0].X == r[1].X && r[0].X < r[4].X)
{
if (r[4].Y + 120 < re.Height || r[4].Y + 60 == re.Height) //下 限制
{
r[0].Location = new Point(r[0].X + 30, r[0].Y);
r[1].Location = new Point(r[1].X, r[1].Y - 30);
r[2].Location = new Point(r[2].X - 30, r[2].Y);
r[3].Location = new Point(r[3].X - 60, r[3].Y + 30);
r[4].Location = new Point(r[4].X - 90, r[4].Y + 60);
}
}
else if (r[0].Y == r[1].Y && r[0].Y < r[4].Y)
{
if (r[1].X > 0 && r[0].X + 50 < re.Width) //左右 限制
{
r[0].Location = new Point(r[0].X + 30, r[0].Y + 30);
r[1].Location = new Point(r[1].X + 60, r[1].Y);
r[2].Location = new Point(r[2].X + 30, r[2].Y - 30);
r[3].Location = new Point(r[3].X, r[3].Y - 60);
r[4].Location = new Point(r[4].X - 30, r[4].Y - 90);
}
}
else if (r[0].X == r[1].X && r[0].X > r[4].X)
{
if (r[0].Y + 90 < re.Height || r[0].Y + 90 == re.Height) //下 限制
{
r[0].Location = new Point(r[0].X - 60, r[0].Y + 30);
r[1].Location = new Point(r[1].X - 30, r[1].Y + 60);
r[2].Location = new Point(r[2].X, r[2].Y + 30);
r[3].Location = new Point(r[3].X + 30, r[3].Y);
r[4].Location = new Point(r[4].X + 60, r[4].Y - 30);
}
}
else if (r[0].Y == r[1].Y && r[0].Y > r[4].Y)
{
if (r[4].X + 90 < re.Width || r[4].X + 90 == re.Width) //右 限制
{
r[0].Location = new Point(r[0].X, r[0].Y - 60);
r[1].Location = new Point(r[1].X - 30, r[1].Y - 30);
r[2].Location = new Point(r[2].X, r[2].Y);
r[3].Location = new Point(r[3].X + 30, r[3].Y + 30);
r[4].Location = new Point(r[4].X + 60, r[4].Y + 60);
}
}
}
}
/// <summary>
/// 图形工厂
/// </summary>
abstract class AbstractTxFactory
{
abstract public TxClass CreateTx();
}
/// <summary>
/// 工厂类
/// </summary>
class txfactory : AbstractTxFactory
{
/// <summary>
/// 随机生成一个图形类实例
/// </summary>
/// <returns></returns>
public override TxClass CreateTx()
{
//return new TxL();
Random ran = new Random();
switch (ran.Next(5))
{
case 0:
return new TxLong();
//break;
case 1:
return new TxBox();
//break;
case 2:
return new TxZ();
//reak;
case 3:
return new TxS();
case 4:
return new TxL();
default :
return null;
//break;
}
}
}
/// <summary>
/// 图形绘制类
/// </summary>
class TxPaint
{
List<TxClass> LTx;
TxClass tx;
AbstractTxFactory txCreate; //创建工厂
Graphics graphics; //用于储存当前图形活动区域
Color color; //储存背景色
/// <summary>
/// 构造函数
/// </summary>
/// <param name="txCreate">图形生成工厂</param>
/// <param name="graphics">绘制图形</param>
/// <param name="color">擦除颜色</param>
public TxPaint(AbstractTxFactory txCreate,Color color)
{
this.txCreate = txCreate;
this.color = color;
LTx = new List<TxClass>();
}
/// <summary>
/// 创建一个新图形
/// </summary>
public void CreateTx()
{
tx = txCreate.CreateTx();
}
/// <summary>
/// 重新绘制图形
/// </summary>
/// <param name="graphics"></param>
public void Paint(Graphics graphics)
{
this.graphics = graphics;
foreach (TxClass t in LTx)
{
t.paint(graphics);
}
SetupGraphics();
tx.paint(graphics);
}
/// <summary>
/// 键盘点击事件
/// </summary>
public void KeyEvent(KeyEventArgs k, Rectangle re)
{
TxClass tempTxC = tx.Clone(tx.GetType());
tx.KeyEvent(k, re);
if (TxPd()) //如果有重叠现象则恢复上次位置(下降 或 变形)
{
tx = tempTxC;
if (k.KeyValue == 83 || k.KeyValue == 40) //往下按键时 碰到其他图形时
{
ClsTx(re); //消除满条图形,并重新创建新积本
}
}
else if (tx.GetMax_Y() > re.Height - 60) //往下按键时 到底部时
{
tx = tempTxC;
graphics.Clear(color); //清除当前活动图形
tx.paint(graphics); //重绘活动图形新坐标位
ClsTx(re);
}
else
{
graphics.Clear(color);
tx.paint(graphics);
}
}
/// <summary>
/// 图形重叠判断
/// </summary>
/// <returns>是/否</returns>
bool TxPd()
{
List<Rectangle> l = new List<Rectangle>();
foreach (TxClass Lt in LTx)
{
foreach (Rectangle Lr in Lt.r)
{
l.Add(Lr);
}
}
foreach (Rectangle r in tx.r)
{
if (l.Contains(r))
{
return true;
}
}
return false;
}
/// <summary>
/// 满条图形消除
/// </summary>
void ClsTx(Rectangle re)
{
LTx.Add(tx);
CreateTx();
if (TxPd()) //创建的同时发生图形重叠则 game over
{
GameOver(re);
}
else
{
#region 图形满格消除
for (int i = 0; i < LTx.Count; i++)
{
for (int j = 0; j < LTx[i].r.Length; j++) //双层循环挨个取出 每个TxClass 下的单个Rectangle
{
int PointY = GetSumX_Y(LTx[i].r[j], re); //调用函数返回满条的 y坐标
if (PointY != 0)
{
foreach (TxClass tc in LTx) //双循环将其 y 坐标相同的注销 小于y坐标的加30 下降
{
for (int k = 0; k < tc.r.Length; k++)
{
if (tc.r[k].Y == PointY)
{
tc.r[k] = Rectangle.Empty;
}
else if (tc.r[k].Y < PointY && tc.r[k] != Rectangle.Empty)
{
tc.r[k].Y += 30;
}
}
}
}
}
}
graphics.Clip = new Region(re);
graphics.Clear(color);
Paint(graphics);
#endregion
#region 清除 LTx 下空的 TxClass 派生类
for (int i = 0; i < LTx.Count; i++)
{
int j;
for (j = 0; j < LTx[i].r.Length; j++)
{
if (LTx[i].r[j] != Rectangle.Empty)
{
break;
}
}
if (j == LTx[i].r.Length)
{
LTx.RemoveAt(i);
}
}
#endregion
SetupGraphics();
}
}
/// <summary>
/// 游戏结束标志
/// </summary>
/// <param name="re"></param>
void GameOver(Rectangle re)
{
graphics.Clip = new Region(re);
Font font = new Font( new FontFamily( System.Drawing.Text.GenericFontFamilies.SansSerif), 50, FontStyle.Bold, GraphicsUnit.Pixel);
StringFormat strformat = new StringFormat();
strformat.Alignment = StringAlignment.Center;
strformat.LineAlignment = StringAlignment.Center;
//strformat.FormatFlags = StringFormatFlags.DirectionVertical;
graphics.DrawString("game over", font, Brushes.DarkSlateBlue, re.Width / 2, re.Height / 2, strformat);
LTx.Clear();
}
/// <summary>
/// 返回满条图形Y坐标
/// </summary>
/// <param name="r">单个txclass 的单个box</param>
/// <param name="re">当前绘制范围</param>
/// <returns></returns>
int GetSumX_Y(Rectangle r,Rectangle re)
{
int tempSum = 0;
for (int i = 0; i < LTx.Count; i++)
{
for (int j = 0; j < LTx[i].r.Length; j++)
{
if (LTx[i].r[j].Y == r.Y)
{
tempSum++;
if (tempSum == (re.Width / 30))
{
return r.Y;
}
}
}
}
return 0;
}
/// <summary>
/// 对当前图形活动区域进行重新设定
/// </summary>
void SetupGraphics()
{
for (int i = 0; i < LTx.Count; i++)
{
for (int j = 0; j < LTx[i].r.Length; j++)
{
LTx[i].r[j].Inflate(1, 1);
graphics.ExcludeClip(LTx[i].r[j]);
LTx[i].r[j].Inflate(-1, -1);
}
}
}
}
}
控制台下 csc 编译下就可以了

