简单Qt贪吃蛇项目

news2024/11/25 2:29:07

目录

先看效果

项目介绍 

界面一:游戏大厅界面

界面二:关卡选择界面​编辑

界面三:游戏界面

游戏大厅页面

游戏关卡选择页面

游戏房间页面

封装贪吃蛇数据结构

初始化游戏房间界面

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

蛇的移动

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

实现各个方向的移动

实现向上移动

实现向下移动

实现向左移动

实现向右移动

检查是否自己会不会撞自己

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

设置退出游戏按钮

获取历史战绩


先看效果

项目介绍 

贪吃蛇游戏是⼀款休闲益智类游戏。它通过控制蛇头⽅向吃⻝物,从⽽使得蛇变得越来越⻓。在本游戏中设置了上下左右四个⽅向键来控制蛇的移动⽅向。⻝物的产⽣是随机⽣成的,当蛇每吃⼀次⻝物就会增加⼀节⾝体,同时游戏积分也会相应的加⼀。在本游戏的设计中,蛇的⾝体会越吃越⻓,⾝体越⻓对应的难度就越⼤,因为⼀旦蛇头和⾝体相交游戏就会结束。

界面一:游戏大厅界面

当用户点击 “开始游戏” 按钮之后,就会进⼊到关卡选择界面。

界面二:关卡选择界面

在关卡选择界⾯上设置了三个游戏模式按钮,分别是:简单模式、正常模式、困难模式;⼀个 “历史战绩” 按钮;⼀个返回游戏⼤厅界⾯的按钮。
当我们点击三个游戏按钮中的任意⼀个时,就会进⼊游戏房间界⾯,游戏房间界⾯如下:

界面三:游戏界面

在游戏界⾯,如果想要开始游戏,⾸先点击 “开始” 按钮,此时蛇就会移动并且还有背景⾳效。如果 想要暂停游戏,那么点击 “暂停” 按钮即可。当我们在游戏时,可以通过右边控制区域的上下左右方向键来控制蛇的移动。当蛇每吃⼀次⻝物时,伴随有吃⻝物的⾳效,蛇⾝会增加⼀节⻓度,并且分数 积分也会相应的加⼀。最后在控制区域的右下⻆布局了⼀个 “退出” 按钮,当点击 “退出” 按钮时,就会弹出一个对话框,我们点击OK就会退出游戏,点击cancel我们便不会退出游戏。

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

游戏大厅页面

主要内容重写了绘图事件

    //重写绘图事件
    void paintEvent(QPaintEvent *event);
void GameHall::paintEvent(QPaintEvent *event)
{

    (void) event;
    //实例化画家对象
    QPainter painter(this);

    //Qpixmap
    QPixmap pix(":/res/game_hall.png");

    //画家绘画
    painter.drawPixmap(0,0,this->width(),this->height(),pix);

}

固定窗口的大小,同时将其与的窗口也设置为(1000,800),设置窗口的图标以及窗口的标题名,使用信号和槽函数点击开始按钮跳转的游戏选择窗口。

GameHall::GameHall(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::GameHall)
{
    ui->setupUi(this);

    //调整窗口大小
    this->setFixedSize(1000,800);

    //设置窗口的图表
    this->setWindowIcon(QIcon(":/res/ico.png"));
    this->setWindowTitle("贪吃蛇游戏");

    QFont font("华为行楷",24);
    QPushButton* starBtn = new QPushButton(this);
    starBtn->move(430,530);
    starBtn->setFont(font);
    starBtn->setText("开始游戏");
    starBtn->setStyleSheet("QPushButton{border:0px;}");  //去掉边框

    //跳转到第二个窗口
    GameSelect * gameSelect = new GameSelect;
    connect(starBtn,&QPushButton::clicked,[=](){
        this->close();
        //设置第二个窗口和第一个窗口一样大
        gameSelect->setGeometry(this->geometry());

        gameSelect->show();
        QSound::play(":/res/clicked.wav");
    });
}

