当前位置: 首页 > news >正文

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(&文件指针)

相关文章:

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

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

Java导出Excel并邮件发送

一、导出Excel 添加maven依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.10-FINAL</version></dependency><dependency><groupId>org.apache.poi</groupI…...

【课程总结】Day12:YOLO的深入了解

前言 在【课程总结】Day11&#xff08;下&#xff09;&#xff1a;YOLO的入门使用一节中&#xff0c;我们已经了解YOLO的使用方法&#xff0c;使用过程非常简单&#xff0c;训练时只需要三行代码&#xff1a;引入YOLO&#xff0c;构建模型&#xff0c;训练模型&#xff1b;预测…...

保护隐私,释放智能:使用LangChain和Presidio构建安全的AI问答系统

保护隐私&#xff0c;释放智能&#xff1a;使用LangChain和Presidio构建安全的AI问答系统 在人工智能&#xff08;AI&#xff09;飞速发展的今天&#xff0c;AI问答系统已经成为企业与客户互动的重要工具。然而&#xff0c;随之而来的个人数据隐私问题也日益凸显。如何在不泄露…...

【高考志愿】自动化

目录 一、专业概述 二、课程设计 三、就业前景与方向 四、志愿填报 五、自动化专业排名 一、专业概述 高考志愿自动化专业选择&#xff0c;无疑是迈向现代化工业与科技发展的一把金钥匙。自动化专业&#xff0c;作为现代工程领域的重要支柱&#xff0c;融合了计算机、电子…...

技巧类题目

目录 技巧类题目 136 只出现一次的数字 191 位1的个数 231. 2 的幂 169 多数元素 75 颜色分类 &#xff08;双指针&#xff09; 287. 寻找重复数 136 只出现一次的数字 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均…...

Vue3自定义指令参数修饰符值(3)

自定义指令参数修饰符值 在vue3中我们如何获取自定义的参数的内容&#xff0c;并根据业务来修改展示的内容呢,需要依靠mounted方法中的bindings参数来获取。 参考实例 directives/unit.js文件 export default function directiveUnit(app){app.directive("unit",{…...

HTML(23)——垂直对齐方式

垂直对齐方式 属性名&#xff1a;vertical-align 属性值效果baseline基线对齐(默认)top顶部对齐middle居中对齐bottom底部对齐 默认情况下浏览器对行内块&#xff0c;行内标签都按文字处理&#xff0c;默认基线对齐 导致图片看起来会偏上&#xff0c;文字偏下。 示例&#…...

linux查看二进制文件

在Linux中&#xff0c;查看二进制文件可以使用hexdump或xxd命令。 例如&#xff0c;要查看一个名为example.bin的二进制文件的内容&#xff0c;可以使用以下命令之一&#xff1a; 使用hexdump&#xff1a; bash hexdump -C example.bin使用xxd&#xff1a; bash xxd exam…...

营销翻车,杜国楹出面道歉,小罐茶的“大师作”故事仓皇结尾

“小罐茶&#xff0c;大师作”&#xff0c;这句slogan曾一度在央视平台长时间、高密度播放&#xff0c;成为家喻户晓的广告词&#xff0c;也打响了小罐茶品牌的名号。但同时&#xff0c;市场上关于“大师作”真实性的质疑也从未停息。 就在6月25日小罐茶十二周年发布会上&#…...

linux server下人脸检测与识别服务程序的系统架构设计

一、绪论 1.1 定义 1.2 研究背景及意义 1.3 相关技术综述 二、人脸检测与识别技术概述 2.1 人脸检测原理与算法 2.2 人脸识别技术及方法 2.3 人脸识别过程简介 三、人脸检测与识别服务程序的系统架构 3.1 系统架构设计 3.2 技术实现流程 四、后续设计及经验瞎谈 4.…...

安装CLion配置opencv和torch环境

配置操作如图&#xff0c;源码见底部附录部分 安装CLion 官网下载 创建项目 设置环境 调整类型为release 配置opencv和项目 编译环境 编译后 重启CLion 测试opencv环境 测试代码 运行main.cpp显示图片 测试torch环境 没标红表示配置成功 附件 CMakeList.txt cmake_mi…...

