【QT5】<应用> 小游戏:贪吃蛇

文章目录

一、项目要求

二、需求分析

三、实现效果

四、代码


一、项目要求

【1】主要实现:游戏界面存在一条蛇🐍,使用键盘wsad或者↑↓←→键盘可以控制蛇的行走方向。同时界面中会随机出现食物,蛇可以吃食物,然后蛇的身体就会变长。吃完一个食物之后才会刷新另外一个食物。

【2】游戏结束:蛇碰壁。

【3】玩家分数:由蛇的存活时间以及长度综合计算。time为蛇存活的秒数,lent-len0表示蛇增加的节点数量。同时,玩家分数需要实时显示

【4】重新开始:点击相应的按钮。

【5】加速模式:双击键盘可以加速蛇的移动。例如按两下w键,蛇的速度变为原来的2倍。

【6】不同食物:食物有多种类别,不同的食物会导致蛇变长的长度不同。


二、需求分析

【1】针对主要实现:

  • 创建蛇(Snake)食物(Food)主要窗口(Widget)类。
  • Snake类:创建方法来实现蛇的移动(头插一个,尾删一个)、蛇的方向检测(根据键盘值)、蛇是否死亡(是否碰壁)以及在窗口中绘制蛇(通过传入painter)。
  • Food类:创建方法来实现食物的坐标生成和类型生成(利用随机数)、在窗口中绘制食物。用type整型变量来标志食物类型,当type=1时蛇吃掉后加1节,当type=2时蛇吃掉后加2节,以此类推。
  • Widget类:创建方法来实现整体的按键检测绘制图像计算玩家分数。为了让蛇不断移动,使用定时器(QTimer)来周期性触发槽函数,在槽函数中执行蛇吃食物、食物更新、画面更新等操作。
  • 按键控制:①↑↓←→键盘控制蛇的移动;②空格键控制游戏的开始/暂停(控制定时器开始/停止)。
  • 综合不同类的绘图:将主要逻辑的Widget类中实例化的painter对象作为形参传入Snake和Food类中,在它们各自的方法中进行各自的绘图操作。

【2】针对重新开始:

  • 在ui设计器中添加QPushButton,并添加相应的槽函数。
  • 槽函数中将分数、暂停标志、时间计数器等属性恢复初始值。
  • 槽函数中将已有的蛇、食物对象delete,再创建新的蛇、食物对象。
  • 槽函数中需要重新聚焦于gameWidget,否则点击按钮后需要再点击gameWidget才能检测键盘的输入。重新聚焦调用"ui->gameWidget->setFocus();"

【3】针对不同速度:

  • 在Snake类中创建属性speed,当speed为1时表示每次触发定时器槽函数执行蛇前进1格,当speed为2时表示每次触发定时器槽函数执行蛇前进2格。
  • 初始化speed为1,当用户手动按下两下↑后会加速,直到用户改变蛇的方向

【4】针对不同食物:

  • 在Food类中创建属性type,当type为1时表示食物类型为1(蛇吃后增加1节),当type为2时表示食物类型为2(蛇吃后增加2节),当type为3时表示食物类型为3(蛇吃后增加3节)。
  • 类型1设定为绿色的圆形
  • 类型2设定为深蓝色的椭圆
  • 类型3设定为浅蓝色的方形

三、实现效果


四、代码

【1】food.h:

#ifndef FOOD_H
#define FOOD_H

#include <QWidget>
#include <QPainter>
#include <QRandomGenerator>


/***********************************************************
  * @类名:	Food
  * @摘要:	食物类
  * @作者:	柯同学
  * @注意:	三种食物类型:type值为几就加几节蛇身
  *********************************************************/
class Food : public QWidget
{
    Q_OBJECT
public:
    explicit Food(QWidget *parent = nullptr);
    int getX();         //返回食物横坐标
    int getY();         //返回食物纵坐标
    int getRadius();    //返回食物半径
    int getType();      //返回食物类型
    void generateFood();//生成食物的坐标和类型
    void paintFood(QPainter &painter);//绘制食物

private:
    int foodX;  //食物横坐标
    int foodY;  //食物纵坐标
    int radius; //食物半径
    int type;   //食物类型:1类型为增加1节,2类型增加2节,3类型增加3节
};

