简易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矩阵
    // 在游戏板上随机生成两个数字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)
点赞加关注,收藏不迷路!本篇文章对你有帮助的话,还请多多点赞支持!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

yolov8实战第五天——yolov8+ffmpg实时视频流检测并进行实时推流——(推流,保姆教学)

yolov8实战第一天——yolov8部署并训练自己的数据集&#xff08;保姆式教程&#xff09;_yolov8训练自己的数据集-CSDN博客 yolov8实战第三天——yolov8TensorRT部署&#xff08;python推理&#xff09;&#xff08;保姆教学&#xff09;-CSDN博客 今天&#xff0c;我们继续y…

比例阀放大器控制阀类型

控制各种不带电气位移反馈的单电磁铁比例方向阀、比例压力阀、比例流量阀、比例减压阀、比例节流阀、比例插装阀的BEUEC比例放大器&#xff0c;供电24VDC&#xff0c;输入指令、输出电流、颤振频率、斜坡时间等可现场设置&#xff0c;适用不同阀易匹配&#xff0c;带参考电压输…

openwrt使用docker部署adguard home

docker创建macvlan&#xff0c;目的使adguard home具备宿主机同网段IP docker network create -d macvlan --subnet192.168.88.0/24 --gateway192.168.88.254 -o parentbr-lan bridge-host&#xff08;虚拟网卡名字)拉取adguard home镜像 docker pull adguard/adguardhome:la…

记一次:职业规划与心灵成长

前言&#xff1a;csdn组织了2023年的年度征文&#xff0c;为了响应号召&#xff08;嘘~其实为了那个铭牌&#xff09;&#xff0c;加上这么多年了也该总结一下了&#xff0c;就写了这么一篇&#xff08;公司正好让写年终总结&#xff0c;巧了么这不是&#xff09; 一、感谢部分…

对图片进行数据增强(基于pytorch)

背景 在进行机器学习的任务中&#xff0c;我们的训练数据往往是有限的&#xff0c;在有限的数据集上获得较好的模型训练结果&#xff0c;我们不仅要在模型结构上下功夫&#xff0c;另一方面也需要对数据集进行数据增强 图片数据增强 图像数据增强是一种在训练机器学习和深度学…

CentOS 8 基于官方源码制作openssh 9.6 rpm包(含ssh-copy-id、openssl) —— 筑梦之路

CentOS 8 制作openssh9.6 rpm(含ssh-copy-id命令)包 —— 筑梦之路_centos8 rpmbuild -ba openssh.spec 9.6-CSDN博客 CentOS 8 制作openssh9.0/9.2/9.3 rpm包——筑梦之路_centos8 openssl rpm包-CSDN博客 效果截图&#xff1a; 和使用官方默认的spec文件制作的区别&#xff…

Redis命令---List篇

目录 1.Redis Lindex 命令 - 通过索引获取列表中的元素简介语法可用版本: > 1.0.0返回值: 列表中下标为指定索引值的元素。 如果指定索引值不在列表的区间范围内&#xff0c;返回 nil 。 示例 2.Redis Rpush 命令 - 在列表中添加一个或多个值简介语法可用版本: > 1.0.0返…

springboot社区养老服务系统设计与实现

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一 、设计说明 1.1 研究背景 当…

记一次 .NET 某药厂业务系统 CPU爆高分析

一&#xff1a;背景 1. 讲故事 前段时间有位朋友找到我&#xff0c;说他们的程序出现了CPU爆高&#xff0c;让我帮忙看下怎么回事&#xff1f;这种问题好的办法就是抓个dump丢给我&#xff0c;推荐的工具就是用 procdump 自动化抓捕。 二&#xff1a;Windbg 分析 1. CPU 真…

drf知识--11

补充 # 研究simple-jwt提供的Token类&#xff1a; 1、RefreshToken:生成refresh token的类 2、AccessToken:生成refresh token的类 3、Token&#xff1a;他们俩的父类 4、str(RefreshToken的对象)---得到字符串 refresh token&#xff0c;Token类写了 …

【小白专用】PHP识别是电脑或手机访问网站

现在通过手机访问网站越来越流行了&#xff0c;如果我们希望统计一下网站通过pc&#xff0c;手机移动端的各自访问量的情况&#xff0c;或者需要为手机移动端做一些特别的处理的话&#xff0c;那么我们就需要对访问网站的用户的客户端做一下鉴别了&#xff0c;下面这个实例就是…

vue2 消息弹框

父页面 <template><div style"margin-top: 20px"><div class"nav-style msg-style"><el-badge :value"value" :max"99" class"num" v-if"value > 0"><i class"el-icon-bell&…

关于开关量信号隔离器在水泥厂的应用探讨-安科瑞 蒋静

摘要&#xff1a;在水泥厂生产过程中&#xff0c;需要皮带与提升机进行运输物料&#xff0c;回转下料器进行投放物料。其中涉及大量电动机相关的机械运动&#xff0c;对这些机械运动状态进行检测&#xff0c;可以及时发现问题避免造成事故。针对机械位置检测&#xff0c;通常使…

Redis第四讲——Redis的数据库结构、删除策略及淘汰策略

一、redis中的数据库 redis服务器将所有数据库都保存在服务器状态redis.h/redisServer结构的db数组中。db数组的每项都是一个redis.h/redisDb结构&#xff0c;而每个redisDb结构就代表一个数据库。在初始化服务器时&#xff0c;程序会根据服务器状态的dbnum属性来决定应该创建多…

【shell漫步】2 运算符

碎碎念 上一章介绍了各种变量的定义和使用&#xff0c;这次要针对数字和文本这两种基本数据类型进行运算和判断了&#xff0c;shell中的运算包括&#xff1a; 对数字类型 算术运算&#xff08;对数字的 数学 运算&#xff09;关系运算&#xff08;用来做数字的条件判断&…

使用Go语言的HTTP客户端进行并发请求

Go语言是一种高性能、简洁的编程语言&#xff0c;它非常适合用于构建并发密集型的网络应用。在Go中&#xff0c;标准库提供了强大的HTTP客户端和服务器功能&#xff0c;使得并发HTTP请求变得简单而高效。 首先&#xff0c;让我们了解为什么需要并发HTTP请求。在许多应用场景中…

「Verilog学习笔记」任意奇数倍时钟分频

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1nsmodule clk_divider#(parameter dividor 5) ( input clk_in,input rst_n,output clk_out );parameter CNT_WIDTH $clog2(dividor - 1) ; reg flag1, f…

「Verilog学习笔记」编写乘法器求解算法表达式

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1nsmodule calculation(input clk,input rst_n,input [3:0] a,input [3:0] b,output [8:0] c);reg [8:0] data1, data2 ; assign c data2 ; always (posed…

基于ssm的订餐管理系统论文

基于JSP的订餐管理系统的设计与实现 摘要 当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。传统的订餐信息管理模式&#xff0c;采用人工登记的方式保存相关数据&#xff0c;这种以人力为主的…

微同城本地小程序源码系统:顺风车+二手市场+跑腿功能+信息发布+广告功能 带完整的搭建教程

随着移动互联网的普及&#xff0c;小程序已成为各行业进行线上业务拓展的重要工具。微同城作为一款集顺风车、二手市场、跑腿功能、信息发布和广告功能于一体的本地小程序源码系统&#xff0c;旨在满足现代城市居民的多元化需求&#xff0c;提供一个方便、快捷、实用的服务平台…