【C++】Qt环境下的五子棋小程序

news2025/1/21 2:55:59

实现要求

这个程序是一个基于Qt的五子棋游戏,实现了人机对战和双人对战两种游戏模式,提供了基本的棋谱记录和游戏音效功能。程序采用了MVC模式,将数据与界面分离,实现了代码的模块化和可扩展性。主要构建包括三个文件,分别为GameModel.h、mainwindow.h和mainwindow.cpp,它们分别实现了游戏逻辑、游戏界面和界面与逻辑的交互。其中,游戏逻辑主要实现在GameModel类中,包括游戏规则、棋盘的数据结构和游戏状态的维护等;游戏界面主要实现在mainwindow.h和mainwindow.cpp中,包括棋盘的绘制、交互事件的处理、音效的播放和游戏结果的显示等。用户可以通过鼠标点击棋盘落下棋子,在游戏中实时查看落子信息,并通过音效提示,游戏结束后弹出对话框。

实现思路

  1. 定义GameModel类,包括游戏规则、棋盘的数据结构和游戏状态的维护等。
  2. 定义MainWindow类,主要用于具体实现游戏界面,包含了一些私有成员变量和函数,如棋盘、鼠标事件的处理、游戏模式切换等。
  3. 在mainwindow.cpp中实现棋盘的绘制、交互事件的处理和音效的播放等功能。
  4. 在GameModel.cpp中实现游戏开始、更新游戏地图、人类和AI的行动、计算得分、判断胜利和平局等游戏逻辑。
  5. 在main.cpp中创建应用程序对象,创建和显示主窗口,启动事件循环。
  6. 结合信号和槽机制,实现游戏界面与游戏逻辑的交互。
  7. 提供基本的棋谱记录和游戏音效功能,使用户在游戏中获得更好的游戏体验。

难点

双人对战只需要判断是否有五个棋子连成线即可判断对局胜负。人机对战相对复杂,需要实现AI下棋的功能。
电脑下棋的思路是通过计算每个空位 AI 下该棋子后的得分,来决定下哪个位置的棋子。得分高的位置就是AI应该下的最佳位置。

当AI需要决定下一步走哪个位置时,它会考虑每个空白位置对游戏胜利的贡献程度,评分函数就是用来计算每个空白位置的得分。

评分函数的计算方式是,在棋盘上遍历每个空白位置,然后从这个位置出发向上下左右、左上到右下、右上到左下三个方向扩展,统计这些方向上连续出现的X或O的个数。对于每个空白位置,分别计算其在三个方向上的得分,然后将三个方向的得分相加,即可得到该位置的总得分。

整体功能架构

文件名称功能描述
GameModel.h定义了游戏模型类GameModel,包括游戏的基本信息和方法,如棋盘、得分地图、玩家标志、游戏状态、游戏类型和各种操作方法等
mainwindow.h定义了MainWindow类,使用继承自QMainWindow类的方式,主要用于具体实现游戏界面,包含了一些私有成员变量和函数,如棋盘、鼠标事件的处理、游戏模式切换等
GameModel.cpp实现了GameModel类的方法函数,如游戏开始、更新游戏地图、人类和AI的行动、计算得分、判断胜利和平局等
mainwindow.cpp实现了游戏界面的方法函数,包括开始游戏、游戏模式切换、棋盘的绘制、鼠标事件的响应、音效的播放、游戏结果的显示等
main.cpp程序入口文件,创建应用程序对象,创建和显示主窗口,启动事件循环

代码实现

GameModel.h

#ifndef GAMEMODEL_H
#define GAMEMODEL_H

#include <QObject>
#include <vector>

enum GameType
{
    person,
    bot
};


enum GameStatus
{
    playing,
    win,
    dead
};

const int kBoardSize=15;

class GameModel
{
public:
    GameModel();

public:
    std::vector<std::vector<int>> gameMap;
    std::vector<std::vector<int>> scoreMap;
    bool playerFlag;
    GameType gameType;
    GameStatus gameStatus;