使用的知识点总结:

  • 通过使用setFixedSize设置窗口的大小
  • 使用setWindowIcon设置左上角的图标
    
  • 使用setWindowTitle设置文本标题
  • 使用lambda表达式
  • 使用信号和槽函数跳转到第二个页面

游戏关卡选择页面

实现代码如下:

    //绘图事件
    void paintEvent(QPaintEvent *event);
GameSelect::GameSelect(QWidget *parent) : QWidget(parent)
{
    
    this->setFixedSize(1000,800); //设置窗口大小(其实可以设置也可以不设置)
    this->setWindowIcon(QIcon(":/res/ico.png"));
    this->setWindowTitle("游戏关卡选择");
    QPushButton* backBtn = new QPushButton(this);
    backBtn->move(900,730);
    backBtn->setIcon(QIcon(":/res/back.png"));
    //信号和槽 跳转到第一个页面
    connect(backBtn,&QPushButton::clicked,[=](){
        this->close();
        GameHall* gameHall = new GameHall;
        gameHall->show();

        //加上音效
        QSound::play(":/res/clicked.wav");
    });

    QFont font("华文行楷",24);

    GameRoom* gameRoom = new GameRoom;

    QPushButton * simpleBtn = new QPushButton(this);
    simpleBtn->move(420,160);
    simpleBtn->setText("简单模式");
    simpleBtn->setFont(QFont(font));
    connect(simpleBtn,&QPushButton::clicked,[=](){
       this->close();
       gameRoom->show();
       QSound::play(":/res/clicked.wav");

       gameRoom->setTimerout(400);
    });

    QPushButton * normalBtn = new QPushButton(this);
    normalBtn->move(420,260);
    normalBtn->setText("正常模式");
    normalBtn->setFont(QFont(font));
    connect(normalBtn,&QPushButton::clicked,[=](){
       this->close();
       gameRoom->setGeometry(this->geometry());
       gameRoom->show();
       QSound::play(":/res/clicked.wav");

       gameRoom->setTimerout(200);
    });

    QPushButton * difficultBtn = new QPushButton(this);
    difficultBtn->move(420,360);
    difficultBtn->setText("困难模式");
    difficultBtn->setFont(QFont(font));
    connect(difficultBtn,&QPushButton::clicked,[=](){
       this->close();
       gameRoom->setGeometry(this->geometry());
       gameRoom->show();
       QSound::play(":/res/clicked.wav");

       gameRoom->setTimerout(50);
    });




    QPushButton * history = new QPushButton(this);
    history->move(420,460);
    history->setText("历史战绩");
    history->setFont(QFont(font));
    QSound::play(":/res/clicked.wav");


    connect(history,&QPushButton::clicked,[=](){
        QWidget * widget = new QWidget;
        widget->setWindowTitle("历史战绩");
        widget->setFixedSize(500,300);
        QTextEdit* edit = new QTextEdit(widget);
        edit->setFont(font);
        edit->setFixedSize(500,300);
        //获取历史战绩  == 获取蛇的长度 -3 就表示吃的食物
        QFile file("C:/Users/19846/Desktop/greedy_snack/1.txt");
        file.open(QIODevice::ReadOnly);
        QTextStream in(&file);
        int data = in.readLine().toInt();

        edit->append("得分为:");
        edit->append(QString::number(data));

        widget->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);
}

游戏房间页面

• 蛇的绘制、蛇的移动、判断蛇是否会撞到自己
• 积分的累加和绘制
在这⾥我们要考虑几个比较核心的问题:
1. 怎么让蛇动起来?
• 我们可以用⼀个链表表示贪吃蛇,⼀个⼩方块表示蛇的⼀个节点, 我们设置蛇的默认长度为3;
• 向上移动的逻辑就是在蛇的上方加入⼀个小方块, 然后把最后⼀个小方块删除即可;
• 需要用到定时器Qtimer 每100 - 200ms 重新渲染。
2. 怎么判断蛇有没有吃到⻝物?
• 判断蛇头和⻝物的坐标是否相交,Qt 有相关的接口调用。
3. 怎么控制蛇的移动?
• 借助QT的实践机制实现, 重写keyPressEvent即可, 在函数中监控想要的键盘事件即可
• 我们通过绘制四个按钮,使⽤信号和槽的机制控制蛇的上、下、左、右移动⽅向

封装贪吃蛇数据结构

//枚举蛇的移动方向
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 moveUp(); //蛇向上移动

    void moveDown();//蛇向下移动

    void moveLeft(); //蛇向左移动

    void moveRight();//蛇向右移动

    bool checkFail(); //判断游戏是否结束

    void crateNewFood(); //创建食物

    void setTimerout(int timeout)
    {
        moveTimeout = timeout;

    }



signals:


private:
    const int kSnakeNodeWidth = 20;  //表示蛇身体节点的宽度
    const int kSnakeNodeHeight = 20; //表示蛇身体的高度
    const int kDefaultTimeout = 200; //设默认的移动速度

    QList<QRectF> snakeList; //表示贪吃蛇链表
    QRectF foodRect;         //表示食物节点

    SnakeDirect moveDirect = SnakeDirect::UP;      //默认移动方向是向上
    QTimer* timer;      //定时器

    bool isGameStart = false;
    QSound* sound;

    int moveTimeout = kDefaultTimeout;
};

