Qt 综合练习小项目--反金币(2/2)

news2024/12/30 3:06:21

目录

4 选择关卡场景

4.2 背景设置

4.3 创建返回按钮

4.3 返回按钮

4.4 创建选择关卡按钮

4.5 创建翻金币场景

5 翻金币场景

5.1 场景基本设置

5.2 背景设置

5.3 返回按钮

5.4 显示当前关卡 

5.5 创建金币背景图片

5.6 创建金币类

5.6.1 创建金币类 MyCoin

5.6.2 构造函数

5.6.3 测试

5.7 引入关卡数据

5.7.1 添加现有文件dataConfig

        5.7.2 添加现有文件

5.7.3 完成添加

5.7.4 数据分析 

5.7.5 测试关卡数据

5.8 初始化各个关卡 

5.9 翻金币特效

5.9.1 MyCoin类扩展属性和行为

5.9.2 创建特效

5.9.3 测试

5.9.3 禁用按钮

5.10 翻周围金币

5.11 判断是否胜利

5.12 胜利图片显示

5.13 胜利后禁用按钮

6 音效添加

6.1 开始音效

6.2 选择关卡音效

6.3 返回按钮音效

6.4 翻金币与胜利音效

7 优化项目


4 选择关卡场景

        4.1 场景基本设置

        选择关卡构造函数如下:

 //设置窗口固定大小
    this->setFixedSize(320,588);
    //设置图标
    this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
    //设置标题
    this->setWindowTitle("选择关卡");

    //创建菜单栏
    QMenuBar * bar = this->menuBar();
    this->setMenuBar(bar);
    //创建开始菜单
    QMenu * startMenu = bar->addMenu("开始");
    //创建按钮菜单项
    QAction * quitAction = startMenu->addAction("退出");
    //点击退出 退出游戏
    connect(quitAction,&QAction::triggered,[=](){this->close();});

运行效果如图:

4.2 背景设置

void ChooseLevelScene::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/res/OtherSceneBg.png");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);

     //加载标题
    pix.load(":/res/Title.png");
    painter.drawPixmap( (this->width() - pix.width())*0.5,30,pix.width(),pix.height(),pix);
}

4.3 创建返回按钮

 //返回按钮
    MyPushButton * closeBtn = new MyPushButton(":/res/BackButton.png",":/res/BackButtonSelected.png");
    closeBtn->setParent(this);
    closeBtn->move(this->width()-closeBtn->width(),this->height()-closeBtn->height());

返回按钮是有正常显示图片和点击后显示图片的两种模式,所以我们需要重写MyPushButton中的 MousePressEvent和MouseReleaseEvent。

//鼠标事件
void MyPushButton::mousePressEvent(QMouseEvent *e)
{
    if(pressedImgPath != "") //选中路径不为空,显示选中图片
    {
        QPixmap pixmap;
        bool ret = pixmap.load(pressedImgPath);
        if(!ret)
        {
            qDebug() << pressedImgPath << "加载图片失败!";
        }

        this->setFixedSize( pixmap.width(), pixmap.height() );
        this->setStyleSheet("QPushButton{border:0px;}");
        this->setIcon(pixmap);
        this->setIconSize(QSize(pixmap.width(),pixmap.height()));
    }
    //交给父类执行按下事件
    return QPushButton::mousePressEvent(e);
}
void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
{
    if(normalImgPath != "") //选中路径不为空,显示选中图片
    {
        QPixmap pixmap;
        bool ret = pixmap.load(normalImgPath);
        if(!ret)
        {
            qDebug() << normalImgPath << "加载图片失败!";
        }
        this->setFixedSize( pixmap.width(), pixmap.height() );
        this->setStyleSheet("QPushButton{border:0px;}");
        this->setIcon(pixmap);
        this->setIconSize(QSize(pixmap.width(),pixmap.height()));
    }
    //交给父类执行 释放事件
    return QPushButton::mouseReleaseEvent(e);
}

