新手练习项目 4:简易2048游戏的实现(C++)

news2024/10/5 23:27:33

名人说:莫听穿林打叶声,何妨吟啸且徐行。—— 苏轼《定风波·莫听穿林打叶声》
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矩阵
    // 在游戏板上随机生成两个数字2
    board[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游戏,主要由以下几个部分组成:

  1. 初始化游戏板 (initializeBoard函数):用于初始化一个SIZE x SIZE(在这个例子中是4x4)的游戏板,并随机在两个位置放置数字2。

  2. 打印游戏板 (printBoard函数):该函数用于遍历游戏板并打印每个元素,其中0被替换为.以便于观看。

  3. 检查是否可以移动 (canMove函数):这个函数用来检查游戏板上是否还有可合并的元素或者空位,以决定游戏是否结束。

  4. 添加数字 (addNumber函数):在玩家移动之后,在一个随机的空位置上添加一个新的数字(90%的概率是2,10%的概率是4)。

  5. 旋转游戏板 (rotateBoard函数):为了简化移动逻辑,此函数用来将游戏板顺时针旋转90度。

  6. 移动方块 (moveTiles函数):该函数用于处理实际的方块移动和合并逻辑。

  7. 移动方向 (moveLeft, moveRight, moveUp, moveDown函数):这些函数使用moveTilesrotateBoard来处理不同方向的移动。

  8. 主函数 (main函数):设置游戏的初始状态,然后进入一个循环,等待玩家输入来移动方块,直到没有移动可做时结束游戏。

补充说明:

  • 游戏板的大小是通过const int SIZE = 4预设的,即方格大小为4x4。
  • 游戏开始时,游戏板上有两个数字2。
  • 玩家可以通过输入’w’, ‘a’, ‘s’, 'd’来控制方块向上、左、下、右移动。
  • 当游戏板上没有空位或者没有可合并的相邻方块时,游戏结束。
  • 这个程序没有实现计分功能,可自己扩充实现。

Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder)
点赞加关注,收藏不迷路!本篇文章对你有帮助的话,还请多多点赞支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1371965.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习|交叉熵

文章目录 什么是交叉熵如何构造信息量的函数关于 C 1 C_1 C1​参数的选择关于 C 2 C_2 C2​参数的选择 一个系统的熵如何比较两个系统的熵交叉熵在神经网络中的应用参考 什么是交叉熵 熵是用来衡量一个系统的混乱程度&#xff0c;混乱程度也其实代表着整个系统内部的不确定性。…

Redis缓存使用问题

数据一致性 只要使用到缓存,无论是本地内存做缓存还是使用 redis 做缓存,那么就会存在数据同步的问题。 以 Tomcat 向 MySQL 中写入和删改数据为例,来解释数据的增删改操作具体是如何进行的。 我们分析一下几种解决方案, 1、先更新缓存,再更新数据库 2、先更新数据库,…

搭建Docker私有镜像服务器

一、前言 1、本文主要内容 基于Decker Desktop&Docker Registry构建Docker私有镜像服务器测试在CentOS 7上基于Docker Registry搭建公共Docker镜像服务器修改Docker Engine配置以HTTP协议访问Docker Registry修改Docker Engine配置通过域名访问Docker Registry配置SSL证书…

1分钟速通Webservice服务端和客户端

服务端实现&#xff1a; 我们随便实现一个简单服务&#xff0c;客户请求我们的服务&#xff0c;我们给客户返回响应的信息 WebService public class HelloServiceImpl implements HelloService {Overridepublic String getString(String name) {return "hello," n…

使用numpy处理图片——基础操作

大纲 准备工作图片像素大小修改透明度 numpy是一款非常优秀的处理多维数组的Python基础包。在现实中&#xff0c;我们最经常接触的多维数组相关的场景就是图像处理。本系列将通过若干篇对图像处理相关的探讨&#xff0c;来介绍numpy的使用方法&#xff0c;以获得直观的体验。 本…

主食冻干哪款好?十大放心主食冻干名单推荐

作为养猫的人&#xff0c;我们都知道每天最担心的事情就是如何为心爱的猫咪选择一款高品质的猫粮。我们都希望为猫咪提供最好的营养&#xff0c;让它们健康快乐地成长。然而&#xff0c;近期的一些事件&#xff0c;如百利猫粮生虫和VE主食冻干掰开有虫&#xff0c;让我们不得不…

【开源商城推荐-LGPL-3.0】ts-mall 聚惠星商城

dts-shop: 聚惠星商城 DTS-SHOP&#xff0c;基于 微信小程序 springboot vue 技术构建 &#xff0c;支持单店铺&#xff0c;多店铺入驻的商城平台。项目包含 微信小程序&#xff0c;管理后台。基于java后台语言&#xff0c;已功能闭环&#xff0c;且达到商用标准的一套项目体…

AI文本朗读应用(二)

调用api实现TTS 注&#xff1a;如对api的使用有任何疑问&#xff0c;可以查阅文本转语音 REST API。 选择右侧“解决方案资源管理器”中的“TTS_Demo”&#xff0c;右键选择“添加”->“新建项”。 选择“类”&#xff0c;名称为“Authentication.cs”&#xff0c;点击“添…

