QT实现五子棋

开发需求:实现一个单机版双人五子棋对战游戏,棋盘大小800*800,网格大小40*40,,棋子大小半径40的圆,玩法:玩家1执黑棋,玩家2执白棋,每回合玩家有一次下棋机会,在玩家成功连上5个棋子时(水平、竖直、倾斜方向连接5个都算玩家胜利)显示玩家游戏胜利,并重新开始。

开发文档:棋盘的实现使用qt的绘制函数实现,玩家的落子标记和落子选择使用qt的鼠标事件。

用一个变量存储当前玩家,为了区分绘制棋子的颜色。

用一个数组存储所有棋子的位置,为了绘制棋盘上所有的棋子。

用一个数组存储棋子属于哪个玩家。是为了最后判断输赢时用的。

要落子位置的判断:根据鼠标当前位置与所在网格的四个点的距离判断,取最小距离的那个网格点。

输赢的判断:以当前落子位置为中心水平、竖直、斜上、斜下方向分别判断是否有5子位置相邻。

上源码:.h

#include <QMainWindow>
#include <QMouseEvent>
#include <QMap>
#include <QtAlgorithms>
#include <QDebug>
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) override;
    // 监听鼠标移动情况,方便落子
    void mouseMoveEvent(QMouseEvent *event) override;
    // 实际落子
    void mouseReleaseEvent(QMouseEvent *event) override;
private slots:
    //void on_actionReStart_triggered();

private:
    void playerCheck(bool player1,bool player2);
    void reStart();
    bool currentPlayerIsWin();
private:
    Ui::MainWindow *ui;
    QPoint chessmanPosition;//棋子的位置
    QPoint mouseHovePosition;//要落子的位置
    QVector<QPoint> haveChessmanVtr; //有棋子的数组
    QVector<QString> chessPlayervtr;
    bool isPlayer1;
    bool isPlayer2;
    QString currentPlayer;

};

.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QMessageBox>
const int  m_width= 800;
const int m_height= 800;
const int m_space= 40;
const int radius=40;
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setGeometry(600,200,m_width,m_height);
    this->setAttribute(Qt::WA_Hover,true);
    this->setMouseTracking(true);
    isPlayer1=true;
    isPlayer2=false;
    currentPlayer="Player1";

}

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

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    // 绘制棋盘
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.drawLine(QPoint(0,0),QPoint(10,0));
    for(int i=0;i<m_height/m_space;i++)
    {
        painter.drawLine(QPoint(0,i*m_space),QPoint(m_width,i*m_space));
    }
    for(int j=0;j<m_width/m_space;j++)
    {
        painter.drawLine(QPoint(j*m_space,0),QPoint(j*m_space,m_height));
    }
    //鼠标悬停 画棋子标记
    {
        painter.drawRect(mouseHovePosition.x()-10,mouseHovePosition.y()-10,20,20);
    }
    //画棋子 棋子位置应该是鼠标位置-棋子半径/2
    {

        QBrush brush;   //画刷

        for(int i=0;i<haveChessmanVtr.size();i++)
        {
            if(0==chessPlayervtr[i].compare("Player1"))
            {
                brush.setColor(QColor(0,0,0));//设置填充颜色
                brush.setStyle(Qt::SolidPattern);
                painter.setBrush(brush);
            }
            else
            {
                brush.setColor(QColor(255,255,255));//设置填充颜色
                brush.setStyle(Qt::SolidPattern);
                painter.setBrush(brush);
            }
            painter.drawEllipse(haveChessmanVtr[i].x()-m_space/2,haveChessmanVtr[i].y()-m_space/2,radius,radius);

        }

    }
    //判断输赢
    {
        //所有棋子填完啦,平局
        if(haveChessmanVtr.size()>=(m_width/m_space+1)*(m_height/m_space+1))
        {
            qDebug()<<"tie game";
        }
        else if(currentPlayerIsWin())
        {
            if(currentPlayer=="Player1")
            {
                int result=QMessageBox::information(this, tr("恭喜"), "Player2 is win");
                if (result == QMessageBox::Ok)
                {
                    reStart();
                }
            }
            else
            {
                int result = QMessageBox::information(this, tr("恭喜"), "Player1 is win");
                if (result == QMessageBox::Ok)
                {
                    reStart();
                }
            }
            
        }

    }

}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    int x=event->pos().x();
    int y=event->pos().y();
    //判断鼠标周围的四点与鼠标悬停的距离
    //左上角
    QPoint leftTopPoistion;
    leftTopPoistion.setX(x/m_space*m_space);
    leftTopPoistion.setY(y/m_space*m_space);
    int leftTop=QPoint::dotProduct(leftTopPoistion,event->pos());
    //左下角
    QPoint leftBottomPoistion;
    leftBottomPoistion.setX(x/m_space*m_space);
    leftBottomPoistion.setY(y/m_space*m_space+m_space);
    int leftBottom=QPoint::dotProduct(leftBottomPoistion,event->pos());
    //右上角
    QPoint rightTopPoistion;
    rightTopPoistion.setX(x/m_space*m_space+m_space);
    rightTopPoistion.setY(y/m_space*m_space);
    int rightTop=QPoint::dotProduct(rightTopPoistion,event->pos());
    //右下角
    QPoint rightBottomPoistion;
    rightBottomPoistion.setX(x/m_space*m_space+m_space);
    rightBottomPoistion.setY(y/m_space*m_space+m_space);
    int rightBottom=QPoint::dotProduct(rightBottomPoistion,event->pos());

    QMap<int,QPoint> map;
    map[leftTop]=leftTopPoistion;
    map[leftBottom]=leftBottomPoistion;
    map[rightTop]=rightTopPoistion;
    map[rightBottom]=rightBottomPoistion;
    QVector<int> vtr;
    vtr.append(leftTop);
    vtr.append(leftBottom);
    vtr.append(rightTop);
    vtr.append(rightBottom);
    qSort(vtr.begin(),vtr.end());
    //让落子位置处于距离最小的那个角上
    mouseHovePosition=map[vtr[0]];
    update();


}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    chessmanPosition=mouseHovePosition;
    if(haveChessmanVtr.count(chessmanPosition)>0)
    {
        return;
    }
    haveChessmanVtr.append(chessmanPosition);
    chessPlayervtr.append(currentPlayer);

    update();
    if(isPlayer1)
    {
        playerCheck(false,true);
    }
    else
    {
        playerCheck(true,false);
    }
}

