标签:als mic 容器 span art tab 代码 开始 键盘
概述
俄罗斯方块(Tetris)是一款由俄罗斯人阿列克谢·帕基特诺夫发明的休闲游戏,帕基特诺夫爱玩拼图,从拼图游戏里得到灵感,设计出了俄罗斯方块。由于上手简单、老少皆宜,从而家喻户晓,风靡世界。本文简述如何通过C#来实现俄罗斯方块,仅供学习分享使用,如有不足之处,还请指正。
涉及知识点
- BackgroundWorker 在单独的线程上执行操作(主要执行比较耗时的操作)。
- Action .NetFramework自带的一个委托方法。
- TableLayoutPanel 表示一个面板,它可以在一个由行和列组成的网格中对其内容进行动态布局,本文主要用作俄罗斯方块的容器。
方块流程图
如下图所示,描述了俄罗斯方块的设计流程图
俄罗斯方块效果图
如下图所示:主要包括状态,得分,开始按钮,停止按钮,按键盘左右箭头移动等功能
核心代码
1. 定义方块的形状
如下所示:共7中形状
1 ///
2 /// 俄罗斯方块的形状
3 ///
4 public enum TetrisStyle
5 {
6 S = 0,
7 Z = 1,
8 L = 2,
9 J = 3,
10 I = 4,
11 O = 5,
12 T = 6
13 }
2. 定义移动的方向
如下所示:默认向下移动,同时可以左右移动
1 ///
2 /// 俄罗斯方块移动方向
3 ///
4 public enum TetrisDirection
5 {
6 UP = 0,//上,表示顺时针旋转
7 DOWN = 1,//下,表示向下移动
8 LEFT = 2,//左,表示往左移动
9 RIGHT = 3, //表示向右移动
10 DEFAULT=4 //默认动作
11 }
3. 俄罗斯方块元素
如下所示,每一种形状都由四个方块组成,根据不同形状设置不同的位置
1 ///
2 /// 俄罗斯方块元素
3 ///
4 public class TetrisElement
5 {
6 ///
7 /// 构造函数
8 ///
9 ///
10 public TetrisElement(TetrisStyle style) {
11 this.style = style;
12 }
13
14 ///
15 /// 构造函数
16 ///
17 /// 形状
18 /// 内容
19 /// 位置
20 public TetrisElement(TetrisStyle style, Point[] content, Point location)
21 {
22 this.style = style;
23 this.content = content;
24 this.location = location;
25 }
26
27 ///
28 /// 元素字母类型
29 ///
30 public TetrisStyle style { get; set; }
31
32 ///
33 /// 内容
34 ///
35 public Point[] content { get; set; }
36
37 ///
38 /// 元素位置
39 ///
40 public Point location { get; set; }
41
44 ///
45 /// 位置改变
46 ///
47 ///
48 ///
49 public void move(int x, int y)
50 {
51 this.location = new Point(x, y);
52 }
53
54 public Point[] getContent(TetrisStyle style)
55 {
56 //内容由四个点组成,顺序:先上后下,先左后右
57 Point[] content = new Point[4];
58 switch (style)
59 {
60 case TetrisStyle.I:
61 //I形状
62 content[0] = new Point(0, 0);
63 content[1] = new Point(0, 1);
64 content[2] = new Point(0, 2);
65 content[3] = new Point(0, 3);
66 break;
67 case TetrisStyle.J:
68 //J形状
69 content[0] = new Point(1, 0);
70 content[1] = new Point(1, 1);
71 content[2] = new Point(1, 2);
72 content[3] = new Point(0, 2);
73 break;
74 case TetrisStyle.L:
75 //L形状
76 content[0] = new Point(0, 0);
77 content[1] = new Point(0, 1);
78 content[2] = new Point(0, 2);
79 content[3] = new Point(1, 2);
80 break;
81 case TetrisStyle.O:
82 //O形状
83 content[0] = new Point(0, 0);
84 content[1] = new Point(1, 0);
85 content[2] = new Point(0, 1);
86 content[3] = new Point(1, 1);
87 break;
88 case TetrisStyle.S:
89 //S形状
90 content[0] = new Point(2, 0);
91 content[1] = new Point(1, 0);
92 content[2] = new Point(1, 1);
93 content[3] = new Point(0, 1);
94 break;
95 case TetrisStyle.T:
96 //T形状
97 content[0] = new Point(0, 0);
98 content[1] = new Point(1, 0);
99 content[2] = new Point(2, 0);
100 content[3] = new Point(1, 1);
101 break;
102 case TetrisStyle.Z:
103 //Z形状
104 content[0] = new Point(0, 0);
105 content[1] = new Point(1, 0);
106 content[2] = new Point(1, 1);
107 content[3] = new Point(2, 1);
108 break;
109 default:
110 //默认I
111 content[0] = new Point(0, 0);
112 content[1] = new Point(0, 1);
113 content[2] = new Point(0, 2);
114 content[3] = new Point(0, 3);
115 break;
116 }
117 return content;
118 }
119 }
4. 容器类
如下所示:容器类主要是移动方块元素,并更新页面上的值
1 ///
2 /// 俄罗斯方块容器
3 ///
4 public class TetrisContainer
5 {
6 private int[,] tetris = new int[10, 20];//定义二维数组,表示坐标信息,默认值为0
7
8 public Action onPartialChanged;//局部变更事件
9
10 public Actionint[,]> onFullChanged;//元素全变更事件,即有整行被清除事件
11
12 public Action onCompleted; //结束事件
13
14 public int scorce = 0;
15
16 ///
17 /// 状态发生改变
18 ///
19 ///
20 ///
21 ///
22 public TetrisElement change(TetrisElement element, TetrisDirection direction)
23 {
24 TetrisElement tmp=null;
25 //判断不同的方向
26 switch (direction) {
27 case TetrisDirection.DEFAULT:
28 //如果可以向下移动
29 if (checkDefault(element))
30 {
31 //向下移动一个元素
32 element.move(element.location.X, element.location.Y + 1);
33 tmp = element;
34 }
35 else {
36 //如果不可以向下移动,则更新容器
37 updateTetris(element);
38 tmp = null;
39 }
40
41 break;
42 case TetrisDirection.DOWN:
43 break;
44 case TetrisDirection.UP:
45 break;
46 case TetrisDirection.LEFT:
47 if (checkLeft(element)){
48 //判断是否可以向左移动
49 //向下移动一个元素
50 element.move(element.location.X-1, element.location.Y);
51 tmp = element;
52 }
53 break;
54 case TetrisDirection.RIGHT:
55 if (checkRight(element))
56 {
57 //判断是否可以右左移动
58 //向下移动一个元素
59 element.move(element.location.X+1, element.location.Y);
60 tmp = element;
61 }
62 break;
63 }
64
65 //局部变更
66 if (onPartialChanged != null)
67 {
68 Point location = element.location;
69 Point[] content = new Point[4];
70 element.content.CopyTo(content, 0);
71
72 for (int i = 0; i )
73 {
74 content[i].X = location.X + content[i].X;
75 content[i].Y = location.Y + content[i].Y;
76 }
77 onPartialChanged(location,content,direction);
78 }
79
80 //判断游戏是否结束
81 if (onCompleted != null) {
82 if (checkComplete()) {
83 onCompleted();
84 }
85 }
86
87 //全部变更
88 if (onFullChanged != null)
89 {
90 //判断是是否有权为1的行,如果有则消掉
91 int[] rows = checkAllTetris();
92 if (rows.Length>0)
93 {
94 updateAllTetris(rows);//消掉行
95 onFullChanged(tetris);
96 }
97 }
98
99 return tmp;
100 }
101
102 ///
103 /// 更新tetris
104 ///
105 ///
106 private void updateTetris(TetrisElement element)
107 {
108 Point location = element.location;
109 Point[] content = element.content;
110 int minX = element.getMinX(element.style);
111 int maxX = element.getMaxX(element.style);
112 int minY = element.getMinY(element.style);
113 int maxY = element.getMaxY(element.style);
114 foreach (Point p in content)
115 {
116 if (location.Y + p.Y 20 && location.Y + p.Y >= 0 && location.X + p.X >= 0 && location.X + p.X 10)
117 {
118 this.tetris[location.X + p.X, location.Y + p.Y] = 1;
119 }
120 }
121 }
122
123 ///
124 /// 检查全部列
125 ///
126 private int[] checkAllTetris()
127 {
128 Listint> lst = new Listint>();
129 //20行
130 for (int y = 0; y 20; y++)
131 {
132 int col = 0;
133 //10列
134 for (int x = 0; x 10; x++)
135 {
136 if (tetris[x, y] == 0)
137 {
138 break;
139 }
140 else
141 {
142 col += 1;
143 }
144 }
145 if (col == 10)
146 {
147 col = 0;
148 lst.Add(y);
149 }
150 }
151 return lst.ToArray();
152 }
153
154 ///
155 /// 更新
156 ///
157 private void updateAllTetris(int[] rows) {
158 foreach (int row in rows) {
159 //当前行清掉
160 for (int x = 0; x 10; x++) {
161 tetris[x, row] = 0;
162 }
163 //row行之上的往下移动一行
164 for (int y = row-1; y >=0; y--) {
165 for (int x = 0; x 10; x++) {
166 if (tetris[x, y] == 1) {
167 tetris[x, y + 1] = 1;
168 tetris[x, y] = 0;
169 }
170 }
171 }
172 }
173 }
174
175 ///
176 /// 判断游戏是否结束
177 ///
178 ///
179 private bool checkComplete() {
180 bool isComplete = false;
181 for (int i = 0; i 10; i++) {
182 if (tetris[i, 0] == 1) {
183 isComplete = true;
184 break;
185 }
186 }
187 return isComplete;
188 }
189
190 ///
191 /// 更新得分
192 ///
193 ///
194 public void updateScore(int s) {
195 this.scorce = this.scorce + s;
196 }
197
198 ///
199 /// 重置信息
200 ///
201 public void Reset() {
202 this.tetris = new int[10, 20];
203 this.scorce = 0;
204 }
205 }
5. 随机生成方块元素和起始位置
1 ///
2 /// 静态函数,生成Tetris元素对象
3 ///
4 ///
5 public static TetrisElement generate()
6 {
7 Random r = new Random(0);
8 //随机生成形状
9 int tstyle = getRandom();
10 tstyle = tstyle % 7;
11 TetrisStyle style = TetrisStyle.I;
12 style = (TetrisStyle)Enum.Parse(typeof(TetrisStyle), tstyle.ToString());
13 //随机生成起始坐标
14 int x = getRandom();
15 x = x % 10;
16 int y = 0;
17 //根据形状生成位置信息
18 TetrisElement element = new TetrisElement(style);
19 //内容由四个点组成,顺序:先上后下,先左后右
20 Point[] content = element.getContent(style);
21 //获取最小坐标和最大坐标,防止越界
22 int minX = element.getMinX(style);
23 int minY = element.getMinY(style);
24 int maxX = element.getMaxX(style);
25 int maxY = element.getMaxY(style);
26 //修正起始坐标
27 x = (x minX : x;
28 x = (x >= maxX) ? maxX : x;
29 y = minY;
30 Point location = new Point(x, y);
31 element.location = location;
32 element.content = content;
33 return element;
34 }
备注
闲下来的时候,放一段柔情音乐,翻阅几页好书,然后睡个懒觉,快哉。
C# 实现俄罗斯方块
标签:als mic 容器 span art tab 代码 开始 键盘
原文地址:https://www.cnblogs.com/hsiang/p/11415810.html