第十三章- 游戏结束

news2024/12/26 21:29:29

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

在这个例子中我们开始研究一个带有记分的真正可玩的游戏。我们给MyWidget一个新的名字GameBoard并添加一些槽。

我们把定义放在gamebrd.h并把实现放在gamebrd.cpp

CannonField现在有了一个游戏结束状态。

LCDRange中的布局问题已经修好了。

  • lcdrange.h包含LCDRange类定义
  • lcdrange.cpp包含LCDRange类实现
  • cannon.h包含CannonField类定义
  • cannon.cpp包含CannonField类实现
  • gamebrd.h包含GameBoard类定义
  • gamebrd.cpp包含GameBoard类实现
  • main.cpp包含MyWidget和main

一行一行地解说

lcdrange.h

#include <QWidget>

class QSlider;
class QLabel;

class LCDRange : public QWidget

我们继承了QWidget,并且使用QVBoxLayout。QVBoxLayout不是一个窗口部件,它管理窗口部件。

lcdrange.cpp

LCDRange::LCDRange(QWidget *parent, Qt::WindowFlags name)
    : QWidget(parent, name)

我们使用一种平常的方式继承QWidget

另外一个构造函数作了同样的改动。init()没有变化

    QVBoxLayout *layout = new QVBoxLayout;

我们使用所有默认值创建一个QVBoxLayout,管理这个窗口部件的子窗口部件。

cannon.h:

CannonField现在有一个游戏结束状态和一些新的函数。

    bool  gameOver() const {return gameEnded;}

如果游戏结束了,这个函数返回TRUE,或者如果游戏还在继续,返回FALSE。

    void  setGameOver();
    void  restartGame();

这里是两个新槽:setGameOver()restartGame()

    void  canShoot(bool);