void MainWindow::playerCheck(bool player1, bool player2)
{
    isPlayer1=player1;
    isPlayer2=player2;
    if(isPlayer1)
    {
        currentPlayer="Player1";
    }
    else
    {
        currentPlayer="Player2";
    }
}

void MainWindow::reStart()
{
    haveChessmanVtr.clear();
    chessPlayervtr.clear();
    isPlayer1=true;
    isPlayer2=false;
    currentPlayer="Player1";
    update();
}

bool MainWindow::currentPlayerIsWin()
{
    //以当前棋子开始,分别计算水平方向、竖直方向、斜方向
    //遍历水平方向 起始位置:当前位置左侧4个,终止位置:当前位置右侧4个
    int horizontalStartX=chessmanPosition.x()-4*m_space;
    QPoint horizontalStartPosition;
    horizontalStartPosition.setX(horizontalStartX);
    horizontalStartPosition.setY(chessmanPosition.y());
    int chessmanCount=0;
    for(int i=0;i<9;i++)
    {
        QPoint tempPoint=QPoint(horizontalStartPosition.x()+i*m_space,horizontalStartPosition.y());
        if(haveChessmanVtr.count(tempPoint)>0)
        {
            int index=haveChessmanVtr.indexOf(tempPoint);
            if(chessPlayervtr[index]!=currentPlayer)
            {
                chessmanCount++;
                if(chessmanCount==5)
                {
                    return true;
                }
            }
            else
            {
                chessmanCount = 0;
            }

        }
    }
    //竖直方向 起始位置:当前位置上面4个,终止位置:当前位置下面4个
    int verticalStartY=chessmanPosition.y()-4*m_space;
    QPoint verticalStartPosition;
    verticalStartPosition.setX(chessmanPosition.x());
    verticalStartPosition.setY(verticalStartY);
    chessmanCount=0;
    for(int i=0;i<9;i++)
    {
        QPoint tempPoint=QPoint(verticalStartPosition.x(),verticalStartPosition.y()+i*m_space);
        if(haveChessmanVtr.count(tempPoint)>0)
        {
            int index=haveChessmanVtr.indexOf(tempPoint);
            if(chessPlayervtr[index]!=currentPlayer)
            {
                chessmanCount++;
                if(chessmanCount==5)
                {
                    return true;
                }
                
            }
            else
            {
                chessmanCount = 0;
            }

        }
    }

    //斜上方向,起始位置:当前位置左下4个位置,终止位置:右上4个位置
    //Oblique upward direction;
    int obliqueUpwardStartX=chessmanPosition.x()-4*m_space;
    int obliqueUpwardStartY=chessmanPosition.y()+4*m_space;
    QPoint obliqueUpwardPosition;
    obliqueUpwardPosition.setX(obliqueUpwardStartX);
    obliqueUpwardPosition.setY(obliqueUpwardStartY);
    chessmanCount=0;
    for(int i=0;i<9;i++)
    {
        QPoint tempPoint=QPoint(obliqueUpwardPosition.x()+i*m_space,obliqueUpwardPosition.y()-i*m_space);
        if(haveChessmanVtr.count(tempPoint)>0)
        {
            int index=haveChessmanVtr.indexOf(tempPoint);
            if(chessPlayervtr[index]!=currentPlayer)
            {
                chessmanCount++;
                qDebug()<<chessmanCount;
                if(chessmanCount==5)
                {
                    return true;
                }
                
            }
            else
            {
                chessmanCount = 0;
            }
        }
    }

    //斜下方向,起始位置:当前位置左上5个位置,终止位置:右下5个位置
    //Oblique upward direction;
    int obliqueDownStartX=chessmanPosition.x()-4*m_space;
    int obliqueDownStartY=chessmanPosition.y()+4*m_space;
    QPoint obliqueDownPosition;
    obliqueDownPosition.setX(obliqueDownStartX);
    obliqueDownPosition.setY(obliqueDownStartY);
    chessmanCount=0;
    for(int i=0;i<9;i++)
    {
        QPoint tempPoint=QPoint(obliqueDownPosition.x()+i*m_space,obliqueDownPosition.y()+i*m_space);
        if(haveChessmanVtr.count(tempPoint)>0)
        {
            int index=haveChessmanVtr.indexOf(tempPoint);
            if(chessPlayervtr[index]!=currentPlayer)
            {
                chessmanCount++;
                if(chessmanCount==5)
                {
                    return true;
                }
                
            }
            else
            {
                chessmanCount = 0;
            }
        }
    }


    return false;
}