4.3 返回按钮

在这里我们点击返回后,延时0.5后隐藏自身,并且发送自定义信号,告诉外界自身已经选择了返回按钮。

//返回按钮功能实现
    connect(closeBtn,&MyPushButton::clicked,[=](){
        QTimer::singleShot(500, this,[=](){
            this->hide();
            //触发自定义信号,关闭自身,该信号写到 signals下做声明
            emit this->chooseSceneBack();
             }
        );
    });

在主场景MainScene中 点击开始按钮显示选择关卡的同时,监听选择关卡的返回按钮消息

//监听选择场景的返回按钮    connect(chooseScene,&ChooseLevelScene::chooseSceneBack,[=](){
                this->show();
            });

测试主场景与选择关卡场景的切换功能。

4.4 创建选择关卡按钮

//创建关卡按钮
    for(int i = 0 ; i < 20;i++)
    {
        MyPushButton * menuBtn = new MyPushButton(":/res/LevelIcon.png");
        menuBtn->setParent(this);
        menuBtn->move(25 + (i%4)*70 , 130+ (i/4)*70);

        //按钮上显示的文字
        QLabel * label = new QLabel;
        label->setParent(this);
        label->setFixedSize(menuBtn->width(),menuBtn->height());
        label->setText(QString::number(i+1));
 label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //设置居中
        label->move(25 + (i%4)*70 , 130+ (i/4)*70);
        label->setAttribute(Qt::WA_TransparentForMouseEvents,true);  //鼠标事件穿透
    }

运行效果如果:

4.5 创建翻金币场景

点击关卡按钮后,会进入游戏的核心场景,也就是翻金币的场景,首先先创建出该场景的.h和.cpp文件

创建PlayScene

点击选择关卡按钮后会跳入到该场景

建立点击按钮,跳转场景的信号槽连接

ChooseLevelScene.h 中声明

PlayScene *pScene = NULL;

 

//监听选择关卡按钮的信号槽
        connect(menuBtn,&MyPushButton::clicked,[=](){
           // qDebug() << "select: " << i;
            if(pScene == NULL)  //游戏场景最好不用复用,直接移除掉创建新的场景
            {
                this->hide();
                pScene = new PlayScene(i+1); //将选择的关卡号 传入给PlayerScene
                pScene->show();
            }
        });

这里pScene = new PlayScene(i+1); 将用户所选的关卡号发送给pScene,也就是翻金币场景,当然PlayScene 要提供重载的有参构造版本,来接受这个参数。

5 翻金币场景

5.1 场景基本设置

PlayScene.h中 声明成员变量,用于记录当前用户选择的关卡。

//成员变量 记录关卡索引
    int levalIndex;

PlayScene.cpp中 初始化该场景配置。

PlayScene::PlayScene(int index)
{
    //qDebug() << "当前关卡为"<< index;
    this->levalIndex = index;
    //设置窗口固定大小
    this->setFixedSize(320,588);
    //设置图标
    this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
    //设置标题
    this->setWindowTitle("翻金币");

    //创建菜单栏
    QMenuBar * bar = this->menuBar();
    this->setMenuBar(bar);
    //创建开始菜单
    QMenu * startMenu = bar->addMenu("开始");
    //创建按钮菜单项
    QAction * quitAction = startMenu->addAction("退出");
    //点击退出 退出游戏
    connect(quitAction,&QAction::triggered,[=](){this->close();});
}

5.2 背景设置

void PlayScene::paintEvent(QPaintEvent *)
{
    //加载背景
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/res/PlayLevelSceneBg.png");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);

    //加载标题
    pix.load(":/res/Title.png");
    pix = pix.scaled(pix.width()*0.5,pix.height()*0.5);
    painter.drawPixmap( 10,30,pix.width(),pix.height(),pix);
}

