用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。

• 如果没有可移动的空位且无法合并,则游戏结束。

希望这个实现对你有帮助!

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

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

相关文章

Julia Distributed(分布式计算)详解

分布式计算是现代计算机科学中日益重要的一个分支&#xff0c;特别是在处理大规模数据和计算密集型应用时变得尤为关键。Julia 语言作为一种高性能的开源编程语言&#xff0c;其内置的分布式计算功能强大且易于使用。本篇博客将深入探讨 Julia Distributed 的基础概念、使用方法…

【开源免费】基于Vue和SpringBoot的在线文档管理系统(附论文)

本文项目编号 T 038 &#xff0c;文末自助获取源码 \color{red}{T038&#xff0c;文末自助获取源码} T038&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

忘记宝塔的访问地址怎么找

在linux中安装宝塔面板后会生成网址、账号和密码 如果网址忘记了那将进不去宝塔面板该怎么办呢&#xff1f; bt命令 我们输入 bt 命令的时候&#xff0c;是在根目录里面进行操作的。 / bt 我们根据自己的需要&#xff0c;选择对应的数字就可以了。 bt 14 输入 14 查看面板默…

FLTK - FLTK1.4.1 - demo - animgifimage

文章目录 FLTK - FLTK1.4.1 - demo - animgifimage概述笔记END FLTK - FLTK1.4.1 - demo - animgifimage 概述 知识点: 注册图像文件类型判断回调 FLTK支持的图像格式 GIF, BMP, ICO, PNM, PNG, jpg, svg 事件回调的注册 GIF图像显示为图片或动画的标志设置 // 超时回调的设置…

力扣hot100-->滑动窗口、贪心

你好呀&#xff0c;欢迎来到 Dong雨 的技术小栈 &#x1f331; 在这里&#xff0c;我们一同探索代码的奥秘&#xff0c;感受技术的魅力 ✨。 &#x1f449; 我的小世界&#xff1a;Dong雨 &#x1f4cc; 分享我的学习旅程 &#x1f6e0;️ 提供贴心的实用工具 &#x1f4a1; 记…

【蓝桥杯嵌入式入门与进阶】2.与开发板之间破冰:初始开发板和原理图2

个人主页&#xff1a;Icomi 专栏地址&#xff1a;蓝桥杯嵌入式组入门与进阶 大家好&#xff0c;我是一颗米&#xff0c;本篇专栏旨在帮助大家从0开始入门蓝桥杯并且进阶&#xff0c;若对本系列文章感兴趣&#xff0c;欢迎订阅我的专栏&#xff0c;我将持续更新&#xff0c;祝你…

Spring Boot - 数据库集成02 - 集成JPA

集成JPA 文章目录 集成JPA一&#xff1a;JPA概述1&#xff1a;JPA & JDBC2&#xff1a;JPA规范3&#xff1a;JPA的状态和转换关系 二&#xff1a;Spring data JPA1&#xff1a;JPA_repository1.1&#xff1a;CurdRepostory<T, ID>1.2&#xff1a;PagingAndSortingRep…

从ai产品推荐到利用cursor快速掌握一个开源项目再到langchain手搓一个Text2Sql agent

目录 0. 经验分享&#xff1a;产品推荐 1. 经验分享&#xff1a;提示词优化 2. 经验分享&#xff1a;使用cursor 阅读一篇文章 3. 经验分享&#xff1a;使用cursor 阅读一个完全陌生的开源项目 4. 经验分享&#xff1a;手搓一个text2sql agent &#xff08;使用langchain l…

基于DeepSeek在藏语学习推广和藏语信息化方面可以做哪些工作?

基于DeepSeek对藏语的技术优势&#xff0c;您可在以下三大方向开展创新性工作&#xff0c;以下是20具体落地方案&#xff1a; 一、藏语智能教育工具开发 《三十颂》AI语法教练 开发虚拟助教自动解析藏文句子结构&#xff08;标注格助词/时态变化&#xff09;错误检测系统&…

【Java-数据结构】Java 链表面试题下 “最后一公里”:解决复杂链表问题的致胜法宝

我的个人主页 我的专栏&#xff1a;Java-数据结构&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞❤ 收藏❤ 引言&#xff1a; Java链表&#xff0c;看似简单的链式结构&#xff0c;却蕴含着诸多有趣的特性与奥秘&#xff0c;等待我们去挖掘。它就像一…