    void startGame(GameType type);
    void calculateScore();
    void actionByPerson(int row,int col);
    void actionByAi(int &row,int &col);
    void updateMap(int row,int col);
    bool isWin(int row,int col);
    bool isDeadGame();

signals:

};
#endif // GAMEMODEL_H

该文件是一个头文件,定义了一个游戏模型类 GameModel,包含一些游戏的基本信息和方法,如游戏地图、得分地图、玩家标志、游戏状态、游戏类型、开始游戏、计算分数、人类玩家行动、计算AI玩家行动、更新地图、判断游戏是否胜利、判断游戏是否结束等。同时包含了两个枚举类型 GameType 和 GameStatus,分别表示游戏类型和游戏状态。

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "GameModel.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    void paintEvent(QPaintEvent *event);

    void mouseMoveEvent(QMouseEvent *event);

    void mouseReleaseEvent(QMouseEvent *event);

private:
    GameModel *game;
    GameType game_type;
    int clickPosRow,clickPosCol;
    void initGame();
    void checkGame(int y,int x);



private slots:
    void chessOneByPerson();
    void chessOneByAi();
    void initPVPGame();
    void initPVCGame();




};
#endif // MAINWINDOW_H

这是一个名为mainwindow.h的头文件,其中定义了一个MainWindow类,该类继承自QMainWindow类。该类主要用于实现一个游戏,包括绘制棋盘,响应鼠标事件等功能。在该文件中还定义了一些私有函数和私有变量,包括一个GameModel类型的指针game,一个GameType类型的game_type,以及一些与游戏操作相关的函数,例如initGame、checkGame、chessOneByPerson、chessOneByAi等。此外,还定义了一些槽函数,例如initPVPGame和initPVCGame等,用于处理不同的游戏模式。

main.cpp

#include "mainwindow.h"

#include <QApplication>

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

此程序文件名为main.cpp,是一个Qt程序的主函数文件。该程序使用了Qt中的MainWindow类作为主窗口,通过调用show函数显示该窗口,然后进入Qt程序的事件循环。此程序中主要功能由MainWindow类实现,通过该类的构造函数和成员函数完成窗口的初始化、显示和其他操作。主函数的作用是创建应用程序对象,然后创建和显示主窗口,最后启动事件循环。整个程序的作用是显示一个Qt窗口,供用户进行交互操作。

GameModel.cpp

#include "GameModel.h"
#include <utility>
#include <time.h>
GameModel::GameModel()
{

}

void GameModel::startGame(GameType type)
{
    gameType = type;

    gameMap.clear();

    for(int i=0;i<kBoardSize;i++)
    {
        std::vector<int> lineBoard;
        for(int j=0;j<kBoardSize;j++)
        {
            lineBoard.push_back(0);
        }
        gameMap.push_back(lineBoard);
    }

    if(gameType==bot)
    {
        scoreMap.clear();

        for(int i=0;i<kBoardSize;i++)
        {
            std::vector<int> lineScores;
            for(int j=0;j<kBoardSize;j++)
            {
                lineScores.push_back(0);
            }
            scoreMap.push_back(lineScores);
        }
    }
    playerFlag=true;
}

void GameModel::updateMap(int row, int col)
{
    if(playerFlag)
        gameMap[row][col]=1;
    else
        gameMap[row][col]=-1;

    playerFlag=!playerFlag;
}

void GameModel::actionByPerson(int row, int col)
{
    updateMap(row,col);
}

void GameModel::actionByAi(int &crow, int &ccol)
{
    calculateScore();
    int maxScore=0;
    std::vector<std::pair<int,int>> maxPoint;

    for(int i=1;i<kBoardSize;i++)
        for(int j=1;j<kBoardSize;j++)
        {
            if(gameMap[i][j]==0)
            {
                if(scoreMap[i][j]>maxScore)
                {
                    maxPoint.clear();
                    maxScore=scoreMap[i][j];
                    maxPoint.push_back(std::make_pair(i,j));
                }
                else if(scoreMap[i][j]==maxScore)
                    maxPoint.push_back(std::make_pair(i,j));
            }
        }
    srand((unsigned)time(0));
    int index=rand()%maxPoint.size();
    std::pair<int,int> pointPair=maxPoint.at(index);

    crow=pointPair.first;
    ccol=pointPair.second;
    updateMap(crow,ccol);
}

