贪吃蛇(Qt版)

2024-08-23 15:28
文章标签 qt 贪吃蛇

本文主要是介绍贪吃蛇(Qt版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、项目介绍

界面一:游戏大厅界面

界面二:关卡选择界面

界面三:游戏界面

最终游戏效果:

二、项目创建与资源配置

1. 创建项目

2. 添加项目资源文件

三、项目实现

1. 游戏大厅界面

2. 关卡选择界面

3. 游戏房间界面

3.1 封装贪吃蛇数据结构

3.2 初始化游戏房间界面

3.3 蛇的移动

3.4 初始化贪吃蛇本体和食物节点

3.5 实现定时器的超时槽函数

3.6 实现各个方向的移动

3.7 重写绘图事件函数进行渲染

3.8 检查是否自己会撞到自己

3.9 设置游戏开始和游戏暂停按钮

3.10 设置退出游戏按钮

3.11 获取历史战绩

四、项目源码


一、项目介绍

        贪吃蛇游戏是一款休闲益智类游戏。它通过控制蛇头方向吃食物,从而使得蛇变得越来越长。

        在本游戏中设置了上下左右四个方向键来控制蛇的移动方向。食物的产生是随机生成的,当蛇每吃一次食物就会增加一节身体,同时游戏积分也会相应的加一。

        在本游戏的设计中,蛇的身体会越吃越长,身体越长对应的难度就越大,因为一旦蛇头和身体相交游戏就会结束。


本项目使用 Qt 实现一款简单的贪吃蛇游戏。

主要界面如下:

界面一:游戏大厅界面

界面二:关卡选择界面

界面三:游戏界面


最终游戏效果:


二、项目创建与资源配置

1. 创建项目

🌴游戏大厅界面:

  • 打开Qt-Creator 创建项目。 注意项目名中不能包含空格、回车、中文等特殊字符

  • 选择基类为 QWidget, 类名为 GameHall 代表游戏大厅界面

 

  • 选择 MinGW 64-bit 编译套件


🌴关卡选择界面: 

  • 添加新文件 

  •  继承自 QWidget, 类名为 GameSelect 代表游戏关卡界面

  • 点击完成 


🌴游戏房间界面: 

  • 添加新文件 

  • 继承自 QWidget, 类名为 GameRoom 代表游戏房间界面

  • 点击完成 


2. 添加项目资源文件

  • 拷贝资源文件到项目文件中

  • 在项目中添加资源文件

  • 给资源文件起名为:res, 点击下一步

  • 点击完成 

  • 添加前缀 

  • 添加资源文件 

三、项目实现

1. 游戏大厅界面

游戏大厅界面比较简单, 只有一个背景图和一个按钮。

  • 背景图的渲染,我们通过QT的绘图事件完成。
#include <QPainter>void GameHall::paintEvent(QPaintEvent *event)
{(void)event;// 去掉警告小技巧QPainter painter(this);// 实例化画家对象QPixmap pix(":res/game_hall.png");// 实例化绘画设备painter.drawPixmap(0, 0, this->width(), this->height(), pix);// 绘画
}
  • 按钮的响应我们通过QT的信号和槽机制完成。
#include "gameselect.h"
#include <QIcon>
#include <QPushButton>
#include <QFont>
#include <QSound>GameHall::GameHall(QWidget *parent): QWidget(parent), ui(new Ui::GameHall)
{ui->setupUi(this);// 设置窗口信息this->setFixedSize(1000, 800);this->setWindowTitle("贪吃蛇游戏");this->setWindowIcon(QIcon(":res/ico.png"));// 设置开始游戏按钮QPushButton* startBtn = new QPushButton(this);startBtn->setText("开始游戏");startBtn->move(this->width() * 0.4, this->height() * 0.7);startBtn->setStyleSheet("QPushButton { border : 0px; }");QFont font("华文行楷", 23, QFont::ExtraLight, false);startBtn->setFont(font);// 点击按钮就会进入游戏关卡界面GameSelect* select = new GameSelect;connect(startBtn, &QPushButton::clicked, [=](){select->setGeometry(this->geometry());// 设置窗口固定this->close();// 关闭游戏大厅界面select->show();// 显示游戏关卡界面// 注意:使用 QSound 类时, 需要添加模块:multimediaQSound::play(":res/clicked.wav");// 添加按钮点击音效});
}

 效果示例:

2. 关卡选择界面

        关卡选择界面包含一个背景图和五个按钮,背景图的绘制和游戏大厅背景图绘制⼀样,同样使用的是Qt中的绘图事件。

  • 背景图的渲染,我们通过QT的绘图事件完成。
#include <QPainter>void GameSelect::paintEvent(QPaintEvent *event)
{(void)event;QPainter painter(this);// 实例化画家对象QPixmap pix(":res/game_select.png");// 实例化绘画设备painter.drawPixmap(0, 0, this->width(), this->height(), pix);// 绘画
}
  •  按钮的响应我们通过QT的信号和槽机制完成。
#include "gameselect.h"
#include "gamehall.h"
#include "gameroom.h"
#include <QIcon>
#include <QFont>
#include <QPushButton>
#include <QSound>
#include <QFile>
#include <QTextStream>
#include <QTextEdit>
#include <QDateTime>GameSelect::GameSelect(QWidget *parent) : QWidget(parent)
{// 设置游戏关卡界面this->setFixedSize(1000, 800);this->setWindowTitle("关卡选择");this->setWindowIcon(QIcon(":res/ico.png"));// 设置字体格式QFont font("华文行楷", 20, QFont::ExtraLight, false);// 创建返回按钮QPushButton* backBtn = new QPushButton(this);QPixmap pix(":res/back.png");backBtn->setIcon(pix);backBtn->move(this->width() * 0.9, this->height() * 0.9);connect(backBtn, &QPushButton::clicked, [=](){emit this->backGameHall();// emit 关键字触发信号QSound::play(":res/clicked.wav");});// 返回游戏大厅界面connect(this, &GameSelect::backGameHall, [=](){this->hide();GameHall* gameHall = new GameHall;gameHall->show();});GameRoom* gameRoom = new GameRoom();// 设置简单模式按钮QPushButton* simpleBtn = new QPushButton(this);simpleBtn->setStyleSheet("QPushButton { background-color:#0072C6; color:white; ""border:2px groove gray; border-radius:10px; padding:6px; }");simpleBtn->setFont(font);simpleBtn->setText("简单模式");simpleBtn->move(395, 140);connect(simpleBtn, &QPushButton::clicked, [=](){gameRoom->setTimeout(300);gameRoom->setGeometry(this->geometry());// 设置窗口固定this->hide();gameRoom->show();QSound::play(":res/clicked.wav");});// 设置正常按钮模式QPushButton* normalBtn = new QPushButton(this);normalBtn->setStyleSheet("QPushButton { background-color:#0072C6; color:white; ""border:2px groove gray; border-radius:10px; padding:6px; }");normalBtn->setFont(font);normalBtn->setText("正常模式");normalBtn->move(395, 260);connect(normalBtn, &QPushButton::clicked, [=](){gameRoom->setTimeout(200);gameRoom->setGeometry(this->geometry());// 设置窗口固定this->hide();gameRoom->show();QSound::play(":res/clicked.wav");});// 设置困难模式按钮QPushButton* hardBtn = new QPushButton(this);hardBtn->setStyleSheet("QPushButton { background-color:#0072C6; color:white; ""border:2px groove gray; border-radius:10px; padding:6px; }");hardBtn->setFont(font);hardBtn->setText("困难模式");hardBtn->move(395, 380);connect(hardBtn, &QPushButton::clicked, [=](){gameRoom->setTimeout(100);gameRoom->setGeometry(this->geometry());// 设置窗口固定this->hide();gameRoom->show();QSound::play(":res/clicked.wav");});// 获取历史战绩QPushButton* hisBtn = new QPushButton(this);hisBtn->setStyleSheet("QPushButton { background-color:#0072C6; color:white; ""border:2px groove gray; border-radius:10px; padding:6px; }");hisBtn->setFont(font);hisBtn->setText("历史战绩");hisBtn->move(395, 500);connect(hisBtn, &QPushButton::clicked, [=](){QSound::play(":res/clicked.wav");QFile file("D:/code/qt/Snake/1.txt");file.open(QIODevice::ReadOnly);QTextStream in(&file);// 创建文本流对象int data = in.readLine().toInt();// 读取第一行作为整形数据QWidget* newWidget = new QWidget;// 一定不能添加到对象书上newWidget->setWindowTitle("历史战绩");newWidget->setFixedSize(500, 300);QTextEdit* edit = new QTextEdit(newWidget);// 将编辑框置于新窗口上edit->setFont(font);edit->setFixedSize(500, 300);// 获取系统时间QDateTime currentTime = QDateTime::currentDateTime();QString time = currentTime.toString("yyyy-MM-dd hh:mm:ss");edit->setText("时间:");edit->append(time);edit->setText("得分为:");edit->append(QString::number(data));newWidget->show();});}

效果示例:

3. 游戏房间界面

游戏房间界面包含下面几个部分:

  1. 背景图的绘制。
  2. 蛇的绘制、蛇的移动、判断蛇是否会撞到自己。
  3. 积分的累加和绘制。

在这里我们要考虑几个比较核心的问题:

1. 怎么让蛇动起来?

  • 我们可以用一个链表表示贪吃蛇,一个小方块表示蛇的一个节点, 我们设置蛇的默认长度为3;
  • 向上移动的逻辑就是在蛇的上方加入一个小方块, 然后把最后一个小方块删除即可;
  • 需要用到定时器 Qtimer 每100 - 200ms 重新渲染。

2. 怎么判断蛇有没有吃到食物?

  • 判断蛇头和食物的坐标是否相交,Qt 有相关的接口调用。

3. 怎么控制蛇的移动?

  • 借助QT的实践机制实现, 重写keyPressEvent即可, 在函数中监控想要的键盘事件即可。
  • 我们通过绘制四个按钮,使用信号和槽的机制控制蛇的上、下、左、右移动方向。

3.1 封装贪吃蛇数据结构

#include <QSound>// 枚举蛇的移动方向
enum class snakeDirect{UP = 0,DOWN,LEFT,RIGHT
};class GameRoom : public QWidget
{Q_OBJECT
public:explicit GameRoom(QWidget *parent = nullptr);// 重写绘图事件,实现贪吃蛇游戏游戏背景效果void paintEvent(QPaintEvent *event);void startGame();void setTimeout(int count) {moveTimeout = count;}void createNewFood();// 生成食物void moveUp();// 蛇向上移动void moveDown();// 蛇向下移动void moveLeft();// 蛇向左移动void moveRight();// 蛇向右移动bool checkFail();// 判断游戏是否结束private:snakeDirect moveDirect = snakeDirect::UP;// 定义蛇的移动方向,默认朝上bool isGameStart = false;// 表示是否开始游戏QTimer* timer;// 定时器QList<QRectF> snakeList;// 表示贪吃蛇链表QRectF foodRect;// 表示食物节点const int kDefaultTimeout = 200;// 表示贪吃蛇默认移动时间const int kSnakeNodeWidth = 20;// 表示蛇身体节点的宽度const int kSnakeNodeHeight = 20;// 表示蛇身体节点的高度int moveTimeout = kDefaultTimeout;QSound* sound;// 音频
};

3.2 初始化游戏房间界面

  • 设置窗口大小、标题、图标等

#include <QIcon>GameRoom::GameRoom(QWidget *parent) : QWidget(parent)
{// 初始化窗口设置this->setFixedSize(1000, 800);this->setWindowTitle("贪吃蛇游戏");this->setWindowIcon(QIcon(":res/ico.png"));
}

3.3 蛇的移动

  • 蛇的移动方向为:上、下、左、右。通过在游戏房间中布局四个按钮来控制蛇的移动方向。
  • 注意: 这里贪吃蛇不允许直接掉头, 比如当前是向上的, 不能直接修改为向下。
    // 方向控制QPushButton* Up = new QPushButton(this);QPushButton* Down = new QPushButton(this);QPushButton* Left = new QPushButton(this);QPushButton* Right = new QPushButton(this);QString buttonStyle ="QPushButton {""    border: 2px solid #8f8f8f;""    border-radius: 10px;""    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f0f0f0, stop: 1 #bbbbbb);""    color: #000000;""}""QPushButton:hover {""    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #8f8f8f);""}""QPushButton:pressed {""    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #dadada, stop: 1 #949494);""}";Up->move(880, 400);Down->move(880, 480);Left->move(840, 440);Right->move(920, 440);QFont font("楷体", 24, QFont::ExtraLight, false);Up->setStyleSheet(buttonStyle);Up->setFont(font);Up->setText("↑");Down->setStyleSheet(buttonStyle);Down->setFont(font);Down->setText("↓");Left->setStyleSheet(buttonStyle);Left->setFont(font);Left->setText("←");Right->setStyleSheet(buttonStyle);Right->setFont(font);Right->setText("→");connect(Up, &QPushButton::clicked, [=](){if (moveDirect != snakeDirect::DOWN){moveDirect = snakeDirect::UP;}});connect(Down, &QPushButton::clicked, [=](){if (moveDirect != snakeDirect::UP){moveDirect = snakeDirect::DOWN;}});connect(Left, &QPushButton::clicked, [=](){if (moveDirect != snakeDirect::RIGHT){moveDirect = snakeDirect::LEFT;}});connect(Right, &QPushButton::clicked, [=](){if (moveDirect != snakeDirect::LEFT){moveDirect = snakeDirect::RIGHT;}});

3.4 初始化贪吃蛇本体和食物节点

GameRoom::GameRoom(QWidget *parent) : QWidget(parent)
{// 初始化贪吃蛇snakeList.push_back(QRectF(this->width() * 0.5, this->height() * 0.5, kSnakeNodeWidth, kSnakeNodeHeight));moveUp();moveUp();createNewFood();// 初始化食物
}
  • moveUp() 的功能是将蛇向上移动一次, 即在上方新增一个节点, 但不删除尾部节点。
  • createNewFood() 方法的功能是随机创建一个食物节点:
void GameRoom::createNewFood()
{foodRect = QRectF(qrand() % (this->width() / kSnakeNodeWidth) * kSnakeNodeWidth,qrand() % (this->height() / kSnakeNodeHeight) *kSnakeNodeHeight,kSnakeNodeWidth,kSnakeNodeHeight);                
}

3.5 实现定时器的超时槽函数

定时器是为了实现每隔一段时间能处理移动的逻辑并且更新绘图事件。

1. 首先, 需要判断蛇头和食物节点坐标是否相交

  • 如果相交, 需要创建新的食物节点, 并且需要更新蛇的长度, 所以 count 需要 +1 ;
  • 如果不相交, 那么直接处理蛇的移动即可。

2. 根据蛇移动方向 moveDirect 来处理蛇的移动, 处理方法是在前方加一个, 并且删除后方节点;

3. 重新触发绘图事件, 更新渲染。

GameRoom::GameRoom(QWidget *parent) : QWidget(parent)
{    timer = new QTimer(this);connect(timer, &QTimer::timeout, [=](){int count = 1;if (snakeList.front().intersects(foodRect)){createNewFood();++count;QSound::play(":res/eatfood.wav");}while (count--) {// 处理蛇的移动switch (moveDirect) {case snakeDirect::UP:moveUp();break;case snakeDirect::DOWN:moveDown();break;case snakeDirect::LEFT:moveLeft();break;case snakeDirect::RIGHT:moveRight();break;default:qDebug() << "非法移动方向";break;}}// 删除最后一个节点snakeList.pop_back();update();});
}

3.6 实现各个方向的移动

        各个方向的移动主要在于更新矩形节点的坐标, 要注意的是一定要处理边界的情况, 当边界不够存储一个新的节点时, 我们需要处理穿墙逻辑。

  • 实现向上移动
void GameRoom::moveUp()
{QPointF leftTop;// 左上角坐标QPointF rightBottom;// 右下角坐标auto snakeNode = snakeList.front();int headX = snakeNode.x();int headY = snakeNode.y();// 如果上面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑if (headY < 0){leftTop = QPointF(headX, this->height() - kSnakeNodeHeight);}else {leftTop = QPointF(headX, headY - kSnakeNodeHeight);}rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop, rightBottom));
}
  • 实现向下移动
void GameRoom::moveDown()
{QPointF leftTop;// 左上角坐标QPointF rightBottom;// 右下角坐标auto snakeNode = snakeList.front();int headX = snakeNode.x();int headY = snakeNode.y();// 如果下面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑if (headY > this->height()){leftTop = QPointF(headX, 0);}else {leftTop = snakeNode.bottomLeft();// 返回矩形左下角的坐标}rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop, rightBottom));
}
  • 实现向左移动
void GameRoom::moveLeft()
{QPointF leftTop;// 左上角坐标QPointF rightBottom;// 右下角坐标auto snakeNode = snakeList.front();int headX = snakeNode.x();int headY = snakeNode.y();// 如果左面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑if (headX < 0){leftTop = QPointF(800 - kSnakeNodeWidth, headY);}else {leftTop = QPointF(headX - kSnakeNodeWidth, headY);}rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop, rightBottom));
}
  • 实现向右移动
void GameRoom::moveRight()
{QPointF leftTop;// 左上角坐标QPointF rightBottom;// 右下角坐标auto snakeNode = snakeList.front();int headX = snakeNode.x();int headY = snakeNode.y();// 如果右面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑if (headX > 760){leftTop = QPointF(0, headY);}else {leftTop = snakeNode.topRight();// 返回矩形右上角的坐标}rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop, rightBottom));
}

3.7 重写绘图事件函数进行渲染

重写基类的 paintEvent() 方法进行渲染:

  • 渲染背景图
  • 渲染蛇头
  • 渲染蛇身体
  • 渲染蛇尾巴
  • 渲染右边游戏控制区域
  • 渲染食物节点
  • 渲染当前分数
  • 游戏结束渲染 game over!
void GameRoom::paintEvent(QPaintEvent *event)
{QPainter painter(this);QPixmap pix;pix.load(":res/game_room.png");painter.drawPixmap(0, 0, 800, 800, pix);painter.setRenderHint(QPainter::Antialiasing);// 设置抗锯齿// 渲染蛇头if (moveDirect == snakeDirect::UP){pix.load(":res/up.png");}else if (moveDirect == snakeDirect::DOWN){pix.load(":res/down.png");}else if (moveDirect == snakeDirect::LEFT){pix.load(":res/left.png");}else {pix.load(":res/right.png");}auto snakeHead = snakeList.front();painter.drawPixmap(snakeHead.x(), snakeHead.y(), snakeHead.width(), snakeHead.height(), pix);// 渲染蛇身体pix.load(":res/Bd.png");for (int i = 1; i < snakeList.size() - 1; i++){auto node = snakeList.at(i);painter.drawPixmap(node.x(), node.y(), node.width(), node.height(), pix);}// 渲染蛇尾巴auto snakeTail = snakeList.back();painter.drawPixmap(snakeTail.x(), snakeTail.y(), snakeTail.width(), snakeTail.height(), pix);// 渲染食物pix.load(":res/food.bmp");painter.drawPixmap(foodRect.x(), foodRect.y(), foodRect.width(), foodRect.height(), pix);// 渲染右边区域pix.load(":res/bg1.png");painter.drawPixmap(800, 0, 200, 1000, pix);// 渲染分数pix.load(":res/sorce_bg.png");painter.drawPixmap(this->width() * 0.85, this->height() * 0.02, 90, 40, pix);QPen pen;pen.setColor(Qt::black);painter.setPen(pen);QFont font("楷体", 22, QFont::ExtraLight, false);painter.setFont(font);painter.drawText(this->width() * 0.9, this->height() * 0.06, QString("%1").arg(snakeList.size()));// 如果失败,渲染 GAME OVERif (checkFail()){pen.setColor(Qt::red);painter.setPen(pen);QFont font("楷体", 50, QFont::ExtraLight, false);painter.setFont(font);painter.drawText(this->width() * 0.5 - 250, this->height() * 0.5, QString("GAME OVER"));timer->stop();QSound::play(":res/gameover.wav");sound->stop();}
}

3.8 检查是否自己会撞到自己

bool GameRoom::checkFail()
{// 判断头尾是否出现相交for (int i = 0; i < snakeList.size(); i++){for (int j = i + 1; j < snakeList.size(); j++){if (snakeList.at(i) == snakeList.at(j)){return true;}}}return false;
}

3.9 设置游戏开始和游戏暂停按钮

    // 开始游戏 & 暂停游戏QPushButton* startBtn = new QPushButton(this);QPushButton* stopBtn = new QPushButton(this);QFont ft("楷体", 20, QFont::ExtraLight, false);// 设置按钮的位置startBtn->move(860, 150);stopBtn->move(860, 200);// 设置按钮文本startBtn->setText("开始");stopBtn->setText("暂停");// 设置按钮样式startBtn->setStyleSheet("QPushButton {""background-color: white;"// 按钮背景颜色"color: #4CAF50;" // 文字颜色"border: 2px solid #4CAF50;" // 边框"border-radius: 8px;" // 边框圆角"padding: 10px 20px;" // 内边距"}");stopBtn->setStyleSheet("QPushButton {""background-color: white;"// 按钮背景颜色"color: #4CAF50;" // 文字颜色"border: 2px solid #4CAF50;" // 边框"border-radius: 8px;" // 边框圆角"padding: 10px 20px;" // 内边距"}");// 设置按钮字体格式startBtn->setFont(ft);stopBtn->setFont(ft);connect(startBtn, &QPushButton::clicked, [=](){sound = new QSound(":res/Trepak.wav");sound->play();sound->setLoops(-1);// 循环播放isGameStart = true;timer->start(moveTimeout);});connect(stopBtn, &QPushButton::clicked, [=](){sound->stop();isGameStart = false;timer->stop();});

3.10 设置退出游戏按钮

当我们点击退出游戏按钮时,当前游戏房间窗口不会立即退出,而是会弹窗提示,提示我们是否要退出游戏,效果如下图示:

这个弹窗提示我们是通过 Qt 中的消息盒子来实现的,具体实现过程如下:

  // 退出游戏按钮QPushButton* exitGame = new QPushButton(this);exitGame->setStyleSheet("QPushButton {""background-color: white;" // 按钮背景颜色"color: #4CAF50;" // 文字颜色"border: 2px solid #4CAF50;" // 边框"border-radius: 8px;" // 边框圆角"padding: 10px 20px;" // 内边距"}");exitGame->move(825, 730);exitGame->setText("退出");exitGame->setFont(font);// 消息提示QMessageBox* messageBox = new QMessageBox(this);QPushButton* okbtn = new QPushButton("ok");QPushButton* cancelbtn = new QPushButton("cancel");messageBox->setWindowTitle("退出游戏");// 设置消息对话框的标题messageBox->setText("确认退出游戏吗?");// 设置消息对话框内容messageBox->setIcon(QMessageBox::Question); //设置消息对话框类型messageBox->addButton(okbtn, QMessageBox::AcceptRole);//Accept Role:接受的角色messageBox->addButton(cancelbtn, QMessageBox::RejectRole);//Reject Role:排斥作用connect(exitGame, &QPushButton::clicked, [=](){messageBox->show();// 消息提示QSound::play(":res/clicked.wav");messageBox->exec();// 阻塞等待用户输入GameSelect* s = new GameSelect;if (messageBox->clickedButton() == okbtn){this->close();//如果点击了 Ok 按钮,那么就会跳转到游戏关卡界⾯s->show();s->setGeometry(this->geometry());QSound::play(":res/clicked.wav");}else{messageBox->close();QSound::play(":res/clicked.wav");}});

3.11 获取历史战绩

对于历史战绩的获取我们是通过 Qt 中的读写文件操作来实现的。具体实现过程如下:

  • 写文件:往文件中写入蛇的长度
 int c = snakeList.size();QFile file("D:/code/qt/Snake/1.txt");if (file.open(QIODevice::WriteOnly | QIODevice::Text)){QTextStream out(&file);int num = c;out << num;// 将int类型数据写入文件file.close();}
  • 读文件:读取写入文件中蛇的长度
QFile file("D:/code/qt/Snake/1.txt");
file.open(QIODevice::ReadOnly);QTextStream in(&file);// 创建文本流对象
int data = in.readLine().toInt();// 读取第一行作为整形数据

 效果示例:

四、项目源码

🌵gamehall.h

#ifndef GAMEHALL_H
#define GAMEHALL_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class GameHall; }
QT_END_NAMESPACEclass GameHall : public QWidget
{Q_OBJECTpublic:GameHall(QWidget *parent = nullptr);~GameHall();//重写绘图事件,绘制游戏大厅界面void paintEvent(QPaintEvent *event);private:Ui::GameHall *ui;
};
#endif // GAMEHALL_H

🌵gamehall.cpp

#include "gamehall.h"
#include "ui_gamehall.h"
#include "gameselect.h"
#include <QPainter>
#include <QIcon>
#include <QPushButton>
#include <QFont>
#include <QSound>GameHall::GameHall(QWidget *parent): QWidget(parent), ui(new Ui::GameHall)
{ui->setupUi(this);// 设置窗口信息this->setFixedSize(1000, 800);this->setWindowTitle("贪吃蛇游戏");this->setWindowIcon(QIcon(":res/ico.png"));// 设置开始游戏按钮QPushButton* startBtn = new QPushButton(this);startBtn->setText("开始游戏");startBtn->move(this->width() * 0.4, this->height() * 0.7);startBtn->setStyleSheet("QPushButton { border : 0px; }");QFont font("华文行楷", 23, QFont::ExtraLight, false);startBtn->setFont(font);// 点击按钮就会进入游戏关卡界面GameSelect* select = new GameSelect;connect(startBtn, &QPushButton::clicked, [=](){select->setGeometry(this->geometry());// 设置窗口固定this->close();// 关闭游戏大厅界面select->show();// 显示游戏关卡界面// 注意:使用 QSound 类时, 需要添加模块:multimediaQSound::play(":res/clicked.wav");// 添加按钮点击音效});
}GameHall::~GameHall()
{delete ui;
}void GameHall::paintEvent(QPaintEvent *event)
{(void)event;// 去掉警告小技巧QPainter painter(this);// 实例化画家对象QPixmap pix(":res/game_hall.png");// 实例化绘画设备painter.drawPixmap(0, 0, this->width(), this->height(), pix);// 绘画
}

 🍇gameselect.h

#ifndef GAMESELECT_H
#define GAMESELECT_H#include <QWidget>class GameSelect : public QWidget
{Q_OBJECT
public:explicit GameSelect(QWidget *parent = nullptr);//重写绘图事件,绘制游戏关卡选择界面void paintEvent(QPaintEvent *event);signals:void backGameHall();// 信号声明};#endif // GAMESELECT_H

 🍇gameselect.cpp 

#include "gameselect.h"
#include "gamehall.h"
#include "gameroom.h"
#include <QPainter>
#include <QIcon>
#include <QFont>
#include <QPushButton>
#include <QSound>
#include <QFile>
#include <QTextStream>
#include <QTextEdit>
#include <QDateTime>GameSelect::GameSelect(QWidget *parent) : QWidget(parent)
{// 设置游戏关卡界面this->setFixedSize(1000, 800);this->setWindowTitle("关卡选择");this->setWindowIcon(QIcon(":res/ico.png"));// 设置字体格式QFont font("华文行楷", 20, QFont::ExtraLight, false);// 创建返回按钮QPushButton* backBtn = new QPushButton(this);QPixmap pix(":res/back.png");backBtn->setIcon(pix);backBtn->move(this->width() * 0.9, this->height() * 0.9);connect(backBtn, &QPushButton::clicked, [=](){emit this->backGameHall();// emit 关键字触发信号QSound::play(":res/clicked.wav");});// 返回游戏大厅界面connect(this, &GameSelect::backGameHall, [=](){this->hide();GameHall* gameHall = new GameHall;gameHall->show();});GameRoom* gameRoom = new GameRoom();// 设置简单模式按钮QPushButton* simpleBtn = new QPushButton(this);simpleBtn->setStyleSheet("QPushButton { background-color:#0072C6; color:white; ""border:2px groove gray; border-radius:10px; padding:6px; }");simpleBtn->setFont(font);simpleBtn->setText("简单模式");simpleBtn->move(395, 140);connect(simpleBtn, &QPushButton::clicked, [=](){gameRoom->setTimeout(300);gameRoom->setGeometry(this->geometry());// 设置窗口固定this->hide();gameRoom->show();QSound::play(":res/clicked.wav");});// 设置正常按钮模式QPushButton* normalBtn = new QPushButton(this);normalBtn->setStyleSheet("QPushButton { background-color:#0072C6; color:white; ""border:2px groove gray; border-radius:10px; padding:6px; }");normalBtn->setFont(font);normalBtn->setText("正常模式");normalBtn->move(395, 260);connect(normalBtn, &QPushButton::clicked, [=](){gameRoom->setTimeout(200);gameRoom->setGeometry(this->geometry());// 设置窗口固定this->hide();gameRoom->show();QSound::play(":res/clicked.wav");});// 设置困难模式QPushButton* hardBtn = new QPushButton(this);hardBtn->setStyleSheet("QPushButton { background-color:#0072C6; color:white; ""border:2px groove gray; border-radius:10px; padding:6px; }");hardBtn->setFont(font);hardBtn->setText("困难模式");hardBtn->move(395, 380);connect(hardBtn, &QPushButton::clicked, [=](){gameRoom->setTimeout(100);gameRoom->setGeometry(this->geometry());// 设置窗口固定this->hide();gameRoom->show();QSound::play(":res/clicked.wav");});// 获取历史战绩QPushButton* hisBtn = new QPushButton(this);hisBtn->setStyleSheet("QPushButton { background-color:#0072C6; color:white; ""border:2px groove gray; border-radius:10px; padding:6px; }");hisBtn->setFont(font);hisBtn->setWindowIcon(QIcon(":res/ico.png"));hisBtn->setText("历史战绩");hisBtn->move(395, 500);connect(hisBtn, &QPushButton::clicked, [=](){QSound::play(":res/clicked.wav");QFile file("D:/code/qt/Snake/1.txt");file.open(QIODevice::ReadOnly);QTextStream in(&file);// 创建文本流对象int data = in.readLine().toInt();// 读取第一行作为整形数据QWidget* newWidget = new QWidget;// 一定不能添加到对象书上newWidget->setWindowTitle("历史战绩");newWidget->setWindowIcon(QIcon(":res/ico.png"));newWidget->setFixedSize(500, 300);QTextEdit* edit = new QTextEdit(newWidget);// 将编辑框置于新窗口上edit->setFont(font);edit->setFixedSize(500, 300);// 获取系统时间QDateTime currentTime = QDateTime::currentDateTime();QString time = currentTime.toString("yyyy-MM-dd hh:mm:ss");edit->setText("时间:");edit->append(time);edit->setText("得分为:");edit->append(QString::number(data));newWidget->show();});}//重写绘图事件,绘制游戏关卡选择界面
void GameSelect::paintEvent(QPaintEvent *event)
{(void)event;QPainter painter(this);// 实例化画家对象QPixmap pix(":res/game_select.png");// 实例化绘画设备painter.drawPixmap(0, 0, this->width(), this->height(), pix);// 绘画
}

🌴gameroom.h

#ifndef GAMEROOM_H
#define GAMEROOM_H#include <QWidget>
#include <QSound>// 枚举蛇的移动方向
enum class snakeDirect{UP = 0,DOWN,LEFT,RIGHT
};class GameRoom : public QWidget
{Q_OBJECT
public:explicit GameRoom(QWidget *parent = nullptr);// 重写绘图事件,实现贪吃蛇游戏游戏背景效果void paintEvent(QPaintEvent *event);void startGame();void setTimeout(int count) {moveTimeout = count;}void createNewFood();// 生成食物void moveUp();// 蛇向上移动void moveDown();// 蛇向下移动void moveLeft();// 蛇向左移动void moveRight();// 蛇向右移动bool checkFail();// 判断游戏是否结束private:snakeDirect moveDirect = snakeDirect::UP;// 定义蛇的移动方向,默认朝上bool isGameStart = false;// 表示是否开始游戏QTimer* timer;// 定时器QList<QRectF> snakeList;// 表示贪吃蛇链表QRectF foodRect;// 表示食物节点const int kDefaultTimeout = 200;// 表示贪吃蛇默认移动时间const int kSnakeNodeWidth = 20;// 表示蛇身体节点的宽度const int kSnakeNodeHeight = 20;// 表示蛇身体节点的高度int moveTimeout = kDefaultTimeout;QSound* sound;// 音频
};#endif // GAMEROOM_H

🌴gameroom.cpp 

#include "gameroom.h"
#include "gameselect.h"
#include <QIcon>
#include <QPixmap>
#include <QPainter>
#include <QTimer>
#include <QDebug>
#include <QFile>
#include <QPushButton>
#include <QMessageBox>
#include <QTextEdit>
#include <QSound>GameRoom::GameRoom(QWidget *parent) : QWidget(parent)
{// 初始化窗口设置this->setFixedSize(1000, 800);this->setWindowTitle("贪吃蛇游戏");this->setWindowIcon(QIcon(":res/ico.png"));// 初始化贪吃蛇snakeList.push_back(QRectF(this->width() * 0.5, this->height() * 0.5, kSnakeNodeWidth, kSnakeNodeHeight));moveUp();moveUp();createNewFood();// 初始化食物timer = new QTimer(this);connect(timer, &QTimer::timeout, [=](){int count = 1;if (snakeList.front().intersects(foodRect)){createNewFood();++count;QSound::play(":res/eatfood.wav");}while (count--) {// 处理蛇的移动switch (moveDirect) {case snakeDirect::UP:moveUp();break;case snakeDirect::DOWN:moveDown();break;case snakeDirect::LEFT:moveLeft();break;case snakeDirect::RIGHT:moveRight();break;default:qDebug() << "非法移动方向";break;}}// 删除最后一个节点snakeList.pop_back();update();});// 开始游戏 & 暂停游戏QPushButton* startBtn = new QPushButton(this);QPushButton* stopBtn = new QPushButton(this);QFont ft("楷体", 15, QFont::ExtraLight, false);// 设置按钮的位置startBtn->move(840, 150);stopBtn->move(840, 220);// 设置按钮文本startBtn->setText("开始");stopBtn->setText("暂停");// 设置按钮样式startBtn->setStyleSheet("QPushButton {""background-color: white;"// 按钮背景颜色"color: #4CAF50;" // 文字颜色"border: 2px solid #4CAF50;" // 边框"border-radius: 8px;" // 边框圆角"padding: 10px 20px;" // 内边距"}");stopBtn->setStyleSheet("QPushButton {""background-color: white;"// 按钮背景颜色"color: #4CAF50;" // 文字颜色"border: 2px solid #4CAF50;" // 边框"border-radius: 8px;" // 边框圆角"padding: 10px 20px;" // 内边距"}");// 设置按钮字体格式startBtn->setFont(ft);stopBtn->setFont(ft);connect(startBtn, &QPushButton::clicked, [=](){sound = new QSound(":res/Trepak.wav");sound->play();sound->setLoops(-1);// 循环播放isGameStart = true;timer->start(moveTimeout);});connect(stopBtn, &QPushButton::clicked, [=](){sound->stop();isGameStart = false;timer->stop();});// 方向控制QPushButton* Up = new QPushButton(this);QPushButton* Down = new QPushButton(this);QPushButton* Left = new QPushButton(this);QPushButton* Right = new QPushButton(this);QString buttonStyle ="QPushButton {""    border: 2px solid #8f8f8f;""    border-radius: 10px;""    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f0f0f0, stop: 1 #bbbbbb);""    color: #000000;""}""QPushButton:hover {""    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #8f8f8f);""}""QPushButton:pressed {""    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #dadada, stop: 1 #949494);""}";Up->move(880, 400);Down->move(880, 480);Left->move(840, 440);Right->move(920, 440);QFont font("楷体", 15, QFont::ExtraLight, false);Up->setStyleSheet(buttonStyle);Up->setFont(font);Up->setText("↑");Down->setStyleSheet(buttonStyle);Down->setFont(font);Down->setText("↓");Left->setStyleSheet(buttonStyle);Left->setFont(font);Left->setText("←");Right->setStyleSheet(buttonStyle);Right->setFont(font);Right->setText("→");connect(Up, &QPushButton::clicked, [=](){if (moveDirect != snakeDirect::DOWN){moveDirect = snakeDirect::UP;}});connect(Down, &QPushButton::clicked, [=](){if (moveDirect != snakeDirect::UP){moveDirect = snakeDirect::DOWN;}});connect(Left, &QPushButton::clicked, [=](){if (moveDirect != snakeDirect::RIGHT){moveDirect = snakeDirect::LEFT;}});connect(Right, &QPushButton::clicked, [=](){if (moveDirect != snakeDirect::LEFT){moveDirect = snakeDirect::RIGHT;}});// 退出游戏按钮QPushButton* exitGame = new QPushButton(this);exitGame->setStyleSheet("QPushButton {""background-color: white;" // 按钮背景颜色"color: #4CAF50;" // 文字颜色"border: 2px solid #4CAF50;" // 边框"border-radius: 8px;" // 边框圆角"padding: 10px 20px;" // 内边距"}");exitGame->move(840, 725);exitGame->setText("退出");exitGame->setFont(font);// 消息提示QMessageBox* messageBox = new QMessageBox(this);QPushButton* okbtn = new QPushButton("ok");QPushButton* cancelbtn = new QPushButton("cancel");messageBox->setWindowIcon(QIcon(":res/ico.png"));// 设置消息对话框的图标messageBox->setWindowTitle("退出游戏");// 设置消息对话框的标题messageBox->setText("确认退出游戏吗?");// 设置消息对话框内容messageBox->setIcon(QMessageBox::Question); //设置消息对话框类型messageBox->addButton(okbtn, QMessageBox::AcceptRole);//Accept Role:接受的角色messageBox->addButton(cancelbtn, QMessageBox::RejectRole);//Reject Role:排斥作用connect(exitGame, &QPushButton::clicked, [=](){messageBox->show();// 消息提示QSound::play(":res/clicked.wav");messageBox->exec();// 阻塞等待用户输入GameSelect* s = new GameSelect;if (messageBox->clickedButton() == okbtn){this->close();//如果点击了 Ok 按钮,那么就会跳转到游戏关卡界⾯s->show();s->setGeometry(this->geometry());QSound::play(":res/clicked.wav");}else{messageBox->close();QSound::play(":res/clicked.wav");}});
}// 重写绘图事件,实现贪吃蛇游戏游戏背景效果
void GameRoom::paintEvent(QPaintEvent *event)
{QPainter painter(this);QPixmap pix;pix.load(":res/game_room.png");painter.drawPixmap(0, 0, 800, 800, pix);painter.setRenderHint(QPainter::Antialiasing);// 设置抗锯齿// 蛇 = 蛇头 + 蛇身体 + 蛇尾巴// 渲染蛇头if (moveDirect == snakeDirect::UP){pix.load(":res/up.png");}else if (moveDirect == snakeDirect::DOWN){pix.load(":res/down.png");}else if (moveDirect == snakeDirect::LEFT){pix.load(":res/left.png");}else {pix.load(":res/right.png");}auto snakeHead = snakeList.front();painter.drawPixmap(snakeHead.x(), snakeHead.y(), snakeHead.width(), snakeHead.height(), pix);// 渲染蛇身体pix.load(":res/Bd.png");for (int i = 1; i < snakeList.size() - 1; i++){auto node = snakeList.at(i);painter.drawPixmap(node.x(), node.y(), node.width(), node.height(), pix);}// 渲染蛇尾巴auto snakeTail = snakeList.back();painter.drawPixmap(snakeTail.x(), snakeTail.y(), snakeTail.width(), snakeTail.height(), pix);// 渲染食物pix.load(":res/food.bmp");painter.drawPixmap(foodRect.x(), foodRect.y(), foodRect.width(), foodRect.height(), pix);// 渲染右边区域pix.load(":res/bg1.png");painter.drawPixmap(800, 0, 200, 1000, pix);// 渲染分数pix.load(":res/sorce_bg.png");painter.drawPixmap(this->width() * 0.85, this->height() * 0.02, 100, 50, pix);QPen pen;pen.setColor(Qt::black);painter.setPen(pen);QFont font("楷体", 15, QFont::ExtraLight, false);painter.setFont(font);painter.drawText(this->width() * 0.9, this->height() * 0.075, QString("%1").arg(snakeList.size()));// 往文件中写入得分int c = snakeList.size();QFile file("D:/code/qt/Snake/1.txt");if (file.open(QIODevice::WriteOnly | QIODevice::Text)){QTextStream out(&file);int num = c;out << num;// 将int类型数据写入文件file.close();}// 如果失败,渲染 GAME OVERif (checkFail()){pen.setColor(Qt::red);painter.setPen(pen);QFont font("微软雅黑", 40, QFont::ExtraLight, false);painter.setFont(font);painter.drawText(this->width() * 0.1, this->height() * 0.5, QString("GAME OVER"));timer->stop();QSound::play(":res/gameover.wav");sound->stop();}
}// 创建食物
void GameRoom::createNewFood()
{foodRect = QRectF(qrand() % (this->width() / kSnakeNodeWidth) * kSnakeNodeWidth,qrand() % (this->height() / kSnakeNodeHeight) *kSnakeNodeHeight,kSnakeNodeWidth,kSnakeNodeHeight);
}// 实现向上移动
void GameRoom::moveUp()
{QPointF leftTop;// 左上角坐标QPointF rightBottom;// 右下角坐标auto snakeNode = snakeList.front();int headX = snakeNode.x();int headY = snakeNode.y();// 如果上面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑if (headY < 0){leftTop = QPointF(headX, this->height() - kSnakeNodeHeight);}else {leftTop = QPointF(headX, headY - kSnakeNodeHeight);}rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop, rightBottom));
}// 实现向下移动
void GameRoom::moveDown()
{QPointF leftTop;// 左上角坐标QPointF rightBottom;// 右下角坐标auto snakeNode = snakeList.front();int headX = snakeNode.x();int headY = snakeNode.y();// 如果下面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑if (headY > this->height()){leftTop = QPointF(headX, 0);}else {leftTop = snakeNode.bottomLeft();// 返回矩形左下角的坐标}rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop, rightBottom));
}// 实现向左移动
void GameRoom::moveLeft()
{QPointF leftTop;// 左上角坐标QPointF rightBottom;// 右下角坐标auto snakeNode = snakeList.front();int headX = snakeNode.x();int headY = snakeNode.y();// 如果左面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑if (headX < 0){leftTop = QPointF(800 - kSnakeNodeWidth, headY);}else {leftTop = QPointF(headX - kSnakeNodeWidth, headY);}rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop, rightBottom));
}// 实现向右移动
void GameRoom::moveRight()
{QPointF leftTop;// 左上角坐标QPointF rightBottom;// 右下角坐标auto snakeNode = snakeList.front();int headX = snakeNode.x();int headY = snakeNode.y();// 如果右面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑if (headX > 760){leftTop = QPointF(0, headY);}else {leftTop = snakeNode.topRight();// 返回矩形右上角的坐标}rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop, rightBottom));
}// 判断游戏是否结束
bool GameRoom::checkFail()
{// 判断头尾是否出现相交for (int i = 0; i < snakeList.size(); i++){for (int j = i + 1; j < snakeList.size(); j++){if (snakeList.at(i) == snakeList.at(j)){return true;}}}return false;
}

这篇关于贪吃蛇(Qt版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

VS配置好Qt环境之后但无法打开ui界面的问题解决

《VS配置好Qt环境之后但无法打开ui界面的问题解决》本文主要介绍了VS配置好Qt环境之后但无法打开ui界面的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目UKeLvb录找到Qt安装目录中designer.UKeLvBexe的路径找到vs中的解决方案资源

Qt之QMessageBox的具体使用

《Qt之QMessageBox的具体使用》本文介绍Qt中QMessageBox类的使用,用于弹出提示、警告、错误等模态对话框,具有一定的参考价值,感兴趣的可以了解一下... 目录1.引言2.简单介绍3.常见函数4.按钮类型(QMessage::StandardButton)5.分步骤实现弹窗6.总结1.引言

Qt中Qfile类的使用

《Qt中Qfile类的使用》很多应用程序都具备操作文件的能力,包括对文件进行写入和读取,创建和删除文件,本文主要介绍了Qt中Qfile类的使用,具有一定的参考价值,感兴趣的可以了解一下... 目录1.引言2.QFile文件操作3.演示示例3.1实验一3.2实验二【演示 QFile 读写二进制文件的过程】4.

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

Qt中QGroupBox控件的实现

《Qt中QGroupBox控件的实现》QGroupBox是Qt框架中一个非常有用的控件,它主要用于组织和管理一组相关的控件,本文主要介绍了Qt中QGroupBox控件的实现,具有一定的参考价值,感兴趣... 目录引言一、基本属性二、常用方法2.1 构造函数 2.2 设置标题2.3 设置复选框模式2.4 是否

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自

Qt spdlog日志模块的使用详解

《Qtspdlog日志模块的使用详解》在Qt应用程序开发中,良好的日志系统至关重要,本文将介绍如何使用spdlog1.5.0创建满足以下要求的日志系统,感兴趣的朋友一起看看吧... 目录版本摘要例子logmanager.cpp文件main.cpp文件版本spdlog版本:1.5.0采用1.5.0版本主要

Qt 中 isHidden 和 isVisible 的区别与使用小结

《Qt中isHidden和isVisible的区别与使用小结》Qt中的isHidden()和isVisible()方法都用于查询组件显示或隐藏状态,然而,它们有很大的区别,了解它们对于正确操... 目录1. 基础概念2. 区别清见3. 实际案例4. 注意事项5. 总结1. 基础概念Qt 中的 isHidd