用C++编写一个2048的小游戏
以下是一个简单的2048游戏的实现。这个实现使用了控制台输入和输出,适合在终端或命令行环境中运行。
2048游戏的实现
1.游戏逻辑
2048游戏的核心逻辑包括:
• 初始化一个4x4的网格。
• 随机生成2或4。
• 处理玩家的移动操作(上、下、左、右)。
• 合并相同的数字。
• 检查游戏是否结束(胜利或失败)。
2.代码实现
```cpp
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <algorithm>
using namespace std;
const int GRID_SIZE = 4;
const int WINNING_SCORE = 2048;
void initializeGrid(vector<vector<int>>& grid) {
for (int i = 0; i < GRID_SIZE; ++i) {
grid.push_back(vector<int>(GRID_SIZE, 0));
}
}
void printGrid(const vector<vector<int>>& grid) {
for (const auto& row : grid) {
for (int val : row) {
cout << val << "\t";
}
cout << endl;
}
cout << endl;
}
void addRandomTile(vector<vector<int>>& grid) {
vector<pair<int, int>> emptyCells;
for (int i = 0; i < GRID_SIZE; ++i) {
for (int j = 0; j < GRID_SIZE; ++j) {
if (grid[i][j] == 0) {
emptyCells.push_back({i, j});
}
}
}
if (!emptyCells.empty()) {
pair<int, int> cell = emptyCells[rand() % emptyCells.size()];
grid[cell.first][cell.second] = (rand() % 2) ? 2 : 4;
}
}
bool canMove(const vector<vector<int>>& grid) {
for (int i = 0; i < GRID_SIZE; ++i) {
for (int j = 0; j < GRID_SIZE; ++j) {
if (grid[i][j] == 0) return true;
if (i > 0 && grid[i][j] == grid[i - 1][j]) return true;
if (j > 0 && grid[i][j] == grid[i][j - 1]) return true;
if (i < GRID_SIZE - 1 && grid[i][j] == grid[i + 1][j]) return true;
if (j < GRID_SIZE - 1 && grid[i][j] == grid[i][j + 1]) return true;
}
}
return false;
}
void compress(vector<int>& row) {
vector<int> temp(GRID_SIZE, 0);
int k = 0;
for (int i = 0; i < GRID_SIZE; ++i) {
if (row[i] != 0) {
temp[k++] = row[i];
}
}
for (int i = 0; i < GRID_SIZE; ++i) {
row[i] = temp[i];
}
}
void merge(vector<int>& row) {
for (int i = 0; i < GRID_SIZE - 1; ++i) {
if (row[i] == row[i + 1] && row[i] != 0) {
row[i] *= 2;
row[i + 1] = 0;
}
}
}
void moveLeft(vector<vector<int>>& grid) {
for (auto& row : grid) {
compress(row);
merge(row);
compress(row);
}
}
void moveRight(vector<vector<int>>& grid) {
for (auto& row : grid) {
reverse(row.begin(), row.end());
compress(row);
merge(row);
compress(row);
reverse(row.begin(), row.end());
}
}
void moveUp(vector<vector<int>>& grid) {
for (int col = 0; col < GRID_SIZE; ++col) {
vector<int> temp(GRID_SIZE, 0);
for (int row = 0; row < GRID_SIZE; ++row) {
temp[row] = grid[row][col];
}
compress(temp);
merge(temp);
compress(temp);
for (int row = 0; row < GRID_SIZE; ++row) {
grid[row][col] = temp[row];
}
}
}
void moveDown(vector<vector<int>>& grid) {
for (int col = 0; col < GRID_SIZE; ++col) {
vector<int> temp(GRID_SIZE, 0);
for (int row = 0; row < GRID_SIZE; ++row) {
temp[row] = grid[row][col];
}
reverse(temp.begin(), temp.end());
compress(temp);
merge(temp);
compress(temp);
reverse(temp.begin(), temp.end());
for (int row = 0; row < GRID_SIZE; ++row) {
grid[row][col] = temp[row];
}
}
}
bool isGameOver(const vector<vector<int>>& grid) {
for (const auto& row : grid) {
for (int val : row) {
if (val == WINNING_SCORE) return true;
}
}
return !canMove(grid);
}
int main() {
srand(static_cast<unsigned int>(time(0)));
vector<vector<int>> grid;
initializeGrid(grid);
addRandomTile(grid);
addRandomTile(grid);
while (true) {
printGrid(grid);
char move;
cout << "Enter move (W/A/S/D): ";
cin >> move;
switch (move) {
case 'W':
case 'w':
moveUp(grid);
break;
case 'A':
case 'a':
moveLeft(grid);
break;
case 'S':
case 's':
moveDown(grid);
break;
case 'D':
case 'd':
moveRight(grid);
break;
default:
cout << "Invalid move. Try again." << endl;
continue;
}
addRandomTile(grid);
if (isGameOver(grid)) {
printGrid(grid);
cout << "Game Over! " << (grid[0][0] == WINNING_SCORE ? "You Win!" : "You Lose!") << endl;
break;
}
}
return 0;
}
```
3.代码说明
• 初始化网格:`initializeGrid`函数初始化一个4x4的网格,所有值初始化为0。
• 打印网格:`printGrid`函数打印当前网格的状态。
• 添加随机瓷砖:`addRandomTile`函数在网格的空位置随机添加一个2或4。
• 移动操作:`moveLeft`、`moveRight`、`moveUp`、`moveDown`函数分别处理左、右、上、下移动操作。
• 压缩和合并:`compress`和`merge`函数分别处理行或列的压缩和合并操作。
• 检查游戏结束:`isGameOver`函数检查游戏是否结束(胜利或失败)。
4.运行游戏
将上述代码保存为一个C++文件(例如`2048.cpp`),然后使用C++编译器编译并运行它。例如,使用g++编译器:
```sh
g++ -o 2048 2048.cpp
./2048
```
5.游戏玩法
• 使用W/A/S/D键控制方向(上/左/下/右)。
• 游戏目标是合并数字,直到出现2048。
• 如果没有可移动的空位且无法合并,则游戏结束。
希望这个实现对你有帮助!
相关文章:
用C++编写一个2048的小游戏
以下是一个简单的2048游戏的实现。这个实现使用了控制台输入和输出,适合在终端或命令行环境中运行。 2048游戏的实现 1.游戏逻辑 2048游戏的核心逻辑包括: • 初始化一个4x4的网格。 • 随机生成2或4。 • 处理玩家的移动操作(上、下、左、…...
为何SAP S4系统中要设置MRP区域?MD04中可否同时显示工厂级、库存地点级的数据?
【SAP系统PP模块研究】 一、物料主数据的MRP区域设置 SAP ECC系统中想要指定不影响MRP运算的库存地点,是针对库存地点设置MRP标识,路径为:SPRO->生产->物料需求计划->计划->定义每一个工厂的存储地点MRP,如下图所示: 另外,在给物料主数据MMSC扩充库存地点时…...
Windows10官方系统下载与安装保姆级教程【U盘-官方ISO直装】
Windows 10 官方系统安装/重装 制作启动盘的U盘微软官网下载Win10安装包创建启动盘U盘 安装Win10 本文采用U盘安装Windows10官方系统。 制作启动盘的U盘 微软官网下载Win10安装包 微软官网下载Win10安装包链接:https://www.microsoft.com/zh-cn/software-downloa…...
第05章 07 切片图等值线代码一则
绘制脑部切面图的阈值等值线是一个常见的任务,通常涉及使用VTK(Visualization Toolkit)库来处理医学图像数据。以下是一个基于VTK/C的示例代码,展示如何读取脑部DICOM图像数据,应用阈值过滤器来提取特定组织的等值线&a…...
【深度学习】线性回归的简洁实现
线性回归的简洁实现 在过去的几年里,出于对深度学习强烈的兴趣,许多公司、学者和业余爱好者开发了各种成熟的开源框架。 这些框架可以自动化基于梯度的学习算法中重复性的工作。 目前,我们只会运用: (1)通…...
渗透测试技法之口令安全
一、口令安全威胁 口令泄露途径 代码与文件存储不当:在软件开发和系统维护过程中,开发者可能会将口令以明文形式存储在代码文件、配置文件或注释中。例如,在开源代码托管平台 GitHub 上,一些开发者由于疏忽,将包含数据…...
【R语言】数学运算
一、基础运算 R语言中能实现加、减、乘、除、求模、取整、取绝对值、指数、对数等运算。 x <- 2 y <- 10 # 求模 y %% x # 整除 y %/% x # 取绝对值 abs(-x) # 指数运算 y ^x y^1/x #对数运算 log(x) #log()函数默认情况下以 e 为底 双等号“”的作用等同于identical(…...
小游戏源码开发搭建技术栈和服务器配置流程
近些年各种场景小游戏开发搭建版本层出不穷,山东布谷科技拥有多年海内外小游戏源码开发经验,现为从事小游戏源码开发或游戏运营的朋友们详细介绍小游戏开发及服务器配置流程。 一、可以对接到app的小游戏是如何开发的 1、小游戏源码开发的需求分析: 明…...
深度学习|表示学习|卷积神经网络|输出维度公式|15
如是我闻: 在卷积和池化操作中,计算输出维度的公式是关键,它们分别可以帮助我们计算卷积操作和池化操作后的输出大小。下面分别总结公式,并结合解释它们的意义: 1. 卷积操作的输出维度公式 当我们对输入图像进行卷积时…...
cpp智能指针
普通指针的不足 new和new[]的内存需要用delete和deletel]释放。 程序员的主观失误,忘了或漏了释放。 程序员也不确定何时释放。 普通指针的释放 类内的指针,在析构函数中释放。 C内置数据类型,如何释放? new出来的类,本身如…...
【面试题】 Java 三年工作经验(2025)
问题列表 为什么选择 spring boot 框架,它与 Spring 有什么区别?spring mvc 的执行流程是什么?如何实现 spring 的 IOC 过程,会用到什么技术?spring boot 的自动化配置的原理是什么?如何理解 spring boot 中…...
MOS的体二极管能通多大电流
第一个问题:MOS导通之后电流方向可以使任意的,既可以从D到S,也可以从S到D。 第二个问题:MOS里面的体二极管电流可以达到几百安培,这也就解释了MOS选型的时候很少考虑体二极管的最大电流,而是考虑DS之间电流…...
Node.js下载安装及环境配置教程 (详细版)
Node.js:是一个基于 Chrome V8 引擎的 JavaScript 运行时,用于构建可扩展的网络应用程序。Node.js 使用事件驱动、非阻塞 I/O 模型,使其非常适合构建实时应用程序。 Node.js 提供了一种轻量、高效、可扩展的方式来构建网络应用程序࿰…...
嵌入式MCU面试笔记2
目录 串口通信 概论 原理 配置 HAL库代码 1. 初始化函数 2. 数据发送和接收函数 3. 中断和DMA函数 4. 中断服务函数 串口通信 概论 我们知道,通信桥接了两个设备之间的交流。一个经典的例子就是使用串口通信交换上位机和单片机之间的数据。 比较常见的串…...
代码随想录算法【Day34】
Day34 62.不同路径 思路 第一种:深搜 -> 超时 第二种:动态规划 第三种:数论 动态规划代码如下: class Solution { public:int uniquePaths(int m, int n) {vector<vector<int>> dp(m, vector<int>(n,…...
《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》重印P126、P131勘误
勘误:打圈的地方有指数二字。 指数滤波器本身是错误的概念,我在书上打了一个叉,排版人员误删了。 滤波器部分从根本上有问题,本来要改,但是时间不够了。 和廖老师讨论多次后,决定大动。指数滤波器的概念…...
vim多文件操作如何同屏开多个文件
[rootxxx ~]# vimdiff aa.txt bb.txt cc.txt #带颜色比较的纵向排列打开的同屏多文件操作 示例: [rootxxx ~]# vimdiff -o aa.txt bb.txt cc.txt #带颜色比较的横向排列打开的同屏多文件操作 示例: [rootxxx ~]# vim -O aa.txt bb.txt c…...
day6手机摄影社区,可以去苹果摄影社区学习拍摄技巧
逛自己手机的社区:即(手机牌子)摄影社区 拍照时防止抖动可以控制自己的呼吸,不要大喘气 拍一张照片后,如何简单的用手机修图? HDR模式就是让高光部分和阴影部分更协调(拍风紧时可以打开&…...
渗透测试之WAF规则触发绕过规则之规则库绕过方式
目录 Waf触发规则的绕过 特殊字符替换空格 实例 特殊字符拼接绕过waf Mysql 内置得方法 注释包含关键字 实例 Waf触发规则的绕过 特殊字符替换空格 用一些特殊字符代替空格,比如在mysql中%0a是换行,可以代替空格 这个方法也可以部分绕过最新版本的…...
C语言【基础篇】之流程控制——掌握三大结构的奥秘
流程控制 🚀前言🦜顺序结构💯 定义💯执行规则 🌟选择结构💯if语句💯switch语句💯case穿透规则 🤔循环结构💯for循环💯while循环💯do -…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
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* …...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
