【Qt项目专栏】贪吃蛇小游戏1.0


  • 博客主页:Duck Bro 博客主页
  • 系列专栏:Qt 专栏
  • 关注博主,后期持续更新系列文章
  • 如果有错误感谢请大家批评指出,及时修改
  • 感谢大家点赞👍收藏⭐评论✍

贪吃蛇小游戏1.0

项目编号:01

文章目录

  • 贪吃蛇小游戏1.0
    • 一、项目介绍及演示
      • 1. 项目介绍
      • 2. 项目演示
      • 3. 窗口介绍
        • 3.1 游戏大厅窗口
        • 3.2 游戏关卡选择窗口
        • 3.3 游戏房间窗口
    • 二、创建项目及资源配置
      • 1. 创建项目(QWidget)
      • 2. 资源配置(图片声音素材)
    • 三、项目实现
      • 1. 游戏大厅
        • 1.1 重写绘图事件
        • 1.2 设置窗口大小、图标、标题
        • 1.3 设置开始按钮样式
      • 2. 游戏关卡选择
        • 2.1 创建GameSelect类
        • 2.2 连接按钮和窗口跳转
      • 3. 游戏房间
        • 3.1 创建GameRoom类
        • 3.2 对游戏房间数据结构进行封装
        • 3.3 初始化游戏房间界面
        • 3.4 绘制界面窗口
        • 3.5 蛇的移动
        • 3.6 绘制蛇头身体尾巴
        • 3.6 绘制食物与分数
        • 3.7 判定游戏结束
        • 3.8 随机生成食物节点
        • 3.9 创建游戏开始和暂停按钮
        • 3.10 实现定时器的超时槽函数
        • 3.11 设置游戏退出按钮
        • 3.12 获取历史战绩
    • 四、项目源码获取
      • 1. 网盘链接
      • 2. Gitee链接


一、项目介绍及演示

1. 项目介绍

贪吃蛇游戏规则:简单来说,贪吃蛇游戏规则是玩家通过四个方向键来控制蛇的移动控制其在地图上吃豆子。蛇运动过程中撞到墙壁或蛇身,则立即结束游戏。

当前是贪吃蛇1.0版本,后续会对贪吃蛇游戏进行美化及增加更多功能,尽情期待。
在贪吃蛇2.0中会对项目进行图片的美化,及键盘快捷键的添加。

2. 项目演示

动图演示【GIF动图演示】
在这里插入图片描述

3. 窗口介绍

3.1 游戏大厅窗口

在首页中有历史战绩、开始游戏两个按钮。历史战绩用于展示以前游玩的历史记录;开始游戏用于跳转到游戏关卡选择难度界面。
在这里插入图片描述

3.2 游戏关卡选择窗口

在这里插入图片描述

3.3 游戏房间窗口

在这里插入图片描述


二、创建项目及资源配置

1. 创建项目(QWidget)

在桌面上创建一个名为Snake的文件夹,用于存放项目代码

在这里插入图片描述
打开Qt,点击新建项目
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

2. 资源配置(图片声音素材)

在上述创建完成后,新建一个qrc文件,步骤如下
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
完成上述步骤,将素材包复制到项目中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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


三、项目实现

1. 游戏大厅

1.1 重写绘图事件

在gamehall.h文件中,进行重写绘图事件函数的声明

在这里插入图片描述

鼠标当到painEvent函数上点击Alt+Enter(回车),为painEvent函数添加定义

在这里插入图片描述
在上述过程后,开始编辑painEvent函数。
第一步,先实例化画家,使用QPainter painter(this)实例化一个画家,this是让画家在当前窗口(gamehall)进行绘制。注意在使用QPainter需要包含头文件#include<QPainter>
第二步,再实例化绘图设备,将图片加载到绘图设备中。注意在使用QPixmap需要包含头文件#include<QPixmap>
第三步,再进行绘画,使用drawPixmap()方法,参数1和参数2,表示绘制开始的坐标;参数3,表示绘制的宽度;参数4,表示绘制的高度;参数5,表示绘制的图片。