#endif // FOOD_H

【2】food.cpp:

#include "food.h"

/***********************************************************
  * @函数名:Food
  * @功  能:食物类的构造函数
  * @参  数:parent父对象
  * @返回值:无
  *********************************************************/
Food::Food(QWidget *parent)
    : QWidget(parent)
    , radius(15)
{
    //初始的食物也随机
    generateFood();
}


/***********************************************************
  * @函数名:getX
  * @功  能:返回食物的横坐标
  * @参  数:无
  * @返回值:食物的横坐标
  *********************************************************/
int Food::getX()
{
    return foodX;
}


/***********************************************************
  * @函数名:getY
  * @功  能:返回食物的纵坐标
  * @参  数:无
  * @返回值:食物的纵坐标
  *********************************************************/
int Food::getY()
{
    return foodY;
}


/***********************************************************
  * @函数名:getRadius
  * @功  能:返回食物的半径
  * @参  数:无
  * @返回值:食物的半径
  *********************************************************/
int Food::getRadius()
{
    return radius;
}


/***********************************************************
  * @函数名:getType
  * @功  能:返回食物的类型
  * @参  数:无
  * @返回值:食物的类型
  *********************************************************/
int Food::getType()
{
    return type;
}


/***********************************************************
  * @函数名:generateFood
  * @功  能:随机生成食物的坐标、类型
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Food::generateFood()
{
    //随机生成坐标,距边界radius降低反应难度
    foodX = QRandomGenerator::global()->bounded(10 + radius, 580 - radius * 2);
    foodY = QRandomGenerator::global()->bounded(20 + radius, 570 - radius * 2);
    //随机生成类型[1,4)
    type = QRandomGenerator::global()->bounded(1, 4);
}


/***********************************************************
  * @函数名:paintFood
  * @功  能:根据食物类型的不同,绘制不同的食物类型。
  * @参  数:painter---画家对象
  * @返回值:无
  * @说  明:type=1---类型1:绿色的圆形
  *         type=2---类型2:深蓝色的椭圆形
  *         type=3---类型3:淡蓝色的矩形
  *********************************************************/
void Food::paintFood(QPainter &painter)
{
    QPen pen;
    QBrush brush;
    //根据type不同,绘制不同的食物
    switch (this->type){
    case 1:
        pen.setColor(QColor(43, 220, 112));
        brush.setColor(QColor(43, 220, 112));
        brush.setStyle(Qt::SolidPattern);
        painter.setPen(pen);
        painter.setBrush(brush);
        painter.drawEllipse(QRect(foodX, foodY, radius, radius));
        break;
    case 2:
        pen.setColor(QColor(0, 62, 146));
        brush.setColor(QColor(0, 62, 146));
        brush.setStyle(Qt::SolidPattern);
        painter.setPen(pen);
        painter.setBrush(brush);
        painter.drawEllipse(QRect(foodX, foodY, radius*2, radius));
        break;
    case 3:
        pen.setColor(QColor(29, 130, 154));
        brush.setColor(QColor(29, 130, 154));
        brush.setStyle(Qt::SolidPattern);
        painter.setPen(pen);
        painter.setBrush(brush);
        painter.drawRect(QRect(foodX, foodY, radius, radius));
        break;
    }
}

【3】snake.h:

#ifndef SNAKE_H
#define SNAKE_H

#include <QWidget>
#include <QEvent>
#include <QPaintEvent>
#include <QPainter>

//枚举蛇前进的方向
enum Direct{
    MOVE_UP,
    MOVE_DOWN,
    MOVE_LEFT,
    MOVE_RIGHT
};

/***********************************************************
  * @类名:	Snake
  * @摘要:	蛇类
  * @作者:	柯同学
  * @注意:	有两种速度:speed为1就每次timeout前进1格,以此类推。
  *         在原有方向的基础上,再次按原方向键能切换到二倍速模式,
  *         比如蛇在往上,再次按up键就两倍速,直到切换方向。
  *********************************************************/
