俄罗斯方块源码解析(带下载)[3]
准备工作都做好了,关键部分“原理”也说了,该干点事了吧
该主调程序 game类出场的时候了,
不得不说的是,首先对于编程的人来说 不管你高手也好 菜鸟也好。
对于你要做的事 目标要明确,你要做什么。
怎么做 先做什么 后做什么,什么情况为“完成”,什么情况为“失败”
这才是一个正常的 程序员应该有的思维,作为一个程序员 我们就是要看透事情的本质。
流程图就免了吧 直接给伪代码得了(其实这是真代码^_^ ,莫打我):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public void go() //主调方法 表示 1 step 如果游戏没结束则继续 如此往复直到游戏结束 { if (downCheck()) //如果有下落空间 { down(); //下落操作 } else //如果到底了 或者 跟其他shape接触 { merge(); //把 “卡住”的方块 “印”到画布(容器gameArea)中去,意思就是把卡住的方块“堆”到游戏区 if (!isOver) //如果游戏没有结束(判断依据为方块是否已经堆积到容器的顶端) 重新实例化一个shape 让他down下来 { shape s = new shape(); int pindx = 0; for ( int i = 0; i < s.transform.GetLength(0); i++) { for ( int j = 0; j < s.transform.GetLength(1); j++) { if (s.transform[i, j] == true ) { sh[pindx++] = new Point(j, i); } } } } } setScore(); //在重新实例化之前先检查 gameArea 看是否有可消除的行 并计算得分 } |
下面是一些具体的东西,比如左移操作啊,落下的动作 啊,判断是否有可消除的行啊,具体实现就看你了 也许你实现的方式 或者算法比我更好,希望分享。
以下是我实现的方式
开始游戏:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public void start() //开始一个游戏 包括初始化gameArea 等 { area = new gameArea(); shape s = new shape(); int pindx = 0; for ( int i = 0; i < s.transform.GetLength(0); i++) { for ( int j = 0; j < s.transform.GetLength(1); j++) { if (s.transform[i, j] == true ) { sh[pindx++] = new Point(j, i); } } } } |
移动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | gameArea area; //容器(存放堆积起来的方块) Point[] sh = new Point[4]; //下落中的方块(每个方块最多只能由四个点组成) enum direction { left, right, down }; void move(direction dir) //移动 { switch (dir) { case direction.left: { bool can = true ; if (sh != null ) foreach (Point p in sh) { if (p.X <=0) { can = false ; break ; } } if (can) { for ( int i = 0; i < sh.Length; i++) sh[i].X--; } break ; } case direction.right: { bool can = true ; if (sh!= null ) foreach (Point p in sh) { if (p.X >= gameArea.width - 1) { can = false ; break ; } } if (can) { for ( int i = 0; i < sh.Length; i++) sh[i].X++; } break ; } case direction.down: { for ( int i = 0; i < sh.Length; i++) sh[i].Y++; break ; } } } |
判断方块是否卡住:
1 2 3 4 5 6 7 8 9 10 11 | bool downCheck() //进行边界检查 比如到底了 或者跟其他shape接触,跟容器中对应的方块比较 看是否产生“边界接触 { foreach (Point p in sh) { if (p.Y >= gameArea.height - 1) return false ; if (area.gameAreaArray[p.Y + 1, p.X] == true ) return false ; } return true ; } |
判断游戏是否结束:
1 2 3 4 5 6 7 8 9 10 11 12 | public bool isOver { //通知外部程序 你y挂了(判断是否已经堆积到gameArea的顶端) get { for ( int j = 0; j < area.gameAreaArray.GetLength(1); j++) { if (area.gameAreaArray[0, j] == true ) return true ; } return false ; } } |
把已经卡住的“方块” “堆”到容器中的方法 ,同志们可能想的比较复杂 。实际上超简单 ,就是把容器中跟方块对应的数组元素(也可以说是坐标吧)改成true就OK了
意为把 卡住方块的像素“写”到容器中去。
just so so
1 2 3 4 5 | void merge() //合并 跟边界产生接触 把shape添加到画布中来 { foreach (Point p in sh) area.gameAreaArray[p.Y, p.X] = true ; } |
怎么样超简单吧 ^_^
终于写了这么多 好累,下一章我将讲一下 查找“图像轮廓”,跟“顺时针旋转”的算法。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Vue3封装支持Base64导出的电子签名组件
· 万字长文详解Text-to-SQL
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)