QT项目实战: 五子棋小游戏

目录

内容介绍

一.添加头文件

二.画棋盘

1.宏定义

2.棋盘

三.画棋子

四.获取棋子摆放位置

五.判断棋子存在

六.判断胜利

1.变量定义和初始化

2.检查获胜条件

3.游戏结束处理

七.重绘

八.效果展示

九.代码

1.mainwindow.h 

2.mainwindow.cpp

3.chessitem.h

4.chessitem.cpp


内容介绍

简单的五子棋游戏

  • MainWindow 类继承自 QMainWindow,用于创建游戏窗口。
  • DrawChessBoard 函数使用 QPainter 绘制棋盘的网格线。
  • DrawHandChess 函数根据当前的棋子颜色在鼠标位置绘制一个棋子。
  • DrawChessItem 函数遍历所有已经放置的棋子并绘制它们。
  • DrawChessAtPoint 函数在指定的位置绘制一个棋子。
  • mousePressEvent 函数处理鼠标点击事件,判断点击位置是否已经有棋子,如果没有,则放置一个新棋子并检查是否胜利。
  • CountNearItem 函数用于计算在特定方向上连续相同颜色的棋子数量。
  • paintEvent 函数是重绘事件,它调用其他函数来绘制整个棋盘和棋子。

一.添加头文件

#include <QKeyEvent> 是 C++ 源代码文件中包含 Qt 库的头文件,用于处理键盘事件。在应用程序中,可以通过重写 QWidget::keyPressEvent() 或 QWidget::keyReleaseEvent() 函数来处理键盘事件。这两个函数的参数都是 QKeyEvent 对象,可以用它来获取键盘事件的详细信息,例如按下或释放的键、键的序号、修饰键等。

#include <QTimer> 是 C++ 源代码文件中包含 Qt 库的头文件,用于创建定时器。QTimer 是 Qt 中用于定时操作的类,可以用来触发特定时间间隔后的操作。通过 QTimer,可以实现定时执行某些任务、定时更新界面等功能。

#include <QPainter> 是 C++ 源代码文件中包含 Qt 库的头文件,用于绘制图形和图像。QPainter 是 Qt 中用于绘制图形和图像的类,可以用来绘制各种形状、文本、图像等。通过 QPainter,可以实现自定义绘制、图形界面美化等功能。

#include <QMouseEvent> 是用于包含 QMouseEvent 类的头文件的指令。在Qt框架中,QMouseEvent 类用于表示鼠标事件,例如鼠标的按下、释放、移动和双击等动作。

二.画棋盘

1.宏定义

  • #define ChessR 12:定义了棋盘的行数,这里是12行。
  • #define ChessC 12:定义了棋盘的列数,这里是12列。
  • #define MaxX 35:定义了棋盘上每个方格的宽度,这里是35个单位。
  • #define MaxY 35:定义了棋盘上每个方格的高度,这里是35个单位。

2.棋盘

  • painter.setPen(QPen(QColor(Qt::black), 2));:设置画笔的颜色为黑色,线宽为2个像素。

  • painter.setBrush(Qt::white);:设置画刷的颜色为白色,用于填充图形。

  • 接下来的双重 for 循环遍历棋盘的列(i)和行(j):painter.drawRect((i+0.5)*Max_X, (j+0.5)*Max_Y, Max_X, Max_Y);:在这个循环中,drawRect 函数被用来绘制一个矩形。矩形的左上角坐标是 (i+0.5)*Max_X 和 (j+0.5)*Max_Y,这样可以确保矩形是从每个方格的中心开始绘制的。矩形的宽度和高度被设置为 Max_X 和 Max_Y

三.画棋子

  • painter.setPen(QPen(QColor(Qt::black), 1));:设置画笔的颜色为黑色,线宽为1个像素。这通常用于绘制棋子的轮廓。

  • 接下来的 for 循环遍历 p_ChessItem 容器中的所有棋子:ChessItem item = p_ChessItem[i];:从 p_ChessItem 容器中获取第 i 个棋子。ChessItem 是一个自定义的结构体或类,包含棋子的位置 _pt 和颜色信息 _blackif(item._black){ painter.setBrush(Qt::black); } else { painter.setBrush(Qt::white); }:根据棋子的颜色属性 _black 设置画刷的颜色。如果 _black 为真,则画刷颜色为黑色,否则为白色。DrawChessAtPoint(painter, item._pt);:调用 DrawChessAtPoint 函数在指定的位置 item._pt 绘制棋子。这个函数需要被定义,它应该接受一个 QPainter 对象和一个 QPoint 对象,并在该点绘制一个圆形或其他形状来表示棋子。