class Snake : public QWidget
{
    Q_OBJECT
public:
    explicit Snake(QWidget *parent = nullptr);
    void paintSnake(QPainter &painter); //绘制蛇身
    void keyPress(QKeyEvent *event);    //键盘控制移动方向
    void autoMove();        //沿着方向自动移动
    void frontAddBody();     //根据方向增加首节点
    QRect getSnakeHead();   //获取蛇的首节点信息
    int getLength();        //返回蛇身节点个数
    bool isOver();          //返回蛇是否死亡,死亡为true

private:
    QList<QRect> body;  //蛇身
    int nodeWidth;      //节点宽度
    int nodeHeight;     //节点高度
    int moveDirect;     //移动方向
    int speed;          //移动速度:1表示默认速度,2表示两倍速度
};

#endif // SNAKE_H

【4】snake.cpp:

#include "snake.h"


/***********************************************************
  * @函数名:Snake
  * @功  能:蛇的构造函数
  * @参  数:parent---父对象
  * @返回值:无
  * @说  明:初始化三节蛇身
  *********************************************************/
Snake::Snake(QWidget *parent)
    : QWidget(parent)
    , nodeWidth(20)
    , nodeHeight(20)
    , moveDirect(MOVE_LEFT)
    , speed(1)
{
    //初始给定三节蛇身
    body.append(QRect(400, 300, nodeWidth, nodeHeight));
    body.append(QRect(400 + nodeWidth, 300, nodeWidth, nodeHeight));
    body.append(QRect(400 + nodeWidth * 2, 300, nodeWidth, nodeHeight));
}


/***********************************************************
  * @函数名:getLength
  * @功  能:获取蛇身的长度,即有几个节点
  * @参  数:无
  * @返回值:蛇身的长度
  *********************************************************/
int Snake::getLength()
{
    return body.length();
}


/***********************************************************
  * @函数名:isOver
  * @功  能:判定蛇是否碰墙死亡
  * @参  数:无
  * @返回值:true---蛇死亡,false---蛇没有死亡
  *********************************************************/
bool Snake::isOver()
{
    if (body[0].y() <= 20 || body[0].y() + nodeHeight >= 570 ||
        body[0].x() <= 10 || body[0].x() + nodeWidth >= 580) {
        return true;
    }
    return false;
}


/***********************************************************
  * @函数名:keyPress
  * @功  能:按键检测,控制蛇的前进方向
  * @参  数:event---按键的事件
  * @返回值:无
  * @说  明:在原有方向的基础上,再次按原方向键能切换到二倍速模式
  *********************************************************/
void Snake::keyPress(QKeyEvent *event)
{
    switch(event->key()) {
    case Qt::Key_Up://蛇往上
        if (MOVE_UP == moveDirect){
            speed = 2;
        }
        else if (moveDirect != MOVE_DOWN){
            moveDirect = MOVE_UP;
            speed = 1;
        }
        break;
    case Qt::Key_Down://蛇往下
        if (MOVE_DOWN == moveDirect){
            speed = 2;
        }
        else if (moveDirect != MOVE_UP){
            moveDirect = MOVE_DOWN;
            speed = 1;
        }
        break;
    case Qt::Key_Left://蛇往左
        if (MOVE_LEFT == moveDirect){
            speed = 2;
        }
        else if (moveDirect != MOVE_RIGHT){
            moveDirect = MOVE_LEFT;
            speed = 1;
        }
        break;
    case Qt::Key_Right://蛇往右
        if (MOVE_RIGHT == moveDirect){
            speed = 2;
        }
        else if (moveDirect != MOVE_LEFT){
            moveDirect = MOVE_RIGHT;
            speed = 1;
        }
        break;
    default:
        break;
    }
}