5.3 返回按钮

 //返回按钮
    MyPushButton * closeBtn = new MyPushButton(":/res/BackButton.png",":/res/BackButtonSelected.png");
    closeBtn->setParent(this);
    closeBtn->move(this->width()-closeBtn->width(),this->height()-closeBtn->height());

    //返回按钮功能实现
    connect(closeBtn,&MyPushButton::clicked,[=](){
        QTimer::singleShot(500, this,[=](){
            this->hide();
            //触发自定义信号,关闭自身,该信号写到 signals下做声明
            emit this->chooseSceneBack();
             }
        );
    });

5.4 在ChooseScene选择关卡场景中,监听PlayScene的返回信号。

connect(pScene,&PlayScene::chooseSceneBack,[=](){
                    this->show();
                    delete pScene;
                    pScene = NULL;
                });

5.4 显示当前关卡 

//当前关卡标题
    QLabel * label = new QLabel;
    label->setParent(this);
    QFont font;
    font.setFamily("华文新魏");
    font.setPointSize(20);
    label->setFont(font);
    QString str = QString("Leavel: %1").arg(this->levalIndex);
    label->setText(str);
    label->setGeometry(QRect(30, this->height() - 50,120, 50)); //设置大小和位置

假设我们选择了第15关卡,运行效果如果:

5.5 创建金币背景图片

//创建金币的背景图片
    for(int i = 0 ; i < 4;i++)
    {
        for(int j = 0 ; j < 4; j++)
        {
           //绘制背景图片
            QLabel* label = new QLabel;
            label->setGeometry(0,0,50,50);
            label->setPixmap(QPixmap(":/res/BoardNode.png"));
            label->setParent(this);
            label->move(57 + i*50,200+j*50);
        }
    }

运行效果如图:

5.6 创建金币类

我们知道,金币是本游戏的核心对象,并且在游戏中可以利用二维数组进行维护,拥有支持点击,翻转特效等特殊性,因此不妨将金币单独封装到一个类中,完成金币所需的所有功能。

5.6.1 创建金币类 MyCoin

并修改MyCoin的基类为QPushButton 

5.6.2 构造函数

在资源图片中,我们可以看到,金币翻转的效果原理是多张图片切换而形成的,而以下八张图片中,第一张与最后一张比较特殊,因此我们在给用户看的时候,无非是金币Coin0001或者是银币 Coin0008这两种图。

因此我们在创建一个金币对象时候,应该提供一个参数,代表着传入的是金币资源路径还是银币资源路径,根据路径我们创建不同样式的图案。

在MyCoin.h中声明:

MyCoin(QString butImg); //代表图片路径 

在MyCoin.cpp中进行实现

MyCoin::MyCoin(QString butImg)
{

    QPixmap pixmap;
    bool ret = pixmap.load(butImg);
    if(!ret)
    {
        qDebug() << butImg << "加载图片失败!";
    }

    this->setFixedSize( pixmap.width(), pixmap.height() );
    this->setStyleSheet("QPushButton{border:0px;}");
    this->setIcon(pixmap);
    this->setIconSize(QSize(pixmap.width(),pixmap.height()));

}

5.6.3 测试

在翻金币场景 PlayScene中,我们测试下封装的金币类是否可用,可以在创建好的金币背景代码后,添加如下代码:

	//金币对象
            MyCoin * coin = new MyCoin(":/res/Coin0001.png");
            coin->setParent(this);
            coin->move(59 + i*50,204+j*50);

运行效果如图

5.7 引入关卡数据

当然上述的测试只是为了让我们知道提供的对外接口可行,但是每个关卡的初始化界面并非如此,因此需要我们引用一个现有的关卡文件,文件中记录了各个关卡的金币排列清空,也就是二维数组的数值。

5.7.1 添加现有文件dataConfig

首先先将dataConfig.h 和 dataConfig.cpp文件放入到当前项目下:

        5.7.2 添加现有文件

