200行C++代码写一个Qt俄罗斯方块小游戏
小小演示一下:

大体思路:
其实很早就想写一个俄罗斯方块了,但是一想到那么多方块还要变形,还要判断落地什么的就脑壳疼。直到现在才写出来。
俄罗斯方块这个小游戏的小难点其实就一个,就是方块的变形,看似每个方块的变形都不一样,找不到共同点,实现起来比较麻烦,不过只要有了思路其实还是可以的。
方块变形:
俄罗斯方块实际上是只有五种(其中有两种“L”形和“Z”形每种有两种对称的)。
每个方块以及变形的样子我都放下面了。


咋一看好像看不出共同点,不过也确实没有啥共同点,实际上我们不需要有共同点,我们只需要知道每个方块变形都是怎么变的。
上面看不出来我们再换个形式。


我们知道,方块变形的本质实际上是旋转,而旋转我们是绕着某个中心点去旋转的,因此我们只需要记录每个方块的中心点以及不同形态时的每个小方块对于中心点的相对位置。
除了正方形怎么变形都一样,其他方块的变形情况都在下面,中心点我加重了颜色。




可以看得出来,方块的每个小方块的位置都可以通过与中心点的相对坐标来获取。
要变换姿势的时候,只要有中心点的坐标,就可以切换姿势。
下面是不同方块不同姿势的不同小方块与中心点的相对位置关系,套了个四维数组写起来好费劲:
//第一层选择方块种类,第二层选择方块形态,第三层装小方块,//第四层装每个小方块对于中心点坐标的相对位置用于变换姿势vector<vector<vector<vector<int>>>>mode{{{{1,0},{1,1},{0,0},{0,1}}}, //方形{{{2,0},{1,0},{0,0},{-1,0}},{{0,-1},{0,0},{0,1},{0,2}}}, //长条形{{{1,0},{1,-1},{0,-1},{-1,-1}},{{1,-1},{1,0},{1,1},{0,1}}, //L形1{{1,1},{0,1},{-1,1},{-1,0}},{{0,-1},{-1,-1},{-1,0},{-1,1}}},{{{1,0},{1,1},{0,1},{-1,1}},{{1,-1},{1,1},{1,0},{0,-1}}, //L形2{{0,1},{-1,0},{-1,1},{-1,-1}},{{1,-1},{0,-1},{-1,-1},{-1,0}}},{{{1,0},{0,0},{0,1},{-1,0}},{{0,-1},{0,0},{0,1},{-1,0}}, //凸形{{1,0},{0,0},{0,-1},{-1,0}},{{1,0},{0,0},{0,-1},{0,1}}},{{{1,-1},{0,-1},{0,0},{-1,0}},{{1,0},{1,1},{0,0},{0,-1}}}, //Z形1{{{1,1},{0,0},{0,1},{-1,0}},{{1,-1},{1,0},{0,0},{0,1}}} //Z形2};
下面是换姿势的代码:
其中 whichOne是选择哪一种方块,index是选择方块的哪一种姿势
//切换模式
vector<vector<int>> block::changeMode(){if (whichOne == 0) return coordinate;vector<vector<int>>res;index++;index %= (mode[whichOne].size());for (auto& m : mode[whichOne][index]) {//根据中心坐标和缓存的模式关系来获取切换模式之后的方块坐标res.push_back({ center[0] - m[0],center[1] - m[1] });}//没有直接切换,而是返回新坐标return res;
}
在获取新姿势的小方块坐标之后没有马上更新,而是返回出去了,因为可能变形之后会不符合要求,例如下面的例子:

变形之后把返回的新坐标返回,我们再用一个函数去检测新坐标是否合法,合法再去修改当前方块的具体坐标,检测函数也很简单:
//检测移动是否合法
int Tetris::checkMove(vector<vector<int>>temp){for (auto& c : temp) {if (c[1] < 0 || c[1] >= 10) return -1; //左右越界返回-1;if (cache[c[0]][c[1]] == 1) return 0; //遇到落地方块返回0;}//一切合法返回1return 1;
}
返回1就是移动合法,我们修改坐标,返回-1就是移动不合法,我们什么也不改。
还剩一个返回-1,就是移动后遇到了已经落地的方块,这时候在调用这个检测函数的函数之中还需要做个判断。
如果是因此下落而造成的移动,那么检测获取-1则将方块的坐标的位置更新对应在缓存中的位置为1,然后生成新方块。
而其他情况,例如是左右移动或是变换姿势而造成的碰到落地方块则是和-1一样不做处理。
否则会有这样的问题:

落地判断:
用Qt来绘图,我向来都是用二维数组来缓存界面,然后通过相应的位置的不同元素来绘制不同的图案。
在这个俄罗斯方块中,我的写法是缓存中的元素一共只有两种情况,0和1,0表示什么都没有,不需要绘制,而1表示已经落地的方块。
那么正在下落的方块呢,缓存里不用存一下吗。我的做法是不需要,等等会说明原因。
因此我们正在下落的方块的坐标我是拿另一个二维数组存起来的。
每次下落时只需要做个判断,我们正在下落的方块之中,只要有一个小方块在下落之后在缓存中对应的位置元素为1,就表示接触到了已经落地的方块,那么当前方块也会变成他们的一部分,然后更新缓存,并且重新生成新的方块。


这里有个小问题,就是在游戏的一开始缓存是全为0的,还没有落地的方块,因此我们上述的判断在游戏的一开始不会触发,解法有两种,一种是多一层判断,如果方块最下面的小方块已经到了界面最下面的地方(对应缓存中的下标为0),那么也算落地。
第二种解法是我的做法,就是直接在缓存下标为0的位置先给铺一层落地的方块也就是1。


消除检测:
消除检测很容易,界面缓存中的元素只有0或1,分别用来表示什么都没有以及已经落地的方块,如果缓存中有一行的元素之和等于10,那么就表示本行塞满了,可以消除。
缓存中下标为0的行在最下面,也就是下标越大,代表的位置就在界面的越上方。
如果检测到了某一行可以消除,那么我们可以直接把这一行从缓存之中直接删除,然后从缓存的尾部再添加上一个长度为10,元素为0的数组即可。
关于消除还有最后一个问题,那就是一个方块落下,可能消除的不止一行,因此我们像上述那样操作,应该从下标较大的地方开始往下标较小的地方遍历寻找,否则可能会漏掉。
并且我们可以想象的到,一个方块落地之后,如果可以消除,那么可以消除的那一行方块一定是在刚落地方块所在的行,因此每次检测的时候,我们只需要检测落地方块的每个小方块所在的行即可。
//检测是否能清除一行方块
void Tetris::clearBlocks(){set<int>s;vector<int>v;//获取方块的y轴,因为能清除方块的话,行数一定在方块的y轴之中for (auto& c : curBlock.coordinate) {if (accumulate(cache[c[0]].begin(), cache[c[0]].end(), 0) == 10) s.insert(c[0]);}//从大到小去清除一整行的界面缓存for (int i : s) v.insert(v.begin(), i);for (int i : v) {score++; //得分增加//删除一行方块后再后面补上一行.cache.erase(cache.begin() + i);cache.push_back(vector<int>(10, 0));}
}
代码获取:
完整的项目文件我已经上传到了CSDN,可以直接免费下载,也可以关注我的公众号“折途想要敲代码”回复关键词“qt俄罗斯方块”免费获取、
相关文章:
200行C++代码写一个Qt俄罗斯方块小游戏
小小演示一下: 大体思路: 其实很早就想写一个俄罗斯方块了,但是一想到那么多方块还要变形,还要判断落地什么的就脑壳疼。直到现在才写出来。 俄罗斯方块这个小游戏的小难点其实就一个,就是方块的变形,看似…...
蓝桥杯每日一题20223.9.26
4407. 扫雷 - AcWing题库 题目描述 分析 此题目使用map等都会超时,所以我们可以巧妙的使用哈希模拟散列表,哈希表初始化为-1首先将地雷读入哈希表,找到地雷的坐标在哈希表中对应的下标,如果没有则此地雷的位置第一次出现&#…...
查看基站后台信息
查看基站后台信息 电脑配置固定ip: 192.168.1.99: 打开“网络和共享中心”,选择更改适配器设置: 右键“本地连接”,选择属性 基站网线直连电脑网口 Telnet 登录基站 打开dos窗口 windows键R”,输入cmd,点确定&…...
关于坐标的旋转变换和坐标系的旋转变换
不管是坐标的旋转变换还是坐标系下的旋转变换,只和旋转的顺时针和逆时针有关。然坐标系间的顺时针和逆时针是根据当前坐标系在目标坐标系下的相对位置确定。 一。逆时针旋转belta角度的公式 二。顺时针旋转belta角度的公式 三。坐标的旋转变换 1.坐标的旋转变换相…...
2023.9.19 关于 数据链路层 和 DNS 协议 基本知识
目录 数据链路层 MTU DNS 协议 补充 DHCP协议 数据链路层 基本概念: 考虑相邻两个节点之间的传输(通过 网线 / 光纤 / 无线 直接相连的两个设备)以太网协议 规定了 数据链路层 和 物理层 的内容 IP地址 与 mac地址 的相互配合 IP地址 描…...
如何保证接口幂等性
简介 接口幂等性就是说用户使用相同的参数请求同一个接口无论是一次还是多次都应该是一样的。不会因为多次的点击产生不同效果。 举个栗子:一个用户在手机APP上提200块钱,然后一不小心点击了两次,那么就应该只提取出200块钱,不应…...
搭建智能桥梁,Amazon CodeWhisperer助您轻松编程
零:前言 随着时间的推移,人工智能技术以惊人的速度向前发展,正掀起着全新的编程范式革命。不仅仅局限于代码生成,智能编程助手等创新应用也进一步提升了开发效率和代码质量,极大地推动着软件开发领域的快速繁荣。 当前…...
数组和指针笔试题解析之【指针】
目录 🍂笔试题1: 🍂笔试题2: 🍂笔试题3: 🍂笔试题4: 🍂笔试题5: 🍂笔试题6: 🍂笔试题7: 🍂笔试题…...
【Linux】之Centos7卸载KVM虚拟化服务
👨🎓博主简介 🏅云计算领域优质创作者 🏅华为云开发者社区专家博主 🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支…...
智能电力运维系统:数字化转型在电力行业的关键应用
随着信息技术、人工智能等的飞速发展,数字化改造已成为各行各业的重要发展趋势。在电力行业中,智能电力运维系统是数字化转型的关键应用之一。 力安科技智能电力运维系统是一种集自动化、智能化、云计算、物联网等先进技术于一体的电力运维管理解决方…...
eslint报错:no-empty-source
问题: 提交代码时,eslint校验没有通过,报错 esc[2m183:9esc[22m esc[31mesc[31m✖esc[39m Unexpected empty source esc[2mno-empty-sourceesc[22m 1 problem (esc[31m1 erroresc[39m, esc[33m0 warnings esc[39m) 原因: …...
图论17(Leetcode864.获取所有钥匙的最短路径)
用二进制表示获得的钥匙,假设n钥匙个数 000000000代表没有钥匙,0000000001代表有idx为1的钥匙,0000000011代表有idx1,2的钥匙 (这方法巧妙又复杂.. 代码: class Solution {static int[][] dirs {{-1,0}…...
vue 脚手架 入门 记录
vue 脚手架 入门 记录 以管理员身份运行PowerShell执行:get-ExecutionPolicy,回复Restricted,表示状态是禁止的 3.执行:set-ExecutionPolicy RemoteSigned 4.选择Y 注意:一定要以管理员的身份运行PowerShellÿ…...
汽车租赁系统演示租车小程序H5开发
一款适合汽车租赁业务的程序系统,支持在线支付、一键续租、在线签名。 为了方便用户端方便租车和查看已租车辆的信息和费用,支持上门取车和到店取车两种模式,支持待付款、待取车、待还车、订单管理、已完成、全部订单等订单状态查看和处理功…...
【MySQL】 MySQL 更新数据机制
MySQL 更新数据机制 一、问题描述 假设我们有这样一张表,且包含一条记录: CREATE TABLE mytest ( id int(11) NOT NULL, c1 int(11) DEFAULT NULL, c2 int(11) DEFAULT NULL, c3 int(11) DEFAULT NULL, PRIMARY KEY (id), KEY c1 (c1), KEY c2 (c2) 包…...
批次管理在MES管理系统中有哪些应用
在制造企业中,批次管理是一项至关重要的管理方法,它贯穿于企业的整个生产过程中。特别是在流程制造行业中,如药品、食品等行业,批次管理显得尤为重要。这些行业的产品通常需要进行严格的质量控制和追踪,以便在问题发生…...
python命名规范
一、概述 以前写python代码没有个代码,写出的代码一点也不规范 二、命名规范 2.1类的命名规范 总是使用首字母大写单词串。如MyClass、ClassName。内部类可以使用额外的前导下划线。 2.2函数和方法的命名规范 小写下划线,如method_name。 2.3函数…...
Redis学习笔记--002
Redis的JAVA客户端 文章目录 Redis的JAVA客户端一、Redis的Java客户端的种类二、Jedis2.1、使用步骤2.2、Jedis连接池 三、[SpringDataRedis](https://spring.io/projects/spring-data-redis)3.1、介绍3.2、RedisTemplate3.3、SpringDataRedis使用步骤3.4、SpringDataRedis的序…...
Visual Stdio 2019 win10 64bit下 无法找到 资源编译器DLL,请确认路径是否正确,和无法下载 win10SDK_10.0
上面的2个原因 第一个原因是因为安装时候,漏掉勾选 vistual stdio sdk 和 windows 通用c运行时 其中的一项目 第2个原因是没有安装 sdk...
设计模式:中介者模式(C++实现)
在中介者模式中,中介者对象负责协调多个对象之间的交互,将对象之间的耦合度降低。 #include <iostream> #include <string> #include <vector>class Colleague;// 中介者接口 class Mediator { public:virtual void sendMessage(Coll…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
