c++编写消消乐游戏

2023-10-28 16:10
文章标签 c++ 编写 游戏 消消

本文主要是介绍c++编写消消乐游戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <time.h>
using namespace sf;#define GAME_ROWS_COUNT  8
#define GAME_COLS_COUNT  8int ts = 57;  // 每一个游戏小方块区域的大小bool isMoving = false;
bool isSwap = false;// 相邻位置的第几次单击,第2次单击才交换方块
int click = 0;Vector2i pos; //鼠标单击时的位置
Vector2i offset(15, 273);int posX1, posY1; //第一次单击的位置(记录行和列的序号)
int posX2, posY2; //第二次单击的位置(记录行和列的序号)struct Block {int x, y; //坐标值     x ==  col * ts   y == row * ts;int row, col;  //第几行,第几列int kind; //表示第几种小方块bool match; //表示是否成三int alpha; //透明度Block() {match = false;alpha = 255;kind = -1;}
} grid[GAME_ROWS_COUNT + 2][GAME_ROWS_COUNT + 2];void swap(Block p1, Block p2) {std::swap(p1.col, p2.col);std::swap(p1.row, p2.row);grid[p1.row][p1.col] = p1;grid[p2.row][p2.col] = p2;
}void doEvent(RenderWindow *window) {Event e;while (window->pollEvent(e)) {if (e.type == Event::Closed) {window->close();}if (e.type == Event::MouseButtonPressed) {if (e.key.code == Mouse::Left) {if (!isSwap && !isMoving) click++;pos = Mouse::getPosition(*window)- offset;}}}if (click == 1) {posX1 = pos.x / ts + 1;posY1 = pos.y / ts + 1;}else if (click == 2) {posX2 = pos.x / ts + 1;posY2 = pos.y / ts + 1;// 是相邻方块就交换位置if (abs(posX2 - posX1) + abs(posY2 - posY1) == 1) {// 交换相邻的两个小方块// 消消乐的方块,怎么表示?swap(grid[posY1][posX1], grid[posY2][posX2]);isSwap = 1;click = 0;}else {click = 1;}}
}void check() {for (int i = 1; i <= GAME_ROWS_COUNT; i++) {for (int j = 1; j <= GAME_COLS_COUNT; j++) {if (grid[i][j].kind == grid[i + 1][j].kind &&grid[i][j].kind == grid[i - 1][j].kind) {//grid[i - 1][j].match++;//grid[i][j].match++;//grid[i + 1][j].match++;for (int k = -1; k <= 1; k++) grid[i+k][j].match++;}if (grid[i][j].kind == grid[i][j - 1].kind &&grid[i][j].kind == grid[i][j + 1].kind) {//grid[i][j - 1].match++;//grid[i][j + 1].match++;//grid[i][j].match++;for (int k = -1; k <= 1; k++) grid[i][j + k].match++;}}}
}void doMoving() {isMoving = false;for (int i = 1; i <= GAME_ROWS_COUNT; i++) {for (int j = 1; j <= GAME_COLS_COUNT; j++) {Block& p = grid[i][j]; // 引用p, 就是grid[i][j]的别名int dx, dy;for (int k = 0; k < 4; k++) {dx = p.x - p.col * ts;dy = p.y - p.row * ts;if (dx) p.x -= dx / abs(dx);if (dy) p.y -= dy / abs(dy);}if (dx || dy) isMoving = true;}}
}void xiaochu() {for (int i = 1; i <= GAME_ROWS_COUNT; i++) {for (int j = 1; j <= GAME_COLS_COUNT; j++) {if (grid[i][j].match && grid[i][j].alpha > 10) {grid[i][j].alpha -= 10;isMoving = true;}}}
}void huanYuan() {if (isSwap && !isMoving) {// 如果此时没有产生匹配效果,就要还原int score = 0;for (int i = 1; i <= GAME_ROWS_COUNT; i++) {for (int j = 1; j <= GAME_COLS_COUNT; j++) {score += grid[i][j].match;}}if (score == 0) {swap(grid[posY1][posX1], grid[posY2][posX2]);}isSwap = false;}
}void updateGrid() {for (int i = GAME_ROWS_COUNT; i > 0; i--) {for (int j = 1; j <= GAME_COLS_COUNT; j++) {if (grid[i][j].match) {for (int k = i - 1; k > 0; k--) {if (grid[k][j].match == 0) {swap(grid[k][j], grid[i][j]);break;}}}}}for (int j = 1; j <= GAME_COLS_COUNT; j++) {int n = 0;for (int i = GAME_ROWS_COUNT; i > 0; i--) {if (grid[i][j].match) {grid[i][j].kind = rand() % 7;grid[i][j].y = -ts * n;n++;grid[i][j].match = false;grid[i][j].alpha = 255;}}}
}void drawBlocks(Sprite * sprite, RenderWindow *window) {for (int i = 1; i <= GAME_ROWS_COUNT; i++) {for (int j = 1; j <= GAME_COLS_COUNT; j++) {Block p = grid[i][j];sprite->setTextureRect(IntRect(p.kind * 52, 0, 52, 52));// 设置透明度sprite->setColor(Color(255, 255, 255, p.alpha));sprite->setPosition(p.x, p.y);// 因为数组gird中的Block, 每个Block的行标,列标是从1计算的,// 并根据行标和列表来计算的x,y坐标// 所以坐标的偏移,需要少便宜一些,也就是相当于在正方形区域的左上角的左上角方向偏移一个单位// 在这个位置开发存放第0行第0列(实际不绘制第0行第0列)sprite->move(offset.x-ts, offset.y-ts);  // to dowindow->draw(*sprite);}}
}void initGrid() {for (int i = 1; i <= GAME_ROWS_COUNT; i++) {for (int j = 1; j <= GAME_COLS_COUNT; j++) {grid[i][j].kind = rand() % 3; grid[i][j].col = j;grid[i][j].row = i;grid[i][j].x = j * ts;grid[i][j].y = i * ts;}}
}int main(void) {srand(time(0));RenderWindow window(VideoMode(485, 917), "Rock-xiaoxiaole");// 设置刷新的最大帧率window.setFramerateLimit(60);Texture t1, t2;t1.loadFromFile("images/bg2.png");if (! t2.loadFromFile("images/t4.png")) {return -1;}Sprite spriteBg(t1);Sprite spriteBlock(t2);initGrid();while (window.isOpen()) {// 处理用户的点击事件doEvent(&window);// 检查匹配情况check();// 移动处理doMoving();// 消除if (!isMoving) {xiaochu();}// 还原处理huanYuan();if (!isMoving) {updateGrid();}// 渲染游戏画面window.draw(spriteBg);// 渲染所有的小方块drawBlocks(&spriteBlock, &window);// 显示window.display();}return 0;
}

  • <SFML/Graphics.hpp>:SFML 图形模块的头文件,用于创建窗口、渲染精灵等图形相关操作。
  • <SFML/Audio.hpp>:SFML 音频模块的头文件,用于音频播放和处理。
  • <time.h>:C 语言标准库中的时间头文件,在此代码中用于生成随机数种子

这段代码需要依赖其他 SFML 库文件和资源文件才能正常编译和运行。在编译和执行之前,请确保已正确配置 SFML 开发环境并添加了必要的依赖项。

  1. swap(Block p1, Block p2): This function swaps the position of two blocks (p1 and p2) by swapping their row and column values.

  2. doEvent(RenderWindow *window): This function handles user events, such as mouse clicks and window closures. It checks for mouse button presses and updates the positions of the clicked blocks accordingly.

  3. check(): This function checks for matches in the game grid. It iterates through each block and checks if there are three identical blocks in a row or column. If a match is found, it increments the match counter for those blocks.

  4. doMoving(): This function moves the blocks to their appropriate positions after a swap or match has occurred. It checks each block's position and adjusts it if it is not aligned with its row or column. It sets the isMoving flag to true if any blocks are still moving.

  5. xiaochu(): This function handles the removal of matched blocks by decreasing their alpha value (transparency). It sets the isMoving flag to true if any blocks are still being removed.

  6. huanYuan(): This function reverts the last swap if no match occurs as a result of the swap. It checks if a swap has occurred (isSwap flag) and if all blocks have finished moving (isMoving flag).

  7. updateGrid(): This function updates the game grid by moving blocks down if there are empty spaces below them and generating new random blocks at the top. It iterates through each column from bottom to top and replaces matched blocks with new random blocks.

  8. drawBlocks(Sprite *sprite, RenderWindow *window): This function draws the blocks on the game window using the provided sprite. It iterates through each block in the game grid, sets the sprite's texture rectangle and color based on the block's properties, and then draws the sprite on the window.

  9. initGrid(): This function initializes the game grid by assigning random block types to each block and setting their initial positions.

  10. main(): The main function of the program. It initializes the window, loads textures for the background and block sprites, calls initGrid() to initialize the game grid, and enters the main game loop. Inside the game loop, it calls the various functions in the correct order to handle events, update the game state, and render the game screen.

These functions together implement the logic and rendering of a basic match-three puzzle game using C++ and SFML.

这篇关于c++编写消消乐游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/294370

相关文章

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif

python编写朋克风格的天气查询程序

《python编写朋克风格的天气查询程序》这篇文章主要为大家详细介绍了一个基于Python的桌面应用程序,使用了tkinter库来创建图形用户界面并通过requests库调用Open-MeteoAPI... 目录工具介绍工具使用说明python脚本内容如何运行脚本工具介绍这个天气查询工具是一个基于 Pyt

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可

C/C++ chrono简单使用场景示例详解

《C/C++chrono简单使用场景示例详解》:本文主要介绍C/C++chrono简单使用场景示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录chrono使用场景举例1 输出格式化字符串chrono使用场景China编程举例1 输出格式化字符串示