void GameModel::calculateScore()
{
    int personNum=0;
    int botNum=0;
    int emptyNum=0;

    scoreMap.clear();
    for(int i=0;i<kBoardSize;i++)
    {
        std::vector<int> lineScore;
        for(int j=0;j<kBoardSize;j++)
            lineScore.push_back(0);
        scoreMap.push_back(lineScore);
    }

    for(int row=0;row<kBoardSize;row++)
        for(int col=0;col<kBoardSize;col++)
        {
            if(row>0&&col>0&&gameMap[row][col]==0)
            {
                for(int y=-1;y<=1;y++)
                    for(int x=-1;x<=1;x++)
                    {
                        int personNum=0;
                        int botNum=0;
                        int emptyNum=0;

                        if(!(y==0&&x==0))
                        {
                            for(int i=1;i<=4;i++)
                            {
                                if(row+i*y>0&&row+i*y<kBoardSize&&col+i*x>0&&col+i*x<kBoardSize&&gameMap[row+i*y][col+i*x]==1)
                                {
                                    personNum++;
                                }
                                else if(row+i*y>0&&row+i*y<kBoardSize&&col+i*x>0&&col+i*x<kBoardSize&&gameMap[row+i*y][col+i*x]==0)
                                {
                                    emptyNum++;
                                    break;
                                }
                                else
                                    break;
                            }
                            for(int i=1;i<=4;i++)
                            {
                                if(row-i*y>0&&row-i*y<kBoardSize&&col-i*x>0&&col-i*x<kBoardSize&&gameMap[row-i*y][col-i*x]==1)
                                {
                                    personNum++;
                                }
                                else if(row-i*y>0&&row-i*y<kBoardSize&&col-i*x>0&&col-i*x<kBoardSize&&gameMap[row-i*y][col-i*x]==0)
                                {
                                    emptyNum++;
                                    break;
                                }
                                else
                                    break;
                            }
                            if(personNum==1)
                                scoreMap[row][col]+=10;
                            else if(personNum==2)
                            {
                                if(emptyNum==1)
                                    scoreMap[row][col]+=30;
                                else if(emptyNum==2)
                                    scoreMap[row][col]+=40;
                            }
                            else if(personNum==3)
                            {
                                if(emptyNum==1)
                                    scoreMap[row][col]+=60;
                                else if(emptyNum==2)
                                    scoreMap[row][col]+=110;
                            }
                            else if(personNum==4)
                                scoreMap[row][col]+=10000;
                            emptyNum=0;


                            for(int i=1;i<=4;i++)
                            {
                                if(row+i*y>0&&row+i*y<kBoardSize&&col+i*x>0&&col+i*x<kBoardSize&&gameMap[row+i*y][col+i*x]==1)
                                {
                                    botNum++;
                                }
                                else if(row+i*y>0&&row+i*y<kBoardSize&&col+i*x>0&&col+i*x<kBoardSize&&gameMap[row+i*y][col+i*x]==0)
                                {
                                    emptyNum++;
                                    break;
                                }
                                else
                                    break;
                            }
                            for(int i=1;i<=4;i++)
                            {
                                if(row-i*y>0&&row-i*y<kBoardSize&&col-i*x>0&&col-i*x<kBoardSize&&gameMap[row-i*y][col-i*x]==-1)
                                {
                                   botNum++;
                                }
                                else if(row-i*y>0&&row-i*y<kBoardSize&&col-i*x>0&&col-i*x<kBoardSize&&gameMap[row-i*y][col-i*x]==0)
                                {
                                    emptyNum++;
                                    break;
                                }
                                else
                                    break;
                            }
                            if(botNum==0)
                                scoreMap[row][col]+=5;
                            else if(botNum==1)
                                scoreMap[row][col]+=10;
                            else if(botNum==2)
                            {
                                if(emptyNum==1)
                                    scoreMap[row][col]+=25;
                                else if(emptyNum==2)
                                    scoreMap[row][col]+=50;

                            }
                            else if(botNum==3)
                            {
                                if(emptyNum==1)
                                    scoreMap[row][col]+=50;
                                else if(emptyNum==2)
                                    scoreMap[row][col]+=110;
                            }
                            else if(botNum==4)
                                scoreMap[row][col]+=10000;
                        }
                    }
            }
        }
}