其次在Qt_Creator项目右键,点击添加现有文件。

5.7.3 完成添加

选择当前项目下的文件,并进行添加

5.7.4 数据分析 

我们可以看到,其实dataConfig.h中只有一个数据是对外提供的,如下图

 

在上图中,QMap<int,QVector<QVector<int>>>mData;都记录着每个关卡中的数据。

其中,int代表对应的关卡 ,也就是QMap中的key值,而value值就是对应的二维数组,我们利用的是 QVector<QVector<int>>来记录着其中的二维组。

5.7.5 测试关卡数据

在Main函数可以测试第一关的数据,添加如下代码:

dataConfig config;
    for(int i = 0 ; i < 4;i++)
    {
        for(int j = 0 ; j < 4; j++)
        {
            //打印第一关所有信息
           qDebug() << config.mData[1][i][j];

        }
        qDebug()<< "";
    }

输出结果如下图:

对应着dataConfig.cpp中第一关数据来看,与之匹配成功,以后我们就可以用dataConfig中的数据来对关卡进行初始化了。

5.8 初始化各个关卡 

首先,可以在playScene中声明一个成员变量,用户记录当前关卡的二维数组。

int gameArray[4][4]; //二维数组数据

之后,在.cpp文件中,初始化这个二维数组

//初始化二维数组
    dataConfig config;
    for(int i = 0 ; i < 4;i++)
    {
        for(int j = 0 ; j < 4; j++)
        {
            gameArray[i][j] = config.mData[this->levalIndex][i][j];
        }
    }

初始化成功后,在金币类 也就是MyCoin类中,扩展属性 posX,posY,以及flag

这三个属性分别代表了,该金币在二维数组中 x的坐标,y的坐标,以及当前的正反标志。

int posX; //x坐标
    int posY; //y坐标
    bool flag; //正反标志

然后完成金币初始化,代码如下:

//金币对象
            	QString img;
            if(gameArray[i][j] == 1)
            {
              img = ":/res/Coin0001.png";
            }
            else
            {
              img = ":/res/Coin0008.png";
            }
            MyCoin * coin = new MyCoin(img);
            coin->setParent(this);
            coin->move(59 + i*50,204+j*50);
            coin->posX = i; //记录x坐标
            coin->posY = j; //记录y坐标
            coin->flag =gameArray[i][j]; //记录正反标志

运行测试各个关卡初始化,例如第一关效果如图:

5.9 翻金币特效

5.9.1 MyCoin类扩展属性和行为

关卡的初始化完成后,下面就应该点击金币,进行翻转的效果了,那么首先我们先在MyCoin类中创建出该方法。

在MyCoin.h中声明:

void changeFlag();//改变标志,执行翻转效果
    QTimer *timer1; //正面翻反面 定时器
    QTimer *timer2; //反面翻正面 定时器
    int min = 1; //最小图片
    int max = 8; //最大图片

MyCoin.cpp中做实现

void MyCoin::changeFlag()
{
    if(this->flag) //如果是正面,执行下列代码
    {
        timer1->start(30);
        this->flag = false;
    }
    else //反面执行下列代码
    {
        timer2->start(30);
        this->flag = true;
    }
}

当然在构造函数中,记得创建出两个定时器。

//初始化定时器
    timer1 = new QTimer(this);
    timer2 = new QTimer(this);

5.9.2 创建特效

当我们分别启动两个定时器时,需要在构造函数中做监听操作,并且做出响应,翻转金币,然后再结束定时器。

