新手练习项目 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游戏,主要由以下几个部分组成:

  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.mzph.cn/news/611206.shtml

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

相关文章

光伏方案设计有什么注意点?

光伏方案设计是实现光伏发电系统高效运行的关键环节。在进行光伏方案设计时&#xff0c;有几个重要的注意点需要特别关注。 首先&#xff0c;要充分考虑地理位置和气候条件。不同地区的日照时数、太阳辐射强度和日照角度都有所不同&#xff0c;这些因素直接影响光伏发电系统的发…

FS【1】:SSP

文章目录 前言1. Abstract2. Introduction2.1. Motivation2.1.1. Few-shot Segmentation (FSS) Task2.1.2. Few-shot Segmentation (FSS) Problem 2.2. Contribution 3. Methods3.1. Motivation3.2. Overview of the architecture4.3. Self-support Prototype4.4. Adaptive Sel…

C++:多态究竟是什么?为何能成为面向对象的重要手段之一?

C&#xff1a;多态究竟是什么&#xff1f;为何能成为面向对象的重要手段之一&#xff1f; 前言一、多态的概念二、多态的定义及实现2.1 多态的构成条件2. 2 虚函数2.3 虚函数的重写2.3.1 虚函数重写的例外1&#xff1a;协变(基类与派生类虚函数返回值类型不同)2.3.2 虚函数重写…

领域驱动模型之各层实体严格分层处理

为什么要分层处理呢&#xff1f; 在领域驱动模型中&#xff0c;分为应用层&#xff08;application&#xff09;、领域层&#xff08;domain&#xff09;、基础设施层&#xff08;infrastructure&#xff09;。各层只能处理和访问自己所属层的 entity 或者 dto 对象&#xff0…

基于ssm的理财通的设计与实现+jsp论文

摘 要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对理财信息管理的提升&#xff0c…

针对大规模服务日志敏感信息的长效治理实践

文章目录 1 背景2 目标与措施3 实施3.1 脱敏工具类3.2 JSON脱敏3.3 APT自动脱敏3.3.1 本地缓存问题3.3.2 JDK序列化问题 3.4 弃用方案 4 规划5 总结 1 背景 近年来&#xff0c;国家采取了多项重要举措来加强个人数据保护&#xff0c;包括实施《中华人民共和国网络安全法》和《…

TypeError: Cannot read properties of undefined (reading ‘namespace‘)

项目场景&#xff1a; 背景&#xff1a; Java 项目中使用 activi 流程引擎&#xff0c; 创建一个带有排他网关的 申请审核流程&#xff0c; 创建之后 查看 流程图出现 如下所示的 错误信息。 前端页面 不显示 任何 流程图信息。 问题描述 问题&#xff1a; 例如&#xff1…

鸿蒙系列--属性动画

一、定义 当组件的通用属性发生改变时而产生的属性渐变效果 说明&#xff1a; 当组件的通用属性发生改变时&#xff0c;组件状态由初始状态逐渐变为结束状态的过程中&#xff0c;会创建多个连续的中间状态&#xff0c;逐帧播放后&#xff0c;就会形成动画 二、创建 给组件(如…

SCS模型(径流曲线法)概述

目录 1.介绍&#xff1a;2.计算公式&#xff1a;参考文献&#xff1a;小结&#xff1a; 1.介绍&#xff1a; SCS模型&#xff08;径流曲线法&#xff09;是由美国农业部水土保持局(Soil Conservation Service) 基于经验提出&#xff0c;最初用于预测在农业用地小型流域降雨所累…

【算法每日一练]-dfs (保姆级教程 篇9) #俄罗斯方块 #ABC Puzzle #lnc的工资

目录 今日知识点&#xff1a; 二维图形的状态压缩&#xff0c;存下所有的合法状态然后暴力遍历 dfs的优化剪枝 二项式定理 俄罗斯方块 ABC Puzzle lnc的工资 俄罗斯方块 322D 题意&#xff1a;在4*4方格中分别给出3个俄罗斯方块&#xff0c;问是否可以经过旋转&#xf…

C/C++动态内存管理

文章目录 前言1.C/C内存分布2.C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free3.C内存管理方式3.1 new/delete操作内置类型3.2 new和delete操作自定义类型 4. operator new与operator delete函数4.1 operator new与operator delete函数 5. new和delete的实现原…

软件测试|MySQL BETWEEN AND:范围查询详解

简介 在MySQL数据库中&#xff0c;使用BETWEEN AND操作符可以进行范围查询&#xff0c;即根据某个字段的值在指定范围内进行检索数据。这个操作符非常有用&#xff0c;因为它可以让我们轻松地筛选出位于两个特定值之间的数据&#xff0c;而不需要使用复杂的条件语句。 BETWEE…

数据挖掘在制造业中的预测与优化应用

随着大数据时代的到来&#xff0c;数据挖掘技术在各行各业的应用日益广泛&#xff0c;尤其在制造业中&#xff0c;其对于提升生产效率、降低运营成本、优化供应链管理等方面发挥着不可替代的作用。本文将探讨数据挖掘在制造业中的预测与优化应用&#xff0c;通过深入剖析实际案…

如何选择最适合的采购付款 (P2P) 解决方案?

无论企业的业务流程执行得如何&#xff0c;流程中始终存在改进空间。更好的管理系统是获得更好结果的关键&#xff0c;尤其是当企业处于增长阶段时。强大的采购到付款&#xff08;P2P&#xff09;系统是加快采购流程&#xff0c;同时保持采购支出可见性的最有效方法之一。 什么…

尚硅谷vite+vue3 (尚医通)项目实战笔记

如何配置项目运行后自动打开&#xff1f; 在package.json 启动命令中添加 “dev”: “vite --open”, 如何配置src的别名&#xff1f; 利用node内置模块path设置一下在vite.config.ts 中的别名 import { defineConfig } from vite import vue from vitejs/plugin-vue import …

IPv6路由协议---IPv6动态路由(OSPFv3-4)

OSPFv3的链路状态通告LSA类型 链路状态通告是OSPFv3进行路由计算的关键依据,链路状态通告包含链路状态类型、链路状态ID、通告路由器三元组唯一地标识了一个LSA。 OSPFv3的LSA头仍然保持20字节,但是内容变化了。在LSA头中,OSPFv2的LS age、Advertising Router、LS Sequence…

Vue3技术解析(小册子)

随着 Vue 3 正式版本的发布&#xff0c;未来 Vue 3 将会成为前端的主流框架&#xff0c;这个毋庸置疑。Vue 3 在使用方面会兼容部分 Vue 2.x 的特性&#xff0c;比如 options API。 所以&#xff0c;究竟是要先学习 Vue 2 打好基础&#xff0c;还是直接学习 Vue 3 呢&#xff…

职场日常英语口语,成人英语培训学校,柯桥学英语推荐哪里

“玩手机”用英语怎么说&#xff1f;你的第一反应是不是&#xff1a;play the phone&#xff1f; 在英语中&#xff0c;play这个动词通常表示“玩耍、娱乐、操纵”等意思&#xff0c;而手机是一种工具&#xff0c;不是玩耍的对象。 换句话说&#xff0c;我们“玩手机”&#xf…

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

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

软件测试|Windows系统配置pytest+allure环境教程

前言 allure可以输出非常精美的测试报告&#xff0c;也可以和pytest进行完美结合&#xff0c;不仅可以渲染页面&#xff0c;还可以控制用例的执行。本文我们将介绍Windows系统中如何配置allure环境。 第一步&#xff1a;配置Java环境 因为allure的运行依赖于Java环境&#x…