这个新的信号表明CannonField使shoot()槽生效的状态。我们将在下面使用它用来使`Shoot按钮生效或失效。

    bool gameEnded;

这个私有变量包含游戏的状态。true说明游戏结束,false说明游戏还将继续。

cannon.cpp:

    gameEnded = false;

这一行已经被加入到构造函数中。最开始的时候,游戏没有结束。

void CannonField::shoot()
{
    if (isShooting())
        return;
    timerCount = 0;
    shoot_ang = ang;
    shoot_f = f;
    autoShootTimer->start(50);
    emit canShoot(false);
}

我们添加一个新的isShooting()函数,所以shoot()使用它替代直接的测试。同样,shoot告诉CannonField现在不可以射击。

void CannonField::setGameOver()
{
    if (gameEnded)
        return;
    if (isShooting())
        autoShootTimer->stop();
    gameEnded = true;
    repaint();
}

这个槽终止游戏。它必须被CannonField外面的调用,因为这个窗口部件不知道什么时候终止游戏。这是组件编程中一条重要设计原则。我们选择使组件可以尽可能灵活以适应不同的规则(比如,在一个首先射中十次的人胜利的多人游戏版本可能使用不变的CannonField)。

如果游戏已经被终止,我们立即返回。如果游戏会继续到我们的射击完成,设置游戏结束标志,并且重新绘制整个窗口部件。

void CannonField::restartGame()
{
    if (isShooting())
        autoShootTimer->stop();
    gameEnded = false;
    repaint();
    emit canShoot(true);
}

这个槽开始一个新游戏。如果炮弹还在空中,我们停止射击。然后我们重置gameEnded变量并重新绘制窗口部件。

就像hit()miss()一样,moveShot()同时也发射新的canShoot(true)信号。

CannonField::paintEvent()的修改:

void CannonField::paintEvent(QPaintEvent *e)
{
    QRect updateR = e->rect();
    QPainter p(this);

    if (gameEnded)
    {
        p.setPen(Qt::black);
        p.setFont(QFont("Courier", 48, QFont::Bold ));
        p.drawText(rect(),Qt::AlignHCenter, "Game Over");
    }

绘画事件已经通过如果游戏结束,比如gameEndedtrue,就显示文本Game Over而被增强了。我们在这里不怕麻烦来检查更新矩形,是因为在游戏结束的时候速度不是关键性的。

为了画文本,我们先设置了黑色的画笔,当画文本的时候,画笔颜色会被用到。接下来我们选择Courier字体中的48号加粗字体。最后我们在窗口部件的矩形中央绘制文本。不幸的是,在一些系统中(特别是使用Unicode的X服务器)它会用一小段时间来载入如此大的字体。因为Qt缓存字体,我们只有第一次使用这个字体的时候才会注意到这一点。

    if (updateR.intersects(cannonRect()))
        paintCannon(&p);
    if (autoShootTimer->isActive() && updateR.intersects(shotRect()))
        paintShot(&p);
    if (updateR.intersects(targetRect()))
        paintTarget(&p);
}

我们只有在射击的时候画炮弹,在玩游戏的时候画目标。

gamebrd.h

这个文件是新的。它包含最后被用来作为MyWidgetGameBoard类的定义。

#ifndef GAMEBOARD_H
#define GAMEBOARD_H

#include <QWidget>
#include "cannon.h"

class LCDRange;
class QLCDNumber;
class CannonField;
class QPushButton;

class GameBoard : public QWidget
{
    Q_OBJECT
public:
    explicit GameBoard(QWidget *parent = 0, Qt::WindowFlags name = Qt::WindowFlags());

protected slots:
    void  fire();
    void  hit();
    void  missed();
    void  newGame();

private:
    QLCDNumber  *hits;
    QLCDNumber  *shotsLeft;
    CannonField *cannonField;
};

#endif // GAMEBOARD_H

我们现在已经添加了四个槽。这些槽都是被保护的,只在内部使用。我们也已经加入了两个QLCDNumbers(hits和shotsLeft)用来显示游戏的状态。

gamebrd.cpp:

这个文件是新的。它包含最后被用来作为MyWidgetGameBoard类的实现,

我们已经在GameBoard的构造函数中做了一些修改。

    cannonField = new CannonField;

cannonField现在是一个成员变量,所以我们在使用它的时候要小心地改变它的构造函数。

    connect(cannonField, SIGNAL(hit()), this, SLOT(hit()));
    connect(cannonField, SIGNAL(missed()), this, SLOT(missed()));

这次当炮弹射中或者射失目标的时候,我们想做些事情。所以我们把CannonFieldhit()missed()信号连接到这个类的两个被保护的同名槽。

    connect(shoot, SIGNAL(clicked()), SLOT(fire()));

以前我们直接把Shoot按钮的clicked()信号连接到CannonField的shoot()槽。这次我们想跟踪射击的次数,所以我们把它改为连接到这个类里面一个被保护的槽。

注意当你用独立的组件工作的时候,改变程序的行为是多么的容易。

    connect(cannonField, SIGNAL(canShoot(bool)), shoot, SLOT(setEnabled(bool)));

我们也使用cannonFieldcanShoot()信号来适当地使Shoot按钮生效和失效。

    QPushButton *restart = new QPushButton("&New Game");
    restart->setFont(QFont("Times", 18, QFont::Bold));
    connect(restart, SIGNAL(clicked()), this, SLOT(newGame()));

我们创建、设置并且连接这个New Game按钮就像我们对其它按钮所做的一样。点击这个按钮就会激活这个窗口部件的newGame()槽。

    hits = new QLCDNumber(2);
    shotsLeft = new QLCDNumber(2);
    QLabel *hitsL = new QLabel("HITS");
    QLabel *shotsLeftL = new QLabel("SHOTS LEFT");

我们创建了四个新的窗口部件。注意我们不怕麻烦的把QLabel窗口部件的指针保留到GameBoard类中是因为我们不想再对它们做什么了。当GameBoard窗口部件被销毁的时候,Qt将会删除它们,并且布局类会适当地重新定义它们的大小。

    QHBoxLayout *topBox = new QHBoxLayout;
    grid->addLayout(topBox, 0, 1);
    topBox->addWidget(shoot);
    topBox->addWidget(hits);
    topBox->addWidget(hitsL);
    topBox->addWidget(shotsLeft);
    topBox->addWidget(shotsLeftL);
    topBox->addStretch(1);
    topBox->addWidget(restart);

右上单元格的窗口部件的数量正在变大。从前它是空的,现在它是完全充足的,我们把它们放到布局中来更好的看到它们。

注意我们让所有的窗口部件获得它们更喜欢的大小,改为在New Game按钮的左边加入了一个可以自由伸展的东西。

    newGame();
}

我们已经做完了所有关于GameBoard的构造,所以我们使用newGame()来开始。(newGame()是一个槽,但是就像我们所说的,槽也可以像普通的函数一样使用。)

void GameBoard::fire()
{
    if (cannonField->gameOver() || cannonField->isShooting())
        return;
    shotsLeft->display(shotsLeft->intValue() - 1);
    cannonField->shoot();
}

这个函数进行射击。如果游戏结束了或者还有炮弹在空中,立即返回。我们减少炮弹的数量并告诉加农炮进行射击。

void GameBoard::hit()
{
    hits->display( hits->intValue() + 1 );
    if ( shotsLeft->intValue() == 0 )
        cannonField->setGameOver();
    else
        cannonField->newTarget();
}

当炮弹击中目标的时候这个槽被激活。我们增加射中的数量。如果没有炮弹了,游戏就结束了。否则,我们会让CannonField生成新的目标。

void GameBoard::missed()
{
    if (shotsLeft->intValue() == 0)
        cannonField->setGameOver();
}

当炮弹射失目标的时候这个槽被激活,如果没有炮弹了,游戏就结束了。

void GameBoard::newGame()
{
    shotsLeft->display( 15 );
    hits->display( 0 );
    cannonField->restartGame();
    cannonField->newTarget();
}

当用户点击Restart按钮的时候这个槽被激活。它也会被构造函数调用。首先它把炮弹的数量设置为15。注意这里是我们在程序中唯一设置炮弹数量的地方。把它改变为你所想要的游戏规则。接下来我们重置射中的数量,重新开始游戏,并且生成一个新的目标。

main.cpp:
这个文件仅仅被删掉了一部分。MyWidget没了,并且唯一剩下的是main()函数,除了名称的改变其它都没有改变。

行为

射中的和剩余炮弹的数量被显示并且程序继续跟踪它们。游戏可以结束了,并且还有一个按钮可以开始一个新游戏。

练习

添加一个随机的风的因素并把它显示给用户看。

当炮弹击中目标的时候做一些飞溅的效果。

实现多个目标。

现在你可以进行第十四章了。


lcdrange.h

#ifndef LCDRANGE_H
#define LCDRANGE_H

#include <QWidget>

class QSlider;
class QLabel;

class LCDRange : public QWidget
{
    Q_OBJECT
public:
    LCDRange(QWidget *parent = 0, Qt::WindowFlags name = Qt::WindowFlags());
    LCDRange(const QString &s, QWidget *parent = 0, Qt::WindowFlags name = Qt::WindowFlags());

    int value() const;
    const QString text() const;

public slots:
    void setValue(int);
    void setRange(int minVal, int maxVal);
    void setText(const QString &s);

signals:
    void valueChanged(int);

private:
    void init();

    QSlider *slider;
    QLabel  *label;
};

#endif // LCDRANGE_H

lcdrange.cpp

#include "lcdrange.h"
#include <QVBoxLayout>
#include <QLCDNumber>
#include <QSlider>
#include <QLabel>

LCDRange::LCDRange(QWidget *parent, Qt::WindowFlags name)
    : QWidget(parent, name)
{
    init();
}

LCDRange::LCDRange(const QString &s, QWidget *parent, Qt::WindowFlags name)
    : QWidget(parent, name)
{
    init();
    setText(s);
}

void LCDRange::init()
{
    QLCDNumber *lcd  = new QLCDNumber(2);
    slider = new QSlider(Qt::Horizontal);
    slider->setRange(0, 99);
    slider->setValue(0);

    label = new QLabel;
    label->setAlignment(Qt::AlignHCenter);

    connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
    connect(slider, SIGNAL(valueChanged(int)), SIGNAL(valueChanged(int)));

    setFocusProxy(slider); //设置这个窗口部件的焦点为slider

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(lcd);
    layout->addWidget(slider);
    layout->addWidget(label);
    setLayout(layout);
}

int LCDRange::value() const
{
    return slider->value();
}

const QString LCDRange::text() const
{
     return label->text();
}

void LCDRange::setValue(int value)
{
    slider->setValue(value);
}

void LCDRange::setRange(int minVal, int maxVal)
{
    if (minVal < 0 || maxVal > 99 || minVal > maxVal)
    {
        qWarning( "LCDRange::setRange(%d,%d)\n"
                 "\tRange must be 0~99\n"
                 "\tand minVal must not be greater than maxVal",
                 minVal, maxVal);
        return;
    }
    slider->setRange(minVal, maxVal);
}

void LCDRange::setText(const QString &s)
{
    label->setText(s);
}

cannon.h

#ifndef CANNON_H
#define CANNON_H

class QTimer;

#include <QWidget>

class CannonField : public QWidget
{
    Q_OBJECT
public:
    CannonField(QWidget *parent = 0, Qt::WindowFlags name = Qt::WindowFlags());
    int angle() const {return ang;}
    int force() const {return f;}
    bool gameOver() const {return gameEnded;}
    bool isShooting() const;

public slots:
    void setAngle(int degrees);
    void setForce(int newton);
    void shoot();
    void newTarget();
    void setGameOver();
    void restartGame();

private slots:
    void moveShot(); // 更新炮弹的位置

signals:
    void hit();
    void missed();
    void angleChanged(int);
    void forceChanged(int);
    void canShoot(bool);

protected:
    void paintEvent(QPaintEvent *); // 窗口刷新/重绘

private:
    void paintShot(QPainter *);
    void paintTarget(QPainter *);
    void paintCannon(QPainter *);
    QRect cannonRect() const;
    QRect shotRect() const;
    QRect targetRect() const;

    int ang;
    int f;

    int timerCount;
    QTimer *autoShootTimer;
    float shoot_ang;
    float shoot_f;

    QPoint target;
    bool gameEnded;
};

#endif // CANNON_H

cannon.cpp

#include "cannon.h"
#include <QPaintEvent>
#include <QDateTime>
#include <QPainter>
#include <QPixmap>
#include <QTimer>

#include <stdlib.h>
#include <math.h>

CannonField::CannonField(QWidget *parent, Qt::WindowFlags name)
    : QWidget(parent, name)
{
    ang = 45;
    f = 0;
    timerCount = 0;
    autoShootTimer = new QTimer();
    connect(autoShootTimer, SIGNAL(timeout()), this, SLOT(moveShot()));
    shoot_ang = 0;
    shoot_f = 0;
    target = QPoint(0, 0);
    gameEnded = false;
    setAutoFillBackground(true);
    setPalette(QPalette(QColor(250, 250, 200)));
    newTarget();
}

void CannonField::setAngle(int degrees)
{
    if (degrees < 5)
        degrees = 5;
    if (degrees > 70)
        degrees = 70;
    if (ang == degrees)
        return;
    ang = degrees;
    repaint(cannonRect());
    emit angleChanged(ang);
}

void CannonField::setForce(int newton)
{
    if (newton < 0)
        newton = 0;
    if (f == newton)
        return;
    f = newton;
    emit forceChanged(f);
}

void CannonField::shoot()
{
    if (isShooting())
        return;
    timerCount = 0;
    shoot_ang = ang;
    shoot_f = f;
    autoShootTimer->start(50);
    emit canShoot(false);
}

void  CannonField::newTarget()
{
    static bool first_time = true;
    if (first_time)
    {
        first_time = false;
        QTime midnight(0, 0, 0);
        srand(midnight.secsTo(QTime::currentTime()));
    }
    QRegion r(targetRect());
    target = QPoint(200 + rand() % 190, 10 + rand() % 255);
    repaint(r.united(targetRect()));
}

void CannonField::setGameOver()
{
    if (gameEnded)
        return;
    if (isShooting())
        autoShootTimer->stop();
    gameEnded = true;
    repaint();
}

void CannonField::restartGame()
{
    if (isShooting())
        autoShootTimer->stop();
    gameEnded = false;
    repaint();
    emit canShoot(true);
}

void CannonField::moveShot()
{
    QRegion r(shotRect());
    timerCount++;

    QRect shotR = shotRect();

    if (shotR.intersects(targetRect()))
    {
        autoShootTimer->stop();
        emit hit();
    }
    else if (shotR.x() > width() || shotR.y() > height())
    {
        autoShootTimer->stop();
        emit missed();
        emit canShoot(true);
    }
    else
    {
        r = r.united(QRegion(shotR));
    }

    repaint(r);
}

void CannonField::paintEvent(QPaintEvent *e)
{
    QRect updateR = e->rect();
    QPainter p(this);

    if (gameEnded)
    {
        p.setPen(Qt::black);
        p.setFont(QFont("Courier", 48, QFont::Bold ));
        p.drawText(rect(),Qt::AlignHCenter, "Game Over");
    }
    if (updateR.intersects(cannonRect()))
        paintCannon(&p);
    if (autoShootTimer->isActive() && updateR.intersects(shotRect()))
        paintShot(&p);
    if (updateR.intersects(targetRect()))
        paintTarget(&p);
}

void CannonField::paintShot(QPainter *p)
{
    p->setBrush(Qt::black);
    p->setPen(Qt::NoPen);
    p->drawEllipse(shotRect()); // 绘制填充圆
}

void CannonField::paintTarget(QPainter *p)
{
    p->setBrush(Qt::red);
    p->setPen(Qt::NoPen);
    p->drawRect(targetRect());
}

const QRect barrelRect(33, -4, 15, 8);

void CannonField::paintCannon(QPainter *p)
{
    QRect cr = cannonRect();
    QPixmap pix(cr.size());
    pix.fill(Qt::transparent); //使用透明像素图

    QPainter tmp(&pix);
    tmp.setBrush(Qt::blue);
    tmp.setPen(Qt::NoPen);

    tmp.translate(0, pix.height() - 1);
    tmp.drawPie(QRect(-35,-35, 70, 70), 0, 90*16);
    tmp.rotate(-ang);
    tmp.drawRect(barrelRect);
    tmp.end();

    p->drawPixmap(cr.topLeft(), pix);
}

QRect CannonField::cannonRect() const
{
    QRect r(0, 0, 50, 50);
    r.moveBottomLeft(rect().bottomLeft());
    return r;
}

QRect CannonField::shotRect() const
{
    const double gravity = 4;

    double time      = timerCount / 4.0;
    double velocity  = shoot_f;
    double radians   = shoot_ang * 3.14159265 / 180;

    double velx      = velocity * cos(radians);
    double vely      = velocity * sin(radians);
    double x0        = (barrelRect.right() + 5) * cos(radians);
    double y0        = (barrelRect.right() + 5) * sin(radians);
    double x         = x0 + velx * time;
    double y         = y0 + vely * time - 0.5 * gravity * time * time;

    QRect r = QRect(0, 0, 6, 6);
    r.moveCenter(QPoint(qRound(x), height() - 1 - qRound(y)));

    return r;
}

QRect CannonField::targetRect() const
{
    QRect r(0, 0, 20, 10);
    r.moveCenter(QPoint(target.x(),height() - 1 - target.y()));
    return r;
}

bool CannonField::isShooting() const
{
    return autoShootTimer->isActive();
}

gamebrd.h

#ifndef GAMEBOARD_H
#define GAMEBOARD_H

#include <QWidget>
#include "cannon.h"

class LCDRange;
class QLCDNumber;
class CannonField;
class QPushButton;

class GameBoard : public QWidget
{
    Q_OBJECT
public:
    explicit GameBoard(QWidget *parent = 0, Qt::WindowFlags name = Qt::WindowFlags());

protected slots:
    void  fire();
    void  hit();
    void  missed();
    void  newGame();

private:
    QLCDNumber  *hits;
    QLCDNumber  *shotsLeft;
    CannonField *cannonField;
};

#endif // GAMEBOARD_H

gamebrd.cpp

#include "gameboard.h"

#include <QApplication>
#include <Qpushbutton>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QLCDNumber>
#include <QLabel>
#include <Qfont>

#include "lcdrange.h"
#include "cannon.h"

GameBoard::GameBoard(QWidget *parent, Qt::WindowFlags name)
    : QWidget(parent, name)
{
    QPushButton *quit = new QPushButton("&Quit");
    quit->setFont(QFont("Times", 18, QFont::Bold));

    connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));

    LCDRange *angle  = new LCDRange("ANGLE");
    angle->setRange(5, 70);

    LCDRange *force  = new LCDRange("FORCE");
    force->setRange(10, 50);

    cannonField = new CannonField;

    connect(angle, SIGNAL(valueChanged(int)), cannonField, SLOT(setAngle(int)));
    connect(cannonField, SIGNAL(angleChanged(int)), angle, SLOT(setValue(int)));

    connect(force, SIGNAL(valueChanged(int)), cannonField, SLOT(setForce(int)));
    connect(cannonField, SIGNAL(forceChanged(int)), force, SLOT(setValue(int)));

    connect(cannonField, SIGNAL(hit()), this, SLOT(hit()));
    connect(cannonField, SIGNAL(missed()), this, SLOT(missed()));

    QPushButton *shoot = new QPushButton("&Shoot");
    shoot->setFont(QFont("Times", 18, QFont::Bold));

    connect(shoot, SIGNAL(clicked()), SLOT(fire()));
    connect(cannonField, SIGNAL(canShoot(bool)), shoot, SLOT(setEnabled(bool)));

    QPushButton *restart = new QPushButton("&New Game");
    restart->setFont(QFont("Times", 18, QFont::Bold));

    connect(restart, SIGNAL(clicked()), this, SLOT(newGame()));

    hits = new QLCDNumber(2);
    shotsLeft = new QLCDNumber(2);
    QLabel *hitsL = new QLabel("HITS");
    QLabel *shotsLeftL = new QLabel("SHOTS LEFT");

    QGridLayout *grid = new QGridLayout;
    grid->addWidget(quit, 0, 0);
    grid->addWidget(cannonField, 1, 1);
    grid->setColumnStretch(1, 10);

    QVBoxLayout *leftBox = new QVBoxLayout;
    grid->addLayout(leftBox, 1, 0);
    leftBox->addWidget(angle);
    leftBox->addWidget(force);

    QHBoxLayout *topBox = new QHBoxLayout;
    grid->addLayout(topBox, 0, 1);
    topBox->addWidget(shoot);
    topBox->addWidget(hits);
    topBox->addWidget(hitsL);
    topBox->addWidget(shotsLeft);
    topBox->addWidget(shotsLeftL);
    topBox->addStretch(1);
    topBox->addWidget(restart);

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addLayout(grid);
    setLayout(layout);

    angle->setValue(60);
    force->setValue(25);
    angle->setFocus();

    newGame();
}

void GameBoard::fire()
{
    if (cannonField->gameOver() || cannonField->isShooting())
        return;
    shotsLeft->display(shotsLeft->intValue() - 1);
    cannonField->shoot();
}

void GameBoard::hit()
{
    hits->display(hits->intValue() + 1);
    if (shotsLeft->intValue() == 0)
        cannonField->setGameOver();
    else
        cannonField->newTarget();
}

void GameBoard::missed()
{
    if (shotsLeft->intValue() == 0)
        cannonField->setGameOver();
}

void GameBoard::newGame()
{
    shotsLeft->display(10);
    hits->display(0);
    cannonField->restartGame();
    cannonField->newTarget();
}


main.cpp

#include <QApplication>
#include "gameboard.h"

int main(int argc, char **argv)
{
    QApplication a(argc, argv);

    GameBoard gb;
    gb.setGeometry(100, 100, 500, 355);
    gb.show();
    return a.exec();
}

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

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

相关文章

如何使用ssm实现学生就业管理系统

TOC ssm328学生就业管理系统jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化管理。…

AI算力资源池建设重点

I算力资源池建设正当时 随着深度学习和计算机视觉领域的快速发展&#xff0c;各行各业对于AI算力资源的需求也在快速增长。AI算力池化不仅有助于提高资源的利用率&#xff0c;还可以提高工作效率、减少管理成本。今天就我们一起探讨如何组织和管理AI算力资源池、实现算力资源的…

真话有危险,测评需谨慎!一个家最大的内耗:谁都在抱怨,没人肯改变——早读(逆天打工人爬取热门微信文章解读)

现在都这么完了吗&#xff1f; 引言Python 代码第一篇 洞见 一个家最大的内耗&#xff1a;谁都在抱怨&#xff0c;没人肯改变第二篇 故事风云录结尾 引言 慢慢调整时间 一是现在有点忙 做那个传播声音的研究实验实在是有点没有头绪 没有头绪的事情你就不知道怎么安排时间 也就…

【随记】开源 AI(Open source AI)

开源 AI(Open source AI) 1. 开源AI的重要性 2. 主要开源AI框架和工具 3. 开源AI项目的典型应用 4. 参与开源AI社区的好处 5. 开源AI的挑战与风险 6. 未来展望 &#x1f388;边走、边悟&#x1f388;迟早会好 开源人工智能&#xff08;Open Source AI&#xff09;指的是…

html+css+js网页设计 个人博客模版 4个页面

htmlcssjs网页设计 个人博客模版 4个页面 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&…

漏洞复现-浪潮-GS企业管理软件-RCE

本文来自无问社区&#xff0c;更多漏洞复现可前往社区查看http://www.wwlib.cn/index.php/artread/artid/4564.html 0x01 产品简介 浪潮GS是浪潮研发的系统软件&#xff0c;浪潮GS&#xff0c;采用SOA 架构和先进开放的GSP 应用中间件开发&#xff0c;面向大中型集团企业提供…

Qt+FFmpeg开发视频播放器笔记(一):环境搭建

一、FFmpeg介绍 FFmpeg是一个开源的跨平台多媒体处理工具集&#xff0c;它可以用于处理音频、视频和其他多媒体数据。FFmpeg提供了一组功能强大的命令行工具&#xff0c;用于音频和视频的编解码、转换、处理、流媒体传输等任务。 FFmpeg支持多种音频和视频格式&#xff0c;包…

数模备赛(二):cvxpy凸优化库安装

03线性规划、整数规划与案例讲解视频上_哔哩哔哩_bilibili 强烈安利b站的司守奎老师讲的python数学建模&#xff0c;非常详细 但是在安装cvxpy库遇到了一点麻烦&#xff08;有的教程用的是linprog这个库&#xff0c;但是要求最优化问题必须先改写成标准型&#xff0c;感觉还是有…

自动分词代码

代码 from wordsegment import load, segment# 加载模型 load()# 示例 actions ["seeyoulater","turnleft","turnr" ]segmented_actions [segment(action) for action in actions] segmented_actions [" ".join(action) for actio…

SAP FI模块开发

1. SAP FI模块财务主数据管理 2. 总账核算

【芯片CDC/RDC】如何解决RDC问题

SoC设计除了包含多个电压域、多个时钟域外还包含了多个异步复位域。如果SoC中存在跨异步复位域时&#xff0c;同样经常会遇到亚稳态的问题。 举个例子&#xff0c;如下图&#xff1a; 好评如潮&#xff0c;一定要把景芯打磨成精品&#xff01; 对于有多个异步复位域的设计&…

拍照还原空白试卷,建议你试试这些工具

拍照还原空白试卷&#xff0c;在现代教育中&#xff0c;试卷的电子化管理变得越来越重要。无论是老师还是学生&#xff0c;都希望能够方便地获取和使用电子版试卷。然而&#xff0c;手写答案和批注常常使得电子版试卷难以还原到原始的空白状态。为此&#xff0c;市场上涌现出许…

【CanMV K230】摄像头使用

【CanMV K230】摄像头使用 摄像头Sensor对象构造函数1.1 sensor.reset()1.2 .sensor.set_framesize1.3 sensor.set_pixformat1.4 sensor.set_hmirror(enable) (略)1.5 sensor.set_vflip(enable)(略)1.6 sensor.run1.7 sensor.snapshot&#xff08;&#xff09; 例程使用 从今天…

56.基于IIC协议的EEPROM驱动控制(3)跨时钟域处理

&#xff08;1&#xff09;跨时钟域处理&#xff1a;在使用低频时钟去采集高频信号时&#xff0c;会出现采集不正确的现象&#xff0c;因此需要进行跨时钟域处理。 多比特信号的跨时钟域处理可以使用FIFO、RAM等IP核进行处理&#xff1b; 单比特信号低频到高频可以使用打拍的方…

GitLab私有代码仓库搭建与使用

文章目录 一、安装GitLab1、下载安装2、修改配置3、启动gitlab4、登录 二、使用1、ssh-key 参考资料 一、安装GitLab 1、下载安装 gitlab-ce的rpm包清华源地址&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/?CN&OD 本次使用gitlab-ce-17.1.1-c…

近500个自然助眠冥想白噪音ACCESS\EXCEL数据包

今天这份数据是从一款特别简单好用助眠辅助应用软件中提取出来的MP3数据包&#xff0c;包含很多纯净音乐、助眠音乐、冥想音乐&#xff0c;可以帮助用户轻松进行多种白噪音音乐播放&#xff0c;帮助用户更好进行压力释放&#xff0c;感受更多舒适身心纯音乐体验。分类非常多&am…

【Java】数据类型与变量(一)

目录 1.字面常量 1.1什么是常量 1.2字面常量的分类: 2.数据类型 2.1基本数据类型 2.2一个小问题&#xff1a;什么是字节&#xff1f; 1.字面常量 1.1什么是常量 在一篇文章HelloWorld程序中&#xff0c;System.Out.println("Hello World");语句,不论程序何时运…

上网行为管理是什么?上网行为管理系统分享(六款上网行为管理系统介绍)2024年必备!

早期的上网行为管理系统&#xff0c;主要是对一些网站进行拦截&#xff0c;但企业数据泄露的现象仍旧普遍&#xff0c;敌人不止黑客。在激烈的商业竞争中&#xff0c;面对利益的诱惑&#xff0c;掌握着公司重要数据的员工也是不可控的危险因素。 本文将深入探讨上网行为管理的概…

2008-2024年荣威汽车维修手册和电路图线路图接线图资料更新

经过整理&#xff0c;2009-2024年名爵汽车全系列已经更新至汽修帮手资料库内&#xff0c;覆盖市面上99%车型&#xff0c;包括维修手册、电路图、新车特征、车身钣金维修数据、全车拆装、扭力、发动机大修、发动机正时、保养、电路图、针脚定义、模块传感器、保险丝盒图解对照表…

程序员阿龙【精选】计算机毕业设计之:基于java房屋租赁网站管理系统

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…