void GameHall::paintEvent(QPaintEvent *event)
{
    //实例化画家,this:让画家在当前窗口进行绘制
    QPainter painter(this);
    //实例化绘图设备
    QPixmap pix(":/res/game_hall.png");
    //绘画 0,0从界面左上角开始绘画根据窗口的宽和高进行绘制
    painter.drawPixmap(0,0,this->width(),this->height(),pix);
}
1.2 设置窗口大小、图标、标题

第一步,先修改窗口的大小通过setFixedSize()方法将窗口的宽度设置为1000,高度设置为800。
第二步,设置窗口的图标先通过QIcon()将图片加载到项目中,再通过setWindowIcon()方法设置到窗口中。
第三步,设置窗口的标题通过setWindowTitle()方法将文字设置到窗口标题中。

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("游戏大厅");
}
1.3 设置开始按钮样式

第一步,通过QPushButton创建一个游戏开始按钮,按钮文本设置为"开始游戏",this在父窗口中显示。
第二步,通过move移动按钮再窗口中的位置,消除按钮的边框。
第三步,修改按钮中的文本样式,需要先创建一个字体样式(字体为黑体,大小为20像素),最后通过setFont方法将字体样式加载到按钮中。

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("游戏大厅");


    //添加开始游戏按钮
    QPushButton * startButton = new QPushButton("开始游戏",this);
    //设置按钮的位置
    startButton->move(450,600);
    //消除按钮边框
    startButton->setStyleSheet("QPushButton{border:0px}");
    //创建字体样式
    QFont font("黑体", 20);
    //将字体样式加入到按钮文本中
    startButton->setFont(font);

}

点击运行,游戏大厅窗口界面就完成了,如下图
在这里插入图片描述

2. 游戏关卡选择

2.1 创建GameSelect类

先创建一个新的类,名为为GameSelect,基类选择QWidget
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 连接按钮和窗口跳转

在gamehall.cpp中进行编辑按钮的信号和槽,实现点击按钮跳转至关卡选择窗口
第一步,先创建出一个GameSelect窗口,在创建时要包含头文件#include "gameselect.h"
第二步,进行连接使用connnect()方法进行信号和槽函数之间的连接,使用Lambda表达式进行槽函数的编写。
第三步,编辑Lambda表达式,使用close()方法关闭当前窗口。
第四步,将关卡选择窗口设置为同游戏大厅窗口大小相同。
第五步,打开游戏关卡选择窗口。
第六步,给按钮添加点击音效,首先在.pro文件中添加multimedia,然后使用play()进行添加音效。
在这里插入图片描述

#include "gamehall.h"
#include "ui_gamehall.h"
#include "gameselect.h"
#include <QPainter>
#include <QPixmap>
#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->setWindowIcon(QIcon(":/res/ico.png"));
    //设置窗口标题
    this->setWindowTitle("游戏大厅");


    //添加开始游戏按钮
    QPushButton * startButton = new QPushButton("开始游戏",this);
    //设置按钮的位置
    startButton->move(450,600);
    //消除按钮边框
    startButton->setStyleSheet("QPushButton{border:0px}");
    //创建字体样式
    QFont font("黑体", 20);
    //将字体样式加入到按钮文本中
    startButton->setFont(font);
    //新建GameSelect窗口
    GameSelect * gameSelect = new GameSelect;

    //Lambda表达式
    connect(startButton,&QPushButton::clicked,[=](){
        //先关闭当前窗口
        this->close();
        //设置gameSelect窗口大小跟gamehall窗口大小一样
        gameSelect->setGeometry(this->geometry());
        //打开gameselect窗口
        gameSelect->show();
        //添加按钮点击的音效
        QSound::play(":/res/clicked.wav");

    });

}

编写gameselect.h文件,同游戏大厅步骤,这里不重复进行介绍,,详细看下下方代码注释。

在这里插入图片描述

