QT-五子棋游戏

news2024/11/23 8:17:23

QT-五子棋游戏

  • 一、演示效果
  • 二、核心代码
  • 三、下载链接


一、演示效果

请添加图片描述

二、核心代码

#include "GameModel.h"
#include <time.h>
#include <stdlib.h>

GameModel::GameModel(){

}

void GameModel::startGame(GameType type){
    gameType = type;
    //初始化棋盤
    gameMapVec.clear();
    for(int i=0;i<BOARD_GRAD_SIZE;i++){
        std::vector<int> lineBoard;
        for(int j=0;j<BOARD_GRAD_SIZE;j++){
            lineBoard.push_back(0);
        }
        gameMapVec.push_back(lineBoard);
    }
    //如果是AI模式,需要初始化評分數組
    if(gameType == AI){
        scoreMapVec.clear();
        for(int i=0;i<BOARD_GRAD_SIZE;i++){
            std::vector<int> lineScores;
            for(int j=0;j<BOARD_GRAD_SIZE;j++){
                lineScores.push_back(0);
            }
            scoreMapVec.push_back(lineScores);
        }
    }
    //輪到黑方下棋為true,反之
    playerFlag = true;
}

void GameModel::actionByPerson(int row, int col){
    updateGameMap(row,col);
}
void GameModel::updateGameMap(int row, int col){
    if(playerFlag){
        gameMapVec[row][col] = 1;
    }else{
        gameMapVec[row][col] = -1;
    }
    //換手
    playerFlag = !playerFlag;
}

bool GameModel::isWin(int row,int col){
    /*判斷下棋點的水平、垂直、左斜、右斜方中
     * 有沒有5子相連的情況,如有則贏
     */
    for(int i=0;i<5;i++){
        //先判斷水平方向是否有5子相連
        if(row>0 && row<BOARD_GRAD_SIZE &&
           col-i>0 && col-i+4<BOARD_GRAD_SIZE &&
           gameMapVec[row][col-i] == gameMapVec[row][col-i+1] &&
           gameMapVec[row][col-i] == gameMapVec[row][col-i+2] &&
           gameMapVec[row][col-i] == gameMapVec[row][col-i+3] &&
           gameMapVec[row][col-i] == gameMapVec[row][col-i+4]){
            return true;
        }
        //先判斷垂直方向是否有5子相連
        if(row-i>0 && row-i+4<BOARD_GRAD_SIZE &&
           col>0 && col<BOARD_GRAD_SIZE &&
           gameMapVec[row-i][col] == gameMapVec[row-i+1][col] &&
           gameMapVec[row-i][col] == gameMapVec[row-i+2][col] &&
           gameMapVec[row-i][col] == gameMapVec[row-i+3][col] &&
           gameMapVec[row-i][col] == gameMapVec[row-i+4][col]){
            return true;
        }
        //先判斷"/"方向是否有5子相連,左下->右上
        if(
           row-i>0 && row-i+4<BOARD_GRAD_SIZE &&
           col+i-4>0 && col+i<BOARD_GRAD_SIZE &&
           gameMapVec[row-i][col+i] == gameMapVec[row-i+1][col+i-1] &&
           gameMapVec[row-i][col+i] == gameMapVec[row-i+2][col+i-2] &&
           gameMapVec[row-i][col+i] == gameMapVec[row-i+3][col+i-3] &&
           gameMapVec[row-i][col+i] == gameMapVec[row-i+4][col+i-4]){
            return true;
        }
        //先判斷"\"方向是否有5子相連,右下->左上
        if(row-i>0 && row-i+4<BOARD_GRAD_SIZE &&
           col-i>0 && col-i+4<BOARD_GRAD_SIZE &&
           gameMapVec[row-i][col-i] == gameMapVec[row-i+1][col-i+1] &&
           gameMapVec[row-i][col-i] == gameMapVec[row-i+2][col-i+2] &&
           gameMapVec[row-i][col-i] == gameMapVec[row-i+3][col-i+3] &&
           gameMapVec[row-i][col-i] == gameMapVec[row-i+4][col-i+4]){
            return true;
        }

    }
    return false;
}