/***********************************************************
  * @函数名:autoMove
  * @功  能:根据speed属性,让蛇前进1格或2格
  * @参  数:无
  * @返回值:无
  * @说  明:蛇的前进做法:每次头插一个节点,删除最后的一个节点
  *********************************************************/
void Snake::autoMove()
{
    if (1 == speed){
        frontAddBody();
        body.removeLast();
    }
    else if (2 == speed){
        frontAddBody();
        frontAddBody();
        body.removeLast();
        body.removeLast();
    }
}


/***********************************************************
  * @函数名:frontAddBody
  * @功  能:根据前进方向,头插不同位置的节点
  * @参  数:无
  * @返回值:无
  * @说  明:由于碰壁就死亡了,无需越界判定
  *********************************************************/
void Snake::frontAddBody()
{
    switch (moveDirect){
    case MOVE_UP:
            body.insert(0, QRect(body[0].x(), body[0].y() - nodeHeight, nodeWidth, nodeHeight));
        break;
    case MOVE_DOWN:
            body.insert(0, QRect(body[0].x(), body[0].y() + nodeHeight, nodeWidth, nodeHeight));
        break;
    case MOVE_LEFT:
            body.insert(0, QRect(body[0].x() - nodeWidth, body[0].y(), nodeWidth, nodeHeight));
        break;
    case MOVE_RIGHT:
            body.insert(0, QRect(body[0].x() + nodeWidth, body[0].y(), nodeWidth, nodeHeight));
        break;
    }
}


/***********************************************************
  * @函数名:getSnakeHead
  * @功  能:返回首节点的拷贝,以防外界修改。
  * @参  数:无
  * @返回值:无
  *********************************************************/
QRect Snake::getSnakeHead()
{
    return body[0];
}


/***********************************************************
  * @函数名:paintSnake
  * @功  能:绘制蛇身,遍历QList
  * @参  数:painter---画家对象
  * @返回值:无
  *********************************************************/
void Snake::paintSnake(QPainter &painter)
{
    //设置painter
    QPen pen(QColor(64, 65, 66));
    QBrush brush(QColor(183, 1, 1));
    painter.setPen(pen);
    painter.setBrush(brush);
    //绘制蛇身
    for (int i = 0; i < body.length(); ++i) {
        painter.drawRect(body[i]);
    }
}

【5】widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "snake.h"
#include "food.h"
#include <QPainter>
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE


/***********************************************************
  * @类名:	Widget
  * @摘要:	主要界面类
  * @作者:	柯同学
  * @注意:	在该类中进行蛇吃食物、游戏结束等逻辑的实现
  *********************************************************/
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void paintEvent(QPaintEvent *event) override;   //绘图
    void keyPressEvent(QKeyEvent *event) override;  //按键检测
    void snakeEatFood();    //蛇吃食物,更新食物
    void computeScore();    //计算玩家分数

private slots:
    void timeOut();         //定时器触发的槽函数
    void on_pushButton_clicked();//"重新开始"按钮的槽函数

private:
    Ui::Widget *ui;
    Snake *snake;   //蛇
    Food *food;     //食物
    QTimer *timer;  //定时器,固定100ms触发
    bool isPause;   //开始或暂停的标志,true为暂停
    int timerCount; //定时器触发次数
    double score;   //玩家分数
};
#endif // WIDGET_H

【6】widget.cpp:

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>


/***********************************************************
  * @函数名:Widget
  * @功  能:主要窗口的构造函数
  * @参  数:parent---父对象
  * @返回值:无
  *********************************************************/
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    , isPause(true)
    , timerCount(0)
    , score(0)
{
    ui->setupUi(this);
    //实例化蛇
    snake = new Snake(ui->gameWidget);
    //实例化食物
    food = new Food(ui->gameWidget);
    //设置定时器
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timeOut()));
    //设置聚焦对象
    ui->gameWidget->setFocus();
}


/***********************************************************
  * @函数名:~Widget
  * @功  能:主要窗口的析构函数
  * @参  数:无
  * @返回值:无
  * @说  明:由于QT的对象树机制,绑定好父对象后无需手动delete其他空间
  *********************************************************/