初始化游戏房间界面

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

GameRoom::GameRoom(QWidget *parent) :
 QWidget(parent),
 ui(new Ui::Widget)
{
 ui->setupUi(this);
 
 // 初始化窗⼝设置
 this->setFixedSize(1000, 800);
 this->setWindowTitle("贪吃蛇游戏");
 this->setWindowIcon(QIcon(":res/ico.png"));
}

蛇的移动

蛇的移动⽅向为:上、下、左、右。通过在游戏房间中布局四个按钮来控制蛇的移动⽅向。
注意: 这⾥贪吃蛇不允许直接掉头, ⽐如当前是向上的, 不能直接修改为向下。
 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 != SnakeDirect::DOWN)
 moveDirect = SnakeDirect::UP;
 });
 connect(Down,&QPushButton::clicked,this,[=](){
 if(moveDirect != SnakeDirect::UP)
 moveDirect = SnakeDirect::DOWN;
 });
 connect(Left,&QPushButton::clicked,this,[=](){
 if(moveDirect != SnakeDirect::RIGHT)
 moveDirect = SnakeDirect::LEFT;
 });
 connect(Right,&QPushButton::clicked,this,[=](){
 if(moveDirect != SnakeDirect::LEFT)
 moveDirect = SnakeDirect::RIGHT;
})

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

GameRoom::GameRoom(QWidget *parent) :
 QWidget(parent),
 ui(new Ui::Widget)
{
 // 初始化贪吃蛇
 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() / kSnakeNodeWidth) * kSnakeNodeWidth,
 kSnakeNodeWidth,
 kSnakeNodeHeight);
}

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

• ⾸先, 需要判断蛇头和食物节点坐标是否相交

        ◦ 如果相交, 需要创建新的食物节点, 并且需要更新蛇的长度, 所以 cnt 需要 +1 ;

        ◦ 如果不相交, 那么直接处理蛇的移动即可。

• 根据蛇移动方向 moveDirect 来处理蛇的移动, 处理方法是在前方加⼀个, 并且删除后方节点; • 重新触绘图事件, 更新渲染。

        

GameRoom::GameRoom(QWidget *parent) :
 QWidget(parent),
 ui(new Ui::Widget)
{
 timer = new QTimer(this);
 connect(timer, &QTimer::timeout, this, [=](){
 int cnt = 1;
 // 判断是否贪吃蛇和⻝物是否相交
 if (snakeList.front().intersects(foodRect)) {
 createNewFood();
 ++cnt;
 }
 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();
 });
}

实现各个方向的移动

