C# 实现俄罗斯方块
程序员文章站
2022-06-29 21:24:40
俄罗斯方块(Tetris)是一款由俄罗斯人阿列克谢·帕基特诺夫发明的休闲游戏,帕基特诺夫爱玩拼图,从拼图游戏里得到灵感,设计出了俄罗斯方块。由于上手简单、老少皆宜,从而家喻户晓,风靡世界。本文简述如何通过C#来实现俄罗斯方块,仅供学习分享使用,如有不足之处,还请指正。 ......
概述
俄罗斯方块(tetris)是一款由俄罗斯人阿列克谢·帕基特诺夫发明的休闲游戏,帕基特诺夫爱玩拼图,从拼图游戏里得到灵感,设计出了俄罗斯方块。由于上手简单、老少皆宜,从而家喻户晓,风靡世界。本文简述如何通过c#来实现俄罗斯方块,仅供学习分享使用,如有不足之处,还请指正。
涉及知识点
- backgroundworker 在单独的线程上执行操作(主要执行比较耗时的操作)。
- action .netframework自带的一个委托方法。
- tablelayoutpanel 表示一个面板,它可以在一个由行和列组成的网格中对其内容进行动态布局,本文主要用作俄罗斯方块的容器。
方块流程图
如下图所示,描述了俄罗斯方块的设计流程图
俄罗斯方块效果图
如下图所示:主要包括状态,得分,开始按钮,停止按钮,按键盘左右箭头移动等功能
核心代码
1. 定义方块的形状
如下所示:共7中形状
1 /// <summary> 2 /// 俄罗斯方块的形状 3 /// </summary> 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 /// <summary> 2 /// 俄罗斯方块移动方向 3 /// </summary> 4 public enum tetrisdirection 5 { 6 up = 0,//上,表示顺时针旋转 7 down = 1,//下,表示向下移动 8 left = 2,//左,表示往左移动 9 right = 3, //表示向右移动 10 default=4 //默认动作 11 }
3. 俄罗斯方块元素
如下所示,每一种形状都由四个方块组成,根据不同形状设置不同的位置
1 /// <summary> 2 /// 俄罗斯方块元素 3 /// </summary> 4 public class tetriselement 5 { 6 /// <summary> 7 /// 构造函数 8 /// </summary> 9 /// <param name="style"></param> 10 public tetriselement(tetrisstyle style) { 11 this.style = style; 12 } 13 14 /// <summary> 15 /// 构造函数 16 /// </summary> 17 /// <param name="style">形状</param> 18 /// <param name="content">内容</param> 19 /// <param name="location">位置</param> 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 /// <summary> 28 /// 元素字母类型 29 /// </summary> 30 public tetrisstyle style { get; set; } 31 32 /// <summary> 33 /// 内容 34 /// </summary> 35 public point[] content { get; set; } 36 37 /// <summary> 38 /// 元素位置 39 /// </summary> 40 public point location { get; set; } 41 44 /// <summary> 45 /// 位置改变 46 /// </summary> 47 /// <param name="x"></param> 48 /// <param name="y"></param> 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 /// <summary> 2 /// 俄罗斯方块容器 3 /// </summary> 4 public class tetriscontainer 5 { 6 private int[,] tetris = new int[10, 20];//定义二维数组,表示坐标信息,默认值为0 7 8 public action<point,point[],tetrisdirection> onpartialchanged;//局部变更事件 9 10 public action<int[,]> onfullchanged;//元素全变更事件,即有整行被清除事件 11 12 public action oncompleted; //结束事件 13 14 public int scorce = 0; 15 16 /// <summary> 17 /// 状态发生改变 18 /// </summary> 19 /// <param name="element"></param> 20 /// <param name="direction"></param> 21 /// <returns></returns> 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 < content.length; 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 /// <summary> 103 /// 更新tetris 104 /// </summary> 105 /// <param name="element"></param> 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 /// <summary> 124 /// 检查全部列 125 /// </summary> 126 private int[] checkalltetris() 127 { 128 list<int> lst = new list<int>(); 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 /// <summary> 155 /// 更新 156 /// </summary> 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 /// <summary> 176 /// 判断游戏是否结束 177 /// </summary> 178 /// <returns></returns> 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 /// <summary> 191 /// 更新得分 192 /// </summary> 193 /// <param name="s"></param> 194 public void updatescore(int s) { 195 this.scorce = this.scorce + s; 196 } 197 198 /// <summary> 199 /// 重置信息 200 /// </summary> 201 public void reset() { 202 this.tetris = new int[10, 20]; 203 this.scorce = 0; 204 } 205 }
5. 随机生成方块元素和起始位置
1 /// <summary> 2 /// 静态函数,生成tetris元素对象 3 /// </summary> 4 /// <returns></returns> 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) ? 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 }
备注
闲下来的时候,放一段柔情音乐,翻阅几页好书,然后睡个懒觉,快哉。
上一篇: 崇祯皇帝励精图治,为什么最后也逃不过亡国之君的下场?
下一篇: 海带炖排骨的功效,你知道多少呢?