Widget::~Widget()
{
    delete ui;
}


/***********************************************************
  * @函数名:~Widget
  * @功  能:主要窗口的析构函数
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)
    QPainter painter(this);
    //判定游戏是否结束,结束则显示提示
    if (snake->isOver()) {//蛇死亡,游戏结束
        timer->stop();
        isPause = true;
        QFont font("宋体", 30, QFont::ExtraBold,false);
        painter.setFont(font);
        QRect showArea(200, 250, 200, 100);
        painter.drawText(showArea, Qt::AlignHCenter | Qt::AlignVCenter, "游戏结束!");
    }
    //绘制蛇和食物
    snake->paintSnake(painter);
    food->paintFood(painter);
    //实时显示玩家分数
    ui->scoreLabel->setText("分数: " + QString::number(score));
}


/***********************************************************
  * @函数名:keyPressEvent
  * @功  能:重写的按键检测事件函数
  * @参  数:event---按键事件
  * @返回值:无
  * @说  明:以防游戏结束后还能控制,首先需要判定游戏是否结束
  *********************************************************/
void Widget::keyPressEvent(QKeyEvent *event)
{
    //游戏未结束才进行按键控制
    if (!(snake->isOver())) {
        //按键控制蛇移动
        snake->keyPress(event);
        //按键控制暂停
        if (event->key() == Qt::Key_Space) {
            if (isPause){
                isPause = false;
                timer->start(100);
            }
            else {
                isPause = true;
                timer->stop();
            }
        }
    }
}


/***********************************************************
  * @函数名:snakeEatFood
  * @功  能:蛇与食物接触,则给蛇加节点,给食物重新生成坐标和类型
  * @参  数:无
  * @返回值:无
  * @说  明:生成食物必须放在蛇加节点之后
  *********************************************************/
void Widget::snakeEatFood()
{
    //蛇与食物接触
    if (abs(snake->getSnakeHead().x() - food->getX()) <= food->getRadius() &&
        abs(snake->getSnakeHead().y() - food->getY()) <= food->getRadius())
    {
        //蛇吃不同类型食物加不同节
        int count = food->getType();
        while (count--){
            snake->frontAddBody();
        }
        //再次生成食物
        food->generateFood();
    }
}


/***********************************************************
  * @函数名:computeScore
  * @功  能:计算玩家分数
  * @参  数:无
  * @返回值:无
  * @说  明:分数由两部分构成:时间分数、长度分数。
  *         每坚持1秒,分数增加1分。
  *         每多一节身体,分数增加10分。
  *********************************************************/
void Widget::computeScore()
{
    double timeScore = (timerCount / 10.0) * 1;     //时间的分数,每秒1分
    int lenScore = (snake->getLength() - 3) * 10;   //长度的分数,增一节10分
    if (lenScore >= 0)
        this->score = timeScore + lenScore;
}


/***********************************************************
  * @函数名:timeOut
  * @功  能:定时器的槽函数
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::timeOut()
{
    //蛇自动移动,吃食物
    snake->autoMove();
    snakeEatFood();
    //计算玩家分数
    timerCount++;
    computeScore();
    //更新界面
    this->update();
}


/*****************************************************************
  * @函数名:on_pushButton_clicked
  * @功  能:"重新开始"按钮的槽函数
  * @参  数:无
  * @返回值:无
  * @说  明:需要重新聚焦于gameWidget,否则点击按钮后需要再点击gameWidget
  ***************************************************************/
void Widget::on_pushButton_clicked()
{
    //清除相关属性
    timerCount = 0; //定时器计数清零
    score = 0;      //分数清零
    isPause = true; //恢复暂停
    //删除已有成员对象
    if (snake) {
        delete snake;
    }
    if (food) {
        delete food;
    }
    //创建新对象
    snake = new Snake(ui->gameWidget);
    food = new Food(ui->gameWidget);
    //更新界面
    this->update();
    ui->gameWidget->setFocus();//重新聚焦于游戏窗口
}

【7】main.cpp: 系统自动生成的,没有改动。

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

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

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