//計算每格分數函數
void GameModel::calculateScore(){
    //統計玩家或者電腦連成的子
    int personNum = 0; //玩家連成子的個數
    int botNum = 0;   //AI連成子的個數
    int emptyNum = 0;   //各方向空白位的個數

    //清空評分數組
    scoreMapVec.clear();
    for(int i=0;i<BOARD_GRAD_SIZE;i++){
        std::vector<int> lineScores;
        for(int j=0;j<BOARD_GRAD_SIZE;j++){
            lineScores.push_back(0);
        }
        scoreMapVec.push_back(lineScores);
    }
    //計分
    /*計分個人理解:
     * 遍歷每一個格子,判斷哪些是空白的點(即為0的點),以該點為中心,判斷周圍的八個點向外延伸的四格裡,
     * 有多少個是黑子、白子、空白,以此作為依據來評分。下方算法是以守為主,所以守的分數>攻的分數
     */
    for(int row=0;row<BOARD_GRAD_SIZE;row++){
        for(int col=0;col<BOARD_GRAD_SIZE;col++){
            //空白點才算
            if(row>0 && col>0 && gameMapVec[row][col]==0){
                //遍歷周圍8個方向
                for(int y=-1;y<=1;y++){
                    for(int x=-1;x<=1;x++){
                        //重置
                        personNum = 0;
                        botNum = 0;
                        emptyNum = 0;
                        //原坐標不算
                        if(!(y==0 && x==0)){
                            //每個方向延伸4個子

                            //對玩家黑子評分(正反兩個方向)
                            for(int i=1;i<=4;i++){
                                if(row+i*y>0 && row+i*y<BOARD_GRAD_SIZE &&
                                   col+i*x>0 && col+i*x<BOARD_GRAD_SIZE &&
                                   gameMapVec[row+i*y][col+i*x]==1){ //真人玩家的子
                                    personNum++;
                                }else if(row+i*y>0 && row+i*y<BOARD_GRAD_SIZE &&
                                         col+i*x>0 && col+i*x<BOARD_GRAD_SIZE &&
                                         gameMapVec[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<BOARD_GRAD_SIZE &&
                                   col-i*x>0 && col-i*x<BOARD_GRAD_SIZE &&
                                   gameMapVec[row-i*y][col-i*x]==1){ //真人玩家的子
                                    personNum++;
                                }else if(row-i*y>0 && row-i*y<BOARD_GRAD_SIZE &&
                                         col-i*x>0 && col-i*x<BOARD_GRAD_SIZE &&
                                         gameMapVec[row-i*y][col-i*x]==0){ //空白位
                                    emptyNum++;
                                    break;
                                }else{ //出邊界,或有白子
                                    break;
                                }
                            }
                            if(personNum == 1){                 //殺2
                                scoreMapVec[row][col]+=10;
                            }else if(personNum == 2){           //殺3
                                if(emptyNum == 1)
                                    scoreMapVec[row][col]+=30;
                                else if(emptyNum == 2)
                                    scoreMapVec[row][col]+=40;
                            }else if(personNum == 3){           //殺4
                                //量變空位不一樣,優先級不一樣
                                if(emptyNum == 1)
                                    scoreMapVec[row][col]+=60;
                                else if(emptyNum == 2)
                                    scoreMapVec[row][col]+=110;
                            }else if(personNum == 4){           //殺5
                                scoreMapVec[row][col]+=10100;
                            }

                            //進行一次清空
                            emptyNum = 0;

                            //對AI白子評分
                            for(int i=1;i<=4;i++){
                                if(row+i*y>0 && row+i*y<BOARD_GRAD_SIZE &&
                                   col+i*x>0 && col+i*x<BOARD_GRAD_SIZE &&
                                   gameMapVec[row+i*y][col+i*x]==-1){ //AI的子
                                    botNum++;
                                }else if(row+i*y>0 && row+i*y<BOARD_GRAD_SIZE &&
                                         col+i*x>0 && col+i*x<BOARD_GRAD_SIZE &&
                                         gameMapVec[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<BOARD_GRAD_SIZE &&
                                   col-i*x>0 && col-i*x<BOARD_GRAD_SIZE &&
                                   gameMapVec[row-i*y][col-i*x]==-1){ //AI的子
                                    botNum++;
                                }else if(row-i*y>0 && row-i*y<BOARD_GRAD_SIZE &&
                                         col-i*x>0 && col-i*x<BOARD_GRAD_SIZE &&
                                         gameMapVec[row-i*y][col-i*x]==0){ //空白位
                                    emptyNum++;
                                    break;
                                }else{ //出邊界
                                    break;
                                }
                            }
                            if(botNum == 0){
                                scoreMapVec[row][col]+=5;  //活1
                            }else if(botNum == 1){
                                scoreMapVec[row][col]+=10; //活2
                            }else if(botNum == 2){         //活3
                                if(emptyNum == 1)
                                    scoreMapVec[row][col]+=25;
                                else if(emptyNum == 2)
                                    scoreMapVec[row][col]+=50;
                            }else if(botNum == 3){         //活4
                                if(emptyNum == 1)
                                    scoreMapVec[row][col]+=55;
                                else if(emptyNum == 2)
                                    scoreMapVec[row][col]+=100;
                            }else if(botNum >= 4){         //活5
                                scoreMapVec[row][col]+=20000;
                            }


                        }
                    }
                }
            }
        }
    }

}
//AI執行下棋
void GameModel::actionByAI(int &clickRow,int &clickCol){
    //計算評分
    calculateScore();

    //從評分中找出最大分數的位置
    int maxScore = 0;
    std::vector<std::pair<int,int>> maxPoints;
    for(int row = 1;row<BOARD_GRAD_SIZE;row++){
        for(int col = 1;col<BOARD_GRAD_SIZE;col++){
            //前提是這個坐標是空的
            if(gameMapVec[row][col] == 0){
                if(scoreMapVec[row][col]>maxScore){     //找最大數和坐標
                    maxPoints.clear();
                    maxScore = scoreMapVec[row][col];
                    maxPoints.push_back(std::make_pair(row,col));
                }else if(scoreMapVec[row][col] == maxScore){   //如果有多個最大值就將他們存儲起來,在後面的代碼隨機抽1個
                    maxPoints.push_back(std::make_pair(row,col));
                }
            }
        }
    }
    //隨機落子,如果有多個點的話
    srand((unsigned)time(0));
    int index = rand()%maxPoints.size();
    std::pair<int,int> pointPair = maxPoints.at(index);
    clickRow = pointPair.first;
    clickCol = pointPair.second;
    updateGameMap(clickRow,clickCol);
}

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QMouseEvent>
#include <math.h>
#include <QMessageBox>
#include <QTimer>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setFixedSize(
     MARGIN*2+BLOCK_SIZE*BOARD_GRAD_SIZE,
     MARGIN*2+BLOCK_SIZE*BOARD_GRAD_SIZE);
    initGame();

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::paintEvent(QPaintEvent* event){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing); //設置抗鋸齒

    for(int i=0;i<BOARD_GRAD_SIZE+1;i++){
        //從左到右,第(i+1)條豎線
        painter.drawLine(MARGIN+BLOCK_SIZE*i,MARGIN,
                         MARGIN+BLOCK_SIZE*i,this->height()-MARGIN);
        //從上到下,第(i+1)條橫線
        painter.drawLine(MARGIN,MARGIN+BLOCK_SIZE*i,
                         this->width()-MARGIN,MARGIN+BLOCK_SIZE*i);
    }
    //繪製選中點
    QBrush brush;
    brush.setStyle(Qt::SolidPattern);
    //繪製落子標記(防止鼠標出框越界)
    if(clickPosRow>0 && clickPosRow<BOARD_GRAD_SIZE &&
       clickPosCol>0 && clickPosCol<BOARD_GRAD_SIZE &&
        game->gameMapVec[clickPosRow][clickPosCol]==0){

        if(game->playerFlag){
            brush.setColor(Qt::black);
        }else{
            brush.setColor(Qt::white);
        }
        painter.setBrush(brush);
        painter.drawRect(MARGIN+BLOCK_SIZE*clickPosCol-MARK_SIZE/2,MARGIN+BLOCK_SIZE*clickPosRow-MARK_SIZE/2,MARK_SIZE,MARK_SIZE);
    }
    for(int i=0;i<BOARD_GRAD_SIZE;i++){
        for(int j=0;j<BOARD_GRAD_SIZE;j++){
            if(game->gameMapVec[i][j]==1){
                brush.setColor(Qt::black);
                painter.setBrush(brush);
                painter.drawEllipse(MARGIN+BLOCK_SIZE*j-CHESS_RADIUS,MARGIN+BLOCK_SIZE*i-CHESS_RADIUS,CHESS_RADIUS*2,CHESS_RADIUS*2);
            }else if(game->gameMapVec[i][j]==-1){
                brush.setColor(Qt::white);
                painter.setBrush(brush);
                painter.drawEllipse(MARGIN+BLOCK_SIZE*j-CHESS_RADIUS,MARGIN+BLOCK_SIZE*i-CHESS_RADIUS,CHESS_RADIUS*2,CHESS_RADIUS*2);
            }

        }
    }
    //判斷輸嬴
    if(clickPosCol>0 && clickPosCol<BOARD_GRAD_SIZE &&
       clickPosRow>0 && clickPosRow<BOARD_GRAD_SIZE &&
       (game->gameMapVec[clickPosRow][clickPosCol]==1||game->gameMapVec[clickPosRow][clickPosCol]==-1)){  //代碼解析:game->gameMapVec[clickPosRow][clickPosCol]==1||game->gameMapVec[clickPosRow][clickPosCol]==-1,防止因為5個0(空白)相連也被判勝利
        if(game->isWin(clickPosRow,clickPosCol) && game->gameStatus == PLAYING){
            game->gameStatus = WIN;
            QString str;
            str = game->gameMapVec[clickPosRow][clickPosCol]==1?u8"黑棋":u8"白棋";
            QMessageBox::StandardButton btnValue = QMessageBox::information(this,u8"五子棋嬴家",str+u8"勝利");
            if(btnValue == QMessageBox::Ok){
                game->startGame(game_type);
                game->gameStatus = PLAYING;
            }

        }
    }
}
//初始化遊戲
void MainWindow::initGame(){
    game = new GameModel();
    QMessageBox::StandardButton select = QMessageBox::question(this,u8"選擇遊戲模式",u8"YES[玩家VS電腦]  NO[玩家VS玩家]");
    if(select == QMessageBox::Yes){
        game_type = AI;
    }else {
        game_type = MAN;
    }
    game->gameStatus = PLAYING;

    game->startGame(game_type);
    update();
}