//void MainWindow::on_actionReStart_triggered()
//{
//    reStart();
//}
 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是基于Qt实现五子棋的代码: mainwindow.h ```cpp #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QPushButton> #include <QLabel> #include <QMouseEvent> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); protected: void paintEvent(QPaintEvent *event); void mousePressEvent(QMouseEvent *event); private: enum {ROW = 15, COL = 15}; // 棋盘行列数 enum {WIDTH = 40, HEIGHT = 40}; // 棋子大小 QPushButton *startButton; // 开始按钮 QPushButton *backButton; // 悔棋按钮 QPushButton *exitButton; // 退出按钮 QLabel *turnLabel; // 提示当前轮到哪个玩家 QLabel *blackCountLabel; // 黑方棋子数 QLabel *whiteCountLabel; // 白方棋子数 QPoint mousePos; // 鼠标点击位置 int board[ROW][COL] = {0}; // 棋盘,0表示空,1表示黑,2表示白 int turn = 1; // 当前轮到哪个玩家,1表示黑,2表示白 int blackCount = 0; // 黑方棋子数 int whiteCount = 0; // 白方棋子数 bool isGameOver = false; // 是否结束游戏 void initUI(); // 初始化UI void startGame(); // 开始游戏 void drawBoard(QPainter &painter); // 绘制棋盘 void drawPiece(QPainter &painter, int row, int col); // 绘制棋子 bool checkWin(int row, int col); // 检查是否胜利 void gameOver(); // 游戏结束 void reset(); // 重置游戏 }; #endif // MAINWINDOW_H ``` mainwindow.cpp ```cpp #include "mainwindow.h" #include <QPainter> #include <QMessageBox> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { initUI(); } MainWindow::~MainWindow() { } void MainWindow::initUI() { setFixedSize(620, 620); startButton = new QPushButton("开始游戏", this); startButton->setGeometry(500, 50, 100, 40); connect(startButton, &QPushButton::clicked, this, &MainWindow::startGame); backButton = new QPushButton("悔棋", this); backButton->setGeometry(500, 130, 100, 40); backButton->setEnabled(false); connect(backButton, &QPushButton::clicked, [=]() { if (!isGameOver) { // 游戏未结束才能悔棋 board[mousePos.x()][mousePos.y()] = 0; // 当前位置清空 turn = turn == 1 ? 2 : 1; // 切换玩家 backButton->setEnabled(false); // 禁用悔棋按钮 update(); // 重新绘制 } }); exitButton = new QPushButton("退出游戏", this); exitButton->setGeometry(500, 210, 100, 40); connect(exitButton, &QPushButton::clicked, [=]() { if (QMessageBox::Yes == QMessageBox::question(this, "提示", "确定要退出吗?")) { qApp->quit(); } }); turnLabel = new QLabel("当前轮到黑方下棋", this); turnLabel->setGeometry(500, 300); blackCountLabel = new QLabel("黑方棋子数:0", this); blackCountLabel->setGeometry(500, 350); whiteCountLabel = new QLabel("白方棋子数:0", this); whiteCountLabel->setGeometry(500, 400); } void MainWindow::startGame() { reset(); // 重置游戏 startButton->setEnabled(false); // 开始游戏后禁用开始按钮 } void MainWindow::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); drawBoard(painter); // 绘制棋盘 for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { if (board[i][j] != 0) { drawPiece(painter, i, j); // 绘制棋子 } } } } void MainWindow::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { // 左键点击 int x = event->x(); int y = event->y(); if (x >= 20 && x <= 580 && y >= 20 && y <= 580) { // 在棋盘内点击 int row = (y - 20) / HEIGHT; int col = (x - 20) / WIDTH; if (board[row][col] == 0) { // 当前位置没有棋子 board[row][col] = turn; // 下棋 if (checkWin(row, col)) { // 检查是否胜利 gameOver(); } else { turn = turn == 1 ? 2 : 1; // 切换玩家 backButton->setEnabled(true); // 开启悔棋按钮 } update(); // 重新绘制 } } } } void MainWindow::drawBoard(QPainter &painter) { painter.setPen(QPen(Qt::black, 2)); for (int i = 0; i < ROW; i++) { painter.drawLine(20, 20 + i * HEIGHT, 20 + (ROW - 1) * WIDTH, 20 + i * HEIGHT); painter.drawLine(20 + i * WIDTH, 20, 20 + i * WIDTH, 20 + (COL - 1) * HEIGHT); } } void MainWindow::drawPiece(QPainter &painter, int row, int col) { if (board[row][col] == 1) { // 黑方棋子 painter.setBrush(QBrush(Qt::black)); } else if (board[row][col] == 2) { // 白方棋子 painter.setBrush(QBrush(Qt::white)); } painter.drawEllipse(QPoint(col * WIDTH + 20, row * HEIGHT + 20), WIDTH / 2, HEIGHT / 2); } bool MainWindow::checkWin(int row, int col) { int i, j, k, count; // 横向 count = 1; for (i = col - 1; i >= 0; i--) { // 向左 if (board[row][i] == turn) { count++; } else { break; } } for (i = col + 1; i < COL; i++) { // 向右 if (board[row][i] == turn) { count++; } else { break; } } if (count >= 5) { return true; } // 纵向 count = 1; for (i = row - 1; i >= 0; i--) { // 向上 if (board[i][col] == turn) { count++; } else { break; } } for (i = row + 1; i < ROW; i++) { // 向下 if (board[i][col] == turn) { count++; } else { break; } } if (count >= 5) { return true; } // 斜向(左上到右下) count = 1; for (i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { // 向左上 if (board[i][j] == turn) { count++; } else { break; } } for (i = row + 1, j = col + 1; i < ROW && j < COL; i++, j++) { // 向右下 if (board[i][j] == turn) { count++; } else { break; } } if (count >= 5) { return true; } // 斜向(左下到右上) count = 1; for (i = row + 1, j = col - 1; i < ROW && j >= 0; i++, j--) { // 向左下 if (board[i][j] == turn) { count++; } else { break; } } for (i = row - 1, j = col + 1; i >= 0 && j < COL; i--, j++) { // 向右上 if (board[i][j] == turn) { count++; } else { break; } } if (count >= 5) { return true; } return false; } void MainWindow::gameOver() { isGameOver = true; backButton->setEnabled(false); // 禁用悔棋按钮 QString message = turn == 1 ? "黑方胜利!" : "白方胜利!"; QMessageBox::information(this, "游戏结束", message); startButton->setEnabled(true); // 开启开始按钮 } void MainWindow::reset() { memset(board, 0, sizeof(board)); // 清空棋盘 turn = 1; // 黑方先手 blackCount = 0; whiteCount = 0; isGameOver = false; backButton->setEnabled(false); // 禁用悔棋按钮 update(); // 重新绘制 } ``` 在.pro文件中添加: ```pro QT += widgets ``` 编译运行即可看到五子棋界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值