C# 实现俄罗斯方块(附源码)
程序员文章站
2022-04-29 14:32:58
概述俄罗斯方块(tetris)是一款由俄罗斯人阿列克谢·帕基特诺夫发明的休闲游戏,帕基特诺夫爱玩拼图,从拼图游戏里得到灵感,设计出了俄罗斯方块。由于上手简单、老少皆宜,从而家喻户晓,风靡世界。本文简述...
概述
俄罗斯方块(tetris)是一款由俄罗斯人阿列克谢·帕基特诺夫发明的休闲游戏,帕基特诺夫爱玩拼图,从拼图游戏里得到灵感,设计出了俄罗斯方块。由于上手简单、老少皆宜,从而家喻户晓,风靡世界。本文简述如何通过c#来实现俄罗斯方块,仅供学习分享使用,如有不足之处,还请指正。
涉及知识点
backgroundworker 在单独的线程上执行操作(主要执行比较耗时的操作)。
action .netframework自带的一个委托方法。
tablelayoutpanel 表示一个面板,它可以在一个由行和列组成的网格中对其内容进行动态布局,本文主要用作俄罗斯方块的容器。
方块流程图
如下图所示,描述了俄罗斯方块的设计流程图
俄罗斯方块效果图
如下图所示:主要包括状态,得分,开始按钮,停止按钮,按键盘左右箭头移动等功能
核心代码
1. 定义方块的形状
如下所示:共7中形状
/// <summary> /// 俄罗斯方块的形状 /// </summary> public enum tetrisstyle { s = 0, z = 1, l = 2, j = 3, i = 4, o = 5, t = 6 }
2. 定义移动的方向
如下所示:默认向下移动,同时可以左右移动
/// <summary> /// 俄罗斯方块移动方向 /// </summary> public enum tetrisdirection { up = 0,//上,表示顺时针旋转 down = 1,//下,表示向下移动 left = 2,//左,表示往左移动 right = 3, //表示向右移动 default=4 //默认动作 }
3. 俄罗斯方块元素
如下所示,每一种形状都由四个方块组成,根据不同形状设置不同的位置
/// <summary> /// 俄罗斯方块元素 /// </summary> public class tetriselement { /// <summary> /// 构造函数 /// </summary> /// <param name="style"></param> public tetriselement(tetrisstyle style) { this.style = style; } /// <summary> /// 构造函数 /// </summary> /// <param name="style">形状</param> /// <param name="content">内容</param> /// <param name="location">位置</param> public tetriselement(tetrisstyle style, point[] content, point location) { this.style = style; this.content = content; this.location = location; } /// <summary> /// 元素字母类型 /// </summary> public tetrisstyle style { get; set; } /// <summary> /// 内容 /// </summary> public point[] content { get; set; } /// <summary> /// 元素位置 /// </summary> public point location { get; set; } /// <summary> /// 位置改变 /// </summary> /// <param name="x"></param> /// <param name="y"></param> public void move(int x, int y) { this.location = new point(x, y); } public point[] getcontent(tetrisstyle style) { //内容由四个点组成,顺序:先上后下,先左后右 point[] content = new point[4]; switch (style) { case tetrisstyle.i: //i形状 content[0] = new point(0, 0); content[1] = new point(0, 1); content[2] = new point(0, 2); content[3] = new point(0, 3); break; case tetrisstyle.j: //j形状 content[0] = new point(1, 0); content[1] = new point(1, 1); content[2] = new point(1, 2); content[3] = new point(0, 2); break; case tetrisstyle.l: //l形状 content[0] = new point(0, 0); content[1] = new point(0, 1); content[2] = new point(0, 2); content[3] = new point(1, 2); break; case tetrisstyle.o: //o形状 content[0] = new point(0, 0); content[1] = new point(1, 0); content[2] = new point(0, 1); content[3] = new point(1, 1); break; case tetrisstyle.s: //s形状 content[0] = new point(2, 0); content[1] = new point(1, 0); content[2] = new point(1, 1); content[3] = new point(0, 1); break; case tetrisstyle.t: //t形状 content[0] = new point(0, 0); content[1] = new point(1, 0); content[2] = new point(2, 0); content[3] = new point(1, 1); break; case tetrisstyle.z: //z形状 content[0] = new point(0, 0); content[1] = new point(1, 0); content[2] = new point(1, 1); content[3] = new point(2, 1); break; default: //默认i content[0] = new point(0, 0); content[1] = new point(0, 1); content[2] = new point(0, 2); content[3] = new point(0, 3); break; } return content; } }
4. 容器类
如下所示:容器类主要是移动方块元素,并更新页面上的值
/// <summary> /// 俄罗斯方块容器 /// </summary> public class tetriscontainer { private int[,] tetris = new int[10, 20];//定义二维数组,表示坐标信息,默认值为0 public action<point,point[],tetrisdirection> onpartialchanged;//局部变更事件 public action<int[,]> onfullchanged;//元素全变更事件,即有整行被清除事件 public action oncompleted; //结束事件 public int scorce = 0; /// <summary> /// 状态发生改变 /// </summary> /// <param name="element"></param> /// <param name="direction"></param> /// <returns></returns> public tetriselement change(tetriselement element, tetrisdirection direction) { tetriselement tmp=null; //判断不同的方向 switch (direction) { case tetrisdirection.default: //如果可以向下移动 if (checkdefault(element)) { //向下移动一个元素 element.move(element.location.x, element.location.y + 1); tmp = element; } else { //如果不可以向下移动,则更新容器 updatetetris(element); tmp = null; } break; case tetrisdirection.down: break; case tetrisdirection.up: break; case tetrisdirection.left: if (checkleft(element)){ //判断是否可以向左移动 //向下移动一个元素 element.move(element.location.x-1, element.location.y); tmp = element; } break; case tetrisdirection.right: if (checkright(element)) { //判断是否可以右左移动 //向下移动一个元素 element.move(element.location.x+1, element.location.y); tmp = element; } break; } //局部变更 if (onpartialchanged != null) { point location = element.location; point[] content = new point[4]; element.content.copyto(content, 0); for (int i = 0; i < content.length; i++) { content[i].x = location.x + content[i].x; content[i].y = location.y + content[i].y; } onpartialchanged(location,content,direction); } //判断游戏是否结束 if (oncompleted != null) { if (checkcomplete()) { oncompleted(); } } //全部变更 if (onfullchanged != null) { //判断是是否有权为1的行,如果有则消掉 int[] rows = checkalltetris(); if (rows.length>0) { updatealltetris(rows);//消掉行 onfullchanged(tetris); } } return tmp; } /// <summary> /// 更新tetris /// </summary> /// <param name="element"></param> private void updatetetris(tetriselement element) { point location = element.location; point[] content = element.content; int minx = element.getminx(element.style); int maxx = element.getmaxx(element.style); int miny = element.getminy(element.style); int maxy = element.getmaxy(element.style); foreach (point p in content) { if (location.y + p.y < 20 && location.y + p.y >= 0 && location.x + p.x >= 0 && location.x + p.x < 10) { this.tetris[location.x + p.x, location.y + p.y] = 1; } } } /// <summary> /// 检查全部列 /// </summary> private int[] checkalltetris() { list<int> lst = new list<int>(); //20行 for (int y = 0; y < 20; y++) { int col = 0; //10列 for (int x = 0; x < 10; x++) { if (tetris[x, y] == 0) { break; } else { col += 1; } } if (col == 10) { col = 0; lst.add(y); } } return lst.toarray(); } /// <summary> /// 更新 /// </summary> private void updatealltetris(int[] rows) { foreach (int row in rows) { //当前行清掉 for (int x = 0; x < 10; x++) { tetris[x, row] = 0; } //row行之上的往下移动一行 for (int y = row-1; y >=0; y--) { for (int x = 0; x < 10; x++) { if (tetris[x, y] == 1) { tetris[x, y + 1] = 1; tetris[x, y] = 0; } } } } } /// <summary> /// 判断游戏是否结束 /// </summary> /// <returns></returns> private bool checkcomplete() { bool iscomplete = false; for (int i = 0; i < 10; i++) { if (tetris[i, 0] == 1) { iscomplete = true; break; } } return iscomplete; } /// <summary> /// 更新得分 /// </summary> /// <param name="s"></param> public void updatescore(int s) { this.scorce = this.scorce + s; } /// <summary> /// 重置信息 /// </summary> public void reset() { this.tetris = new int[10, 20]; this.scorce = 0; } }
5. 随机生成方块元素和起始位置
/// <summary> /// 静态函数,生成tetris元素对象 /// </summary> /// <returns></returns> public static tetriselement generate() { random r = new random(0); //随机生成形状 int tstyle = getrandom(); tstyle = tstyle % 7; tetrisstyle style = tetrisstyle.i; style = (tetrisstyle)enum.parse(typeof(tetrisstyle), tstyle.tostring()); //随机生成起始坐标 int x = getrandom(); x = x % 10; int y = 0; //根据形状生成位置信息 tetriselement element = new tetriselement(style); //内容由四个点组成,顺序:先上后下,先左后右 point[] content = element.getcontent(style); //获取最小坐标和最大坐标,防止越界 int minx = element.getminx(style); int miny = element.getminy(style); int maxx = element.getmaxx(style); int maxy = element.getmaxy(style); //修正起始坐标 x = (x <= minx) ? minx : x; x = (x >= maxx) ? maxx : x; y = miny; point location = new point(x, y); element.location = location; element.content = content; return element; }
备注
以上就是c# 实现俄罗斯方块(附源码)的详细内容,更多关于c# 实现俄罗斯方块的资料请关注其它相关文章!
推荐阅读
-
PHP在线调试执行的实现方法(附demo源码)
-
Android编程实现TextView垂直自动滚动功能【附demo源码下载】
-
Asp.net(C#)读取数据库并生成JS文件制作首页图片切换效果(附demo源码下载)
-
Android实现下载zip压缩文件并解压的方法(附源码)
-
超简单实现Android自定义Toast示例(附源码)
-
ASP.NET验证码实现(附源码)
-
Android编程实现手绘及保存为图片的方法(附demo源码下载)
-
asp.net实现非常实用的自定义页面基类(附源码)
-
Android编程之ICS式下拉菜单PopupWindow实现方法详解(附源码下载)
-
PHP+Ajax实现无刷新分页实例详解(附demo源码下载)