【C++】对俄罗斯方块小程序的简单修改
1. 简介
本次作业的内容是找一个已有的软件项目,阅读分析,找出软件尚存的缺陷, 改进其软件做二次开发。我找到了一个简单的C++俄罗斯方块小程序,并为其添加一些功能。
原作者信息:
原作者文章:https://blog.csdn.net/m0_46480441/article/details/111976092
GitHub:https://github.com/maodeshu/c-work
2. 准备工作
首先要下载SFML多媒体库。这个程序使用的SFML版本是2.5.1 - Visual C++ 15 (2017) – 64位,再按照原文章中的步骤进行属性配置。不过,在我的电脑上,光是将bin文件夹中的所有.dll文件复制到项目的Debug文件夹中,程序仍无法运行。参照网上查找的方法将这些文件复制到C:\Windows\System32 和 C:\Windows\SysWOW64 后,程序才能正常运行。
此外,我还修改了原先的代码中的文件路径,使得后续不再需要因为上级文件夹的名称变动等事项而修改代码。
3. 功能添加
(1) 难度选择
一般来说一款游戏都会有难度选择系统,俄罗斯方块也不例外。我为程序新增了难度选择系统,分为三个等级。不同的难度有不同的收益,因此在不同难度下消除一行的得分也有所区别,分别为5分、10分和15分。
1 //各难度有不同的下降速度 2 const float SPEED_EASY = 0.5; 3 const float SPEED_NORMAL = 0.4; 4 const float SPEED_HARD= 0.3; 5 const float SPEED_QUICK = 0.05;//快速下降 6 float CURRENT_SPEED = SPEED_NORMAL;//玩家所选难度的速度 7 float delay = CURRENT_SPEED; 8 //各难度得分不同 9 const int SCORE_EASY = 5; 10 const int SCORE_NORMAL = 10; 11 const int SCORE_HARD = 15; 12 int CURRENT_SCORE = SCORE_NORMAL;
然后,在main函数中添加一个简单的难度选择界面:
1 /* 修改:添加难度选择 */ 2 int difficulty; 3 bool flag_difficulty = false; 4 cout << "请选择难度:\n1:简单\n2:普通\n3:困难" << endl; 5 while (flag_difficulty == false) 6 { 7 cin >> difficulty; 8 switch (difficulty) 9 { 10 case 1: 11 CURRENT_SPEED = SPEED_EASY; 12 CURRENT_SCORE = SCORE_EASY; 13 flag_difficulty = true; 14 break; 15 case 2: 16 CURRENT_SPEED = SPEED_NORMAL; 17 CURRENT_SCORE = SCORE_NORMAL; 18 flag_difficulty = true; 19 break; 20 case 3: 21 CURRENT_SPEED = SPEED_HARD; 22 CURRENT_SCORE = SCORE_HARD; 23 flag_difficulty = true; 24 break; 25 default: 26 cout << "无效选择,请重选。" << endl; 27 break; 28 } 29 }
同时对消除时的得分进行修改:
1 if (count < COL_COUNT) 2 { 3 k--;//拿去覆盖 4 } 5 else 6 { 7 score += CURRENT_SCORE; 8 sou.play();//放消除音效 9 }
这样,就完成了一个简单的难度系统。
下方可见选择简单难度时,消除了两行共获得10分。
(2) 旋转优化
原作者使用了check()函数来判断方块在移动后是否处于游戏区域内。这一函数在方块左右平移、方块落地、和方块旋转的函数中都有被调用。而在平移和旋转(doRotate()函数)
的操作中是这样使用check()的:
1 void doRotate() { 2 if (blockIndex == 7) { // 田字形,不需要旋转 3 return; 4 } 5 //备份当前方块,出问题再回退 6 for (int i = 0; i < 4; i++) { 7 bakBlock[i] = curBlock[i]; 8 } 9 10 Point p = curBlock[1]; //旋转中心 11 //a[i].x=p.x-a[i].y+p.x 12 //a[i].y=p.y+a[i].x-p.x; 13 for (int i = 0; i < 4; i++) 14 { 15 struct Point tmp = curBlock[i]; 16 curBlock[i].x = p.x - tmp.y + p.y; 17 curBlock[i].y = p.y + tmp.x - p.x; 18 } 19 if (!check()) { 20 for (int i = 0; i < 4; i++) { 21 curBlock[i] = bakBlock[i];//备份 22 } 23 } 24 }
在判断到方块在位置变化后会部分离开游戏区域时,会调用此前创建的方块备份,等同于无效掉玩家试图将方块移出游戏区域的操作。
但这样的使用方式有一个缺陷:当我们在游戏区域的边缘进行方块的旋转时,对于部分摆放方式的方块会出现按下旋转按键,但方块却不旋转的情况。对于俄罗斯方块来讲,在边缘无法旋转方块无疑是降低操作性和游戏体验的。我对旋转部分调用check()的部分做了优化,引入了rotateAdjuster()函数来解决这一问题:
1 void rotateAdjuster() {//防止因旋转后超过边界而导致旋转不生效的问题。 2 for (int i = 0; i < 4; i++) { 3 if (curBlock[i].x < 0 ) 4 { 5 for (int cx = 0; cx < 4; cx++) 6 { 7 ++curBlock[cx].x; 8 } 9 } 10 else if (curBlock[i].x >= COL_COUNT) 11 { 12 for (int cx = 0; cx < 4; cx++) 13 { 14 --curBlock[cx].x; 15 } 16 } 17 } 18 }
此外,还新增了checkLegit ()函数,将是否接触顶边或和现有方块重叠的判断拆分出来,在旋转部分单独判断,以防止不正常的旋转结果。
1 bool checkLegit() //检查是否接触顶边/重叠 2 { 3 for (int i = 0; i < 4; i++) { 4 if (curBlock[i].y <= 0 || table[curBlock[i].y][curBlock[i].x]) 5 { 6 return true; 7 } 8 } 9 return false; 10 }
修改后的doRotate()函数:
1 void doRotate() { 2 if (blockIndex == 7) { // 田字形,不需要旋转 3 return; 4 } 5 //备份当前方块,出问题再回退 6 for (int i = 0; i < 4; i++) { 7 bakBlock[i] = curBlock[i]; 8 } 9 10 Point p = curBlock[1]; //旋转中心 11 //a[i].x=p.x-a[i].y+p.x 12 //a[i].y=p.y+a[i].x-p.x; 13 for (int i = 0; i < 4; i++) 14 { 15 struct Point tmp = curBlock[i]; 16 curBlock[i].x = p.x - tmp.y + p.y; 17 curBlock[i].y = p.y + tmp.x - p.x; 18 } 19 if (!check()) { 20 rotateAdjuster(); 21 if (checkLegit()) 22 { 23 for (int i = 0; i < 4; i++) { 24 curBlock[i] = bakBlock[i];//备份 25 } 26 } 27 } 28 }
修改后效果:
4. 总结
以上就是我对这一开源的俄罗斯方块小程序做的二次开发。通过源代码和游玩,我找到了一个可改善事项和一个问题:
(1)游戏可以设置难度分级
(2)方块位于区域侧边时,无法旋转方块
当然,这一程序还可进行一些改进,例如为其添加下一个下落的方块的预览图。这次实践,我主要是为了探索与思考寻找软件缺陷与尝试二次开发的流程。在这一过程中,我锻炼了自己解决问题和设计功能的能力。
修改后的项目文件:https://wwqu.lanzoum.com/i8qMe0pkc4xa
posted on 2023-03-08 00:49 BadPiggy1024 阅读(412) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理