深入探索 HTML5 拖拽效果 API:打造流畅交互体验

在现代的 Web 开发中&#xff0c;交互性和用户体验一直是开发者关注的重点。HTML5 的拖拽效果 API (Drag and Drop API) 提供了一种非常直观的方式来让网页元素或文件能够被拖动并放置到页面的指定位置&#xff0c;极大提升了用户的交互体验。本篇文章将深入探讨如何使用 HTML5…

智慧园区系统的类型及其在企业管理效率提升中的关键作用解析

内容概要 在智慧园区的建设中&#xff0c;各类系统的采用是提升管理效率的关键所在。快鲸智慧园区(楼宇)管理系统&#xff0c;通过其全面数字化的管理手段&#xff0c;已经成为了企业管理的新标杆。这一系统能够有效整合租赁管理、资产管理、招商管理和物业管理等功能&#xf…

微信小程序压缩图片

由于wx.compressImage(Object object) iOS 仅支持压缩 JPG 格式图片。所以我们需要做一下特殊的处理&#xff1a; 1.获取文件&#xff0c;判断文件是否大于设定的大小 2.如果大于则使用canvas进行绘制&#xff0c;并生成新的图片路径 3.上传图片 async chooseImage() {let …

国内flutter环境部署(记录篇)

设置系统环境变量 export PUB_HOSTED_URLhttps://pub.flutter-io.cn export FLUTTER_STORAGE_BASE_URLhttps://storage.flutter-io.cn使用以下命令下载flutter镜像 git clone -b stable https://mirror.ghproxy.com/https://github.com/<github仓库地址>#例如flutter仓…

【uniapp】uniapp使用java线程池

标题 由于js是性能孱弱的单线程语言&#xff0c;只要在渲染中执行了一些其他操作&#xff0c;会中断渲染&#xff0c;导致页面卡死&#xff0c;卡顿&#xff0c;吐司不消失等问题。在安卓端可以调用java线程池&#xff0c;把耗时操作写入线程池里面&#xff0c;优化性能。 实…

多级缓存(亿级并发解决方案)

多级缓存&#xff08;亿级流量&#xff08;并发&#xff09;的缓存方案&#xff09; 传统缓存的问题 传统缓存是请求到达tomcat后&#xff0c;先查询redis&#xff0c;如果未命中则查询数据库&#xff0c;问题如下&#xff1a; &#xff08;1&#xff09;请求要经过tomcat处…

第27篇 基于ARM A9处理器用C语言实现中断<三>

Q&#xff1a;基于ARM A9处理器怎样设计C语言工程&#xff0c;同时使用按键中断和定时器中断在红色LED上计数&#xff1f; A&#xff1a;基本原理&#xff1a;设置HPS Timer 0和按键中断源&#xff0c;主程序调用set_A9_IRQ_stack( )函数设置中断模式的ARM堆栈指针&#xff0c…

C++ 中用于控制输出格式的操纵符——setw 、setfill、setprecision、fixed

目录 四种操纵符简要介绍 setprecision基本用法 setfill的基本用法 fixed的基本用法 setw基本用法 以下是一些常见的用法和示例&#xff1a; 1. 设置字段宽度和填充字符 2. 设置字段宽度和对齐方式 3. 设置字段宽度和精度 4. 设置字段宽度和填充字符&#xff0c;结合…

JS宏进阶:闭包与代理

在JavaScript中&#xff0c;闭包和代理是两种重要的概念&#xff0c;它们各自具有独特的功能和用途。闭包&#xff0c;它指的是一个函数能够访问并操作其父函数作用域中的变量&#xff0c;即使父函数已经执行完毕。它允许内部函数访问外部函数的变量&#xff0c;从而提供了强大…

【1.安装ubuntu22.04】

目录 参考文章链接电脑参数安装过程准备查看/更改引导方式查看/更改磁盘的分区格式关闭BitLocker加密压缩分区关闭独显直连制作Ubuntu安装盘下载镜像制作启动盘 进入BIOS模式进行设置Secure Boot引导项顺序try or install ubuntu 进入安装分区启动引导器个人信息和重启 参考文章…