void MainWindow::mouseMoveEvent(QMouseEvent* event){
    //通過鼠標的hover確定落子的標記
    int x = event->x();
    int y = event->y();

    //棋盤邊緣不能落子
    if(x>=MARGIN+BLOCK_SIZE/2&&
           x<this->width()-MARGIN-BLOCK_SIZE/2&&
           y>=MARGIN+BLOCK_SIZE/2&&
           y<this->height()-MARGIN-BLOCK_SIZE/2){
        //獲取最近的左上角的點
        int col = (x-MARGIN)/BLOCK_SIZE;
        int row = (y-MARGIN)/BLOCK_SIZE;

        int leftTopPosX = MARGIN+BLOCK_SIZE*col;
        int leftTopPosY = MARGIN+BLOCK_SIZE*row;

        //根據距離算出合適的點擊位置,一共四個點,根據半徑距離選最近的
        clickPosRow = -1; //初始化最終值
        clickPosCol = -1;
        int len = 0;  //計算完後取整就可以了

        selectPos = false;

        //確定一個誤差在範圍內的點,且只可能確定一個出來
        //len:與左上角的點的距離
        len = sqrt((x-leftTopPosX)*(x-leftTopPosX)+(y-leftTopPosY)*(y-leftTopPosY));
        if(len<POS_OFFSET){
            clickPosRow = row;
            clickPosCol = col;
            if(game->gameMapVec[clickPosRow][clickPosCol]==0){
                selectPos = true;
            }
        }
        //len:與右上角的點的距離
        len = sqrt((x-leftTopPosX-BLOCK_SIZE)*(x-leftTopPosX-BLOCK_SIZE)+(y-leftTopPosY)*(y-leftTopPosY));
        if(len<POS_OFFSET){
            clickPosRow = row;
            clickPosCol = col+1;
            if(game->gameMapVec[clickPosRow][clickPosCol]==0){
                selectPos = true;
            }
        }
        //len:與左下角的點的距離
        len = sqrt((x-leftTopPosX)*(x-leftTopPosX)+(y-leftTopPosY-BLOCK_SIZE)*(y-leftTopPosY-BLOCK_SIZE));
        if(len<POS_OFFSET){
            clickPosRow = row+1;
            clickPosCol = col;
            if(game->gameMapVec[clickPosRow][clickPosCol]==0){
                selectPos = true;
            }
        }
        //len:與右下角的點的距離
        len = sqrt((x-leftTopPosX-BLOCK_SIZE)*(x-leftTopPosX-BLOCK_SIZE)+(y-leftTopPosY-BLOCK_SIZE)*(y-leftTopPosY-BLOCK_SIZE));
        if(len<POS_OFFSET){
            clickPosRow = row+1;
            clickPosCol = col+1;
            if(game->gameMapVec[clickPosRow][clickPosCol]==0){
                selectPos = true;
            }
        }
    }
    //存了坐標後也要重繪
    update();
}