#include "gameselect.h"
#include "gamehall.h"
#include <QPainter>
#include <QPixmap>
#include <QPushButton>
#include <QIcon>
#include <QSound>
GameSelect::GameSelect(QWidget *parent) : QWidget(parent)
{
    //设置窗口大小
    this->setFixedSize(1000,800);
    //设置窗口的图标
    this->setWindowIcon(QIcon(":/res/ico.png"));
    //设置窗口标题
    this->setWindowTitle("关卡选择");


    //创建返回按钮
    QPushButton * returnbutton = new QPushButton(this);
    returnbutton->resize(50,50);
    returnbutton->setIcon(QIcon(":/res/back.png"));
    returnbutton->setIconSize(returnbutton->size());
    returnbutton->move(900,700);

    //建立信号和槽函数的联系
    connect(returnbutton,&QPushButton::clicked,[=](){
        //创建游戏大厅窗口
        GameHall * gamehall = new GameHall;
        //关闭当前窗口
        this->close();
        //展开游戏大厅窗口
        gamehall->show();
        //添加音效
        QSound::play(":/res/clicked.wav");

    });

    //创建文本样式
    QFont font("黑体",30);

    //创建简单难度按钮
    QPushButton * simplebutton = new QPushButton("简单模式",this);
    //将样式设置到按钮中
    simplebutton->setFont(font);
    //设置按钮在窗口中的位置
    simplebutton->move(400,170);
    //进行信号与槽的连接
    
    //创建普通难度按钮
    QPushButton * commonbutton = new QPushButton("普通模式",this);
    //将样式设置到按钮中
    commonbutton->setFont(font);
    //设置按钮在窗口中的位置
    commonbutton->move(400,270);

    //创建困难难度按钮
    QPushButton * difficultybutton = new QPushButton("困难模式",this);
    //将样式设置到按钮中
    difficultybutton->setFont(font);
    //设置按钮在窗口中的位置
    difficultybutton->move(400,370);

    //创建历史记录按钮
    QPushButton * hisbutton = new QPushButton("历史记录",this);
    //将样式设置到按钮中
    hisbutton->setFont(font);
    //设置按钮在窗口中的位置
    hisbutton->move(400,470);

}

void GameSelect::paintEvent(QPaintEvent *event)
{
    //实例化画家,this:让画家在当前窗口进行绘制
    QPainter painter(this);
    //实例化绘图设备
    QPixmap pix(":/res/game_select.png");
    //绘画
    painter.drawPixmap(0,0,this->width(),this->height(),pix);
}

3. 游戏房间

3.1 创建GameRoom类

根据上面步骤后,新建GameRoom类
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.2 对游戏房间数据结构进行封装
#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 moveUp(); //向上移动
    void moveDown();//向下移动
    void moveLeft();//向左移动
    void moveRight();//向右移动
    bool checkFail();//判断游戏结束
    void createNewFood();//创建食物
    void setTimeout(int timeout){moveTimeout =timeout;}

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;

};

#endif // GAMEROOM_H


3.3 初始化游戏房间界面
//设置窗口大小
    this->setFixedSize(1000,800);
    //设置窗口的图标
    this->setWindowIcon(QIcon(":/res/ico.png"));
    //设置窗口标题
    this->setWindowTitle("游戏房间");
3.4 绘制界面窗口
void GameRoom::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    QPixmap pix;

    pix.load(":/res/game_room.png");

    painter.drawPixmap(0,0,800,800,pix);

    pix.load(":/res/bg1.png");

    painter.drawPixmap(800,0,200,850,pix);
}
3.5 蛇的移动
//创建上下左右按钮
    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->setFont(font);
    down->setFont(font);
    left->setFont(font);
    right->setFont(font);

    up->setStyleSheet("QPushButton{border:0px}");
    down->setStyleSheet("QPushButton{border:0px}");
    left->setStyleSheet("QPushButton{border:0px}");
    right->setStyleSheet("QPushButton{border:0px}");

    //按钮控制移动方向,不能直接掉头
    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;
    });

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>800-2*KSnakeNodeWidth)
    {
        leftTop=QPointF(0,headY);
    }else{
        leftTop=snakeNode.topRight();
    }
    rightBottom = leftTop + QPointF(KSnakeNodeWidth,KSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop,rightBottom));
}
3.6 绘制蛇头身体尾巴
//绘制蛇
    //蛇头
    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);