实现向上移动
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();  //蛇头x
    int headY = snakeNode.y();  //蛇头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 rightButtom;
    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);
    }
    rightButtom = leftTop +QPointF(kSnakeNodeWidth,kSnakeNodeHeight);

    snakeList.push_front(QRectF(leftTop,rightButtom));

}
实现向右移动
void GameRoom::moveRight()
{
    QPointF leftTop;
    QPointF rightButtom;
    auto snakeNode = snakeList.front();

    int headX = snakeNode.x();
    int headY = snakeNode.y();
    if(headX + kSnakeNodeWidth > 780)
    {
        leftTop = QPointF(0,headY);
    }
    else
    {
        leftTop = snakeNode.topRight();
    }

    rightButtom = leftTop + QPointF(kSnakeNodeWidth,kSnakeNodeHeight);

    snakeList.push_front(QRectF(leftTop,rightButtom));
}

重写绘图事件函数进行渲染 重写基类的 paintEvent() 方法进行渲染:

  • 渲染背景图
  • 渲染蛇头
  • 渲染蛇⾝体
  • 渲染蛇尾巴
  • 渲染右边游戏控制区域
  • 渲染食物节点
  • 渲染当前分数
  • 游戏结束渲染 game over!
void gameroom::paintEvent(QPaintEvent *event)
{
 QPainter painter(this);
 QPixmap pix;
 pix.load(":res/simple_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/body.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.heig
ht(),pix);
 //渲染⻝物
 pix.load(":res/normal_food.bmp");
 painter.drawPixmap(foodRect.x(), foodRect.y(), foodRect.width(), 
foodRect.height(), pix);
 //渲染右边区域
 pix.load(":res/right_area.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.90, this->height() * 0.06, 
QString("%1").arg(snakeList.size()));
 // 如果检查失败, 渲染game over
 if(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();
}
}

检查是否自己会不会撞自己

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;
}

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

 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{border:0px;}");
 stopbtn->setStyleSheet("QPushButton{border:0px;}");
//设置按钮字体格式
 startbtn->setFont(ft);
 stopbtn->setFont(ft);
 connect(startbtn,&QPushButton::clicked,this,[=](){
 sound = new QSound(":res/Trepak.wav"); //声⾳路径
 sound->play(); //播放
 sound->setLoops(-1); //循环播放
 isGameStart = true;
 timer->start(moveTimeout);
 });
 connect(stopbtn,&QPushButton::clicked,this,[=](){
 sound->stop();
 isGameStart = false;
 timer->stop();
 });

设置退出游戏按钮

当我们点击退出游戏按钮时,当前游戏房间窗口不会立即退出,是会弹窗提示,提示我们是否要退出游戏
//退出游戏按钮
 QPushButton *ExitGame = new QPushButton(this);
 ExitGame->setStyleSheet("QPushButton{border:0px;}");
 ExitGame->move(860,750);
 ExitGame->setFont(ft);
 ExitGame->setText("退出");
 //消息提⽰
 QPushButton *okbtn = new QPushButton("Ok");
 QPushButton *cancelbtn = new QPushButton("Cancel");
 QMessageBox *msg = new QMessageBox(this);
 msg->setWindowTitle("退出游戏"); //设置消息对话框的标题
 msg->setText("确认退出游戏吗?"); //设置消息对话框内容
 msg->setIcon(QMessageBox::Question); //设置消息对话框类型
 msg->addButton(okbtn,QMessageBox::AcceptRole); //Accept Role:接受的⻆⾊
 msg->addButton(cancelbtn,QMessageBox::RejectRole); //Reject Role:排斥
作⽤
 connect(ExitGame,&QPushButton::clicked,[=](){
 //消息提⽰
 msg->show();
 QSound::play(":res/clicked.wav");
 msg->exec(); //阻塞等待⽤⼾输⼊
 if(msg->clickedButton() == okbtn) //点击了ok按钮
 {
 this->close();
 //如果点击了 Ok 按钮,那么就会跳转到游戏关卡界⾯
 GameSelect *s = new GameSelect;
 s->show();
 s->setGeometry(this->geometry());
 QSound::play(":res/clicked.wav");
 sound->stop(); //停⽌背景⾳乐
 }
 else
 {
 msg->close();
 QSound::play(":res/clicked.wav");
 }
 });

获取历史战绩

int c = snakeList.size();
2 QFile file("C:/Users/Lenovo/Desktop/1.txt");
3 if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
4 QTextStream out(&file);
5 int num = c;
6 out << num; // 将int类型数据写⼊⽂件
7 file.close();