void MainWindow::mouseReleaseEvent(QMouseEvent* event){
    if(selectPos == false){
        return;
    }else{
        selectPos = false;
    }
    //由人來下棋
    chessOneByPerson();
    if(game_type == AI){ //人機模式
        //AI 下棋
        QTimer::singleShot(AI_THINK_TIME,this,SLOT(chessOneByAI()));
    }
}

void MainWindow::chessOneByPerson(){
    if(clickPosRow!=-1 && clickPosCol!=-1 && game->gameMapVec[clickPosRow][clickPosCol]==0){
        //在遊戲的數據模型中落子
        game->actionByPerson(clickPosRow,clickPosCol);
        //播放落子音效

        //重繪
        update();

    }
}

void MainWindow::chessOneByAI(){
    game->actionByAI(clickPosRow,clickPosCol);
    update();
}

三、下载链接

https://download.csdn.net/download/u013083044/89656663

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

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

相关文章

【备忘录模式】设计模式系列:掌握状态回溯的艺术(设计详解)

文章目录 备忘录设计模式详解引言1. 设计模式概述2. 备忘录模式的基本概念2.1 备忘录模式的定义2.2 备忘录模式的关键角色 3. 备忘录模式的实现原理3.1 备忘录模式的工作流程3.2 模式的优缺点分析3.3 与其他模式的对比 4. 实际案例分析4.1 游戏状态保存与恢复4.2 文档编辑器撤销…