相关文章

【NI国产替代】高速数据采集模块,最大采样率为 125 Msps,支持 FPGA 定制化

• 双通道高精度数据采集 • 支持 FPGA 定制化 • 双通道高精度采样率 最大采样率为 125 Msps12 位 ADC 分辨率 最大输入电压为 0.9 V -3 dB 带宽为 30 MHz 支持 FPGA 定制化 根据需求编程实现特定功能和性能通过定制 FPGA 实现硬件加速&#xff0c;提高系统的运算速度FPGA…

第十二届蓝桥杯C++青少年组中/高级组选拔赛2020年11月22日真题解析

一、编程题 第1题&#xff1a;求和 【题目描述】 输入一个正整数 N(N < 100)&#xff0c;输出 1 到 N(包含 1 和 N)之间所有奇数的和。 【输入描述】 输入一个正整数 N(N < 100) 【输出描述】 输出 1 到 N 之间的所有奇数的和 【输入样例】 3【输出样例】 4答案&…

探索 Noisee AI 的奇妙世界与变现之旅

日赚800&#xff0c;利用淘宝/闲鱼进行AI音乐售卖实操 如何让AI生成自己喜欢的歌曲-AI音乐创作的正确方式 抖音主播/电商人员有福了&#xff0c;利用Suno创作产品宣传&#xff0c;让产品动起来-小米Su7 用sunoAI写粤语歌的方法&#xff0c;博主已经亲自实践可行 五音不全也…

使用 Elasticsearch 调用 OpenAI 函数

作者&#xff1a;来自 Elastic Ashish Tiwari 介绍 OpenAI 中的函数调用是指 AI 模型与外部函数或 API 交互的能力&#xff0c;使它们能够执行文本生成之外的任务。此功能使模型能够通过调用预定义函数来执行代码、从数据库检索信息、与外部服务交互等。 该模型根据用户提示智…

玩转ChatGPT:最全学术论文提示词分享【中】

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 本篇文章&#xff0c;我们继续为大家分享「最全学术论文提示词【中】」。上篇文章的内容请到文末链接处跳转&#x1f447;&#x1f3fb; 6.数据分析 prompt 1&#xff1a;分析[定量/定…

内存管理--4.用幻灯片讲解内存分配器Allocator

用幻灯片讲解内存分配器Allocators Allocators 内存分配器 提供内存分配策略的通用接口委托给 C 运行时&#xff1a;new / delete使用块内存池管理内存使用不同大小的块内存池管理内存 为什么用分配器? 将容器逻辑与内存分配策略解耦速度&#xff1a;内存分配速度慢确保…

YOLOv8改进 | 卷积模块 | 在主干网络中添加/替换蛇形卷积Dynamic Snake Convolution

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 蛇形动态卷积是一种新型的卷积操作&#xff0c;旨在提高对细长和弯曲的管状结构的特征提取能力。它通过自适应地调整卷积核的权重&#xff0…

D455相机RGB与深度图像对齐,缓解相机无效区域的问题

前言 上一次我们介绍了深度相机D455的使用&#xff1a;intel深度相机D455的使用-CSDN博客&#xff0c;我们也看到了相机检测到的无效区域。 在使用Intel深度相机D455时&#xff0c;我们经常会遇到深度图中的无效区域。这些无效区域可能由于黑色物体、光滑表面、透明物体以及视…

Redis中的主从复制

分布式系统中的几种Redis部署方式 为了解决一个程序只部署在一个服务器上的单点问题&#xff1a; 可用性问题&#xff0c;如果这个机器挂了&#xff0c;就意味着服务就中断了 一个程序只部署在一台机器上&#xff0c;它的性能/支持的并发量也是有限的 所以&#xff0c;就引…

若依原生框架集成mybatisplus

1、进入父级依赖 将这个阿里数据库连接池druid注释掉&#xff0c;然后将pagehelper排除jsqlparser分页&#xff0c;使用mybatisplus分页查询防止mybatisplus与pagehelper版本不匹配&#xff0c;不然会报错 2、进入disease-framework模块&#xff1a; config的下面DruidConf…