构造函数中 进行下列监听代码:

  //监听正面翻转的信号槽
    connect(timer1,&QTimer::timeout,[=](){
        QPixmap pixmap;
        QString str = QString(":/res/Coin000%1.png").arg(this->min++);
        pixmap.load(str);
        this->setFixedSize(pixmap.width(),pixmap.height() );
        this->setStyleSheet("QPushButton{border:0px;}");
        this->setIcon(pixmap);
        this->setIconSize(QSize(pixmap.width(),pixmap.height()));
        if(this->min > this->max) //如果大于最大值,重置最小值,并停止定时器
        {
            this->min = 1;
            timer1->stop();
        }
    });

    connect(timer2,&QTimer::timeout,[=](){
        QPixmap pixmap;
        QString str = QString(":/res/Coin000%1.png").arg((this->max)-- );
        pixmap.load(str);
        this->setFixedSize(pixmap.width(),pixmap.height() );
        this->setStyleSheet("QPushButton{border:0px;}");
        this->setIcon(pixmap);
        this->setIconSize(QSize(pixmap.width(),pixmap.height()));
        if(this->max < this->min) //如果小于最小值,重置最大值,并停止定时器
        {
            this->max = 8;
            timer2->stop();
        }
    });

5.9.3 测试

监听每个按钮的点击效果,并翻转金币。

connect(coin,&MyCoin::clicked,[=](){
                //qDebug() << "点击的位置: x = " <<  coin->posX << " y = " << coin->posY ;
                coin->changeFlag();
                gameArray[i][j] = gameArray[i][j] == 0 ? 1 : 0; //数组内部记录的标志同步修改
            });

5.9.3 禁用按钮

此时,确实已经可以执行翻转金币代码了,但是如果快速点击,会在金币还没有执行一个完整动作之后 ,又继续开始新的动画,我们应该在金币做动画期间,禁止再次点击,并在完成动画后,开启点击。

在MyCoin类中加入一个标志 isAnimation 代表是否正在做翻转动画。

bool isAnimation  = false; //做翻转动画的标志

在MyCoin做动画期间加入

this->isAnimation  = true;

也就是changeFlag函数中将标志设为true

加入位置如下:

并且在做完动画时,将标志改为false

 

重写按钮的按下事件,判断如果正在执行动画,那么直接return掉,不要执行后续代码。

代码如下:

void MyCoin::mousePressEvent(QMouseEvent *e)
{
    if(this->isAnimation )
    {
        return;
    }
    else
    {
        return QPushButton::mousePressEvent(e);
    }
}

5.10 翻周围金币

将用户点击的周围 上下左右4个金币也进行延时翻转,代码写到监听点击金币下。

此时我们发现还需要记录住每个按钮的内容,所以我们将所有金币按钮也放到一个二维数组中,在.h中声明

MyCoin * coinBtn[4][4]; //金币按钮数组

并且记录每个按钮的位置

coinBtn[i][j] = coin;

延时翻动其他周围金币 。

QTimer::singleShot(300, this,[=](){
                    if(coin->posX+1 <=3)
                    {
                      coinBtn[coin->posX+1][coin->posY]->changeFlag();
                      gameArray[coin->posX+1][coin->posY] = gameArray[coin->posX+1][coin->posY]== 0 ? 1 : 0;
                    }
                    if(coin->posX-1>=0)
                    {
                      coinBtn[coin->posX-1][coin->posY]->changeFlag();
                      gameArray[coin->posX-1][coin->posY] = gameArray[coin->posX-1][coin->posY]== 0 ? 1 : 0;
                    }
                    if(coin->posY+1<=3)
                    {
                     coinBtn[coin->posX][coin->posY+1]->changeFlag();
                     gameArray[coin->posX][coin->posY+1] = gameArray[coin->posX+1][coin->posY]== 0 ? 1 : 0;
                    }
                    if(coin->posY-1>=0)
                    {
                     coinBtn[coin->posX][coin->posY-1]->changeFlag();
                     gameArray[coin->posX][coin->posY-1] = gameArray[coin->posX+1][coin->posY]== 0 ? 1 : 0;
                    }
                });

5.11 判断是否胜利

在MyCoin.h中加入 isWin标志,代表是否胜利。

bool isWin = true; //是否胜利