四.获取棋子摆放位置

  • QPoint ptCenter((point.x() + 0.5) * Max_X, (point.y() + 0.5) * Max_Y);:计算棋子的中心点位置。Max_X 和 Max_Y 是棋盘上每个格子宽度和高度的常量。(point.x() + 0.5) * Max_X 和 (point.y() + 0.5) * Max_Y 的计算是为了将棋子的位置从棋盘的离散格子坐标转换为中心点坐标。

  • painter.drawEllipse(ptCenter, Max_X / 3, Max_Y / 3);:在计算出的中心点位置 ptCenter 绘制一个椭圆。椭圆的宽度是 Max_X / 3,高度是 Max_Y / 3。这表示椭圆的尺寸是棋盘格尺寸的三分之一,从而在棋盘上绘制一个大小合适的棋子。

五.判断棋子存在

  • for 循环遍历 p_ChessItem 容器中的所有棋子。
  • if 语句检查当前棋子的位置 _pt 是否与给定的点 pt 相等。
  • 如果位置相等,函数立即返回 true,表示棋子存在。
  • 如果 for 循环完成后没有找到相等的点,函数返回 false,表示棋子不存在。

六.判断胜利

1.变量定义和初始化

nLeftnLeftUpnUpnRightnRightUpnRightDownnDownnLeftDown 这些变量通过调用 CountNearItem 函数来计算,该函数接受一个棋子对象 item 和一个表示方向的 QPoint 对象,返回该方向上相邻的棋子数量。

2.检查获胜条件

代码检查四个方向上的棋子数量组合

  • (nRightUp + nLeftDown) >= 4:检查右上到左下对角线方向上是否有至少四个连续的棋子。
  • (nUp + nDown) >= 4:检查垂直方向上是否有至少四个连续的棋子。
  • (nLeftUp + nRightDown) >= 4:检查左上到右下对角线方向上是否有至少四个连续的棋子。
  • (nLeft + nRight) >= 4:检查水平方向上是否有至少四个连续的棋子。

3.游戏结束处理

  • 如果上述任一条件满足,即有一方玩家形成了至少四个连续棋子的组合,游戏结束。
  • 根据 b_black 变量的值(如果为真,表示黑棋赢;否则,表示白棋赢),构建一个字符串 str 来显示获胜信息。
  • 使用 QMessageBox::information 函数显示一个消息框,通知玩家游戏结束,并显示获胜信息。
  • 清除棋盘上的所有棋子(通过 p_ChessItem.clear();)。
  • 函数返回,结束游戏。

七.重绘

八.效果展示

九.代码

1.mainwindow.h 

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPainter>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QVector>
#include <QDebug>
#include "chessitem.h"
#include <QMessageBox>

#define ChessR 12
#define ChessC 12
#define MaxX 35
#define MaxY 35

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    void paintEvent(QPaintEvent *event);

    void mousePressEvent(QMouseEvent *event); //鼠标变形

    int CountNearItem(ChessItem item , QPoint pt); //判断棋子连接

private:
    Ui::MainWindow *ui;
    void InitUI();
    void DrawChessBoard();//画棋盘
    void DrawChessItem();//绘制棋盘上的棋子
    void DrawChessAtPoint(QPainter &painter , QPoint &point); //画棋子的样式和位置

    bool b_black; //定义棋子的颜色

    QVector<ChessItem> p_ChessItem;//存储棋子

};
#endif // MAINWINDOW_H

2.mainwindow.cpp

#include "mainwindow.h"
#include "./ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    InitUI();
}

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

void MainWindow::InitUI()
{
     //定义棋盘的大小
    this->resize((ChessC + 1) * MaxX, (ChessR + 1) * MaxX);

    b_black = false;
}