19529 照明灯安装

### 详细分析 这个问题可以通过二分查找和贪心算法来解决。我们需要找到一个最大值&#xff0c;使得在这个最大值下&#xff0c;能够在给定的坐标上安装 k 个照明灯&#xff0c;并且相邻的照明灯之间的距离至少为这个最大值。 ### 思路 1. **排序**&#xff1a;首先对给定的…

S3C2440中断处理

一、中断处理机制概述 中断是CPU在执行程序过程中&#xff0c;遇到急需处理的事件时&#xff0c;暂时停止当前程序的执行&#xff0c;转而执行处理该事件的中断服务程序&#xff0c;并在处理完毕后返回原程序继续执行的过程。S3C2440提供了丰富的中断源&#xff0c;包括内部中…

微信小程序:开发工具修改js编译后还是旧的js逻辑

1、清理所有缓存&#xff0c;重新导入项目 2、语法存在问题无法编译,导致内存堆积&#xff0c;无法自动编译 3、npm 存在问题&#xff0c;可以重新构建 4、有时候编译器也没报错都是一切正常&#xff0c;但是编译后依然不是最新。这个时候需要考虑下电脑是否存在问题&#xff0…

使用gitee存储项目

gitee地址&#xff1a;Gitee - 基于 Git 的代码托管和研发协作平台 创建gitee远程仓库 将远程仓库内容拉取到本地仓库 复制下面这个地址 通过小乌龟便捷推送拉取代码&#xff1a;https://blog.csdn.net/m0_65520060/article/details/140091437

Ubuntu | 解决 VMware 中 Ubuntu 虚拟机磁盘空间不足的问题

目录 一、存在的问题二、解决的步骤第一步&#xff1a;扩展磁盘空间第二步&#xff1a;查看磁盘空间使用情况第三步&#xff1a;安装分区工具第四步&#xff1a;启动分区工具第五步&#xff1a;修改挂载文件夹的读写权限第六步&#xff1a;扩展文件系统大小第七步&#xff1a;验…

Prometheus2:被监控机器安装node_exporter与配置

1. 下载node_exporter [rootlocalhost ~]# wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz 2. 解压缩 [rootlocalhost ~]# tar -zxvf node_exporter-1.8.2.linux-amd64.tar.gz 3. 复制到/usrl/local路…

sed命令用法与案例

在Linux操作系统中&#xff0c;sed&#xff08;stream editor&#xff09;是一种功能强大的文本处理工具&#xff0c;用于执行文本的查找、替换、删除、新增等操作。sed命令以其简洁的语法和高效的执行速度&#xff0c;在自动化脚本和文本处理中扮演着重要角色。本文将探讨sed命…

探索串行通信的奥秘:Python中的pyserial库

文章目录 探索串行通信的奥秘&#xff1a;Python中的pyserial库背景&#xff1a;为何选择pyserial&#xff1f;pyserial是什么&#xff1f;如何安装pyserial&#xff1f;pyserial的五个简单函数场景应用&#xff1a;pyserial在实际中的使用常见bug及解决方案总结 探索串行通信的…