【python】OpenCV—Blob Detection(11)

学习来自OpenCV基础&#xff08;10&#xff09;使用OpenCV进行Blob检测 文章目录 1、cv2.SimpleBlobDetector_create 中文文档2、默认 parameters3、配置 parameters附录——cv2.drawKeypoints 1、cv2.SimpleBlobDetector_create 中文文档 cv2.SimpleBlobDetector_create 是 O…

平衡二叉树详解

目录 平衡二叉树的定义 平衡二叉树的基本操作 查找 插入 AVL树的建立 平衡二叉树的定义 平衡二叉树仍然是一棵二叉查找树&#xff0c;只是在其基础上增加了平衡的要求&#xff0c;也就是其左右子树的高度之差的绝对值不超过1。 在定义树的结构时需要加入一个变量height&…

外卖APP与外卖小程序开发:从源码到上线的全流程

本文&#xff0c;小编将详细介绍外卖系统与小程序开发的全过程&#xff0c;从源码的编写到系统的上线&#xff0c;为开发者提供全面的指导。 一、需求规划 用户需要一个简单易用的点餐界面&#xff0c;商家需要管理菜单、订单和配送&#xff0c;后台管理则需要监控系统运行状况…

韩顺平0基础学java——第19天

p396-406 final关键字 1.final修饰的为“常量”&#xff0c;需要给初始值。1可以直接定义时赋值&#xff0c;2在构造器中&#xff0c;3在代码块中。 注意静态代码块只能访问静态变量。 2.如果final修饰的关键字是静态的&#xff0c;那就不能在构造器中赋值&#xff0c;只能…

linux经典例题编程

编写Shell脚本&#xff0c;计算1~100的和 首先vi 1.sh,创建一个名为1.sh的脚本&#xff0c;然后赋予这个脚本权限&#xff0c;使用命令chmod 755 1.sh&#xff0c;然后就可以在脚本中写程序&#xff0c;然后运行。 shell脚本内容 运行结果&#xff1a; 编写Shell脚本&#xf…

人工智能在交通与物流领域的普及及应用

文章目录 &#x1f40b;引言 &#x1f40b;自动驾驶 &#x1f988;自动驾驶汽车 &#x1f421;应用现状 &#x1f421;技术实现 &#x1f421;实现过程及代码 &#x1f40b;智能交通管理 &#x1f988;应用现状 &#x1f988;技术实现 &#x1f988;实现过程及代码 &…

Polar Web【中等】反序列化

Polar Web【中等】反序列化 Contents Polar Web【中等】反序列化思路&探索EXPPHP生成PayloadGET传递参数 运行&总结 思路&探索 一个经典的反序列化问题&#xff0c;本文采用PHP代码辅助生成序列字符串的方式生成 Payload 来进行手动渗透。 打开站点&#xff0c;分析…

2024 vite 静态 scp2 自动化部署

1、导入库 npm install scp2 // 自动化部署 npm install chalk // 控制台输出的语句 npm install ora2、核心代码 创建文件夹放在主目录下的 deploy/index.js 复制粘贴以下代码&#xff1a; import client from scp2; import chalk from chalk; import ora from ora;const s…

聊一聊大数据需求的流程

大致的流程&#xff1a;需求对接、口径梳理、数据开发、任务发布、任务监控、任务保障 流程图 startuml skinparam packageStyle rectangleactor 需求方 participant 数据BP as 数据组 participant 离线数仓 participant 实时数仓需求方 -> 数据组: 提出需求 数据组 -> …

数据挖掘--认识数据

数据挖掘--引论 数据挖掘--认识数据 数据挖掘--数据预处理 数据挖掘--数据仓库与联机分析处理 数据挖掘--挖掘频繁模式、关联和相关性&#xff1a;基本概念和方法 数据挖掘--分类 数据挖掘--聚类分析&#xff1a;基本概念和方法 数据对象与属性类型 属性&#xff1a;是一…