直接上代码:
using System; using System.Drawing; namespace Tetris_CS { /// @function 绘制基本方块形状图案 ///@auther ldd /// @create 2018.4.30 public class Shape { public Shape() { } public Shape(int index) { Create(index); } private Block[] blockList; private int indexDef; private Point ptPosition; private struct TETRIS { public int[,] def; public int size; } private static TETRIS[] tetrisDef; //设置所处位置的函数 相当于给所在坐标的位置赋值 //tetrisDef[0].def[1,0] = 1;代表给坐标1,0处代表要填充 至于这个1则换成别的数也行 //只要不是零均可 public static void InitTetrisDefine() { tetrisDef = new TETRIS[7]; tetrisDef[0].def = new int[4,4]; tetrisDef[0].def[1,0] = 1; // 0800 tetrisDef[0].def[1,1] = 1; // 0800 tetrisDef[0].def[1,2] = 1; // 0800 tetrisDef[0].def[1,3] = 1; // 0800 tetrisDef[0].size = 4; tetrisDef[1].def = new int[3,3]; tetrisDef[1].def[1,0] = 8; // 088 tetrisDef[1].def[1,1] = 8; // 080 tetrisDef[1].def[1,2] = 8; // 080 tetrisDef[1].def[2,0] = 8; tetrisDef[1].size = 3; tetrisDef[2].def = new int[3,3]; tetrisDef[2].def[1,0] = 8; // 880 tetrisDef[2].def[1,1] = 8; // 080 tetrisDef[2].def[1,2] = 8; // 080 tetrisDef[2].def[0,0] = 8; tetrisDef[2].size = 3; tetrisDef[3].def = new int[3,3]; tetrisDef[3].def[1,0] = 8; // 080 tetrisDef[3].def[0,1] = 8; // 888 tetrisDef[3].def[1,1] = 8; // 000 tetrisDef[3].def[2,1] = 8; tetrisDef[3].size = 3; tetrisDef[4].def = new int[3,3]; tetrisDef[4].def[0,0] = 8; // 880 tetrisDef[4].def[1,0] = 8; // 088 tetrisDef[4].def[1,1] = 8; // 000 tetrisDef[4].def[2,1] = 8; tetrisDef[4].size = 3; tetrisDef[5].def = new int[3,3]; tetrisDef[5].def[1,0] = 8; // 088 tetrisDef[5].def[2,0] = 8; // 880 tetrisDef[5].def[0,1] = 8; // 000 tetrisDef[5].def[1,1] = 8; tetrisDef[5].size = 3; tetrisDef[6].def = new int[2,2]; tetrisDef[6].def[0,0] = 8; // 88 tetrisDef[6].def[0,1] = 8; // 88 tetrisDef[6].def[1,0] = 8; tetrisDef[6].def[1,1] = 8; tetrisDef[6].size = 2; } //建立了一个块链表数组 public void Create(int index) { indexDef = index; blockList = new Block[4]; int count = 0; for (int i=0; i<tetrisDef[index].size; i++) { for (int j=0; j<tetrisDef[index].size; j++) { if (tetrisDef[index].def[i,j] != 0) { blockList[count] = new Block(index, i, j); count++; if (count > 4) return; } } } } public void Copy(Shape s) { ptPosition = s.Position; for (int i=0; i<4; i++) { blockList[i].Position = s.GetBlock(i).Position; } } public Point Position { get { return ptPosition; } set { ptPosition = value; } } public int IndexDef { get { return indexDef; } } public void Draw(Graphics g) { Draw(g, false); } //绘制图形,先绘制图形所在坐标位置 在绘制整个图形 public void Draw(Graphics g, Size sz) { Point pt = new Point((sz.Width - tetrisDef[indexDef].size * Block.Size) / 2, (sz.Height - tetrisDef[indexDef].size * Block.Size) / 2); for (int i=0; i<blockList.GetLength(0); i++) { blockList[i].Draw(g, pt, false); } } public void Draw(Graphics g, bool clear) { for (int i=0; i<blockList.GetLength(0); i++) { blockList[i].Draw(g, new Point(ptPosition.X * Block.Size, ptPosition.Y * Block.Size), clear); } } //旋转图形 public void Roate() { for (int i=0; i<blockList.GetLength(0); i++) { Point pt = blockList[i].Position; int temp = pt.X; pt.X = tetrisDef[indexDef].size - pt.Y - 1; pt.Y = temp; blockList[i].Position = pt; } } public Block GetBlock(int index) { return blockList[index]; } } }
using System; using System.Drawing; using System.Collections; namespace Tetris_CS { /// 移动旋转,底行胜利与否判断 主体功能实现 /// @create 5.1 public class Body { //建立body区域的长宽 初始化参数得 public Body() { maxWidth = 10; maxHeight = 15; } public enum MOVE_TYPE {MOVE_LEFT=0, MOVE_RIGHT=1, MOVE_DOWN=2, MOVE_FALL=3, MOVE_ROATE=4}; private ArrayList blockList = new ArrayList(); private Shape nextShape; private int maxWidth; private int maxHeight; public bool SetNextShape(Shape s) { nextShape = s; nextShape.Position = new Point(4, 0); bool ret = false; //* while (!ShapeCanPlace(nextShape)) { Point pt = nextShape.Position; pt.Y--; nextShape.Position = pt; ret = true; } //*/ return ret; } public void Draw(Graphics g) { DrawNextShape(g); for (int i=0; i<blockList.Count; i++) { ((Block)(blockList[i])).Draw(g); } } public bool MoveShape(Graphics g, MOVE_TYPE m) { Shape s = new Shape(nextShape.IndexDef); s.Copy(nextShape); Point pt = s.Position; switch (m) { case MOVE_TYPE.MOVE_FALL: { while (ShapeCanPlace(s)) { pt.Y++; s.Position = pt; } nextShape.Draw(g, true); pt.Y--; s.Position = pt; nextShape.Copy(s); nextShape.Draw(g); PlaceShape(); return true; //break; } case MOVE_TYPE.MOVE_DOWN: pt.Y++; break; case MOVE_TYPE.MOVE_LEFT: pt.X--; break; case MOVE_TYPE.MOVE_RIGHT: pt.X++; break; case MOVE_TYPE.MOVE_ROATE: s.Roate(); break; default: break; } s.Position = pt; if (ShapeCanPlace(s)) { nextShape.Draw(g, true); nextShape.Copy(s); nextShape.Draw(g); } else { if (m == MOVE_TYPE.MOVE_DOWN) { PlaceShape(); return true; } } return false; } //判断位置是否到底 public bool ShapeCanPlace(Shape s) { for (int i=0; i<4; i++) { Point pt = s.Position; Point ptOff = s.GetBlock(i).Position; pt.Offset(ptOff.X, ptOff.Y); if (PositionHasBlock(pt)) return false; } return true; } public bool PositionHasBlock(Point pt) { if (pt.Y < 0) return false; Rectangle rc = new Rectangle(0, 0, maxWidth, maxHeight); if (!rc.Contains(pt)) { return true; } for (int i=0; i<blockList.Count; i++) { if (((Block)(blockList[i])).Position == pt) { return true; } } return false; } public void PlaceShape() { for (int i=0; i<4; i++) { Point pt = nextShape.Position; Point ptOff = nextShape.GetBlock(i).Position; pt.Offset(ptOff.X, ptOff.Y); nextShape.GetBlock(i).Position = pt; blockList.Add(nextShape.GetBlock(i)); } } public void Reset() { blockList.Clear(); } //清行程序 把的填满的一行清除 首先判断是否存在一行中的空块 //存在的话则不能清除 反之 则清除 如果第i行清除 那么就把比i行少 //那些行自动沉下来一个 public int ClearLines() { int count = 0; for (int i=0; i<maxHeight; i++) { bool clear = true; for (int j=0; j<maxWidth; j++) { if (!PositionHasBlock(new Point(j, i))) { clear = false; break; } } if (clear) { for (int n=blockList.Count-1; n>=0; n--) { //如果第i行满了 则清除i行 if (((Block)(blockList[n])).Position.Y == i) { blockList.RemoveAt(n); } //其他的比i行小的那些行则自动沉下来 else if (((Block)(blockList[n])).Position.Y < i) { Point pt = ((Block)(blockList[n])).Position; pt.Y++; ((Block)(blockList[n])).Position = pt; } } count++; } } return count; } public void DrawNextShape(Graphics g) { nextShape.Draw(g); } } }
using System; using System.Drawing; namespace Tetris_CS { ///@verison 1.0.0 ///@function 方块绘制与颜色填充 ///@created 2018.4.30 public class Block { public Block() { } public Block(int index, Point pt) { colorIndex = index; ptPosition = pt; } public Block(int index, int x, int y) { colorIndex = index; ptPosition.X = x; ptPosition.Y = y; } // 颜色序号 private int colorIndex; // 位置 private Point ptPosition; // 方块大小 private static int size = 20; private static int COLOR_CHANGE = 60; //System.Drawing.Color表示ARGB颜色从指定的8位颜色值(红色,绿色,蓝色)中创建结构 //制定的默认alpha 默认为255 意为完全不透明 private static Color[] clrDefine = new Color[7]{ Color.FromArgb(51, 204, 102), // 绿 Default color, or extend block color Color.FromArgb(200, 200, 102), // 黄 Color.FromArgb(0, 143, 224), // 蓝 Color.FromArgb(153, 153, 204), // 青 Color.FromArgb(204, 204, 204), // 灰 Color.FromArgb(232, 123, 20), // 橙 Color.FromArgb(220, 39, 75) // 红 sample block color }; // 颜色 public int ColorIndex { get { return colorIndex; } set { colorIndex = value; } } public Point Position { get { return ptPosition; } set { ptPosition = value; } } //验证是否要绘图 如果clear为真 则要清除产生的块 因为方块产生了 //并且移动 必须把移动前一秒的块描成白色 public void Draw(Graphics g, Point ptStart, bool clear) { if (clear) { g.FillRectangle(new SolidBrush(Color.White), ptStart.X + (ptPosition.X * size), ptStart.Y + (ptPosition.Y * size), size, size); } else { g.FillRectangle(new SolidBrush(clrDefine[colorIndex]), ptStart.X + (ptPosition.X * size), ptStart.Y + (ptPosition.Y * size), size, size); //绘制四条边 两条亮色的边 两条暗色的边 使块的形状更加突出 g.DrawLine(new Pen(GetLightColor(colorIndex), 1), ptStart.X + (ptPosition.X * size), ptStart.Y + (ptPosition.Y * size), ptStart.X + (ptPosition.X * size) + size - 1, ptStart.Y + (ptPosition.Y * size)); g.DrawLine(new Pen(GetLightColor(colorIndex), 1), ptStart.X + (ptPosition.X * size), ptStart.Y + (ptPosition.Y * size), ptStart.X + (ptPosition.X * size), ptStart.Y + (ptPosition.Y * size) + size - 1); g.DrawLine(new Pen(GetDarkColor(colorIndex), 1), ptStart.X + (ptPosition.X * size) + size - 1, ptStart.Y + (ptPosition.Y * size) + size - 1, ptStart.X + (ptPosition.X * size) + size - 1, ptStart.Y + (ptPosition.Y * size)); g.DrawLine(new Pen(GetDarkColor(colorIndex), 1), ptStart.X + (ptPosition.X * size) + size - 1, ptStart.Y + (ptPosition.Y * size) + size - 1, ptStart.X + (ptPosition.X * size), ptStart.Y + (ptPosition.Y * size) + size - 1); } } public void Draw(Graphics g) { Draw(g, new Point(0, 0), false); } public static int Size { get { return size; } set { size = value; } } public static Color GetColor(int index) { return clrDefine[index]; } // GetDarkColor和GetLightColor的作用是添加亮边和暗边 // 使产生的模块具有立体感 Color GetDarkColor(int index) { int r = clrDefine[index].R; int g = clrDefine[index].G; int b = clrDefine[index].B; //将改变后的颜色alpha值与0做个比较 不能低于0 否则将超出界限 //如果小于0 则选0 否则选r-COLOR_CHANGE r = r-COLOR_CHANGE<0 ? 0 : r-COLOR_CHANGE; g = g-COLOR_CHANGE<0 ? 0 : g-COLOR_CHANGE; b = b-COLOR_CHANGE<0 ? 0 : b-COLOR_CHANGE; Color c = Color.FromArgb(r, g, b); return c; } Color GetLightColor(int index) { int r = clrDefine[index].R; int g = clrDefine[index].G; int b = clrDefine[index].B; //将改变后的颜色alpha值与255做个比较 不能高于255 否则将超出界限 //如果大于255 则选255 否则选r+COLOR_CHANGE r = r+COLOR_CHANGE>255 ? 255 : r+COLOR_CHANGE; g = g+COLOR_CHANGE>255 ? 255 : g+COLOR_CHANGE; b = b+COLOR_CHANGE>255 ? 255 : b+COLOR_CHANGE; Color c = Color.FromArgb(r, g, b); return c; } } }