默认设置为true,只要有一个反面的金币,就将该值改为false,视为未成功。

代码写到延时翻金币后 进行判断。

//判断是否胜利
                this->isWin = true;
                for(int i = 0 ; i < 4;i++)
                {
                    for(int j = 0 ; j < 4; j++)
                    {
                        //qDebug() << coinBtn[i][j]->flag ;
                        if( coinBtn[i][j]->flag == false)
                        {
                            this->isWin = false;
                            break;
                        }
                    }
                }

如果isWin依然是true,代表胜利了!

if(this->isWin)
       {
              qDebug() << "胜利";
       }

5.12 胜利图片显示

将胜利的图片提前创建好,如果胜利触发了,将图片弹下来即可

QLabel* winLabel = new QLabel;
    QPixmap tmpPix;
    tmpPix.load(":/res/LevelCompletedDialogBg.png");
    winLabel->setGeometry(0,0,tmpPix.width(),tmpPix.height());
    winLabel->setPixmap(tmpPix);
    winLabel->setParent(this);
    winLabel->move( (this->width() - tmpPix.width())*0.5 , -tmpPix.height());

如果胜利了,将上面的图片移动下来

if(this->isWin)
    {
       qDebug() << "胜利";
        QPropertyAnimation * animation1 =  new QPropertyAnimation(winLabel,"geometry");
                        animation1->setDuration(1000);
                        animation1->setStartValue(QRect(winLabel->x(),winLabel->y(),winLabel->width(),winLabel->height()));
                        animation1->setEndValue(QRect(winLabel->x(),winLabel->y()+114,winLabel->width(),winLabel->height()));
                        animation1->setEasingCurve(QEasingCurve::OutBounce);
                        animation1->start();
                    }

5.13 胜利后禁用按钮

当胜利后,应该禁用所有按钮的点击状态,可以在每个按钮中加入标志位 isWin,如果isWin为true,MousePressEvent直接return掉即可

MyCoin中.h里添加:
bool isWin = false;//胜利标志

在鼠标按下事件中修改为
void MyCoin::mousePressEvent(QMouseEvent *e)
{
    if(this->isAnimation|| isWin == true )
    {
        return;
    }
    else
    {
        return QPushButton::mousePressEvent(e);
    }
}
//禁用所有按钮点击事件
    for(int i = 0 ; i < 4;i++)
      {
        for(int j = 0 ; j < 4; j++)
        {
          coinBtn[i][j]->isWin = true;
        }
}

测试,胜利后不可以点击任何的金币。

6 音效添加

6.1 开始音效

QSound *startSound = new QSound(":/res/TapButtonSound.wav",this);

点击开始按钮,播放音效

startSound->play(); //开始音效

6.2 选择关卡音效

在选择关卡场景中,添加音效。

//选择关卡按钮音效
    QSound *chooseSound = new QSound(":/res/TapButtonSound.wav",this);

选中关卡后,播放音效

chooseSound->play();

6.3 返回按钮音效

在选择关卡场景与翻金币游戏场景中,分别添加返回按钮音效如下:

        

//返回按钮音效
    QSound *backSound = new QSound(":/res/BackButtonSound.wav",this);

分别在点击返回按钮后,播放该音效

        

backSound->play();

6.4 翻金币与胜利音效

在PlayScene中添加,翻金币的音效以及 胜利的音效

//翻金币音效
    QSound *flipSound = new QSound(":/res/ConFlipSound.wav",this);
    //胜利按钮音效
    QSound *winSound = new QSound(":/res/LevelWinSound.wav",this);

在翻金币时播放 翻金币音效

flipSound->play();

胜利时,播放胜利音效

winSound->play();

测试音效,使音效正常播放。

7 优化项目

当我们移动场景后,如果进入下一个场景,发现场景还在中心位置,如果想设置场景的位置,需要添加如下下图中的代码:

MainScene中添加:

ChooseScene中添加: 

测试切换三个场景的进入与返回都在同一个位置下,优化成功。

至此,本案例全部制作完成。

 

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

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

相关文章

GPT系列论文解读:GPT-2

GPT系列 GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一系列基于Transformer架构的预训练语言模型&#xff0c;由OpenAI开发。以下是GPT系列的主要模型&#xff1a; GPT&#xff1a;GPT-1是于2018年发布的第一个版本&#xff0c;它使用了12个Transformer…

JavaEE 网络原理——TCP的工作机制(中篇 三次握手和四次挥手)

文章目录 一、TCP 内部工作机制——连接管理1. 连接(三次握手)(1).有连接和确认应答之间的关系(2). 通过客户端和服务器详细描述三次握手 2. 断开连接(四次挥手)(1)讨论“四次握手”中间步骤的合并问题。(2) 根据简单的 TCP 代码解释断开连接(3) 四次挥手中的两个重要的 TCP 状…

计算机网络-计算机网络体系结构-物理层

目录 一、通信基础 通信方式 传输方式 码元 传输率 *二 准则 2.1奈氏准则(奈奎斯特定理) 2.2香农定理 三、信号的编码和调制 *数字数据->数字信号 数字数据->模拟信号 模拟数据->数字信号 模拟数据->模拟信号 *四、数据交换方式 电路交换 报文交换…

【刷题笔记10.5】LeetCode:排序链表

LeetCode&#xff1a;排序链表 一、题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 二、分析 这题咱们默认要求&#xff1a;空间复杂度为O(1)。所以这把咱们用自底向上的方法实现归并排序&#xff0c;则可以达到O(1) 的空间复杂…

[极客大挑战 2019]FinalSQL - 异或盲注

1、这题的关键是找注入点&#xff0c;如果选择用户名、密码作为输入点就麻烦了 2、注入点&#xff1a;按钮&#xff0c;点击就传id&#xff1b;当id1时&#xff0c;提示Click others   可以利用id的特性&#xff0c;构造异或匹配   payload: f"1^(ord(substr((select…

nodejs+vue中医体质的社区居民健康管理系统elementui

可以实现首页、中医体质量表、健康文章、健康视频、我的等&#xff0c;在我的页面可以对医生、小区单元、医疗药品等功能进行操作。目前主要的健康管理系统是以西医为主&#xff0c;而为了传扬中医文化&#xff0c;提高全民健康意识&#xff0c;解决人民日益增长的美好生活需要…

基于SpringBoot的图书进销存管理系统

目录 前言 一、技术栈 二、系统功能介绍 用户信息管理 图书类型管理 商品退货管理 客户信息管理 图书添加 客户添加 应收金额 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实…

Ubuntu无法引导启动的修复

TLDR&#xff1a;使用Boot-Repair工具。 Boot-Repair Boot-Repair是一个简单的工具&#xff0c;用于修复您在Ubuntu中可能遇到的常见启动问题&#xff0c;例如在安装Windows或其他Linux发行版后无法启动Ubuntu时&#xff0c;或者在安装Ubuntu后无法启动Windows时&#xff0c;…

[CISCN 2019华北Day2]Web1 - 布尔盲注

考点&#xff1a;布尔盲注【注意&#xff0c;sql中的substr初始位置是1不是0】 1、页面提示用id传参&#xff0c;而且我们发现是post传参 2、我们传了id1后提示“Hello, glzjin wants a girlfriend.“ 3、由于这题直接输入查询字符&#xff0c;可以通过字典爆破过滤&#xff0…

深度学习基础之参数量(3)

