Qt—贪吃蛇项目(由0到1实现贪吃蛇项目)

用Qt实现一个贪吃蛇项目

  • 一、项目介绍
  • 二、游戏大厅界面实现
    • 2.1完成游戏大厅的背景图。
    • 2.2创建一个按钮,给它设置样式,并且可以跳转到别的页面
  • 三、难度选择界面实现
  • 四、 游戏界面实现
  • 五、在文件中写入历史战绩
    • 5.1 从文件里提取分数
    • 5.2 把贪吃蛇的长度存入文件
  • 六、总结

一、项目介绍

贪吃蛇是久负盛名的游戏,它也和俄罗斯⽅块,扫雷等游戏位列经典游戏的⾏列。 在编程语⾔的教学中,我们以贪吃蛇为例,从设计到代码实现来提升编程能⼒和逻辑能⼒。它通过控制蛇头⽅向吃⻝物,从⽽使得蛇变得越来越⻓。在本游戏中设置了上下左右四个⽅向键来控制蛇的移动⽅向。⻝物的产⽣是随机⽣成的,当蛇每吃⼀次⻝物 就会增加⼀节⾝体,同时游戏积分也会相应的加⼀。
在本游戏的设计中,蛇的⾝体会越吃越⻓,⾝体越⻓对应的难度就越⼤,因为⼀旦蛇头和⾝体相交游戏就会结束。
本项⽬使⽤ Qt 实现⼀款简单的贪吃蛇游戏。
项目的目标:

  1. 游戏大厅界面实现
  2. 难度选择界面实现
  3. 游戏界面实现
  4. 分数记录界面实现

二、游戏大厅界面实现

2.1完成游戏大厅的背景图。

1.背景图的渲染,我们通过QT的绘图事件完成