[leetcode]number-of-longest-increasing-subsequence

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int findNumberOfLIS(vector<int> &nums) {int n nums.size(), maxLen 0, ans 0;vector<int> dp(n), cnt(n);for (int i 0; i < n; i) {dp[i] 1;cnt[i] 1;for (int j 0; j < i…...

[MYSQL] MYSQL库的操作

前言 本文主要介绍MYSQL里 库 的操作 请注意 : 在MYSQL中,命令行是不区分大小写的 1.创建库 create database [if not exists] database_name [charsetutf8 collateutf8_general_ci] ...] create database 是命名语法,不可省略[if not exists] 如果不存在创建,如果存在跳过…...

数字黄金 vs 全球计算机:比特币与以太坊现货 ETF 对比

撰文&#xff1a;Andrew Kang 编译&#xff1a;J1N&#xff0c;Techub News 本文来源香港Web3媒体&#xff1a;Techub News 比特币现货 ETF 的通过为许多新买家打开了进入加密货币市场的大门&#xff0c;让他们可以在投资组合中配置比特币。但以太坊现货 ETF 的通过&#xf…...

互联网直播/点播技术与平台创新应用:视频推拉流EasyDSS案例分析

随着互联网技术的快速发展&#xff0c;直播/点播平台已成为信息传播和娱乐的重要载体。特别是在电视购物领域&#xff0c;互联网直播/点播平台与技术的应用&#xff0c;不仅为用户带来了全新的购物体验&#xff0c;也为商家提供了更广阔的营销渠道。传统媒体再一次切实感受到了…...

怎么在线电脑上做图片二维码?在线3步图片转活码的制作方法

图片怎么才能做成二维码展示呢&#xff1f;图片生成二维码的方式能够在手机上查看图片&#xff0c;有利于图片的快速分享&#xff0c;通过这种方法能够减少对内存的占用&#xff0c;也提高了用户获取图片的便利性。通过生成图片活码能够不断提供最新的图片给用户展示&#xff0…...

lighttpd安装和配置https

apt install lighttpd apt-get install php-cgi lighttpd-enable-mod fastcgi fastcgi-php service lighttpd force-reload lighttpd配置https sudo nano /etc/lighttpd/lighttpd.conf加入&#xff1a; server.modules ("mod_openssl") $SERVER["socket&quo…...

淘客返利平台的API设计与安全

淘客返利平台的API设计与安全 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在构建淘客返利平台时&#xff0c;API设计和安全是两个至关重要的方面。API设计…...

SQL面试真题解答 SQL求连续五天上升 (SQL窗口函数使用)

SQL面试真题解答 SQL求连续五天上升 &#xff08;SQL窗口函数使用&#xff09; sql进阶:求某个日期的连续上涨天数 求解连续区间是数据分析、数据仓库笔试面试中常考的SQL题目&#xff0c;今天分享笔试面试题&#xff0c;期待各位拿到心仪的offer或有所收获&#xff01; 一…...

39 - 安全技术与防火墙

39、安全技术和防火墙 一、安全技术 入侵检测系统&#xff1a;特点是不阻断网络访问&#xff0c;主要是提供报警和事后监督。不主动介入&#xff0c;默默看着你&#xff08;监控&#xff09;。 入侵防御系统&#xff1a;透明模式工作&#xff0c;数据包&#xff0c;网络监控…...

Python学习笔记26:进阶篇(十五)常见标准库使用之性能测试cProfile模块学习使用

前言 本文是根据python官方教程中标准库模块的介绍&#xff0c;自己查询资料并整理&#xff0c;编写代码示例做出的学习笔记。 根据模块知识&#xff0c;一次讲解单个或者多个模块的内容。 教程链接&#xff1a;https://docs.python.org/zh-cn/3/tutorial/index.html 本文主要…...

python中类的继承详解

面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力&#xff1a;它可以使用现有类的所有功能&#xff0c;并在无需重新编写原来的类的情况下对这些功能进行扩展 &#xff08;1&#xff09;在类的继承中&#xff0c;存在父类跟子类&#xff0c;子类可以继…...

社交风潮塑造者:探索用户在Facebook的影响力

在当今数字化社会中&#xff0c;Facebook不仅是人们社交互动的主要平台&#xff0c;更是塑造社交风潮和文化趋势的重要力量。本文将从另一个角度深入探讨用户在Facebook上的影响力&#xff0c;探索其如何通过个人行为和互动&#xff0c;影响和改变社会的各个方面。 个人表达和内…...

Kotlin设计模式:代理模式详解

Kotlin设计模式&#xff1a;代理模式详解 在软件开发中&#xff0c;设计模式是解决常见问题的一种优雅方法。本文将介绍Kotlin中的代理模式&#xff08;Proxy Pattern&#xff09;&#xff0c;其应用场景&#xff0c;以及如何通过实例代码实现这一模式。 代理模式的目的 代理…...

PostgreSQL逻辑备份-pg_dump

1.pg_dump备份恢复 pg_dump 是一个逻辑备份工具。使用 pg_dump 可以在数据库处于使用状态下进行一致 性的备份&#xff0c; 它不会阻塞其他用户对数据库的访问 。 一致性备份是 pg_dump 开始运行时&#xff0c;给数据库打了一个快照&#xff0c;且在 pg_dump 运行过程 中发生…...

UG_NX11.0之Windows11中安装出错及解决方法

UG_NX11.0之Windows11中安装出错及解决方法 文章目录 UG_NX11.0之Windows11中安装出错及解决方法1. 安装出错2. 解决方法1. 设置以兼容性模式运行2. 配置环境变量 3. 再次安装问题解决4. 安装后可删除配置的环境变量(可选) 1. 安装出错 以管理员身份运行Launch.exe,如下 点击D…...

android view 设置过 transalationY/X 后 marginTop/marginStart/Left 不变

在 Android 开发中&#xff0c;当你对一个视图(View)设置了 translationY 属性后&#xff0c;这个视图的 marginTop 属性实际上并不会改变。这是因为 translationY 只会影响视图的绘制位置&#xff0c;而不会改变视图的布局参数。换句话说&#xff0c;translationY 是一个运行时…...

解释在Android中如何实现本地存储,包括SQLite数据库和SharedPreferences。

在Android开发中&#xff0c;本地存储是不可或缺的一部分&#xff0c;它允许应用程序在用户的设备上保存和检索数据。两种常见的本地存储方式是SQLite数据库和SharedPreferences。下面我将从技术难点、面试官关注点、回答吸引力和代码举例四个方面来详细解释如何在Android中实现…...

鸿蒙开发 之 健康App案例

1.项目介绍 该项目是记录用户日常饮食情况&#xff0c;以及针对不同食物摄入营养不同会有对应的营养摄入情况和日常运动消耗情况&#xff0c;用户可以自己添加食品以及对应的热量。 1.1登陆页 1.2饮食统计页 1.3 食物列表页 2.登陆页 2.1自定义弹框 import preferences from oh…...

umi3项目axios 请求参数序列化参数

由于get 请求中有一个日期参数 dates 是一个数组类型。 未处理参数时请求地址是这样的&#xff1a;/api/list?page1&pageSize10&keyWord&dates[]2024-06-10&dates[]2024-06-24 会发现dates后面有中括号,所以前端需要将参数格式处理变成如下&#xff1a;/api…...

js实现数据去重合并

应用场景&#xff0c;一个list&#xff0c;包含已经选择的数据和未选择的数据&#xff0c;新增数据到已选择的数据中。 要考虑到二次选择的数据和已经选择的数据有重复的可能&#xff0c;所以&#xff0c;第一步先从二次选择的数据中进行去重&#xff0c;然后再将两个list进行数…...

[ios逆向]查看ios安装包ipa签名证书embedded.mobileprovision解密 附带解密环境openssl

openssl smime -inform der -verify -noverify -in embedded.mobileprovision 解密embedded.mobileprovision文件 链接&#xff1a;https://pan.baidu.com/s/1UwNOWONKV1SNj5aX_ZZCzQ?pwdglco 提取码&#xff1a;glco –来自百度网盘超级会员V8的分享 可以使用everything 查看…...

tr、cut、split、grep -E

目录 tr命令&#xff1a;替换和删除 cut命令&#xff1a;快速裁剪 split命令&#xff1a;文件拆分 文件合并 面试题 1.现在有一个日志文件&#xff0c;有5个G&#xff0c;能不能快速的打开 2.cat合并和paste合并之间的区别&#xff1f; 3.统计当前主机的连接状态&#…...

《分析模式》漫谈08-单继承不是“唯一继承”

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 《分析模式》第2章这一段&#xff1a; 划线处的single inheritance&#xff0c;2004中译本的翻译&#xff1a; 翻译为“单继承”&#xff0c;是正确的。 2020中译本的翻译&#xff1a…...

c++字典

在C中&#xff0c;“字典”通常指的是std::map或std::unordered_map&#xff0c;它们是标准库中提供的关联容器&#xff0c;用于存储键值对。以下是一些常见的操作示例&#xff0c;包括插入、访问、删除和遍历元素。 使用 std::map std::map 是一种有序的关联容器&#xff0c;键…...

rga_mm: RGA_MMU unsupported Memory larger than 4G!解决

目录 报错完整log如下:解决方案:报错完整log如下: [ 3668.824164] rga_mm: RGA_MMU unsupported Memory larger than 4G! [ 3668.824305] rga_mm: scheduler core[4] unsupported mm_flag[0x0]! [ 3668.824320] rga_mm: rga_mm_map_buffer map dma_buf err...

构建个人文件上传服务:Python Flask实现上传和下载完整指南

介绍 在本教程中&#xff0c;我们将学习如何使用Python Flask框架将文件上传到服务器&#xff0c;并使用SQLite数据库来跟踪上传的文件。我们将提供后端代码和一个示例项目的Git链接&#xff0c;以便您可以轻松地跟随本教程。 准备工作 首先&#xff0c;您需要安装Python和F…...

瓦罗兰特新赛季更新资讯 瓦罗兰特新赛季免费加速器

瓦罗兰特新赛季来喽&#xff0c;这是一款由拳头开发的免费第一人称射击游戏&#xff0c;游戏凭借其独特的玩法和丰富的英雄选择吸引了大量玩家。 我们可以在游戏中选择自己喜欢的角色出场与敌人进行对战&#xff0c;而且每一个角色都有自己独特的道具以及技能&#xff0c;使用好…...

希尔排序的实现

引言 排序在我们生活中十分常见&#xff0c;无论是购物软件中的商品推荐还是名次、排名都与排序算法息息相关。希尔排序是排序中较快的一种&#xff0c;而希尔排序实现的基础是插入排序。 排序的实现 插入排序&#xff08;以升序为例&#xff09; 插入排序的原理是从第二个数…...

使用Python selenium爬虫领英数据,并进行AI岗位数据挖掘

随着OpenAI大火&#xff0c;从事AI开发的人趋之若鹜&#xff0c;这次使用Python selenium抓取了领英上几万条岗位薪资数据&#xff0c;并使用Pandas、matplotlib、seaborn等库进行可视化探索分析。 但领英设置了一些反爬措施&#xff0c;对IP进行限制封禁&#xff0c;因此会用到…...

如何在Android应用程序中实现高效的图片加载和缓存机制。

在Android应用程序中实现高效的图片加载和缓存机制 一、技术难点 在Android应用程序中实现高效的图片加载和缓存机制&#xff0c;主要面临以下几个技术难点&#xff1a; 内存管理&#xff1a;Android设备的内存资源有限&#xff0c;如果加载大量高清图片而不进行适当的内存管…...

【机器学习项目实战(二)】基于朴素贝叶斯的中文垃圾短信分类

完整代码、数据集和相应的报告 链接已经放在了正文最下方, 供大家参考学习 摘要 ​ 本文探讨了中文垃圾短信分类的问题,通过收集实际数据集,运用多种机器学习算法进行分类,并对比了不同算法在垃圾短信分类任务上的性能。本研究旨在提高中文垃圾短信的识别准确率,为构建更…...

当用户需求不详细时,如何有效应对

在项目沟通时&#xff0c;用户对需求说明不详细&#xff0c;可能是由于多种原因。以下是一些可能的原因及如何应对这些问题的建议&#xff1a; 1. 用户不完全理解自己的需求 原因&#xff1a; 用户对技术细节不了解&#xff0c;不知道如何具体描述需求。 用户对项目的全局和…...

最新AI智能聊天对话问答系统源码(图文搭建部署教程)+AI绘画,文生图,TTS语音识别输入,文档分析

一、人工智能语言模型和AI绘画在多个领域广泛应用 人工智能语言模型和AI绘画在多个领域都有广泛的应用。以下是一些它们的主要用处&#xff1a; 人工智能语言模型 内容生成 写作辅助&#xff1a;帮助撰写文章、博客、报告、剧本等。 代码生成&#xff1a;自动生成或补全代码&…...

[图解]SysML和EA建模住宅安全系统-02-现有运营领域-块定义图

1 00:00:00,840 --> 00:00:02,440 首先我们来看画在哪里 2 00:00:02,570 --> 00:00:08,310 你看&#xff0c;这是图的类型&#xff0c;图里面内容 3 00:00:08,320 --> 00:00:10,780 这是元素类型 4 00:00:10,790 --> 00:00:14,900 这是位置&#xff0c;哪个包 …...

【vuejs】首次页面加载时触发那些声明周期钩子函数

1. 首次页面加载触发的钩子 在Vue.js中&#xff0c;页面或组件的首次加载会触发一系列预定义的生命周期钩子函数&#xff0c;这些钩子函数按照特定的顺序执行&#xff0c;允许开发者在组件的不同阶段执行代码。以下是首次页面加载时触发的钩子及其作用&#xff1a; 2.1 befor…...

adb热更新

模拟器连接AndroidStudio 解决:adb server version (36) doesnt match this client (40); killing... 1.G:\ProgramFils\android-sdk\platform-tools adb --version 2.H:\yeshen\Nox\bin adb --version 3.把G:\ProgramFils\android-sdk\platform-…...

Nuxt 的路由结构系统(七)

基本路由配置 在 Nuxt.js 中&#xff0c;每个 .vue 文件在 pages/ 目录下都会自动成为一个路由。文件名决定了路由的路径。例如&#xff1a; pages/ |-- index.vue # 映射到根路径 / |-- about.vue # 映射到路径 /about |-- contact.vue # 映射到路径 /conta…...

不使用AMap.DistrictSearch,通过poi数据绘制省市县区块

个人申请高德地图key时无法使用AMap.DistrictSearch&#xff0c;可以通过poi数据绘制省市县区块 1.进入POI数据网站找到需要的省市县&#xff0c;下载对应的GeoJson文件 &#xff0c;此处为poi数据网站链接 2.​ 处理geoJson数据&#xff0c;可以直接新建json文件&#xff0c;…...

从零开始使用WordPress搭建个人网站并一键发布公网详细教程

文章目录 前言1. 搭建网站&#xff1a;安装WordPress2. 搭建网站&#xff1a;创建WordPress数据库3. 搭建网站&#xff1a;安装相对URL插件4. 搭建网站&#xff1a;内网穿透发布网站4.1 命令行方式&#xff1a;4.2. 配置wordpress公网地址 5. 固定WordPress公网地址5.1. 固定地…...

机器学习——岭回归

1、岭回归与线性回归的区别 岭回归&#xff08;Ridge Regression&#xff09;和线性回归&#xff08;Linear Regression&#xff09;都是用于回归分析的统计方法&#xff0c;但它们在处理方式和应用场景上有一些关键的区别&#xff1a; a)基本概念 线性回归&#xff1a;目标是…...

微信小程序:图片转icon

svg方式 通过svg图片的方式也能实现自定义icon。但是相比第一种方式&#xff0c;svg图片可以修改颜色&#xff0c;并且缩放的失真率也比较低。不过小程序wxss并不支持加载本地的svg图片。我们可以通过在线(https://www.sojson.com/image2base64.html)svg转base64的方式在wxss中…...

菜鸡的原地踏步史(◐‿◑)

leetcode启动&#xff01;(╯‵□′)╯︵┻━┻ 尝试改掉想到哪写哪的代码坏习惯 链表 相交链表 public class Solution {/**ac&#xff08;公共长度&#xff09;b所以 链表A的长度 a c&#xff0c;链表B的长度b ca b c b c a只要指针a从headA开始走&#xff0c;走完再…...

简述Vue中的数据双向绑定原理

Vue中的数据双向绑定原理是Vue框架的核心特性之一&#xff0c;它通过数据劫持结合发布者-订阅者模式来实现。下面将详细阐述Vue中数据双向绑定的原理&#xff0c;并尽量按照清晰的结构进行归纳&#xff1a; 一、数据劫持 使用Object.defineProperty()&#xff1a; Vue在组件…...

基于jeecgboot-vue3的Flowable流程-集成仿钉钉流程(二)增加基本的发起人审批与多用户多实例

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、AssigneeNode 增加approvalText public abstract class AssigneeNode extends Node {// 审批对象private AssigneeTypeEnum assigneeType;// 表单内人员private String formUser;// 表…...

对比探界者Plus、探岳、CR-V,该如何选?

对于多数以家庭为购车出发点的消费者来说,一台15-20万级的合资SUV,基本能够满足品牌、空间、配置、品质方面的多重购车需求。因此这个价位的车型往往有着巨大的体量和需求,同时也意味着竞争的激烈程度非比寻常。以往大家做选择时,可能会将注意力放在德系和日系合资车型上,…...

售价为36.98万元斯巴鲁WRX正式上市,值得入手吗?

在汽车市场上,每一次新车型的发布都是一场技术与激情的盛宴,尤其是对于性能车的狂热爱好者来说。2024年5月10日,斯巴鲁宣布其WRX车型的2025款将正式在中国市场上市,定价为36.98万元。这款车将通过平行进口的方式引进,且仅限量200台。考虑到其在车迷中的地位及其性能指标,…...

本田CR-V与大众途观L车辆对比:资深人士解析,长期使用明显区别

在汽车市场领域,本田CR-V及大众途观L皆为备受瞩目的SUV车型。它们在市场上一直是激烈的竞争对手,消费者往往在它们之间犹豫不决。关于本田CR-V与大众途观L的对比文章,以帮助消费者更好地了解这两款车型的优劣势,并做出更明智的选择。一、车型特点本田CR-V是一款紧凑型SUV,…...

车身结构的匠心打造:星途揽月与传祺GS8的安全对决

在谈论汽车的安全性时,车身结构作为一个核心要素,其重要性不言而喻。今天,我们将对两款备受瞩目的SUV——星途揽月和传祺GS8的车身结构进行深入剖析。我们将详细探讨这两款车型在车身设计上如何精益求精,通过独特的匠心独运,旨在为乘客提供最为周全和最大程度的保护,从而…...

ffmpeg3.1.1版本连接ftp服务器失败

发现这个问题是在ffmpeg4之后修复的&#xff1a; 原因在于libavformat文件下的ftp.c文件&#xff1a; 修改方法&#xff1a;加入在TCP控制连接时加入应答代码202&#xff1a; static int ftp_features(FTPContext *s) {static const char *feat_command "FEAT\r\…...

【技术】汉诺塔的递归问题解析及多语言实现

汉诺塔的递归问题解析及多语言实现 汉诺塔&#xff08;Hanoi Tower&#xff09;问题是一个非常经典的递归问题。它起源于一个古老的传说&#xff1a;有三个柱子和64个大小不一的金盘&#xff0c;开始时这些金盘按从小到大的顺序放在柱子A上&#xff0c;目标是在柱子B上按同样的…...