【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();          //返回蛇是否死亡,死亡为trueprivate: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)
{//设置painterQPen 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_OBJECTpublic: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();
}

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

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

相关文章

近期面试HW中级蓝问题(非常详细)零基础入门到精通,收藏这一篇就够了

01 — HW问题 1.sqlmap拿shell的原理&#xff0c;需要什么条件&#xff0c;–os-shell的原理 2.冰蝎的流量特征 3.哥斯拉的流量特征 4.如果判断一个web是s2写的 5.fastjson了解嘛&#xff1f;Log4j了解嘛&#xff1f;如何在流量中发现Log4j的攻击特征 6.HW前的准备工作…

微信小程序基础工作模板

1.轮播图 点击跳转官方文档 简单例子 <!-- 顶部轮播图 --> <swiper indicator-dots"true" class"banner" autoplay"true" interval"2000"><swiper-item><image src"../../images/轮播图1.jpg" >…

【JMeter接口测试工具】第二节.JMeter基本功能介绍(下)【入门篇】

文章目录 前言八、Jmeter常用逻辑控制器 8.1 如果&#xff08;if&#xff09;控制器 8.2 循环控制器 8.3 ForEach控制器九、Jmeter关联 9.1 正则表达式提取器 9.2 xpath提取器 9.3 JSON提取器十、跨越线程组传值 10.1 高并发 10.2 高频…

关于修改Python中pip默认安装路径的终极方法

别想了&#xff0c;终极方法就是手动复制&#xff0c;不过我可以给你参考一下手动复制的方法 关于手动移动pip安装包的方法 别想了&#xff0c;终极方法就是手动复制&#xff0c;不过我可以给你参考一下手动复制的方法一、首先确认一下pip默认安装路径二、再确认一下需要移动到…

信号:干扰类别及特征提取(二)

目录 第二部分&#xff1a;特征提取 一&#xff1a;瞬时特征参数 1.零中心归一化瞬时幅度之谱密度的最大值 2.非弱信号段零中心归一化瞬时幅度的标准偏差 3.零中心归一化瞬时幅度绝对值的标准偏差 4.零中心归一化非弱信号段瞬时频率的标准偏差 5.零中心归一化非弱信号段…

Codeforces Round 951 (Div. 2)

A - Guess the Maximum 直接暴力枚举 a i , a i 1 a_i,a_{i1} ai​,ai1​找最小的最大值 答案即为最小的最大值-1 code: #include<bits/stdc.h> #define endl \n #define fast() ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr) #define F first #…

1118 如需挪车请致电(测试点4)

solution 测试点4&#xff1a;直接给出数字&#xff0c;即零个运算符的情况 #include<iostream> #include<string> #include<map> #include<cmath> using namespace std; int main(){string s, ans "";map<string, int> mp {{&quo…

用HAL库改写江科大的stm32入门-输入捕获原理图示

原理与接线&#xff1a; &#xff08;输入捕获的结构&#xff09; cubeMx: PA11&#xff1a;

OpenCV学习(4.7) Canndy边缘检测

1.目标 在本章中&#xff0c;我们将了解 Canny 边缘检测的概念OpenCV 的功能&#xff1a; cv.Canny&#xff08;&#xff09; Canny边缘检测是一种经典的边缘检测算法&#xff0c;由John F. Canny在1986年提出。Canny算法的目标是找到图像中真正的边缘&#xff0c;同时尽可能…

【旅行】关于毕业旅行与长期旅行计划(城市、攻略、预算、交通、面基等)

【旅行】关于毕业旅行与长期旅行计划&#xff08;城市、攻略、预算、交通、面基等&#xff09; 文章目录 一、目的地与去哪儿玩1、可能2、人民币3、国家地理4、省份与城市5、环球旅行 二、攻略之怎么玩&#xff08;旅行预算、攻略&#xff09;1、旅行预算之交通、住宿、门票等2…

【Autopilot】没有自动添加本地管理员的问题处理

【问题】某公司选用了D记的笔记本电脑&#xff0c;约定出厂就预配置好Autopilot&#xff0c;当时向D记提供了三个信息&#xff1a; 1. M365的租户ID 2. 公司域名信息 3. Group Tag (某公司为跨国公司&#xff0c;通过Group Tag来区分国家&#xff0c;比如CHN-中国&#xff0c;L…

【python】OpenCV GUI——Mouse(14.1)

参考学习来自 文章目录 背景知识cv2.setMouseCallback 介绍小试牛刀 背景知识 GUI&#xff08;Graphical User Interface&#xff0c;图形用户界面&#xff09; 是一种允许用户通过图形元素&#xff08;如窗口、图标、菜单和按钮&#xff09;与电子设备进行交互的界面。与传统…

四种跨域解决方案

文章目录 1.引出跨域1.基本介绍2.具体演示1.启动之前学习过的springboot-furn项目2.浏览器直接访问 [localhost:8081/furns](http://localhost:8081/furns) 可以显示信息3.启动前端项目&#xff0c;取消请求拦截器&#xff0c;这样设置&#xff0c;就会出现跨域4.跨域原因 2.跨…

Intel VT-x怎么开启?如何解决VMware打开虚拟机报错问题?

许多小伙伴在安装完VMware不能打开虚拟机&#xff0c;每次打开都会出现一个“此主机支持 Intel VT-x&#xff0c;但 Intel VT-x 处于禁用状态”的报错&#xff0c;然后因此启动不了虚拟机。今天小编就带来如何解决这个报错的方法。 什么是Intel VT-x&#xff1f; 这是英特尔cp…

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

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

Dockerfille解析

用于构建Docker镜像的文本&#xff0c;由一条条指令构成 Docker执行Dockerfile的流程 1. Docker从基础镜像执行一个容器 2. 执行一条指令并对容器进行修改 3. 执行类型Docker commit的命令添加一个新的镜像层 4. Docker再基于新的镜像执行一个新的容器 5. 执行Dockerfile中…

[ssi-uploader插件]解决如何接收服务器返回数据+修改参数名称

前言 ssi-uploader是一款非常好用的多文件上传插件&#xff0c;源码是开源的&#xff0c;在github上面即可下载&#xff1a; https://github.com/ssbeefeater/ssi-uploader 但是源码有些微小的不足&#xff0c;今天我们解决两点问题&#xff1a; 上传文件完成后&#xff0c…

opera打不开网页最简单的解决办法

如果以上为解决问题&#xff0c;继续下面操作 检查网络连接&#xff1a; 确认您的电脑已连接到互联网。 检查网络连接是否稳定&#xff0c;网络速度慢或链路拥堵可能会导致网页加载失败。 修改Local State文件&#xff1a; 关闭Opera浏览器。 定位到Opera浏览器的配置…

植物大战僵尸杂交版2024潜艇伟伟迷

在广受欢迎的游戏《植物大战僵尸》的基础上&#xff0c;我最近设计了一款创新的杂交版游戏&#xff0c;简直是太赞了&#xff01;这款游戏结合了原有游戏的塔防机制&#xff0c;同时引入新的元素、角色和挑战&#xff0c;为玩家提供了全新的游戏体验。 植物大战僵尸杂交版最新绿…

使用cv2控制鼠标实现circle的拖拽

2.代码 import numpy as np import cv2x_center [100,200,300,400] y_center [200,200,200,200] radius 30def mouse_LButtonDown(event, x, y, flags, param):global tempif event cv2.EVENT_LBUTTONDOWN:print(f" Down Clicked at ({x}, {y})")for i in range…