HR招聘,如何解决招聘需求不明确的问题

在HR招聘过程中&#xff0c;遇到招聘需求不明确的问题时&#xff0c;可以通过一系列措施来明确需求&#xff0c;提高招聘效率和质量。同时&#xff0c;在线人才测评、职业性格测试、认知能力测试和心理健康测试等工具也可以作为辅助手段&#xff0c;帮助HR更准确地评估候选人。…

【大模型从入门到精通33】开源库框架LangChain RAG 系统中的问答技术3

这里写目录标题 理论问答过程的三个主要阶段传递文档片段至 LM 上下文窗口的局限性及策略向量数据库的重要性RetrievalQA 链的作用MapReduce 与 Refine 的区别分布式系统中的实际考量实验的重要性RetrievalQA 链的主要限制对话记忆的重要性 实践初始化向量数据库设置 Retrieval…

GD32双路CAN踩坑记录

GD32双路CAN踩坑记录 目录 GD32双路CAN踩坑记录1 问题描述2 原因分析3 解决办法4 CAN配置参考代码 1 问题描述 GD32的CAN1无法进入接收中断&#xff0c;收不到数据。 注&#xff1a;MCU使用的是GD32E50x&#xff0c;其他型号不确定是否一样&#xff0c;本文只以GD32E50x举例说…

【Docker】gitea的ssh容器直通

本文首发于 ❄️慕雪的寒舍 1.跟着文档走 gitea的安装比较简单&#xff0c;直接使用官方文档中的docker-compose文件即可。如果想实现ssh容器直通&#xff0c;需要对这个docker-compose文件做一定修改。 如果你还没有安装docker&#xff0c;参考本站教程 linux安装docker&…

QT-贪吃蛇小游戏

QT-贪吃蛇小游戏 一、演示效果二、核心代码三、下载链接 一、演示效果 二、核心代码 #include "Food.h" #include <QTime> #include <time.h> #include "Snake.h"Food::Food(int foodSize):foodSize(foodSize) {coordinate.x -1;coordinate.…

多线程(4)——单例模式、阻塞队列、线程池、定时器

1. 多线程案例 1.1 单例模式 单例模式能保证某个类在程序中只存在唯一一份实例&#xff0c;不会创建出多个实例&#xff08;这一点在很多场景上都需要&#xff0c;比如 JDBC 中的 DataSource 实例就只需要一个 tip&#xff1a;设计模式就是编写代码过程中的 “软性约束”&am…

系统稳定性建设的深度剖析与未来展望

一、系统稳定性的重要意义 系统稳定性是系统正常运行的关键&#xff0c;其缺失会导致严重后果&#xff0c;如经济损失、用户流失等。 以在线学习平台为例&#xff0c;如果系统频繁出现卡顿、掉线等问题&#xff0c;影响用户的学习体验&#xff0c;导致用户流失&#xff0c;平…

【HTML】从0开始构建HTML页面

1、HTML文档基本格式 1.1、!DOCTYPE:文档类型声明 1.2、html:根标签 1.3、head:头部标签 1.4、body:主体标签 2、头部相关标签 2.1、< title> < title>标签用于定义HTML页面的标题&#xff0c;即给网页取一个名字&#xff0c;必须位于< head>标签之内。 …

Programmatically add website content to OpenAI with C#

题意&#xff1a;使用 C# 以编程方式将网站内容添加到 OpenAI。 问题背景&#xff1a; Our goal is to have a ChatGPT answer questions about our websites content. 我们的目标是让 ChatGPT 回答关于我们网站内容的问题。 We are trying to integrate something similar t…

设计模式笔记01(java版)

文章目录 设计模式概述学习设计模式的必要性设计模式分类创建型模式结构型模式行为型模式 UML类图概述类图的作用类图表示法类的表示方式类与类之间关系的表示方式1&#xff0c;单向关联2&#xff0c;双向关联3&#xff0c;自关联聚合关系组合关系依赖关系继承关系实现关系 软件…

【hot100篇-python刷题记录】【买卖股票的最佳时机】

摆烂几天,又来了。 R5-贪心篇(不像) 贪心的常规思路是找到贪心切入点,例如最经典的算法是安排最多活动问题,需要以结束时间排序,然后遍历不冲突,计算最大数即可(每次都选择最早结束的活动)。 贪心算法的使用需要满足贪心特征。即局部最优解等于全局最优解。 对于本…