void gamehall::paintEvent(QPaintEvent *event)
{//实例化一个画家QPainter paint(this);//实例化一个设备QPixmap pix(":res/game_hall.png");//进行绘画paint.drawPixmap(0,0,this->width(),this->height(),pix);}

2.对我们的标题栏进行设置

 	//设置窗口大小this->setFixedSize(1000,800);//设置标题栏图标this->setWindowIcon(QIcon(":res/ico.png"));//设置标题栏标签this->setWindowTitle("游戏大厅");

在这里插入图片描述

2.2创建一个按钮,给它设置样式,并且可以跳转到别的页面

1.创建一个按钮,给它设置样式

  QFont font("华文行楷",25);//设置按钮QPushButton *intoBtn= new QPushButton(this);intoBtn->setFont(font);intoBtn->setText("开始游戏");intoBtn->setStyleSheet("QPushButton{border:0px;}");intoBtn->move(450,520);

2.创建的新页面
点击add new
在这里插入图片描述
3. 建立信号槽,使按钮被点击后跳转界面(这个跳转的界面,是新创建的文件,点击按钮会发出声音)

	//创建另一个窗口GameSelect *select=new GameSelect();connect(intoBtn,&QPushButton::clicked,[=]{//关闭上个窗口this->close();//设置窗口大小select->setGeometry(this->geometry());//显示窗口select->show();//发出声音QSound::play(":res/clicked.wav");

在这里插入图片描述
4.总代码

#include "gamesnake.h"
#include "ui_gamesnake.h"
#include "gameselect.h"
#include <QPainter>
#include <QPixmap>
#include <QIcon>
#include <QPushButton>
#include <QSound>
GameSnake::GameSnake(QWidget *parent): QWidget(parent), ui(new Ui::GameSnake)
{ui->setupUi(this);//设置窗口大小this->setFixedSize(1000,800);//设置窗口图标this->setWindowIcon(QIcon(":res/ico.png"));//设置窗口标签this->setWindowTitle("游戏大厅");//设置字体QFont font("华文行楷",25);//设置按钮QPushButton *intoBtn= new QPushButton(this);intoBtn->setFont(font);intoBtn->setText("开始游戏");intoBtn->setStyleSheet("QPushButton{border:0px;}");intoBtn->move(450,520);//创建另一个窗口GameSelect *select=new GameSelect();connect(intoBtn,&QPushButton::clicked,[=]{//关闭上个窗口this->close();select->setGeometry(this->geometry());select->show();QSound::play(":res/clicked.wav");});
}GameSnake::~GameSnake()
{delete ui;
}void GameSnake::paintEvent(QPaintEvent *event)
{//实例化一个画家QPainter paint(this);//实例化一个设备QPixmap pix(":res/game_hall.png");//进行绘画paint.drawPixmap(0,0,this->width(),this->height(),pix);
}

注意pro文件里的配置加上multimedai

三、难度选择界面实现

我们已经把贪吃蛇的游戏界面完成了,下面就进入关卡选择界面。
在关卡选择界⾯上设置了四个游戏模式按钮,分别是:容易模式、正常模式、困难模式、地狱模式;⼀个 “历史战绩” 按钮;⼀个返回游戏⼤厅界⾯的按钮。
1. 创建按钮,给它设置样式。

    //容易关卡QPushButton *briefnessBtn= new QPushButton(this);briefnessBtn->setStyleSheet("QPushButton{background-color:#0072C6;color: black; border:0px groove gray;border-radius:10px;padding:6px;}");briefnessBtn->move(400,200);QFont font("华文行楷",25);briefnessBtn->setFont(font);briefnessBtn->setText("容易模式");

如图,我已经创建了5个按钮:
在这里插入图片描述

2. 为了使第二个界面可以返回到第一个界面,创建一个按钮,按下按钮触发信号,就可以返回第一个页面。(返回按钮)

//返回按钮
QPushButton *returnBtn= new QPushButton(this);
returnBtn->move(850,700);
returnBtn->setIcon(QIcon(":res/up.png"));connect(returnBtn,&QPushButton::clicked,[=]{this->close();GameSnake *snake= new GameSnake();snake->show();QSound::play(":res/clicked.wav");});

在这里插入图片描述
3. 游戏选择页面跳转到游戏大厅
实现页面之间的跳转

 //实现游戏房间和选择关卡切换//创建另一个窗口GameRoom *room=new GameRoom();//创建按钮,给按钮设置格式//容易关卡QPushButton *briefnessBtn= new QPushButton(this);briefnessBtn->setStyleSheet("QPushButton{background-color:#0072C6;color: black; border:0px groove gray;border-radius:10px;padding:6px;}");briefnessBtn->move(400,200);QFont font("华文行楷",25);briefnessBtn->setFont(font);briefnessBtn->setText("容易模式");connect(briefnessBtn,&QPushButton::clicked,[=]{//关闭上个窗口this->close();room->setGeometry(this->geometry());room->show();QSound::play(":res/clicked.wav");});

以第一个按钮为例,运行后点击简单模式效果如下(这是一个新的界面):
在这里插入图片描述
4. 总代码

#include "gameselect.h"
#include <QPainter>
#include <QPixmap>
#include <QPushButton>
#include "gamesnake.h"#
#include "gameroom.h"
#include <QSound>
GameSelect::GameSelect(QWidget *parent) : QWidget(parent)
{this->setFixedSize(1000,800);//设置窗口图标this->setWindowIcon(QIcon(":res/ico.png"));//设置窗口标签this->setWindowTitle("选择大厅");//实现游戏房间和选择关卡切换//创建另一个窗口GameRoom *room=new GameRoom();//创建按钮,给按钮设置格式//容易关卡QPushButton *briefnessBtn= new QPushButton(this);briefnessBtn->setStyleSheet("QPushButton{background-color:#0072C6;color: black; border:0px groove gray;border-radius:10px;padding:6px;}");briefnessBtn->move(400,200);QFont font("华文行楷",25);briefnessBtn->setFont(font);briefnessBtn->setText("容易模式");connect(briefnessBtn,&QPushButton::clicked,[=]{//关闭上个窗口this->close();room->setGeometry(this->geometry());room->show();QSound::play(":res/clicked.wav");});//正常关卡QPushButton *normalBtn= new QPushButton(this);normalBtn->setStyleSheet("QPushButton{background-color:#0072C6;color: black; border:0px groove gray;border-radius:10px;padding:6px;}");normalBtn->move(400,280);QFont font1("华文行楷",25);normalBtn->setFont(font);normalBtn->setText("正常模式");connect(normalBtn,&QPushButton::clicked,[=]{//关闭上个窗口this->close();room->setGeometry(this->geometry());room->show();QSound::play(":res/clicked.wav");});//困难关卡QPushButton *difficultyBtn= new QPushButton(this);difficultyBtn->setStyleSheet("QPushButton{background-color:#0072C6;color: black; border:0px groove gray;border-radius:10px;padding:6px;}");difficultyBtn->move(400,360);QFont font2("华文行楷",25);difficultyBtn->setFont(font);difficultyBtn->setText("困难模式");connect(difficultyBtn,&QPushButton::clicked,[=]{//关闭上个窗口this->close();room->setGeometry(this->geometry());room->show();QSound::play(":res/clicked.wav");});//地狱关卡
QPushButton *bhellBtn= new QPushButton(this);
bhellBtn->setStyleSheet("QPushButton{background-color:#0072C6;color: black; border:0px groove gray;border-radius:10px;padding:6px;}");
bhellBtn->move(400,440);
QFont font3("华文行楷",25);
bhellBtn->setFont(font);
bhellBtn->setText("地狱模式");
connect(bhellBtn,&QPushButton::clicked,[=]{//关闭上个窗口this->close();room->setGeometry(this->geometry());room->show();QSound::play(":res/clicked.wav");});//排行榜
QPushButton *ranpingBtn= new QPushButton(this);
ranpingBtn->setStyleSheet("QPushButton{background-color:#0072C6;color: black; border:0px groove gray;border-radius:10px;padding:6px;}");
ranpingBtn->move(400,520);
QFont font4("华文行楷",25);
ranpingBtn->setFont(font);
ranpingBtn->setText("历史战绩");//返回按钮
QPushButton *returnBtn= new QPushButton(this);
returnBtn->move(850,700);
returnBtn->setIcon(QIcon(":res/up.png"));connect(returnBtn,&QPushButton::clicked,[=]{this->close();GameSnake *snake= new GameSnake();snake->show();QSound::play(":res/clicked.wav");});
}
void GameSelect::paintEvent(QPaintEvent *event)
{//设置窗口大小this->setFixedSize(1000,800);//创建绘画者QPainter paint(this);//创建画板QPixmap pix(":res/game_select.png");paint.drawPixmap(0,0,this->width(),this->height(),pix);
}

在这里插入图片描述

注意:历史战绩还没有设计

四、 游戏界面实现

前两个页面已经实现完成了,最后完成游戏界面,我们就可以玩上自己写的游戏了。

游戏房间界⾯包含下⾯⼏个部分:
• 背景图的绘制。
• 蛇的绘制、蛇的移动、判断蛇是否会撞到⾃⼰ 。
• 积分的累加和绘制 在这⾥我们要考虑⼏个⽐较核⼼的问题:

  1. 怎么让蛇动起来?
    • 我们可以⽤⼀个链表表⽰贪吃蛇,⼀个⼩⽅块表⽰蛇的⼀个节点, 我们设置蛇的默认⻓度为3。
    • 向上移动的逻辑就是在蛇的上⽅加⼊⼀个⼩⽅块, 然后把最后⼀个⼩⽅块删除即可。
    • 需要⽤到定时器Qtimer 每100 - 200ms 重新渲染。
  2. 怎么判断蛇有没有吃到⻝物?
    • 判断蛇头和⻝物的坐标是否相交,Qt 有相关的接⼝调⽤。
  3. 怎么控制蛇的移动?
    • 借助QT的实践机制实现, 重写keyPressEvent即可, 在函数中监控想要的键盘事件即可 。
    • 我们通过绘制四个按钮,使⽤信号和槽的机制控制蛇的上、下、左、右移动⽅向。

1.先要对游戏界面进行渲染,用到pixmap和painter。

void GameRoom::paintEvent(QPaintEvent *event)
{qDebug("开始绘画");//创建绘画者QPainter paint(this);//创建画板,不带有参数QPixmap pix;//load方法,加载资源或者数据//游戏区域pix.load(":res/game_room.png");paint.drawPixmap(0,0,800,800,pix);//控制区域pix.load(":res/bg1.png");paint.drawPixmap(800,0,201,900,pix);
}

2.创建一个按钮,实现页面之间的跳转

  //创建一个返回按钮QPushButton* returnButton = new QPushButton(this);//设置位置和按钮照片returnButton->move(900,700);returnButton->setIcon(QIcon(":res/up.png"));//创建信号槽connect(returnButton,&QPushButton::clicked,[=]{//关闭当前页面this->close();GameSelect *gameRn = new GameSelect();//显示上个页面gameRn->show();QSound::play(":res/clicked.wav");});

如图:
在这里插入图片描述
3. 对游戏房间数据结构进行封装
gameroom的头文件

#define GAMEROOM_H#include <QWidget>
//枚举蛇的移动方向
enum class kSnakeDirect
{UP = 0,DOWN,LEFT,RIGHT
};class GameRoom : public QWidget
{Q_OBJECT
public:explicit GameRoom(QWidget *parent = nullptr);//重写绘画事件void paintEvent(QPaintEvent *event);
private://表示蛇身体结点的宽度const int kSnakeNodeWidth = 20;//表示蛇身体节点的高度const int kSnakeNodeHeight = 20;//表示蛇的速度const int KDefountTimeout = 100;//表示贪吃蛇的链表QList<QRectF> snakeList;//表示食物的结点QRectF foodRect;//表示蛇初始方向的默认值kSnakeDirect moveDirect = kSnakeDirect::UP;
};

4.蛇移动方向的实现

注意: 这⾥贪吃蛇不允许直接掉头, ⽐如当前是向上的, 不能直接修改为向下。

分别声明:

void moveUp();//蛇向上移动
void moveDown();//蛇向下移动
void moveLeft();//蛇向左移动
void moveRight();//蛇向右移动

在这里插入图片描述
列如蛇向上移动的定义

void GameRoom::moveUp()
{QPointF leftTop; // 左上⻆坐标QPointF rightBottom; // 右下⻆坐标auto snakeNode = snakeList.front();int headX = snakeNode.x();int headY = snakeNode.y();// 如果上⾯剩余的空间不够放⼊⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑if(headY-kSnakeNodeWidth < 0) {leftTop = QPointF(headX, this->height() - kSnakeNodeHeight);} else {leftTop = QPointF(headX, headY - kSnakeNodeHeight);}rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop, rightBottom));
}

5.判断游戏是否结束
贪吃蛇游戏的结束标志是自己碰到自己,才算结束。

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;//游戏正常运行
}

6.在绘图事件里把蛇绘画出来,并初始化贪吃蛇

 //绘制蛇:蛇头+蛇身+蛇尾//绘制蛇头的上下左右if(moveDirect==kSnakeDirect::UP){pix.load(":res/rescopy.png");//加载资源}else if(moveDirect == kSnakeDirect::DOWN){pix.load(":res/rescopy1.png");//加载资源}else if(moveDirect==kSnakeDirect::LEFT){pix.load(":res/rescopy 2.png");//加载资源}else{pix.load(":res/rescopy3.png");//加载资源}//获取链表的头结点auto snakeHeadNode=snakeList.front();//画家绘画,给这个结点绘制pix里面的资源paint.drawPixmap(snakeHeadNode.x(),snakeHeadNode.y(),snakeHeadNode.width(),snakeHeadNode.height(),pix);//绘制蛇身pix.load(":res/rescopy 5.png");for(int i=1;i<snakeList.size()-1;i++){auto node=snakeList.at(i);paint.drawPixmap(node.x()+2,node.y(),node.width()-3,node.height(),pix);}//绘制蛇尾auto TailNode = snakeList.back();paint.drawPixmap(TailNode.x()+2,TailNode.y(),TailNode.width()-3,TailNode.height(),pix);

在构造函数里,初始化贪吃蛇

  // 初始化贪吃蛇snakeList.push_back(QRectF(this->width() * 0.5, this->height() * 0.5,kSnakeNodeWidth, kSnakeNodeHeight));moveUp();moveUp();

7. 定义贪吃蛇的食物

//创建随机的食物
void GameRoom::creatNewFood()
{foodRect= QRectF(qrand()%(800/kSnakeNodeWidth)*kSnakeNodeWidth,qrand()%(800/kSnakeNodeHeight)*kSnakeNodeHeight,kSnakeNodeWidth,kSnakeNodeHeight);
}
//在绘图事件里,绘制食物//绘制食物pix.load(":res/food.bmp");paint.drawPixmap(foodRect.x(),foodRect.y(),foodRect.width(),foodRect.height(),pix);

8.让贪吃蛇移动起来

定时器的是为了实现每隔⼀段时间能处理移动的逻辑并且更新绘图事件。
• ⾸先, 需要判断蛇头和⻝物节点坐标是否相交 ◦ 如果相交, 需要创建新的⻝物节点, 并且需要更新蛇的⻓度, 所以 cnt 需要 +1 ;
• 如果不相交, 那么直接处理蛇的移动即可。
• 根据蛇移动⽅向 moveDirect 来处理蛇的移动, 处理⽅法是在前⽅加⼀个, 并且删除后⽅节点;
• 重新触发绘图事件, 更新渲染。

//在构造函数里编写
timer = new QTimer(this);connect(timer, &QTimer::timeout, this, [=](){int cnt = 1;// 判断是否贪吃蛇和⻝物是否相交if (snakeList.front().intersects(foodRect)) {createNewFood();++cnt;//蛇吃食物的声音QSound::play(":res/eatfood.wav");}while(cnt--) {// 处理蛇的移动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();});

9.设置游戏开始和游戏暂停按钮

在刚进⼊游戏房间界⾯时,⼀定不能点击 “退出” 按钮,如果点击 “退出” 按钮,那么程 序就会异常退出。点击的顺序⼀定是:先点击 “开始” 按钮,最后才能点击 “退出” 。

    //设置开始暂停按钮QPushButton *startbtn = new QPushButton(this);QPushButton *stopbtn = new QPushButton(this);QFont ft("楷体", 20);//设置按钮的位置startbtn->move(860,150);stopbtn->move(860,200);//设置按钮⽂本startbtn->setText("开始");stopbtn->setText("暂停");//设置按钮样式startbtn->setStyleSheet("QPushButton{border:0px;}");stopbtn->setStyleSheet("QPushButton{border:0px;}");//设置按钮字体格式startbtn->setFont(ft);stopbtn->setFont(ft);//蛇移动connect(startbtn,&QPushButton::clicked,this,[=](){isGameStart = true;timer->start(kDefountTimeout);sound = new QSound(":res/Trepak.wav"); //声⾳路径sound->play(); //播放sound->setLoops(-1); //循环播放});//蛇暂停connect(stopbtn,&QPushButton::clicked,this,[=](){isGameStart = false;timer->stop();//停止工作sound->stop();//停止播放});

10. 设置蛇的方向控制

 //设置蛇2的移动方向QPushButton *Up = new QPushButton(this);QPushButton *Down = new QPushButton(this);QPushButton *Left = new QPushButton(this);QPushButton *Right = new QPushButton(this);Up->move(880,400);Down->move(880,480);Left->move(840,440);Right->move(920,440);Up->setStyleSheet("QPushButton{border:0px;}");Up->setFont(font);Up->setText("↑");Down->setStyleSheet("QPushButton{border:0px;}");Down->setFont(font);Down->setText("↓");Left->setStyleSheet("QPushButton{border:0px;}");Left->setFont(font);Left->setText("←");Right->setStyleSheet("QPushButton{border:0px;}");Right->setFont(font);Right->setText("→");connect(Up,&QPushButton::clicked,this,[=](){if(moveDirect != kSnakeDirect::DOWN)moveDirect = kSnakeDirect::UP;});connect(Down,&QPushButton::clicked,this,[=](){if(moveDirect != kSnakeDirect::UP)moveDirect = kSnakeDirect::DOWN;});connect(Left,&QPushButton::clicked,this,[=](){if(moveDirect != kSnakeDirect::RIGHT)moveDirect = kSnakeDirect::LEFT;});connect(Right,&QPushButton::clicked,this,[=](){if(moveDirect != kSnakeDirect::LEFT)moveDirect = kSnakeDirect::RIGHT;});

我们也可以用键盘来控制蛇的方向

void GameRoom::keyPressEvent(QKeyEvent *event)
{switch (event->key()) {case Qt::Key_W :case Qt::Key_Up :if(moveDirect != kSnakeDirect::DOWN)moveDirect = kSnakeDirect::UP;break;case Qt::Key_S :case Qt::Key_Down :if(moveDirect != kSnakeDirect::UP)moveDirect=kSnakeDirect::DOWN;break;case Qt::Key_D :case Qt::Key_Right :if(moveDirect != kSnakeDirect::LEFT)moveDirect=kSnakeDirect::RIGHT;break;case Qt::Key_A :case Qt::Key_Left :if(moveDirect != kSnakeDirect::RIGHT)moveDirect=kSnakeDirect::LEFT;break;//开始case Qt::Key_F :isGameStart = true;timer->start(moveDefount);sound = new QSound(":res/Trepak.wav"); //声⾳路S径sound->play(); //播放sound->setLoops(-1); //循环播放break;
//      //暂停case Qt::Key_G :isGameStart = false;timer->stop();//停止工作sound->stop();//停止播放break;}
}

11.设置游戏退出按钮,并设置一个消息盒子。

    //设置退出按钮,并给他设置样式QPushButton *exitBtn=new QPushButton(this);exitBtn->setText("退出");exitBtn->move(870,750);exitBtn->setFont(font);//设置消息盒子QMessageBox *msg=new QMessageBox(this);QPushButton *okBtn =new QPushButton("OK");QPushButton *cancelBtn =new QPushButton("cancel");msg->addButton(okBtn,QMessageBox::AcceptRole);msg->addButton(cancelBtn,QMessageBox::RejectRole);msg->setWindowTitle("退出游戏");msg->setText("确认退出游戏吗?");connect(exitBtn,&QPushButton::clicked,[=]{//显示消息盒子msg->show();QSound::play(":res/clicked.wav");//事件轮询msg->exec();if(msg->clickedButton()==okBtn){this->close();//关闭程序}else{msg->close();//关闭信息盒子}});

12. 分数的绘制

 //绘制分数pix.load(":res/sorce_bg.png");paint.drawPixmap(this->width()*0.85,this->height()*0.06,90,40,pix);QPen pen;pen.setColor(Qt::black);QFont font("方正舒体",22);paint.setPen(pen);paint.setFont(font);paint.drawText(this->width()*0.9,this->height()*0.1,QString("%1").arg(snakeList.size()));

13.游戏失败的绘制

   //绘制游戏失败效果if(checkFail()){pen.setColor(Qt::red);paint.setPen(pen);QFont font("方正舒体",50);paint.setFont(font);paint.drawText(this->width()*0.25,this->height()*0.5,QString("GAME OVER!"));timer->stop();QSound::play((":res/gameover.wav"));sound->stop();}

在这里插入图片描述
14.实现4种不同游戏模式
在这里插入图片描述
先对各个模式的时间进行设置,然后设置房间的定时器时间,从而改变游戏的模式。

room->setTimer(200);//改变各个模式的速度默认值

通过默认值去改变时间,从而设置游戏模式

在这里插入图片描述

五、在文件中写入历史战绩

通过文件的方式用来显示历史战绩

5.1 从文件里提取分数

读⽂件:读取写⼊⽂件中蛇的⻓度

connect(ranpingBtn,&QPushButton::clicked,[=]{//创建一个窗口控件QWidget *wGet=new QWidget();wGet->setWindowTitle("历史战绩");wGet->setFixedSize(500,300);//创建一个多行输入框QTextEdit *edit=new QTextEdit(wGet);edit->setFont(font);edit->setFixedSize(500,300);//打开文件,并且只能读,文件要自己创建QFile file("D:/QT_creator_3_25/greedy_snake1/Snake/res/1.txt");file.open(QIODevice::ReadOnly);//文本流对象QTextStream in(&file);//in.表示文件,把文件里的数据按行读取,并且转化为整数int data=in.readLine().toInt();edit->append("得分为:");//这里需要的是QString类型,把整形转化为字符串edit->append(QString::number(data));//显示窗口wGet->show();QSound::play(":res/clicked.wav");file.close();
});

在这里插入图片描述

5.2 把贪吃蛇的长度存入文件

写⽂件:往⽂件中写⼊蛇的⻓度

 //把分数存入文件int c=snakeList.size();QFile file("D:/QT_creator_3_25/greedy_snake1/Snake/res/1.txt");if(file.open(QIODevice::Text|QIODevice::WriteOnly)){//输入文本和只写QTextStream out(&file);out<<c;//关闭文件file.close();}

在这里插入图片描述
在这里插入图片描述

最后通过黑盒测试的方法,解决程序的一些问题,确保程序正常运行。(解决了按左右键,游戏就失败的问题;解决了蛇不在窗口跑的问题)

六、总结

做完这个项目,收获非常大。对qt代码的理解也更加深刻,同时也了解了一点额外的知识点
注意:

  1. QPixmap中的load函数是将图片加载到缓冲区,即QPixmapCache中存放图片,当把第一张图片加载到缓冲区会显示图片1,当加载第二张图片时缓冲区的图片1并没有被覆盖,实际是缓冲区存了两张图片,并显示图片2,当再次加载图片1到缓冲区时,这时QPixmapCache认为已经有了图片1,会直接返回true,缓冲区的图片排列顺序并没有发生变化,固依旧显示图片2。
    解决办法:
    (1)QPixmap直接定义局部变量,这样每次会开辟新的缓冲区
    (2)每次加载图片时先清空缓冲区,调用QPixmapCache::clear()
  2. QPointF就是Float QPoint,用法的话QPointF在浮点精度上表示平面上的点,绝大部分操作都是与QPoint相类似的,细微的差别在于运算符重载以及提供了QPoint与QPointF的相互转换。
  3. 在Qt中QList和QVector一般获取元素都是通过 at(index) 来获取得,但是at获取的元素返回值是一个const & 常引用,也就是元素不支持改变。
  4. snakeList.front().intersects(foodRect),判断两个矩形会不会相交。
  5. QTextStream文本流对象
    QTextStream out(&文件指针)
    QTextStream in(&文件指针)

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

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

相关文章

关于vue创建项目失败报错(镜像过期)的解决方案

在新建vue项目时出现以下错误&#xff1a; 原因&#xff1a; npm.taobao.org和registry.npm.taobao.org旧域名于2021年官方公告域名更换事件&#xff0c;已于2022年05月31日零时起停止服务&#xff0c;域名HTTPS证书于2024年1月22日正式到期&#xff0c;不可再用。 解决方案:…

【vue3】【vant】 移动端古诗词句子发布收藏项目

更多项目点击&#x1f446;&#x1f446;&#x1f446;完整项目成品专栏 【vue3】【vant】 移动端古诗词句子发布收藏项目 获取源码方式项目说明&#xff1a;其中功能包括素材包含&#xff1a;项目运行环境运行截图 获取源码方式 加Q群&#xff1a;632562109项目说明&#xf…

突破Web3红海,DePIN如何构建创新生态系统?

撰文&#xff1a;TinTinLand 本文来源香港Web3媒体Techub News专栏作者TinTinLand 2023 年 DePIN 赛道的火热成为 Web3 行业的重点关注方向&#xff0c;当前如何以可扩展、去中心化、安全方式推动 DePIN 赛道赋能下的 AI 版图建设&#xff0c;寻找更多 Web3 行业创新机遇成为…

JS(JavaScript)事件处理(事件绑定)趣味案例

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

创新前沿:Web3如何颠覆传统计算机模式

随着Web3技术的快速发展&#xff0c;传统的计算机模式正面临着前所未有的挑战和改变。本文将深入探讨Web3技术的定义、原理以及它如何颠覆传统计算机模式&#xff0c;以及对全球科技发展的潜在影响。 1. 引言&#xff1a;Web3技术的兴起与背景 Web3不仅仅是技术创新的一种&…

QT中的样式表.qss文件

一、前言 qt中样式表的改变有几种方法&#xff0c;第一种就是直接在ui界面对应的组件右键修改样式表&#xff0c;还有一种就是直接在程序里面修改样式表&#xff0c;我知道的还有一种就是qss文件&#xff0c;这个文件就是将在程序中写的修改样式表的语句写道qss文件中&#xff…

次世代霍尔电磁摇杆搭配磁悬浮马达,这款手柄手感超丝滑,谷粒金刚3Pro体验

燥热的天气里&#xff0c;周末在家打上几局游戏&#xff0c;确实更容易放松身心&#xff0c;玩游戏的时候&#xff0c;键鼠、手柄一类的游戏外设特别重要&#xff0c;对我们的游戏体验影响很大&#xff0c;所以挑选起来总是格外挑剔。现在国产的游戏手柄已经今非昔比了&#xf…

grpc学习golang版(八、双向流示例)

系列文章目录 第一章 grpc基本概念与安装 第二章 grpc入门示例 第三章 proto文件数据类型 第四章 多服务示例 第五章 多proto文件示例 第六章 服务器流式传输 第七章 客户端流式传输 第八章 双向流示例 文章目录 一、前言二、定义proto文件三、编写server服务端四、编写client客…

YouTube广告投放指南:如何投放 YouTube视频广告

在海外广告投放中&#xff0c;YOutube是重要的渠道之一。这篇文章Maskfog将为你介绍Youtube广告类型以及广告投放流程&#xff0c;继续看下去&#xff01; YouTube 视频广告的类型 1.信息流视频广告 信息流视频广告显示在 YouTube 主页、搜索结果页面上&#xff0c;并作为 Yo…

餐饮点餐系统

餐饮点餐系统是一款为餐厅和顾客提供便捷点餐服务的在线平台。 1.DDL CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY COMMENT 用户ID,username VARCHAR(50) NOT NULL UNIQUE COMMENT 用户名,password VARCHAR(255) NOT NULL COMMENT 密码,email VARCHAR(100) UNIQUE…

python爬虫之scrapy框架基本使用

python爬虫之scrapy框架基本使用 1、环境安装&#xff1a;pip install scrapy 2、创建一个工程&#xff1a;scrapy startproject xxxPro 3、cd xxxPro 4、在spiders子目录中创建一个爬虫文件&#xff1a;scrapy genspider spiderName www.xxx.com 5、执行工程&#xff1a;scra…

3DEXPERIENCE平台正在推动仿真技术的创新,旨在创造仿真设计的新境界

随着企业数字化转型的不断推进&#xff0c;3DEXPERIENCE 平台正以其前瞻性的技术和服务重塑仿真设计领域的新高度&#xff0c;助力企业实现仿真技术的再次飞跃。该平台不仅整合了先进的仿真工具与设计流程&#xff0c;还促进了跨部门的协作&#xff0c;降低分析仿真对硬件的要求…

远程桌面无法复制粘贴文件到本地怎么办?

远程桌面不能复制粘贴问题 Windows远程桌面为我们提供了随时随地访问文件和数据的便捷途径&#xff0c;大大提升了工作和生活的效率。然而&#xff0c;在使用过程中&#xff0c;我们也可能遇到一些问题。例如&#xff0c;在通过远程桌面传输文件时&#xff0c;常常会出现无法复…

突破SaaS产品运营困境:多渠道运营如何集中管理?

随着数字化时代的到来&#xff0c;SaaS&#xff08;软件即服务&#xff09;产品已成为企业日常运营不可或缺的工具。然而&#xff0c;在竞争激烈的市场环境下&#xff0c;SaaS产品运营越来越重视多渠道、多平台布局&#xff0c;以更广泛地触及潜在用户&#xff0c;然而&#xf…

Android Native 客户端属性配置系统使用说明

Android Native 客户端属性配置系统使用说明 背景和问题现代 android 开发基本都基于 gradle 属性设置来进行定制化编译,随着项目的迭代,工程结构越发复杂,配置属性越来越多,越来越多的配置使得上手难度越来越大。 解决方案设计一般而言,在 android 开发中,Gradle 属性系…

新国都:昙花一现or未来可期?

从波动起伏到强势爆发&#xff0c;这份业绩能否持续&#xff1f; 今天我们抽取一名铁杆粉丝想要咨询的公司来说一说——新国都。 一句话总结这家以第三方支付为主营业务的公司业绩&#xff1a;盈利能力突然爆发&#xff0c;23年净利润暴增近16倍&#xff0c;24年Q1净利润大增6…

mysql解压版本安装5.7

1. 官网下载好解压版本 我这边5.7版本 https://dev.mysql.com/downloads/file/?id523570 mysql官网 创建 my.ini文件 内容如下 [client] #客户端设置&#xff0c;即客户端默认的连接参数# socket /data/mysqldata/3306/mysql.sock #用于本地连接的socket套接字 # 默…

ASP.NET MVC-简单例子-配置日志文件-log4net

环境&#xff1a; win10&#xff0c;SQL Server 2008 R2 安装 使用NuGet 安装时发现报错并无法安装&#xff1a; 现有 packages.config 文件中检测到一个或多个未解析包依赖项约束。必须解析所有依赖项约束以添加或更新包。如果正在更新这些包&#xff0c;则可忽略此消息&am…

Linux命令 wc(word count)-l(lines)用于统计文件中的行数。

文章目录 1、wc -l2、实战3、wc --help 1、wc -l 在命令 wc -l 中&#xff0c;-l 的英文全称是 lines。这个选项用于指定 wc&#xff08;word count&#xff0c;单词计数&#xff09;命令来统计文件的行数。 例如&#xff0c;当你运行 wc -l load_user_100w_sort.sql 时&…

操作系统之《PV操作》【知识点+详细解题过程】

1、并发进程 &#xff1a; 并发的实质是一个处理器在几个进程之间的多路复用&#xff0c;并发是对有限的物理资源强制行使多用户共享&#xff0c;消除计算机部件之间的互等现象&#xff0c;以提高系统资源利用率。 &#xff08;1&#xff09;并发进程——互斥性&#xff1a; 进…