bool GameModel::isWin(int row, int col)
{
    for(int i=0;i<5;i++)
    {
        if(col-i>0&&col-i+4<kBoardSize&&gameMap[row][col-i]==gameMap[row][col-i+1]&&gameMap[row][col-i]==gameMap[row][col-i+2]&&gameMap[row][col-i]==gameMap[row][col-i+3]&&gameMap[row][col-i]==gameMap[row][col-i+4])
            return true;
    }
    for(int i=0;i<5;i++)
    {
        if(row-i>0&&row-i+4<kBoardSize&&gameMap[row-i][col]==gameMap[row-i+1][col]&&gameMap[row-i][col]==gameMap[row-i+2][col]&&gameMap[row-i][col]==gameMap[row-i+3][col]&&gameMap[row-i][col]==gameMap[row-i+4][col])
            return true;
    }
    for(int i=0;i<5;i++)
    {
        if(row+i<kBoardSize&&row+i-4>0&&col-i>0&&col-i+4<kBoardSize&&gameMap[row+i][col-i]==gameMap[row+i-1][col-i+1]&&gameMap[row+i][col-i]==gameMap[row+i-2][col-i+2]&&gameMap[row+i][col-i]==gameMap[row+i-3][col-i+3]&&gameMap[row+i][col-i]==gameMap[row+i-4][col-i+4])
            return true;
    }
    for(int i=0;i<5;i++)
    {
        if(row-i>0&&row-i+4<kBoardSize&&col-i>0&&col-i+4<kBoardSize&&gameMap[row-i][col-i]==gameMap[row-i+1][col-i+1]&&gameMap[row-i][col-i]==gameMap[row-i+2][col-i+2]&&gameMap[row-i][col-i]==gameMap[row-i+3][col-i+3]&&gameMap[row-i][col-i]==gameMap[row-i+4][col-i+4])
            return true;
    }
    return false;

}

bool GameModel::isDeadGame()
{
    for(int i=1;i<kBoardSize;i++)
        for(int j=1;j<kBoardSize;j++)
        {
            if(!(gameMap[i][j]==1||gameMap[i][j]==-1))
                return false;
        }
    return true;
}

该程序文件是一个游戏模型的实现,其中包含了游戏开始、更新游戏地图、人类和AI的行动、计算得分、判断胜利和平局等功能。程序使用了C++语言,其中定义了常量kBoardSize表示棋盘的大小。程序中的gameMap代表游戏地图,scoreMap代表每个空位的得分,playerFlag代表玩家的标记(true表示玩家为黑棋,false表示玩家为白棋),gameType代表游戏类型(bot表示人机对战)。在startGame()中初始化gameMap和scoreMap,并根据游戏类型初始化玩家标记。在actionByPerson()和actionByAi()中分别更新gameMap,并在actionByAi()中使用calculateScore()计算每个空位的得分,再根据得分为AI选择最好的空位进行行动。在calculateScore()中,分别计算空位周围读和AI已下的棋子形成的连续棋子数,并将其转换为得分,存储在scoreMap中。在isWin()中,根据五子棋规则判断某个空位是否胜利。在isDeadGame()中,判断游戏是否为平局。

mainwindow.cpp

#include "mainwindow.h"
#include <QPainter>
#include <QTimer>
#include <QSound>
#include <QMouseEvent>
#include <QMessageBox>
#include <QMenu>
#include <QMenuBar>
#include <QDebug>
#include <math.h>

