Qt小项目贪吃蛇实线,主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等
Qt小项目贪吃蛇实线,主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等
- Qt 贪吃蛇演示
- QWidget 绘制界面
- 项目源文件 注释清晰
- widget.h
- widget.cpp
- 拓展
- QTimer
- QKeyEvent
- QRectF
- QPointF
- QPainter
- QIcon
Qt 贪吃蛇演示



QWidget 绘制界面


项目源文件 注释清晰
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QtDebug>#include <QKeyEvent>
#include <QTimer>
#include <QRectF>
#include <QPointF>#include <QIcon>
#include <QPainter>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEtypedef enum direct {dir_UP,dir_DOWN,dir_LEFT,dir_RIGHT
}dir_t;class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:void topAddRect();void deleteLast();void downAddRect();void leftAddRect();void rightAddRect();void addFood();bool checkHit();protected:// 按键按压处理void keyPressEvent(QKeyEvent *event);void paintEvent(QPaintEvent *event);private Q_SLOTS:void my_timeout();private:Ui::Widget *ui;int moveFlag = dir_t::dir_UP;bool gameStart = false;QTimer *timer;const int startTime = 100;// 贪吃蛇QList<QRectF>snakeList;// 贪吃蛇小方块const int nodeWidth = 20;const int nodeHeight = 20;// 食物QRectF food;};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"// 三个方块代码蛇,最上面的第一个和最后面的一个通过按键进行交替删除 即snake[0]永远表示头Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowTitle("贪吃蛇疯子");this->setWindowIcon(QIcon(":/icons/title.jpg"));qDebug()<<"x = "<<this->x()<<" y = "<<this->y()<<" height = "<<this->height()<<" width = "<<this->width();timer = new QTimer();connect(timer, &QTimer::timeout, this , &Widget::my_timeout);// 初始化蛇身子 3个方块QRectF rect(this->width()/2,this->height()/2,nodeWidth,nodeHeight);snakeList.append(rect);topAddRect();topAddRect();// 添加食物addFood();
}Widget::~Widget()
{delete ui;
}// 增加一个方块 左上和右下确认一个方块坐标系
void Widget::topAddRect()
{QPointF leftTop; // 左上角坐标QPointF rightBottom; // 右上角坐标if (snakeList[0].y() <= 0) {// 当蛇移动到窗口顶部:确认新坐标 y = 窗口高度 - 蛇方块高度leftTop = QPointF(snakeList[0].x(), this->height() - nodeHeight);rightBottom = QPointF(snakeList[0].x() + nodeWidth , this->height());}else {// 向上移动: y坐标必然减少 减少的右下角坐标为之前的下一个方块的右上角坐标leftTop = QPointF(snakeList[0].x(), snakeList[0].y() - nodeHeight);rightBottom = snakeList[0].topRight();}// 插入矩形小方块1个,由于采用的是List链表,这是典型的前插,追加snakeList.insert(0,QRectF(leftTop,rightBottom));
}void Widget::downAddRect()
{QPointF leftTop; // 左上角坐标QPointF rightBottom; // 右上角坐标if (snakeList[0].y() > this->height() - nodeHeight) {// 当蛇移动到窗口底部:确认新坐标 y = 0leftTop = QPointF(snakeList[0].x(), 0);rightBottom = QPointF(snakeList[0].x() + nodeWidth, 0 + nodeHeight);}else {// 向下移动: y坐标必然增加leftTop = QPointF(snakeList[0].x(), snakeList[0].y() + nodeHeight);rightBottom = snakeList[0].bottomRight() + QPointF(0,nodeHeight);}// 插入矩形小方块1个snakeList.insert(0,QRectF(leftTop,rightBottom));
}void Widget::leftAddRect()
{QPointF leftTop; // 左上角坐标QPointF rightBottom; // 右上角坐标if (snakeList[0].x() <= 0) {// 当蛇移动到窗口最左部:确认新坐标 x = 窗口宽度 - 小方块宽度leftTop = QPointF(this->width() - nodeWidth, snakeList[0].y());}else {// 向左移动:x坐标必然减少leftTop = QPointF(snakeList[0].x() - nodeWidth, snakeList[0].y());}// 右下角坐标 = 之前一个的左上角坐标x,y + 小方块的宽高rightBottom = leftTop + QPointF(nodeWidth, nodeHeight);// 插入矩形小方块1个snakeList.insert(0,QRectF(leftTop,rightBottom));
}void Widget::rightAddRect()
{QPointF leftTop; // 左上角坐标QPointF rightBottom; // 右上角坐标if (snakeList[0].x() + nodeWidth > this->width()) {// 当蛇移动到窗口最右部:确认新坐标 x = 0leftTop = QPointF(0, snakeList[0].y());}else {// 向右移动:x坐标必然增加leftTop = QPointF(snakeList[0].x() + nodeWidth, snakeList[0].y());}// 右下角坐标 = 之前一个的左上角坐标x,y + 小方块的宽高rightBottom = leftTop + QPointF(nodeWidth, nodeHeight);// 插入矩形小方块1个snakeList.insert(0,QRectF(leftTop,rightBottom));
}// 删除蛇身最后一个
void Widget::deleteLast()
{snakeList.removeLast();
}// 食物是随机出现的
void Widget::addFood()
{int rectX = (qrand() % (this->width() / 20)) * 20;int rectY = (qrand() % (this->height() / 20)) * 20;// 控制小球出现的范围if (rectX >= 0 && rectY>=0) {food = QRectF(rectX, rectY, nodeWidth, nodeHeight);qDebug()<<"food = "<<food;}
}// 蛇头和蛇身碰撞检查,其实就是蛇头和蛇尾其中一个方块重合
bool Widget::checkHit()
{// 整个蛇的长度都遍历一遍for (int i =0 ; i < snakeList.length(); i++) {// 从蛇头后的第一个开始检查 只要有for (int j= i+ 1; j < snakeList.length();j++) {// rect0和rectx相等,表示它们的坐标、宽度和高度都一致if (snakeList[0] == snakeList[j]) {return true;}}}return false;
}void Widget::keyPressEvent(QKeyEvent *event)
{switch (event->key()) {case Qt::Key::Key_Up:if (moveFlag != dir_DOWN) {moveFlag = dir_UP;}break;case Qt::Key::Key_Down:if (moveFlag != dir_UP) {moveFlag = dir_DOWN ;}break;case Qt::Key::Key_Left:if (moveFlag != dir_RIGHT) {moveFlag = dir_LEFT;}break;case Qt::Key::Key_Right:if (moveFlag != dir_LEFT) {moveFlag = dir_RIGHT;}break;case Qt::Key_Space:if (gameStart == false) {gameStart = true;timer->start(startTime); // 100ms}else {gameStart = false;timer->stop();}break;default:break;}
}void Widget::paintEvent(QPaintEvent *event)
{QPainter painter(this);QPen pen;QBrush brush;QPixmap pix;// 绘制图片背景pix.load(":/icons/bg_snake.png");painter.drawPixmap(0,0,this->width(),this->height(),pix);// 绘制蛇pen.setColor(Qt::color0);brush.setColor(Qt::darkGreen); // 绿色brush.setStyle(Qt::SolidPattern); // 实线图案painter.setPen(pen);painter.setBrush(brush);for (int i = 0; i < snakeList.length(); i++) {painter.drawRect(snakeList[i]);}// 分数ui->label_score->setText(QString::number(snakeList.length() -3));// 绘制食物painter.drawEllipse(food);// 蛇头碰到蛇身结束游戏if (checkHit()) {QFont font("方正舒体",30,QFont::ExtraLight,false);painter.setFont(font);painter.drawText((this->width() - 200)/2,this->height()/2,QString("游戏结束"));timer->stop();}QWidget::paintEvent(event);}// 定时器槽函数
void Widget::my_timeout()
{//int count = 1; // 采用这种方式也可以加长蛇身,不过我还是喜欢我的烂方法// 判断蛇是否吃到食物 是否重合[交叉;相交;贯穿;横穿;横断] 蛇变长if (snakeList[0].intersects(food)) {qDebug()<<"吃到食物 snakeList[0] = "<<snakeList[0]<<" food = "<<food;//count ++ ; // 例如 2switch (moveFlag) {case dir_UP:this->topAddRect(); // +1break;case dir_DOWN:this->downAddRect(); // +1break;case dir_LEFT:this->leftAddRect(); // +1break;case dir_RIGHT:this->rightAddRect(); // +1break;default:break;}addFood(); // 食物位置变化return;}// 加长蛇身 每次在最前面增加一个// while (count--) {switch (moveFlag) {case dir_UP:this->topAddRect(); // +1break;case dir_DOWN:this->downAddRect(); // +1break;case dir_LEFT:this->leftAddRect(); // +1break;case dir_RIGHT:this->rightAddRect(); // +1break;default:break;}//}// 为了动态显示每次最前面插入一个,最后面就减少一个deleteLast(); // 删除蛇尾 -1this->update(); // 刷新绘制函数
}
拓展
QTimer
QTimer是Qt中用于定时器操作的类,它提供了一些常用的函数来控制和管理定时器的运行。下面是一些常用的QTimer函数的简介:
start(int msec): 启动定时器,以指定的毫秒数为间隔触发定时器的timeout()信号。stop(): 停止定时器,不再触发timeout()信号。setInterval(int msec): 设置定时器的间隔时间,以毫秒为单位。interval(): 获取当前定时器的间隔时间。isActive(): 判断定时器是否处于活动状态,即是否正在运行。setSingleShot(bool singleShot): 设置定时器的运行模式,如果设置为true,则定时器只触发一次;如果设置为false(默认值),则定时器会一直触发。singleShot(int msec, const QObject* receiver, const char* member): 创建一个单次触发的定时器,指定触发时间、接收信号的对象和相应的槽函数。remainingTime(): 获取定时器剩余的触发时间,以毫秒为单位。
这些函数提供了基本的定时器操作功能,可以配合定时器的信号timeout()以及连接(Qt的信号与槽机制)来实现所需的定时操作。
QKeyEvent
QKeyEvent是Qt中用于处理键盘事件的类,它提供了一些常用的函数来获取和处理键盘事件的相关信息。下面是一些常用的QKeyEvent函数的简介:
key(): 获取触发键盘事件的按键的Qt键盘码,返回一个Qt::Key枚举值。text(): 获取触发键盘事件的按键对应的文字,返回一个QString。modifiers(): 获取触发键盘事件时的修饰键状态,返回一个Qt::KeyboardModifiers枚举值,可用于检查Shift、Ctrl、Alt等修饰键的状态。isAutoRepeat(): 判断触发键盘事件的按键是否是自动重复的按下事件。count(): 获取自动重复按键连续触发的次数。nativeVirtualKey(): 获取底层平台的虚拟键码,返回一个int值。nativeModifiers(): 获取底层平台的修饰键状态,返回一个int值。
这些函数可以帮助你获取与键盘事件相关的信息,例如获取按下的键是哪个键,是否同时按下了修饰键,以及自动重复事件的次数等。你可以使用这些函数来处理键盘事件并根据需要执行相应的操作。
QRectF
QRectF是Qt中用于表示浮点数精度的矩形区域的类,它提供了一些常用的函数来操作和管理矩形区域。下面是一些常用的QRectF函数的简介:
QRectF(): 默认构造函数,创建一个无效的矩形区域。QRectF(qreal x, qreal y, qreal width, qreal height): 构造函数,创建一个以给定坐标、宽度和高度定义的矩形区域。setRect(qreal x, qreal y, qreal width, qreal height): 设置矩形区域的位置和尺寸。setCoords(qreal x1, qreal y1, qreal x2, qreal y2): 设置矩形区域的左上角和右下角的坐标。x(),y(),width(),height(): 获取矩形区域的左上角的x和y坐标,以及宽度和高度。left(),top(),right(),bottom(): 获取矩形区域的左、上、右、下边界的坐标。setX(qreal x),setY(qreal y),setWidth(qreal width),setHeight(qreal height): 设置矩形区域的左上角的x和y坐标,以及宽度和高度。setLeft(qreal left),setTop(qreal top),setRight(qreal right),setBottom(qreal bottom): 设置矩形区域的左、上、右、下边界的坐标。moveTo(qreal x, qreal y): 移动矩形区域的位置,将其左上角设置为给定坐标。translated(qreal dx, qreal dy): 平移矩形区域,沿x和y方向分别平移给定的距离。contains(const QPointF &point): 判断矩形区域是否包含给定的点。isEmpty(): 判断矩形区域是否为空,即宽度或高度是否为0。isNull(): 判断矩形区域是否为空,即宽度和高度是否为0。
QPointF
QPointF是Qt中用于表示浮点数精度的二维点的类,它提供了一些常用的函数来操作和管理点的坐标。下面是一些常用的QPointF函数的简介:
QPointF(): 默认构造函数,创建一个具有零值坐标的点。QPointF(qreal x, qreal y): 构造函数,创建一个具有给定坐标的点。setX(qreal x),setY(qreal y): 设置点的x和y坐标。x(),y(): 获取点的x和y坐标。isNull(): 判断点是否为空,即坐标是否为零值。manhattanLength(): 计算点到坐标原点的曼哈顿距离(绝对值之和)。distanceToLine(const QLineF &line): 计算点到给定直线的距离。distanceToPoint(const QPointF &point): 计算点到给定点的距离。operator==(const QPointF &p1, const QPointF &p2): 判断两个点是否相等。operator!=(const QPointF &p1, const QPointF &p2): 判断两个点是否不相等。isNull(const QPointF &point): 判断给定点是否为空,即坐标是否为零值。
这些函数提供了对点的基本操作,包括设置坐标、获取坐标、判断点是否为空、计算与其他点或直线的距离等。你可以使用这些函数来创建、修改和计算点的坐标,以满足你的需求。
QPainter
QPainter是Qt提供的一个用于绘图的类,它封装了绘制图形、图像以及文本的功能。下面是一些常用的QPainter函数的简介:
begin(QPaintDevice *device): 开始在给定的绘图设备上进行绘制,device可以是QWidget、QImage等。end(): 结束绘制操作。setPen(const QPen &pen): 设置绘制的画笔,用于定义线条的样式、颜色等属性。setBrush(const QBrush &brush): 设置绘制的刷子,用于填充封闭图形的颜色、渐变等属性。setRenderHint(RenderHint hint, bool on = true): 开启或关闭绘制的渲染提示,例如抗锯齿、文本反锯齿等。drawLine(const QLine &line): 绘制直线。drawRect(const QRect &rect): 绘制矩形。drawEllipse(const QRect &rect): 绘制椭圆。drawText(const QPointF &pos, const QString &text): 在给定点位置绘制文本。drawPixmap(const QRectF &targetRect, const QPixmap &pixmap): 在给定矩形区域绘制像素图。save(),restore(): 保存和恢复绘图状态,用于实现绘制状态的切换、叠加效果等。resetTransform(): 重置坐标变换矩阵。translate(qreal dx, qreal dy): 平移画笔的原点。scale(qreal sx, qreal sy): 缩放画笔,按比例调整绘图。rotate(qreal angle): 旋转画笔,围绕原点进行旋转。
这些函数提供了绘制基本图形、文本和图像的能力,通过设置画笔、刷子和渲染提示等属性,可以实现不同样式的绘制效果。同时,你还可以使用平移、缩放和旋转等变换函数来改变画笔的绘制位置和方向。使用这些函数,你可以实现各种绘图需求,创建出丰富多样的用户界面。
QIcon
QIcon是Qt提供的一个用于管理图标的类,它可以加载、显示和操作图标。下面是一些常用的QIcon函数的简介:
QIcon(): 默认构造函数,创建一个空的图标。QIcon(const QString &filename): 构造函数,根据给定的文件名加载图标。QIcon(const QPixmap &pixmap): 构造函数,根据给定的像素图创建图标。QIcon(const QIcon &other): 拷贝构造函数,创建一个与给定图标相同的拷贝。addFile(const QString &filename, const QSize &size = QSize(), QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off): 添加一个图像文件到图标中,可以指定图像的大小、模式和状态。isNull(): 判断图标是否为空,即没有加载任何图像。pixmap(const QSize &size, QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) const: 获取图标的像素图,可以指定图像的大小、模式和状态。paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment = Qt::AlignCenter, QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) const: 在给定的矩形区域内绘制图标,可以指定对齐方式、模式和状态。operator=(const QIcon &other): 赋值运算符,将给定图标的内容复制到当前图标。operator==,operator!=: 用于比较两个图标是否相等或不相等。
这些函数提供了加载、显示和操作图标的功能,你可以根据需要加载图像文件,设置图标的大小、模式和状态,绘制图标到指定的区域,并进行图标的比较和赋值操作。QIcon类在Qt中广泛用于界面开发,它使得图标的管理和使用变得简单和灵活。
相关文章:
Qt小项目贪吃蛇实线,主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等
Qt小项目贪吃蛇实线,主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等 Qt 贪吃蛇演示QWidget 绘制界面项目源文件 注释清晰widget.hwidget.cpp 拓展QTimerQKeyEventQRectFQPointFQPainterQIcon Qt 贪吃蛇演示 QWidget 绘制界面 项目源文件 注…...
使用HTTP隧道时如何应对目标网站的反爬虫监测?
在进行网络抓取时,我们常常会遇到目标网站对反爬虫的监测和封禁。为了规避这些风险,使用代理IP成为一种常见的方法。然而,如何应对目标网站的反爬虫监测,既能保证数据的稳定性,又能确保抓取过程的安全性呢?…...
怎么样通过Bootstrap已经编译好(压缩好)的源码去查看符合阅读习惯的源码【通过Source Map(源映射)文件实现】
阅读本篇博文前,建议大家先看看下面这篇博文: https://blog.csdn.net/wenhao_ir/article/details/132089650 Bootstrap经编译(压缩)后的源码百度网盘下载地址: https://pan.baidu.com/s/14BM9gpC3K-LKxhyLGh4J9Q?pwdm02m Bootstrap未经编译…...
【排序算法】python之冒泡,选择,插入,快速,归并
参考资料: 《Python实现5大排序算法》《六大排序算法:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序》 --代码似乎是C语言 ———————— 本文介绍5种常见的排序算法和基于Python实现: 冒泡排序(Bubble Sort&am…...
UML—用例图的那些事
目录 背景: 1.用例图的发展史 过程: 1.用例图中的元素和关系 2.应用中的例子 总结: 背景: 1.用例图的发展史 用例图是一种常用的软件工程工具,用于描述系统的功能需求和用户与系统的交互。它在软件开发过程中起到了重要的作用,并且经历了…...
迷宫出口问题求解(DFS)
题面 一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由 nn 的格点组成,每个格点只有 22 种状态, 00 和 11,前者表示可以通行后者表示不能通行。 同时当Extense处在某个格点时,他只能移动到东南西北…...
基础算法模板
数据结构 单链表的插入删除 const int N=1e6+10; int head,e[N],ne[N],idx; //head 存储头节点的下标 //idx 存储当前已经用到的那个点 void init() {head=-1;idx=0; } void add_to_head(int x)//插入头节点操作 {e[idx]=x;ne[idx]=head;head=idx;idx++; } void add(int k)/…...
react Ref 的基本使用
类组件中使用ref 在类组件中,你可以使用createRef来创建一个ref,并将它附加到DOM元素或类组件实例上。使用ref允许你在类组件中访问和操作特定的DOM元素或类组件实例。 下面是在类组件中使用ref的步骤: 引入React和createRef: …...
宝塔面板点击SSL闪退打不开怎么解决?
宝塔Linux面板点击SSL证书闪退如何解决?旧版本的宝塔Linux面板确实存在这种情况,如何解决?升级你的宝塔Linux面板即可。新手站长分享宝塔面板SSL闪退的解决方法: 宝塔面板点击SSL证书闪退解决方法 问题:宝塔Linux面板…...
如何将安卓 Gradle 模块打包发布到本地 Maven 仓库
文章目录 具体流程 笔者的运行环境: Android Studio Flamingo | 2022.2.1 Android SDK 33 Gradle 8.0.1 JDK 17 Android 的 Gradle 项目与一般的 Gradle 项目是不同的,因此对将 Gradle 模块打包发布到本地 Maven 仓库来说,对普通 Gradle …...
【Docker】Docker比虚拟机快的原因、ubuntu容器、镜像的分层概念和私有库的详细讲解
🚀欢迎来到本文🚀 🍉个人简介:陈童学哦,目前学习C/C、算法、Python、Java等方向,一个正在慢慢前行的普通人。 🏀系列专栏:陈童学的日记 💡其他专栏:CSTL&…...
java.lang.IllegalArgumentException: Invalid character found in methodname
postman请求异常:java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens...
【PCB专题】Allegro高速电路Xnet网络等长约束——SDIO信号为例
高速PCB板布线过程中,经常遇到等长设置问题,例如DDR的一组数据线和地址线等。但是由于数据线和地址线中间有一个电阻(或排阻),这种情况下设置等长就要引入Xnet的概念,通过设置Xnet的等长来确保数据线和地址线的等长。 由无源、分立器件(电阻、电容、电感)连接起来的几段…...
leetcode每日一练-第278题-第一个错误的版本
一、思路 二分查找——因为它可以快速地将版本范围缩小一半,从而更快地找到第一个坏版本。 二、解题方法 维护一个左边界 left 和一个右边界 right,在每一步循环中,我们计算中间版本 mid,然后检查它是否是坏版本。如果是坏版本…...
最小生成树笔记(Prim算法Kruskal算法)
1.最小生成树 最小生成树(Minimum Spanning Tree,简称MST)是指:在一个连通无向图中,找到一个包含所有顶点的树,且该树的所有边的权重之和最小。 换句话说,最小生成树是原图中的一个子图&#…...
4、数据清洗
4、数据清洗 前面我们处理的数据实际上都是已经被处理好的规整数据,但是在大数据整个生产过程中,需要先对数据进行数据清洗,将杂乱无章的数据整理为符合后面处理要求的规整数据。 数据去重 1.删除重复数据groupby().count():可以…...
Python-OpenCV 图像的基础操作
图像的基础操作 获取图像的像素值并修改获取图像的属性信息图像的ROI区域图像通道的拆分及合并图像扩边填充图像上的算术运算图像的加法图像的混合图像的位运算 获取图像的像素值并修改 首先读入一副图像: import numpy as np import cv2# 1.获取并修改像素值 # 读…...
test111
step3:多线程task 首先,实现两个UserService和AsyncUserService两个服务接口: package com.example.demospringboot.service;public interface UserService {void checkUserStatus(); }package com.example.demospringboot.service.impl;im…...
17. Spring 事务
目录 1. 事务定义 2. MySQL 中的事务使用 3. 没有事务时的插入 4. Spring 编程式事务 5. Spring 声明式事务 5.1 Transactional 作用范围 5.2 Transactional 参数说明 5.3 Transactional 工作原理 1. 事务定义 将⼀组操作封装成一个执行单元(封装到一起…...
【C# 基础精讲】运算符和表达式
在C#编程中,运算符和表达式是构建复杂逻辑的关键元素。运算符用于执行各种数学、逻辑和其他操作,而表达式则由运算符、变量、常量和函数组成,用于生成计算结果。本文将详细介绍C#中常见的运算符和表达式的概念,以及它们在程序中的…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