void MainWindow::DrawChessBoard()
{
    QPainter painter(this);
    painter.setPen(QPen(QColor(Qt::black),2));
    painter.setBrush(Qt::white);
    //棋盘格子
    for(int i=0; i <ChessC; i++){
        for(int j =0; j<ChessR;j++){
            painter.drawRect((i+0.5)*MaxX,(j+0.5)*MaxY,MaxX,MaxY);
        }
    }
}



//绘制棋盘上的所有棋子
void MainWindow::DrawChessItem()
{
    QPainter painter(this);
    painter.setPen(QPen(QColor(Qt::black),1));
    //遍历棋子,有就绘制,没有就不绘制
    for(int i = 0; i < p_ChessItem.size() ; i++){
        ChessItem item = p_ChessItem[i]; //当前棋子的样式和位置复制给棋子这个类
        if(item._black){
            painter.setBrush(Qt::black);
        }else {
            painter.setBrush(Qt::white);
        }
        DrawChessAtPoint(painter,item._pt);
    }
}

void MainWindow::DrawChessAtPoint(QPainter &painter , QPoint &point)
{
    //获取棋子的摆放位置
    QPoint ptCenter((point.x() + 0.5) * MaxX , (point.y() + 0.5) * MaxY);
    painter.drawEllipse(ptCenter,MaxX/3,MaxY/3);
}


void MainWindow::mousePressEvent(QMouseEvent *event)
{

    QPoint pt;  //定义点位
    pt.setX((event->pos().x())/MaxX);
    pt.setY((event->pos().y())/MaxY);

    //判断棋子是否存在
    for(int i = 0 ; i<p_ChessItem.size(); i++){
        ChessItem item = p_ChessItem[i];
        if(item._pt == pt){
            return ;
        }
    }

    //如果不存在,进行绘制和判断五子链接
    ChessItem item(pt,b_black);
    p_ChessItem.append(item);

    //统计四个点位是否连接
    int nLeft       = CountNearItem(item,QPoint(-1,0));
    int nLeftUp     = CountNearItem(item,QPoint(-1,-1));;
    int nUp         = CountNearItem(item,QPoint(0,-1));;
    int nRight      = CountNearItem(item,QPoint(1,0));;
    int nRightUp    = CountNearItem(item,QPoint(1,-1));;
    int nRightDown = CountNearItem(item,QPoint(1,1));;
    int nDown       = CountNearItem(item,QPoint(0,1));;
    int nLeftDown   = CountNearItem(item,QPoint(-1,1));;

    if( (nLeft + nRight) >= 4 || (nLeftUp + nRightDown) >=4
        || (nUp + nDown) >=4 || (nRightUp + nLeftDown) >= 4)
    {
        QString str = b_black ? "black win" : "white win";
        QMessageBox::information(NULL,"GAME OVER",str,QMessageBox::Yes);
        p_ChessItem.clear();
        return;
    }

    //换人下棋
    b_black = !b_black;
}

int MainWindow::CountNearItem(ChessItem item, QPoint pt)
{
    int nCount = 0;

    item._pt += pt;
    while (p_ChessItem.contains(item)) {
        nCount++;
        item._pt += pt;
    }

    return nCount;
}


void MainWindow::paintEvent(QPaintEvent *event)
{
    DrawChessBoard();
    DrawChessItem();
    update();
}



3.chessitem.h

#ifndef CHESSITEM_H
#define CHESSITEM_H

#include <QObject>
#include <QPoint>

class ChessItem
{
public:
    ChessItem();
    ChessItem(QPoint point,bool isBluck);  //位置和颜色

    bool operator==(const ChessItem &t1)const{
        return ((_pt==t1._pt) && (_black==t1._black));
    }

    QPoint _pt;  //棋子的位置
    bool _black; //棋子的颜色
};

#endif // CHESSITEM_H

4.chessitem.cpp

#include "chessitem.h"

ChessItem::ChessItem(void) {}

ChessItem::ChessItem(QPoint point, bool isBluck)
{
    _pt = point;
    _black = isBluck;
}

  • 29
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值