一般的CNN网络的参数量估计代码 class ResidualBlock(nn.Module):def __init__(self, in_planes, planes, norm_fngroup, stride1):super(ResidualBlock, self).__init__()print(in_planes, planes, norm_fn, stride)self.conv1 nn.Conv2d(in_planes, planes, kernel_size3, …

人机关系不是物理关系也不是数理关系

人机关系是一种复杂的社会技术系统&#xff0c;涉及到人类和机器、环境之间的相互作用和影响。它不仅限于物理接触和数理规律&#xff0c;同时还包括了思维、情感、意愿等方面的交流和互动。在人机关系中&#xff0c;人类作为使用者和机器作为工具&#xff08;将来可能会上升到…

rust入门一:安装 Hello World

环境&#xff1a; window 11 专业版rust 1.72.1 一、下载安装 直接去官网&#xff1a; https://www.rust-lang.org/tools/install 下载完成后如下&#xff1a; 双击运行一步步安装就行。 如果是更新或卸载&#xff0c;在命令行中运行&#xff1a; rustup update&#xff1a…

ChatGPT基础使用总结

文章目录 一、ChatGPT基础概念大型语言模型LLMs---一种能够以类似人类语言的方式“说话”的软件ChatGPT定义---OpenAI 研发的一款聊天机器人程序&#xff08;2022年GPT-3.5&#xff0c;属于大型语言模型&#xff09;ChatGPT4.0---OpenAI推出了GPT系列的最新模型ChatGPT典型使用…

[GXYCTF2019]禁止套娃 无回显 RCE 过滤__FILE__ dirname等

扫除git 通过githack 获取index.php <?php include "flag.php"; echo "flag在哪里呢&#xff1f;<br>"; if(isset($_GET[exp])){if (!preg_match(/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i, $_GET[exp])) {if(; preg_replace(/[a-z,_]\(…

DevicData-D-XXXXXXXX勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

引言&#xff1a; 在数字时代&#xff0c;数据安全成为一项至关重要的挑战。DevicData-D-XXXXXXXX勒索病毒&#xff08;以下简称DevicData病毒&#xff09;是这场战斗中的新敌人&#xff0c;它能够以毁灭性的方式加密您的数据&#xff0c;迫使您在数据和时间之间做出艰难的选择…

nodejs+vue游戏测评交流系统elementui

可以实现首页、发布招募、公司资讯、我的等&#xff0c;另一方面来说也可以提高在游戏测评交流方面的效率给相关管理人员的工作带来一定的便利。在我的页面可以对游戏攻略、我的收藏管理、实际上如今信息化成为一个未来的趋势或者可以说在当前现代化的城市典范中,发布招募等功能…

[图论]哈尔滨工业大学(哈工大 HIT)学习笔记23-31

视频来源&#xff1a;4.1.1 背景_哔哩哔哩_bilibili 目录 1. 哈密顿图 1.1. 背景 1.2. 哈氏图 2. 邻接矩阵/邻接表 3. 关联矩阵 3.1. 定义 4. 带权图 1. 哈密顿图 1.1. 背景 &#xff08;1&#xff09;以地球为建模&#xff0c;从一个大城市开始遍历其他大城市并且返回…

逆变器下垂控制单机

仿真控制参数 主电路 坐标变换 功率计算 下垂控制 电压电流双闭环控制 结果变量监控 断路器闭合&#xff0c;负载突增 负载突增&#xff0c;有功和无功突增 有功增加&#xff0c;频率减小 无功增加&#xff0c;参考电压减小

【JavaScript】相等运算符(== 和 ===)

如果x和y的类型相同&#xff0c;JavaScript会用equals 方法比较这两个值或对象。 没有出现在表格中的情况都会返回 false。&#xff08;表格中的方法都是内部规定的&#xff09; 对于 toNumber 方法&#xff1a; 对于 toPrimitive 方法&#xff1a; // 举个例子&#xff1a; c…

基于JavaWeb技术的在线考试系统设计与实现

目录 前言 一、技术栈 二、系统功能介绍 用户信息管理 考试统计管理 专业列表管理 忘记密码人员登记管理 修改密码 试卷信息 考试信息管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理…