新手练习项目 4:简易2048游戏的实现(C++)
名人说:莫听穿林打叶声,何妨吟啸且徐行。—— 苏轼《定风波·莫听穿林打叶声》
Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder)
目录
- 一、效果图
- 二、代码(带注释)
- 三、说明
一、效果图

二、代码(带注释)
//创作者:Code_流苏(CSDN)
//未经允许,禁止转载发布,可自己学习使用
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>using namespace std;const int SIZE = 4; // 定义游戏板的大小为4x4// 初始化游戏板
void initializeBoard(vector<vector<int>>& board) {board.assign(SIZE, vector<int>(SIZE, 0)); // 将游戏板初始化为SIZE x SIZE的0矩阵// 在游戏板上随机生成两个数字2board[rand() % SIZE][rand() % SIZE] = 2;board[rand() % SIZE][rand() % SIZE] = 2;
}// 打印游戏板
void printBoard(const vector<vector<int>>& board) {for (int i = 0; i < SIZE; ++i) {for (int j = 0; j < SIZE; ++j) {if(board[i][j] == 0) cout << ".";else cout << board[i][j];cout << "\t";}cout << endl;}
}// 检查是否还有可移动的格子
bool canMove(const vector<vector<int>>& board) {for (int i = 0; i < SIZE; ++i) {for (int j = 0; j < SIZE; ++j) {// 如果有空格或者有相邻的相同数字,则可以移动if (board[i][j] == 0) return true;if (i < SIZE - 1 && board[i][j] == board[i + 1][j]) return true;if (j < SIZE - 1 && board[i][j] == board[i][j + 1]) return true;}}return false;
}// 在随机位置添加一个数字2或4
void addNumber(vector<vector<int>>& board) {int i, j;do {i = rand() % SIZE;j = rand() % SIZE;} while (board[i][j] != 0); // 选择一个空的格子board[i][j] = (rand() % 10 == 0) ? 4 : 2; // 有10%的概率生成4,90%的概率生成2
}// 旋转游戏板
void rotateBoard(vector<vector<int>>& board) {vector<vector<int>> temp(SIZE, vector<int>(SIZE));for (int i = 0; i < SIZE; ++i) {for (int j = 0; j < SIZE; ++j) {temp[j][SIZE - 1 - i] = board[i][j]; // 旋转90度}}board = temp;
}// 向左移动格子并合并
void moveTiles(vector<vector<int>>& board) {for (int i = 0; i < SIZE; ++i) {int lastMergePosition = -1; for (int j = 1; j < SIZE; ++j) {if (board[i][j] == 0) continue; // 如果当前格子为空,则跳过int previousPosition = j - 1;// 寻找可以合并或移动的位置while (previousPosition > lastMergePosition && board[i][previousPosition] == 0) {previousPosition--;}if (previousPosition == j) continue; // 如果没有可移动或合并的位置,继续下一个格子// 根据情况移动或合并格子if (board[i][previousPosition] == 0) {board[i][previousPosition] = board[i][j];board[i][j] = 0;} else if (board[i][previousPosition] == board[i][j]) {board[i][previousPosition] *= 2;board[i][j] = 0;lastMergePosition = previousPosition;} else if (previousPosition + 1 != j) {board[i][previousPosition + 1] = board[i][j];board[i][j] = 0;}}}
}// 定义不同方向的移动
void moveLeft(vector<vector<int>>& board) {moveTiles(board);
}void moveRight(vector<vector<int>>& board) {rotateBoard(board);rotateBoard(board);moveTiles(board);rotateBoard(board);rotateBoard(board);
}void moveUp(vector<vector<int>>& board) {rotateBoard(board);rotateBoard(board);rotateBoard(board);moveTiles(board);rotateBoard(board);
}void moveDown(vector<vector<int>>& board) {rotateBoard(board);moveTiles(board);rotateBoard(board);rotateBoard(board);rotateBoard(board);
}// 主函数
int main() {srand(time(NULL)); // 设置随机种子vector<vector<int>> board;initializeBoard(board); // 初始化游戏板printBoard(board); // 打印游戏板while (true) {if (!canMove(board)) {cout << "游戏结束!" << endl;break;}char input;cout << "选择方向 (w/a/s/d): ";cin >> input; // 获取用户输入switch (input) {case 'a':moveLeft(board);break;case 'd':moveRight(board);break;case 'w':moveUp(board);break;case 's':moveDown(board);break;default:cout << "无效输入! 请使用 w/a/s/d." << endl;continue;}if (canMove(board)) {addNumber(board); // 在合适位置添加新的数字}printBoard(board); // 打印更新后的游戏板}return 0;
}
三、说明
上述代码实现了一个简单的2048游戏,主要由以下几个部分组成:
-
初始化游戏板 (
initializeBoard函数):用于初始化一个SIZE x SIZE(在这个例子中是4x4)的游戏板,并随机在两个位置放置数字2。 -
打印游戏板 (
printBoard函数):该函数用于遍历游戏板并打印每个元素,其中0被替换为.以便于观看。 -
检查是否可以移动 (
canMove函数):这个函数用来检查游戏板上是否还有可合并的元素或者空位,以决定游戏是否结束。 -
添加数字 (
addNumber函数):在玩家移动之后,在一个随机的空位置上添加一个新的数字(90%的概率是2,10%的概率是4)。 -
旋转游戏板 (
rotateBoard函数):为了简化移动逻辑,此函数用来将游戏板顺时针旋转90度。 -
移动方块 (
moveTiles函数):该函数用于处理实际的方块移动和合并逻辑。 -
移动方向 (
moveLeft,moveRight,moveUp,moveDown函数):这些函数使用moveTiles和rotateBoard来处理不同方向的移动。 -
主函数 (
main函数):设置游戏的初始状态,然后进入一个循环,等待玩家输入来移动方块,直到没有移动可做时结束游戏。
补充说明:
- 游戏板的大小是通过
const int SIZE = 4预设的,即方格大小为4x4。 - 游戏开始时,游戏板上有两个数字2。
- 玩家可以通过输入’w’, ‘a’, ‘s’, 'd’来控制方块向上、左、下、右移动。
- 当游戏板上没有空位或者没有可合并的相邻方块时,游戏结束。
- 这个程序没有实现计分功能,可自己扩充实现。
Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder)
点赞加关注,收藏不迷路!本篇文章对你有帮助的话,还请多多点赞支持!
相关文章:
新手练习项目 4:简易2048游戏的实现(C++)
名人说:莫听穿林打叶声,何妨吟啸且徐行。—— 苏轼《定风波莫听穿林打叶声》 Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder) 目录 一、效果图二、代码(带注释)三、说明 一、效果图 二、代码(带…...
2023年度总结:技术沉淀、持续学习
2023年度总结:技术沉淀、持续学习 一、引言 今年是我毕业的第二个年头,也是完整的一年,到了做年终总结的时候了 这一年谈了女朋友,学习了不少技术,是充实且美好的一年! 首先先看年初定的小目标…...
Unity 利用UGUI之Slider制作进度条
在Unity中使用Slider和Text组件可以制作简单的进度条。 首先在场景中右键->UI->Slider,新建一个Slider组件: 同样方法新建一个Text组件,最终如图: 创建一个进度模拟脚本,Slider_Progressbar.cs using System.C…...
OCS2 入门教程(四)- 机器人示例
系列文章目录 前言 OCS2 包含多个机器人示例。我们在此简要讨论每个示例的主要特点。 System State Dim. Input Dim. Constrained Caching Double Integrator 2 1 No No Cartpole 4 1 Yes No Ballbot 10 3 No No Quadrotor 12 4 No No Mobile Manipul…...
FreeRTOS学习第6篇–任务状态挂起恢复删除等操作
目录 FreeRTOS学习第6篇--任务状态挂起恢复删除等操作任务的状态设计实验IRReceiver_Task任务相关代码片段实验现象本文中使用的测试工程 FreeRTOS学习第6篇–任务状态挂起恢复删除等操作 本文目标:学习与使用FreeRTOS中的几项操作,有挂起恢复删除等操作…...
BLE Mesh蓝牙组网技术详细解析之Access Layer访问层(六)
目录 一、什么是BLE Mesh Access Layer访问层? 二、Access payload 2.1 Opcode 三、Access layer behavior 3.1 Access layer发送消息的流程 3.2 Access layer接收消息的流程 3.3 Unacknowledged and acknowledged messages 3.3.1 Unacknowledged message …...
Netlink 通信机制
文章目录 前言一、Netlink 介绍二、示例代码参考资料 前言 一、Netlink 介绍 Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口。 在Linux 内核中,使用netlink 进行应用与内核通信的应用有…...
2024.1.8每日一题
LeetCode 回旋镖的数量 447. 回旋镖的数量 - 力扣(LeetCode) 题目描述 给定平面上 n 对 互不相同 的点 points ,其中 points[i] [xi, yi] 。回旋镖 是由点 (i, j, k) 表示的元组 ,其中 i 和 j 之间的距离和 i 和 k 之间的欧式…...
看了致远OA的表单设计后的思考
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码: https://gitee.com/nbacheng/n…...
mmdetection训练自己的数据集
mmdetection训练自己的数据集 这里写目录标题 mmdetection训练自己的数据集一: 环境搭建二:数据集格式转换(yolo转coco格式)yolo数据集格式coco数据集格式yolo转coco数据集格式yolo转coco数据集格式的代码 三: 训练dataset数据文件配置config…...
MySQL取出N列里最大or最小的一个数据
如题,现在有3列,都是数字类型,要取出这3列里最大或最小的的一个数字 -- N列取最小 SELECT LEAST(temperature_a,temperature_b,temperature_c) min FROM infrared_heat-- N列取最大 SELECT GREATEST(temperature_a,temperature_b,temperat…...
编写.NET的Dockerfile文件构建镜像
创建一个WebApi项目,并且创建一个Dockerfile空文件,添加以下代码,7.0代表的你项目使用的SDK的版本,构建的时候也需要选择好指定的镜像tag FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443F…...
【C语言】浙大版C语言程序设计(第三版) 练习7-4 找出不是两个数组共有的元素
前言 最近在学习浙大版的《C语言程序设计》(第三版)教材,同步在PTA平台上做对应的练习题。这道练习题花了比较长的时间,于是就写篇博文记录一下我的算法和代码。 2024.01.03 题目 练习7-4 找出不是两个数组共有的元素 作者 张彤…...
7.27 SpringBoot项目实战 之 整合Swagger
文章目录 前言一、Maven依赖二、编写Swagger配置类三、编写接口配置3.1 控制器Controller 配置描述3.2 接口API 配置描述3.3 参数配置描述3.4 忽略API四、全局参数配置五、启用增强功能六、调试前言 在我们实现了那么多API以后,进入前后端联调阶段,需要给前端同学提供接口文…...
创建第一个SpringMVC项目,入手必看!
文章目录 创建第一个SpringMVC项目,入手必看!1、新建一个maven空项目,在pom.xml中设置打包为war之前,右击项目添加web框架2、如果点击右键没有添加框架或者右击进去后没有web框架,点击左上角file然后进入项目结构在模块…...
go 切片长度与容量的区别
切片的声明 切片可以看成是数组的引用(实际上切片的底层数据结构确实是数组)。在 Go 中,每个数组的大小是固定的,不能随意改变大小,切片可以为数组提供动态增长和缩小的需求,但其本身并不存储任何数据。 …...
回归和分类区别
回归任务(Regression): 特点: 输出是连续值,通常是实数。任务目标是预测或估计一个数值。典型应用包括房价预测、销售额预测、温度预测等。 目标: 最小化预测值与真实值之间的差异,通常使用…...
docker nginx滚动日志配置
将所有日志打印到控制台 nginx.conf user nginx; worker_processes auto; # 日志打印控制台 error_log /dev/stdout; #error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;events {worker_connections 1024; }http {include /etc/nginx/m…...
大数据分析案例-基于LinearRegression回归算法构建房屋价格预测模型
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...
React-hook-form-mui(一):基本使用
前言 在项目开发中,我们选择了ReactMUI作为技术栈。在使用MUI构建form表单时,我们发现并没有与antd类似的表单验证功能,于是我们选择了MUI推荐使用的react-hook-form-mui库去进行验证。但是发现网上关于这个库的使用方法和demo比较少且比较简…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