#define CHESS_ONE_SOUND ":/res/chessone.wav"
#define WIN_SOUND ":/res/win.wav"
#define LOSE_SOUND ":/res/lose.wav"

const int kBoardMargin = 30; // 棋盘边缘空隙
const int kRadius = 15; // 棋子半径
const int kMarkSize = 6; // 落子标记边长
const int kBlockSize = 40; // 格子的大小
const int kPosDelta = 20; // 鼠标点击的模糊距离上限

const int kAIDelay = 700; // AI下棋的思考时间

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    //ui->setupUi(this);

    setFixedSize(kBoardMargin*2+kBlockSize*kBoardSize,kBoardMargin*2+kBlockSize*kBoardSize);
    //setStyleSheet("background-color:white;");
    //setStyleSheet("background-color:transparent;");
    setMouseTracking(true);


    QMenu *gameMenu = menuBar()->addMenu(tr("Game Model:"));
    QAction *actionPVP = new QAction("PVP",this);
    connect(actionPVP,SIGNAL(triggered()),this,SLOT(initPVPGame()));
    menuBar()->addAction(actionPVP);
    //gameMenu->addAction(actionPVP);

    QAction *actionPVC = new QAction("PVC",this);
    connect(actionPVC,SIGNAL(triggered()),this,SLOT(initPVCGame()));
    menuBar()->addAction(actionPVC);
    //gameMenu->addAction(actionPVC);


    initGame();
}

MainWindow::~MainWindow()
{

    if(game)
    {
        delete game;
        game=nullptr;
    }
}

void MainWindow::initGame()
{
    game = new GameModel;
    initPVPGame();
}

void MainWindow::initPVPGame()
{
    game_type=person;
    game->gameStatus=playing;
    game->startGame(game_type);
    update();

}