【漏洞复现】锐捷EG易网关cli.php后台命令执行漏洞

Nx01 产品简介 锐捷EG易网关是一款综合网关&#xff0c;由锐捷网络完全自主研发。它集成了先进的软硬件体系架构&#xff0c;配备了DPI深入分析引擎、行为分析/管理引擎&#xff0c;可以在保证网络出口高效转发的条件下&#xff0c;提供专业的流控功能、出色的URL过滤以及本地化…

14:00面试,14:07就出来了,问的问题有点变态。。。

前言 刚从小厂出来&#xff0c;没想到在另一家公司我又寄了。 在这家公司上班&#xff0c;每天都要加班&#xff0c;但看在钱给的比较多的份上&#xff0c;也就不太计较了。但万万没想到一纸通知&#xff0c;所有人不准加班了&#xff0c;不仅加班费没有了&#xff0c;薪资还…

Zustand 状态管理

Zustand 状态管理 安装创建 Store给 Store 添加TS类型约束在页面使用 Store返回 Store 中所有状态在 Store 中使用 async 异步方法使用 Immer Middleware (中间件) 更新深层嵌套的 State使用 get 方法&#xff0c;在 set 方法外访问 State 中的数据使用 selector什么是 selecto…

炫技作品!极好!独家原创!一种新型改进的蜣螂优化算法(CCCDBO)

炫技作品&#xff01;&#xff0c;独家原创&#xff01; 蜣螂优化算法DBO的含金量不用我多介绍了吧&#xff0c;这是和麻雀优化算法SSA同一个课题组出的算法&#xff0c;业内公认的比较好的算法&#xff0c;这个算法认可度很高&#xff01; 一种新型改进蜣螂优化算法&#xf…

【web缓存】nginx和CDN应用

目录 一、代理的工作机制 二、代理服务器的概念 三、代理服务器的作用 四、常用的代理服务器 五、nginx缓存代理部署 步骤一&#xff1a;首先脚本完成三台nginx的部署 步骤二&#xff1a;在两个后端原始服务器上分别创建测试页面 步骤三&#xff1a;完成nginx缓存服务器…

中央处理器CPU(2)---流水CPU与RISC

1.流水CPU &#xff08;一看到这个就想起老家的流水席了&#xff0c;不知道各位吃过没。&#xff09; &#x1f308;1.1并行处理技术 对于计算机来说不论如何发展&#xff0c;最重要的一个追求目标就是很高的运算速度&#xff0c;冯诺依曼机是&#xff0c;现代计算机依然是&…

高效实用的电商数据分析产品之店铺分析如何入手?

在电商行业&#xff0c;如何做好店铺分析&#xff1f;应该从哪几个方面进行&#xff1f; 1、寻找竞品店铺 在众多店铺中找到与自己风格&#xff08;定位/用户群体等&#xff09;相仿的相关竞争对手的标签。研究竞品店铺中爆款产品作为一个店铺运营&#xff08;新品开发等&…

HubSpot CRM:卓越客户服务的关键引擎

在数字化时代&#xff0c;提供卓越的客户服务是企业成功的关键之一。HubSpot CRM以其强大的功能和灵活性&#xff0c;成为实现卓越客户服务的关键引擎&#xff0c;以下是强调HubSpot CRM在客户服务中的应用的关键方面&#xff1a; 1. 全面的客户视图 HubSpot CRM集成了全面的…

解决:接口中返回的文本不能保持原本格式也无法换行

一、问题&#xff1a; 原本传入的文本是有换行的&#xff0c;但是用div展示接口返回的文本&#xff0c;所示内容没有保持原有格式没达到换行效果 以下是传入到接口的文本格式 使用div标签展示接口返回的文本&#xff0c;但并没有保持原有格式&#xff0c;文本也没换行 <di…

docker 容器添加指定网络地址

docker 容器添加指定网络地址 在搭建halo博客时&#xff0c;准备让 halo、mysql8.1、nginx 三个容器在同一个网段中&#xff0c;并指定IP。 实现docker内部容器之间网络互通。 查看容器网络信息命令 docker inspect 容器名各容器部署成功后网络效果如下&#xff1a; nginx …

城堡世界源码

随着数字技术的飞速发展和人们对于娱乐需求的不断提升&#xff0c;城堡世界源码开发逐渐成为了新的热门话题。城堡世界是一个集潮流、艺术、科技于一体的数字娱乐新领域&#xff0c;通过将虚拟现实、增强现实等技术融入传统玩具设计中&#xff0c;为玩家们带来了全新的互动体验…

如何高效阅读Linux的man page

有时候需要在man page中查某个命令的用法&#xff0c;我们一般会使用man command的方式来查询&#xff0c;例如man vmstat.但是对于一些bash内置的命令&#xff0c;如alias,如果使用man alias会打开General Commands Manual ,如下图 可以看到&#xff0c;内置命令很多&#xff…