3.6 绘制食物与分数
//绘制食物节点
    //先进行加载食物
    pix.load(":/res/food.bmp");
    painter.drawPixmap(foodRect.x(),foodRect.y(),foodRect.width(),foodRect.height(),pix);
    //绘制分数
    pix.load(":res/sorce_bg.png");
    painter.drawPixmap(this->width()*0.85,this->height()*0.03,100,50,pix);
    QPen pen;
    pen.setColor(Qt::black);
    painter.setPen(pen);
    QFont font("黑体",22);
    painter.setFont(font);
    painter.drawText(this->width()*0.9,this->height()*0.08,QString("%1").arg(snakeList.size()));
    //往文件中写分数
    int c = snakeList.size();
    QFile file("C:/Users/26256/Desktop/his.txt");
    if(file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        QTextStream out(&file);
        int num = c;
        out << num;
        file.close();
    }

3.7 判定游戏结束
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.8 随机生成食物节点
void GameRoom::createNewFood()
{
    foodRect=QRectF(qrand() %(800/KSnakeNodeWidth)*KSnakeNodeWidth,
                    qrand() %(this->height()/KSnakeNodeHeight)*KSnakeNodeHeight,
                    KSnakeNodeWidth,
                    KSnakeNodeHeight
                    );

}
3.9 创建游戏开始和暂停按钮
//开始游戏   结束游戏

    QPushButton * startButton = new QPushButton("开始",this);
    QPushButton *failButton = new QPushButton("暂停",this);

    startButton->move(860,100);
    failButton->move(860,150);

    startButton->setFont(font2);
    failButton->setFont(font2);

    connect(startButton,&QPushButton::clicked,[=](){
        isGameStart=true;
        timer->start(moveTimeout);
        sound = new QSound(":res/Trepak.wav");
        sound->play();
        sound->setLoops(-1);
    });

    connect(failButton,&QPushButton::clicked,[=](){
        isGameStart=false;
        timer->stop();
        sound->stop();
3.10 实现定时器的超时槽函数
  timer = new QTimer(this);
    connect(timer,&QTimer::timeout,[=]()
    {
        int cont =1;
        if(snakeList.front().intersects(foodRect))
        {
            createNewFood();
            cont++;
            QSound::play(":/res/eatfood.wav");

        }

        while(cont--)
        {
            switch (moveDirect) {

            case SnakeDirect::UP :
                moveUp();
                break;
            case SnakeDirect::DOWN:
                moveDown();
                break;
            case SnakeDirect::LEFT:
                moveLeft();
                break;
            case SnakeDirect::RIGHT:
                moveRight();
                break;

            }
        }
        snakeList.pop_back();
        update();
    });
3.11 设置游戏退出按钮

    //退出游戏按钮

    QPushButton *backButton = new QPushButton("退出",this);
    backButton->move(860,700);
    backButton->setFont(font2);
    QMessageBox * messbox = new QMessageBox(this);
     QPushButton * ok = new QPushButton("ok");
    QPushButton * no = new QPushButton("no");



    messbox->addButton(ok,QMessageBox::AcceptRole);
    messbox->addButton(no,QMessageBox::ResetRole);

    messbox->setText("确定要退出游戏吗?");

    connect(backButton,&QPushButton::clicked,[=](){
        messbox->show();
        messbox->exec();
        QSound::play("clicked.wav");

        GameSelect* select = new GameSelect;
        if(messbox->clickedButton()==ok)
        {
            this->close();
            select->show();
       }else{
            messbox->close();
        }

    });
3.12 获取历史战绩
//创建历史记录按钮
    QPushButton * hisbutton = new QPushButton("历史记录",this);
    //将样式设置到按钮中
    hisbutton->setFont(font);
    //设置按钮在窗口中的位置
    hisbutton->move(400,470);
    connect(hisbutton,&QPushButton::clicked,[=](){
        QWidget * widget = new QWidget();
        widget->setFixedSize(200,80);
        widget->setWindowTitle("历史战绩");
        QTextEdit * edit = new QTextEdit(widget);
        edit->setFixedSize(200,80);
        edit->setFont(font);
        QFile file("C:/Users/26256/Desktop/his.txt");
        file.open(QIODevice::ReadOnly);

        QTextStream in(&file);
        int data = in.readLine().toInt();
        edit->append("得分为:");
        edit->append(QString::number(data));

        widget->show();

    });

四、项目源码获取

1. 网盘链接

百度网盘:https://pan.baidu.com/s/1Vm1aJ6AtyzfPdYSCIC0ygg?pwd=duck
提取码:duck

2. Gitee链接

Gitee链接:Qt贪吃蛇小游戏项目代码


在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

生信技能48 - 如何获取基因的SNP及RefSeq参考序列命名规则

1. SNP概念 SNP 是指基因组水平上由单个核苷酸的变异所引起的DNA 序列多态性,在群体中的发生频率不小于1 %,包括单个碱基的转换、颠换、插入和缺失等。每核苷酸发生突变的概率大约为10 -9 , 由于压力选择,SNP在单个基因和基因组以及动物不同种群间分布是不均匀的,在非编码…

虚拟机使用桥接模式网络配置

1、获取本机的网络详细信息 windowr 输入cmd 使用ipconfig -all 一样即可 在自己的虚拟机中设置网络 虚拟机中的ip ---------192.168.36.*&#xff0c;不要跟自己的本机ip冲突 网关-----------192.168.36.254 一样即可 dns -----------一样即可&#xff0c;我多写了几个&am…

C | 在ubuntu22下开发的一些配置

目录 VScode设置 要下载的插件&#xff1a; 卸载VScode的话就是哪装的哪删。 浅用gcc 预处理指令 使用gcc 语言编译过程 1. 预处理&#xff08;Preprocessing&#xff09; 2. 编译&#xff08;Compilation&#xff09; 3. 汇编&#xff08;Assembly&#xff09; 4. …

最长回文子串问题详解

最长回文子串的问题描述&#xff1a;给出一个字符串S&#xff0c;求S的最长回文子串的长度。 针对这个问题&#xff0c;先看暴力解法&#xff1a;枚举子串的两个端点i和j&#xff0c;判断在[i,j]区间内的子串是否回文。从复杂度上来看&#xff0c;枚举端点需要&#xff0c;判断…

Linux、Windows安全加固

为了减少系统被黑客入侵&#xff0c;对操作系统的安全加固是网络安全和主机安全必不可少的一部分。 一、Linux安全加固 1.不使用默认的ssh端口&#xff0c;修改默认ssh22端口号 sudo vim /etc/ssh/ssh_config 去掉#注释&#xff0c;修改端口号并保存 2.关闭不必要的系统服务…

芯片验证分享8 —— 代码审查2

大家好&#xff0c;我是谷公子&#xff0c;上节课给大家讲了代码审查中的代码正向检查&#xff0c;今天我们来讲代码审查的其他方法。 今天介绍的检查方法有&#xff1a; 代码反向检查 桌面检查 同行评审 可用性验证 这些验证方法可以应用在芯片开发的任何阶段。代码审查…

vitepress搭建的博客系统cdn引入github discussions评论系统

github仓库必须是公开的。 按照CDN的方式引入 打开discussions模块 安装giscus app 配置giscus 就是刚安装了giscus app的仓库 页面往下走&#xff0c;生成了代码&#xff1a; 配置vitepress 采用了CDN的方式引入 使用web component 随便找个地方试试组件 效果 有了…

Windows 托盘图标实现类封装及使用(附源码)

在系统桌面右下角的托盘区域,创建一个托盘图标,已经是很多软件的标配了,特别是IM即时通讯软件,要在托盘图标上显示来消息时的闪动头像。 其实托盘图标创建很简单,使用起来也比较方便,主要是调用Shell_NotifyIcon API函数,传入不同参数表示对应的操作: 1)NIM_AD…

ROS创建一个软件包

 首先&#xff0c; 配置您的 ROS 2 安装环境。 让我们使用您在 先前教程 中创建的工作空间 ros2_ws 来创建您的新软件包。 在运行软件包创建命令之前&#xff0c;请确保您位于 src 文件夹中。 LinuxmacOSWindows cd ~/ros2_ws/src在ROS 2中创建新包的命令语法如下&#…

R进阶使用技巧

Introduction 分享一些R进阶使用的技巧&#xff0c;相当于是之前写的R语言学习的实践和总结了。 Online slide: https://asa-blog.netlify.app/R_tips_for_advanced_use_byAsa/R_tips.html 下载slide和相关的各种test文件: https://asa-blog.netlify.app/R_tips_for_advanced…

会声会影2024一共新增了8项功能

会声会影2024一共新增了8项功能。 一、语音转文字视频中语音能自动转换成文本&#xff0c;节省手动创建字幕时间&#xff01;会声会影2022可以捕获视频中的字幕&#xff0c;并将它应用到任何地方。这个功能是我觉得本次更新中最强大的&#xff0c;再也不需要为手动输入字幕发愁…

以太网基础知识(二)—NRZ,PAM4调制技术

1&#xff1a;码元 了解调制技术需要引出“码元”的概念。 一个码元就是一个脉冲信号&#xff0c;即一个最小信号周期内的信号&#xff0c;我们都能够理解&#xff0c;最简单的电路&#xff0c;以高电平代表1&#xff0c;低电平代表0&#xff0c;一个代表1或者0的信号&#x…

关于QTcreator,19年大学时写的文章了,之前写在印象笔记现在拉过来,往事如烟呐

1.初来乍到&#xff0c;先按照书本写一个基础列程理解一下原理。 这里创建工程的时候选择Qdialog基类&#xff0c;dialog.h头文件&#xff0c;并且勾选了创建界面 &#xff08;勾选之后可以通过手动添加组块并且可以自生成他们的函数定义&#xff0c;如果没有勾选&#xff0c;…

纽约华尔街Wall Street 简介

中文版 华尔街简介 华尔街位于纽约市曼哈顿下城&#xff0c;是全球最重要的金融中心之一。它代表了美国的金融市场&#xff0c;并且是许多重要金融机构的所在地。以下是对华尔街的概述&#xff1a; Source: Google Map 历史背景 起源&#xff1a;"华尔街"这个名字…

springboot + Vue前后端项目(第十六记)

项目实战第十六记 写在前面1 第一个bug1.1 完整的Role.vue 2 第二个bug2.1 修改路由router下面的index.js 总结写在最后 写在前面 发现bug&#xff0c;修复bug 1 第一个bug 分配菜单时未加入父id&#xff0c;导致分配菜单失效 <!-- :check-strictly"true" 默…

框架的使用

什么是框架&#xff1f; 盖房子&#xff0c;框架结构 框架结构就是房子主体&#xff0c;基本功能 把很多基础功能已经实现&#xff08;封装了&#xff09; 框架&#xff1a;在基础语言之上&#xff0c;对各种基础功能进行封装&#xff0c;方便开发者&#xff0c;提高开发效…

FreeBSD通过CBSD管理低资源容器jail来安装Ubuntu子系统实践

简介 FreeBSD、CBSD、Jail和Ubuntu&#xff0c;四者的组合方案可以说是强强联合&#xff0c;极具性价比和竞争力&#xff01;同时安装简单方便&#xff0c;整体方案非常先进。 CBSD是为FreeBSD jail子系统、bhyve、QEMU/NVMM和Xen编写的管理层。该项目定位为一个综合解决方案…

机器学习(V)--无监督学习(二)主成分分析

当数据的维度很高时&#xff0c;很多机器学习问题变得相当困难&#xff0c;这种现象被称为维度灾难&#xff08;curse of dimensionality&#xff09;。 在很多实际的问题中&#xff0c;虽然训练数据是高维的&#xff0c;但是与学习任务相关也许仅仅是其中的一个低维子空间&am…

python3GUI--记账助手By:PyQt5(附下载地址)

文章目录 一&#xff0e;前言二&#xff0e;开发环境三&#xff0e;预览1.登录&注册2.主界面3.新增账单1.当前日期2.选择日期3.添加成功 4.删除账单4.筛选账单5.账单数据汇总1.日账单2.月账单3.年账单 四&#xff0e;设计心得1.项目代码结构2.UI设计概览3.UI设计详细1.登录…

【数据结构】三路快速排序

1. 简介 传统快速排序用的是双路快速排序&#xff0c;即将大于基准值的部分放到基准值右侧&#xff0c;小于基准值的部分放到基准值左侧&#xff0c;但是这种算法面对过多的重复数据的数组&#xff0c;时间复杂度会增多&#xff0c;于是就有了三路快速排序的思想&#xff0c;其…