读⽂件:读取写⼊文件中蛇的长度

QFile file("C:/Users/Lenovo/Desktop/1.txt");
2 file.open(QIODevice::ReadOnly);
3
4 QTextStream in(&file); //创建⽂本流对象
5 int data = in.readLine().toInt(); //读取第⼀⾏作为整形数据

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

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

相关文章

TR3复现Tramsformer

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 Transformer模型是深度学习中的一个革命性架构&#xff0c;自从在NLP领域引入以来&#xff0c;就因其高效处理序列数据的能力而迅速成为主流。本文将通过…

谷粒商城实战笔记-nginx问题记录

记录在使用nginx中遇到的问题。 文章目录 1&#xff0c;网关路由匹配不生效2&#xff0c;网关路由配置前后顺序导致的问题(非nginx问题)3&#xff0c;nginx.conf upstream配置缺少端口4&#xff0c;配置结尾少分号5&#xff0c; proxy_pass 后跟的服务器 URL 是否以 / 结尾5.1 …

C语言学习:汉诺塔问题

汉诺塔_百度百科 (baidu.com)https://baike.baidu.com/item/%E6%B1%89%E8%AF%BA%E5%A1%94/3468295 // // Created by zzh on 2024/8/6. ////汉诺塔问题#include<stdio.h>void move(char x, char y) {printf("%c --> %c \n", x, y); }int hanoi(int count, i…

2024新版软件测试八股文及答案解析

前言 前面看到了一些面试题&#xff0c;总感觉会用得到&#xff0c;但是看一遍又记不住&#xff0c;所以我把面试题都整合在一起&#xff0c;都是来自各路大佬的分享&#xff0c;为了方便以后自己需要的时候刷一刷&#xff0c;不用再到处找题&#xff0c;今天把自己整理的这些…

WEB渗透未授权访问篇-Redis

测试 redis-cli redis-cli -h 127.0.0.1 flunshall 192.168.0.110:6379>ping PONG 存在未授权访问 JS打内网 var cmd new XMLHttpRequest(); cmd.open("POST", "http://127.0.0.1:6379"); cmd.send(flushall\r\n); var c…

51单片机之LED篇(二)独立按键

一、独立按键的介绍 1.1 独立按键的基本原理 相当于一种电子开关&#xff0c;按下时开关接通&#xff0c;松开时开关断开。 开关功能&#xff1a;独立按键内部通常包含一个有弹性的金属片&#xff0c;当按键被按下时&#xff0c;金属片与触点接触&#xff0c;电路连通&#x…

鸿蒙AI功能开发【hiai引擎框架-语音识别】 基础语音服务

hiai引擎框架-语音识别 介绍 本示例展示了使用hiai引擎框架提供的语音识别能力。 本示例展示了对一段音频流转换成文字的能力展示。 需要使用hiai引擎框架文本转语音接口kit.CoreSpeechKit.d.ts. 效果预览 使用说明&#xff1a; 在手机的主屏幕&#xff0c;点击”asrDemo…

CMake基础教程二

常用 环境变量 SET(ENV{VAR} VALUE)**常用变量&#xff1a;**| 变量名 | 含义 | | ----------------------------- | ---------------------------------------------------------…

Bitwise 首席投资官:忽略短期的市场波动,关注加密货币的发展前景

原文标题&#xff1a;《The Crypto Market Sell-Off: What Happened and Where We Go From Here》撰文&#xff1a;Matt Hougan&#xff0c;Bitwise 首席投资官编译&#xff1a;Chris&#xff0c;Techub News 加密货币市场在周末经历了大幅下跌。从上周五下午 4 点到周一早上 7…

2024年下软考报名全流程+备考指南(八月最新版)

2024年下半年软考备考&#xff0c;一定要知道这几点&#xff01; 2024年下半年软考报名已迫在眉睫&#xff0c;不知不觉间&#xff0c;留给下半年考试小伙伴们的复习时间只有三个月。备考的小伙伴们准备好了吗&#xff1f;这些全程重点&#xff0c;请务必收藏保存&#xff0c;…