void MainWindow::initPVCGame()
{
    game_type=bot;
    game->gameStatus=playing;
    game->startGame(game_type);
    update();
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    painter.setRenderHint(QPainter::Antialiasing,true);

    for(int i=0;i<kBoardSize+1;i++)
    {
        painter.drawLine(kBoardMargin+kBlockSize*i,kBoardMargin,kBoardMargin+kBlockSize*i,size().height()-kBoardMargin);
        painter.drawLine(kBoardMargin,kBoardMargin+kBlockSize*i,size().width()-kBoardMargin,kBoardMargin+kBlockSize*i);
    }
    QBrush brush;
    brush.setStyle(Qt::SolidPattern);
    if(clickPosRow>0&&clickPosRow<kBoardSize&&clickPosCol>0&&clickPosCol<kBoardSize&&game->gameMap[clickPosRow][clickPosCol]==0)
    {
        if(game->playerFlag)
            brush.setColor(Qt::white);
        else
            brush.setColor(Qt::black);
        painter.setBrush(brush);
        painter.drawRect(kBoardMargin+kBlockSize*clickPosCol-kMarkSize/2,kBoardMargin+kBlockSize*clickPosRow-kMarkSize/2,kMarkSize,kMarkSize);
    }

    for(int i=0;i<kBoardSize;i++)
        for(int j=0;j<kBoardSize;j++)
        {
            if(game->gameMap[i][j]==1)
            {
                brush.setColor(Qt::white);
                painter.setBrush(brush);
                painter.drawEllipse(kBoardMargin+kBlockSize*j-kRadius,kBoardMargin+kBlockSize*i-kRadius,kRadius*2,kRadius*2);
            }
            else if(game->gameMap[i][j]==-1)
            {
                brush.setColor(Qt::black);
                painter.setBrush(brush);
                painter.drawEllipse(kBoardMargin+kBlockSize*j-kRadius,kBoardMargin+kBlockSize*i-kRadius,kRadius*2,kRadius*2);
            }
        }

    if(clickPosRow>0&&clickPosRow<kBoardSize&&clickPosCol>0&&clickPosCol<kBoardSize&&(game->gameMap[clickPosRow][clickPosCol]==1||game->gameMap[clickPosRow][clickPosCol]==-1))
    {
        if(game->isWin(clickPosRow,clickPosCol)&&game->gameStatus==playing)
        {
            qDebug()<<"win";
            game->gameStatus=win;
            QSound::play(WIN_SOUND);

            QString str;
            if(game->gameMap[clickPosRow][clickPosCol]==1)
                str="white player";
            else if(game->gameMap[clickPosRow][clickPosCol]==-1)
                str="black player";
            QMessageBox::StandardButton btnValue = QMessageBox::information(this,"congratulations",str+"win");

            if(btnValue==QMessageBox::Ok)
            {
                game->startGame(game_type);
                game->gameStatus=playing;
            }
        }
    }
    if(game->isDeadGame())
    {
        QSound::play(LOSE_SOUND);
        QMessageBox::StandardButton btnValue=QMessageBox::information(this,"oops","dead game");
        if(btnValue==QMessageBox::Ok)
        {
            game->startGame(game_type);
            game->gameStatus=playing;
        }
    }
}

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    int x=event->x();
    int y=event->y();

    if(x>=kBoardMargin+kBlockSize/2&&x<size().width()-kBoardMargin&&y>=kBoardMargin+kBlockSize/2&&y<size().height()-kBoardMargin)
    {
        int col=x/kBlockSize;
        int row=y/kBlockSize;

        int leftTopPosX=kBoardMargin+kBlockSize*col;
        int leftTopPosY=kBoardMargin+kBlockSize*row;

        clickPosRow=-1;
        clickPosCol=-1;
        int len=0;

        len=sqrt((x - leftTopPosX) * (x - leftTopPosX) + (y - leftTopPosY) * (y - leftTopPosY));
        if(len<kPosDelta)
        {
            clickPosRow = row;
            clickPosCol = col;
        }
        len=sqrt((x - leftTopPosX - kBlockSize) * (x - leftTopPosX - kBlockSize) + (y - leftTopPosY) * (y - leftTopPosY));
        if (len < kPosDelta)
        {
            clickPosRow = row ;
            clickPosCol = col + 1;
        }
        len=sqrt((x-leftTopPosX)*(x-leftTopPosX)+(y-leftTopPosY-kBlockSize)*(y-leftTopPosY-kBlockSize));
        if(len<kPosDelta)
        {
            clickPosRow=row+1;
            clickPosCol=col;
        }
        len=sqrt((x-leftTopPosX-kBlockSize)*(x-leftTopPosX-kBlockSize)+(y-leftTopPosY-kBlockSize)*(y-leftTopPosY-kBlockSize));
        if(len<kPosDelta)
        {
            clickPosRow=row+1;
            clickPosCol=col+1;
        }

    }
    update();
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    // 人下棋,并且不能抢机器的棋
    if (!(game_type == bot && !game->playerFlag))
    {
        chessOneByPerson();
        // 如果是人机模式,需要调用AI下棋
        if (game->gameType == bot && !game->playerFlag)
        {
            // 用定时器做一个延迟
            QTimer::singleShot(kAIDelay, this, SLOT(chessOneByAi()));
        }
    }

}

void MainWindow::chessOneByPerson()
{
    if(clickPosRow!=-1&&clickPosCol!=-1&&game->gameMap[clickPosRow][clickPosCol]==0)
    {
        game->actionByPerson(clickPosRow,clickPosCol);
        QSound::play(CHESS_ONE_SOUND);
        update();
    }
}

void MainWindow::chessOneByAi()
{
    game->actionByAi(clickPosRow,clickPosCol);
    QSound::play(CHESS_ONE_SOUND);
    update();
}

该程序实现了一个围棋游戏的主窗口界面,可以通过菜单选择双人对战或人机对战,人机对战中可以调节AI下棋的思考时间。用户可以通过鼠标点击棋盘落下棋子,在游戏中实时查看落子信息,并通过音效提示,游戏结束后弹出对话框。程序采用了MVC模式,利用GameModel类管理游戏逻辑,将数据与界面分离,实现了代码的模块化和可扩展性。

程序运行结果

如下图所示:
在这里插入图片描述
在这里插入图片描述

打包发布

可以使用Enigma Virtual Box软件打包程序。
Enigma Virtual Box是一个用于将应用程序打包为单一可执行文件的工具。它将应用程序和所有相关文件打包到一个虚拟的可执行文件中,这个文件可以像一个普通的可执行文件一样运行,而不需要安装或配置任何依赖项。这样在其他计算机上程序也可以运行,实现可移植性。

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

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

相关文章

Java - 数据结构,哈希表

一、概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须要经过关键码的多次比较。顺序查找时间复杂度为O(N)&#xff0c;平衡树中为树的高度&#xff0c;即O( )&#xff0c;搜索的效率取决于搜…

Ambari【部署 01】最新版本ambari-2.7.7下载编译打包安装使用(踩坑实录)

Ambari 官网 本次安装的为当前最新版本 2.7.7 文档 。 1.环境及准备 1.1 环境 # 系统 [roottcloud ~]# cat /etc/centos-release CentOS Linux release 7.9.2009 (Core) # JDK [roottcloud ~]# java -version java version "1.8.0_241" Java(TM) SE Runtime Envir…

java模板/策略模式打怪兽

模板&策略模式 实现姿势 我们会从简单到复杂&#xff0c;讲解代码正确的实现姿势&#xff0c;分别为最 Low 方式、常规方式、模板模式和策略模式。 最 Low 方式 假如现在有 3 个奥特曼&#xff0c;都喜欢 “训练&#xff0c;飞翔&#xff0c;打怪兽” public class OldTig…

jsp+java自行车租赁租借和买卖系统

自行车租借和买卖系统 系统包括四个模块。1&#xff0c;系统模块&#xff0c;2&#xff0c;车辆管理模块&#xff0c;3.租借车管理模块&#xff0c;4&#xff0c;买卖车管理模块。 1&#xff0c;系统模块包括: 连接数据库&#xff0c;工作人员登录&#xff0c;退出。 2&#…

《类和对象》(中篇)

本文主要介绍类里面的六大默认成员函数 文章目录 前言类的6个默认成员函数1、构造函数1.1 概念1.2 特性 2、析构函数2.1 概念2.2 特性 3 、拷贝构造函数3.1 概念3.2 特性3.3 使用场景 4、运算符重载4.1 规则4.2 赋值运算符重载 5、const 成员6、取地址与const取地址操作符重载总…

Shiro安全框架简介

一、权限管理 1.1 什么是权限管理 基本上只要涉及到用户参数的系统都要进行权限管理&#xff0c;使用权限管理实现了对用户访问系统的控制&#xff0c;不同的用户访问不同的资源。按照安全规则或者安全策略控制用户访问资源&#xff0c;而且只能访问被授权的资源 权限管理包括认…

学成在线笔记+踩坑(1)——项目思路、架构、父工程和基础工程,Gogs使用

【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线牛客面试题 目录 简历-技术架构 项目预览 后台页面 课程管理 媒资管理页面上传视频 新增课程 课程管理页提交审核 审核员审核后发布课程 前台页面 主页 验证码登录…

uniapp系列-超详细教你在uni-app+vue3里通过web-view组件传递信息打开H5页面写入localstorage并解决兼容性

web-view是什么 web-view 是一个 web 浏览器组件&#xff0c;可以用来承载网页的容器&#xff0c;会自动铺满整个页面&#xff08;nvue 使用需要手动指定宽高&#xff09;。点击这里直达官网文档点击这里下载我的代码demo本文最下面还有一些常见或者奇怪问题解决方案哦~ 为什…

GMRES算法及Matlab程序

关于GMRES的总结 一些理论以及代码 首先是我们要解决的问题&#xff0c;也就是最常见的问题&#xff0c;即求解 A x b Axb Axb Galerkin条件 krylov子空间 我们所做的GMRES实际上就是在Galerkin条件的扩张下&#xff0c;n o r m ( r ) normnorm不断减小的一个过程。这也是…