C/C++数字与字符串互相转换

前言&#xff1a; 在C/C程序中&#xff0c;会需要把数字与字符串做出互相转换的操作&#xff0c;用于实现程序想要的效果。下面将介绍多种方法实现数字与字符串互相转换。 字符串转为数字 一、利用ASCII 我们知道每个字符都有一个ASCII码&#xff0c;利用这一点可以将字符-0…

vue文件style标签变成黄色,media query is expected

效果如下图所示&#xff0c;红色波浪线&#xff0c;鼠标放上去提示 media query is expected 对比其他文件后发现是引入scss文件后后面少了分号&#xff0c;导致报错&#xff0c;加上分号&#xff0c;效果如下图&#xff0c;完美解决~

文件操作常用函数及makefile的使用

文件操作中常用函数 1. getpwuid 定义: struct passwd *getpwuid(uid_t uid);功能: 根据用户ID&#xff08;UID&#xff09;返回与之对应的passwd结构体指针&#xff0c;该结构体包含用户的详细信息。常用字段: pw_name: 用户名。pw_uid: 用户ID。pw_gid: 用户的组ID。pw_dir…

Qt实现类似淘宝商品看板的界面,带有循环翻页以及点击某页跳转的功能

效果如下&#xff1a; #ifndef ModelDashboardGroup_h__ #define ModelDashboardGroup_h__#include <QGridLayout> #include <QLabel> #include <QPushButton> #include <QWidget>#include <QLabel> #include <QWidget> #include <QMou…

Jenkins保姆笔记(3)——Jenkins拉取Git代码、编译、打包、远程多服务器部署Spring Boot项目

前面我们介绍过&#xff1a; Jenkins保姆笔记&#xff08;1&#xff09;——基于Java8的Jenkins安装部署 Jenkins保姆笔记&#xff08;2&#xff09;——基于Java8的Jenkins插件安装 本篇主要介绍基于Java8的Jenkins第一个Hello World项目&#xff0c;一起实践下Jenkins拉…

第十九节 大语言模型与多模态大模型loss计算

文章目录 前言一、大语言模型loss计算1、loss计算代码解读2、构建模型输入内容与label标签二、多模态大模型loss计算方法1、多模态loss计算代码解读2、多模态输入内容2、大语言模型输入内容3、图像embending如何嵌入文本embeding前言 如果看了我前面文章,想必你基本对整个代码…

Java学习Day24:基础篇14:多线程

1.程序、进程和线程 程序 进程 进程(process)是程序的一次执行过程&#xff0c;或是一个正在执行的程序。是一个动态的过程&#xff1a;有它自身的产 生、存在和消亡的过程。 如&#xff1a; 运行中的QQ运行中的音乐播放器视频播放器等&#xff1b;程序是静态的&#xff0c…

写给小白程序员的一封信

文章目录 1.编程小白如何成为大神&#xff1f;大学新生的最佳入门攻略2.程序员的练级攻略3.编程语言的选择4.熟悉Linux5.学会git6.知道在哪寻求帮助7.多结交朋友8.参加开源项目9.坚持下去 1.编程小白如何成为大神&#xff1f;大学新生的最佳入门攻略 编程已成为当代大学生的必…

音视频开发,最新学习心得与感悟

音视频技术的知识海洋浩瀚无垠&#xff0c;自学之路显得尤为崎岖&#xff0c;技术门槛的存在是毋庸置疑的事实。 对于渴望踏入这一行业的初学者而言&#xff0c;学习资源的匮乏成为了一道难以逾越的障碍。 本次文章主要是给大家分享音视频开发进阶学习路线&#xff0c;虽然我…

三大口诀不一样的代码,小小的制表符和换行符玩的溜呀

# 小案例&#xff0c;打印输出加法口诀 for i in range(1,10):for j in range(1,10):if j>i:breakprint(f"{j}{i}{ji}".strip(),end\t)print() print(\n) for i in range(1,10):for j in range(1,10):if j>i:breakprint(f"{j}x{i}{j*i}",end\t)print…