家用洗地机哪种好?性价比高的洗地机推荐

选择清洁家电时&#xff0c;首先需要考虑你需要清洁的区域和清洁的方式。如果你需要清洁的是地面&#xff0c;那么洗地机可能是一个不错的选择。洗地机的优势在于它可以自动清洁地面&#xff0c;并且可以在较短的时间内完成清洁工作。相比于其他的清洁家电&#xff0c;洗地机的…

设计链表(链表篇)

你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则还需要属性 prev 以指示链表中的上一个节点…

Linux_红帽8学习笔记分享_5

Linux_红帽8学习笔记分享_5 文章目录 Linux_红帽8学习笔记分享_51. UMASK反掩码1.1如何查看反掩码umask1.2 UMASK反掩码的作用1.2.1对于目录来说1.2.2对于文件来说 1.3如何修改UMASK反掩码1.4普通用户反掩码的测试 2.whereis的使用3. SUID权限弥补(主要针对文件,所有者执行位变…

第14章_数据结构与集合源码

第14章_数据结构与集合源码 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. 数据结构剖析 我们举一个形象的例子来理解数据结构的作用&#xff1a; 战场&#xff1a;程序运行…

认识Object类和深浅拷贝

本文介绍了Object类以及Object类部分方法,toString方法,equals和hashCode方法(重写前和重写后的对比),getClass方法,clone方法,以及拷贝新对象时会出现的深浅拷贝, 内容较长,耗时一天,建议收藏后观看~ Object类和深浅拷贝 一.初识Object类1.Object类接收所有子类实例2.Object类…

【C 字符串】02 常用字符串函数(命令行参数)

Navigator 一、strlen()函数—统计长度二、strcat()函数—拼接三、strncat()函数—strcat()的升级四、strcmp()和strncmp()—比较五、strcpy()和strncpy()—拷贝六、sprintf()函数—合并多个字符串七、其他可能用到的字符串函数八、ctype.h中的字符函数九、把字符串转换为数字十…

(03)基础强化:静态类静态成员,静态构造函数,抽象类抽象成员,值类型和引用类型,Ref

一、静态成员 1、方法重写注意事项 1&#xff09;子类重写父类方法时&#xff0c;必须与父类保持一致的方法签名与返回值类型。即: 方 法名、返回值类型、参数列表都必须保持一致。[访问修饰符也得一致] 2&#xff09;“方法签名”:一般是指…

VScode---visual stdio code快速安装教程(Windows系统)

1.下载VSCode安装包&#xff0c;官网传送门https://code.visualstudio.com/ 选择Windows下的User Installer 64 bit 直接下载速度如果很慢&#xff0c;在浏览器或者下载软件中就可以看到这么一个下载地址了&#xff0c;复制链接地址&#xff08;如下图箭头所指&#xff09;。 …

本节作业之5秒后自动关闭广告、倒计时、发送短信、5秒之后自动跳转页面、获取URL参数数据

本节作业之5秒后自动关闭广告、倒计时、发送短信、5秒之后自动跳转页面、获取URL参数数据 1 5秒后自动关闭广告2 倒计时3 发送短信4 5秒之后自动跳转页面5 获取URL参数数据 1 5秒后自动关闭广告 <!DOCTYPE html> <html lang"en"> <head><meta …

管理系统的前端模板(vue2+Element UI)

目录 前言 一、模板展示图 二、获取的方式及操作运行步骤 &#xff08;一&#xff09;获取方式 &#xff08;二&#xff09;操作步骤 1.下载安装node.js 2.下载完成解压缩后在idea的里面打开终端。 3.输入下载相关依赖的命令 4.运行项目的命令 5.然后把给到的地址…

腾讯云渲染实战

UE使用流渲染技术的主要原因是为了提高渲染效率和降低成本。流渲染技术可以将渲染任务分配到多个计算节点上进行并行处理&#xff0c;从而加快渲染速度。同时&#xff0c;流渲染技术还可以将渲染任务分配到云端进行处理&#xff0c;减少本地计算机的负担&#xff0c;降低成本。…