【Qt象棋游戏】02_绘画象棋棋盘


01 - 相关成员与方法

  进行代码编写之前,在chessarea.h 增加相关成员和方法定义,同时加入Qt需要使用到的基本头文件。主要用到Qt绘画类:Qpen,QBrush,QPoint,QpaintEvent等,重写 paintEvent,达到绘制棋盘线功能。

#ifndef CHESSAREA_H
#define CHESSAREA_H
#include <QWidget>         // 基本窗口widget
#include <QPen>            // 画笔
#include <QBrush>          // 画刷
#include <QPainter>        // 画布
#include <QPoint>          // 点
#include <QColor>          // 颜色
#include <QColorDialog>    // 颜色Dialog
#include <QMouseEvent>     // 鼠标事件
#include <QPaintEvent>     // 绘画事件
#include "chess.h"
class ChessArea : public QWidget
{    
public:
   //构造函数
   explicit ChessArea(QWidget *parent = NULL);
   // 重绘事件,用来画棋盘线
   void paintEvent(QPaintEvent *);
   
private:
    int chessArea;    // 这个用来定义棋盘线之间的宽度,这里初始化为60
};
#endif // CHESSAREA_H

02 - 棋盘颜色

  修改棋盘颜色比较简单,直接修改widget背景颜色。在chessarea.cpp的构造函数中添加以下代码,修改棋盘的背景色为米黄色。

 //设置棋盘去区的背景颜色和大小
    QPalette palette;
 
    // 设置棋盘成了米黄
    QLinearGradient linearGradient(0, 0, 400, 400);
    linearGradient.setColorAt(0.0, QColor(216, 180, 80));
    linearGradient.setColorAt(0.2, QColor(216, 160, 72));
    linearGradient.setColorAt(1.0, QColor(216, 156, 72));

    palette.setBrush(QPalette::Background,  QBrush(linearGradient));
 
    setPalette(palette);
 
    setAutoFillBackground(true);
    setMinimumSize(600, 660);

03 - 绘画棋盘线

  *paintEvent(QPaintEvent)**函数是QWidget类中的虚函数,用于绘制UI。
  一个重绘事件用来重绘一个部件的全部或者部分区域,下面几个原因的任意一个都会发生重绘事件:
  (1)repaint()函数或者update()函数被调用;
  (2)被隐藏的部件现在被重新显示;
  (3)其他一些原因。
Qt的paintEvent使用文档  了解paintEvent如何使用后,添加代码重写paintEvent事件,绘制象棋的棋盘线,代码如下:

void ChessArea::paintEvent(QPaintEvent *)
{
    // 设置画笔为实线 
    QPen pen(Qt::SolidLine);
    pen.setWidth(10);
    pen.setColor(Qt::green);
 
    QPainter p(this);
    p.setPen(pen);
 
    //反锯齿
    p.setRenderHint(QPainter::Antialiasing);
 
    //初始化描绘四个绿色点坐标
    p.drawPoint(chessArea-5, chessArea-5);
    p.drawPoint(chessArea*9+5, chessArea-5);
    p.drawPoint(chessArea-5, chessArea*10+5);
    p.drawPoint(chessArea*9+5, chessArea*10+5);
 
 
    //设置画笔颜色和宽度
    pen.setColor(Qt::black);
    pen.setWidth(3);
    p.setPen(pen);
 
    // 1.画棋盘的轮廓线
    p.drawLine(chessArea-5, chessArea-5, chessArea*9+5, chessArea-5);
    p.drawLine(chessArea-5, chessArea-5, chessArea-5, chessArea*10+5);
    p.drawLine(chessArea-5, chessArea*10+5, chessArea*9+5, chessArea*10+5);
    p.drawLine(chessArea*9+5, chessArea-5, chessArea*9+5, chessArea*10+5);
 
 
    // 2.画棋盘的18条垂直线
    //pen = p.pen();
    //background.setColor(Qt::black);
    pen.setWidth(2);
    p.setPen(pen);
 
    for (int i=1; i<10; i++) {
         p.drawLine(chessArea*i, chessArea,  chessArea*i, chessArea*5);
         p.drawLine(chessArea*i, chessArea*6,chessArea*i, chessArea*10);
    }
 
    // 3.楚河 汉界
    p.drawLine(chessArea, chessArea*5, chessArea, chessArea*6);
    p.drawLine(chessArea*9, chessArea*5 ,chessArea*9, chessArea*6);
 
    // 4.画棋盘的10条水平线
    for(int i=1;i<=10; i++)
         p.drawLine(chessArea,chessArea*i, chessArea*9, chessArea*i);
 
    // 5.画棋盘“士”行走的斜线
    p.drawLine(chessArea*4, chessArea,  chessArea*6, chessArea*3);
    p.drawLine(chessArea*6, chessArea,  chessArea*4, chessArea*3);
    p.drawLine(chessArea*4, chessArea*8,chessArea*6, chessArea*10);
    p.drawLine(chessArea*6, chessArea*8,chessArea*4, chessArea*10);
 
    // 6. 写上楚河汉界
    QPointF point(chessArea*2.6, chessArea*5.7);
    p.setFont(QFont("Arial", 25));
    p.drawText(point, "楚河         汉界");
}

  此时基本的棋盘样子就出来了,样子大概是这样的:
在这里插入图片描述

04 - 添加“井”字格

  通过步骤02和03,棋盘基本形状就出来了,但和现实生活中的棋盘相比还欠缺一点瑕疵,于是,可以在 paintEvent 函数里面继续添加以下代码,增加棋盘上面棋子炮和兵的站位直角。(接着上面的第 6 步写)

    // 7. 直角折线
    pen.setWidth(4);
    p.setPen(pen);
 
    for(int j=2; j>0; j--)
    {
        for(int i=1; i<5; i++)  /* 兵的井字格 */
        {
            QPoint points1[3] = {
                QPoint(chessArea*(2*i-1)+5,  chessArea*(10-j*3)-15),
                QPoint(chessArea*(2*i-1)+5,  chessArea*(10-j*3)-5),
                QPoint(chessArea*(2*i-1)+15, chessArea*(10-j*3)-5),
            };
            p.drawPolyline(points1, 3);
 
            QPoint points2[3] = {
                QPoint(chessArea*(2*i+1)-15, chessArea*(10-j*3)-5),
                QPoint(chessArea*(2*i+1)-5,  chessArea*(10-j*3)-5),
                QPoint(chessArea*(2*i+1)-5,  chessArea*(10-j*3)-15),
            };
            p.drawPolyline(points2, 3);
 
            QPoint points3[3] = {
                QPoint(chessArea*(2*i-1)+5,  chessArea*(10-j*3)+15),
                QPoint(chessArea*(2*i-1)+5,  chessArea*(10-j*3)+5),
                QPoint(chessArea*(2*i-1)+15, chessArea*(10-j*3)+5),
            };
            p.drawPolyline(points3, 3);
 
            QPoint points4[3] = {
                QPoint(chessArea*(2*i+1)-15, chessArea*(10-j*3)+5),
                QPoint(chessArea*(2*i+1)-5,  chessArea*(10-j*3)+5),
                QPoint(chessArea*(2*i+1)-5,  chessArea*(10-j*3)+15),
            };
            p.drawPolyline(points4, 3);
 
 
            if(i < 3)   /* 炮的井字格 */
            {
                QPoint points5[3] = {
                    QPoint(chessArea*pow(2, 2*i-1)-15,  chessArea*(pow(j+1,2)-1)-5),
                    QPoint(chessArea*pow(2, 2*i-1)-5,   chessArea*(pow(j+1,2)-1)-5),
                    QPoint(chessArea*pow(2, 2*i-1)-5,   chessArea*(pow(j+1,2)-1)-15),
                };
                p.drawPolyline(points5, 3);
 
                QPoint points6[3] = {
                    QPoint(chessArea*pow(2, 2*i-1)+15,  chessArea*(pow(j+1,2)-1)-5),
                    QPoint(chessArea*pow(2, 2*i-1)+5,   chessArea*(pow(j+1,2)-1)-5),
                    QPoint(chessArea*pow(2, 2*i-1)+5,   chessArea*(pow(j+1,2)-1)-15),
                };
                p.drawPolyline(points6, 3);
 
                QPoint points7[3] = {
                    QPoint(chessArea*pow(2, 2*i-1)-15,  chessArea*(pow(j+1,2)-1)+5),
                    QPoint(chessArea*pow(2, 2*i-1)-5,   chessArea*(pow(j+1,2)-1)+5),
                    QPoint(chessArea*pow(2, 2*i-1)-5,   chessArea*(pow(j+1,2)-1)+15),
                };
                p.drawPolyline(points7, 3);
 
                QPoint points8[3] = {
                    QPoint(chessArea*pow(2, 2*i-1)+15,  chessArea*(pow(j+1,2)-1)+5),
                    QPoint(chessArea*pow(2, 2*i-1)+5,   chessArea*(pow(j+1,2)-1)+5),
                    QPoint(chessArea*pow(2, 2*i-1)+5,   chessArea*(pow(j+1,2)-1)+15),
                };
                p.drawPolyline(points8, 3);
            }
 
        }
 
    }

  添加完棋子站位直角后,棋盘绘制成形了。和现实生活的棋盘就比较像,同时也美观了很多,到此,棋盘的绘制就成功了。
在这里插入图片描述

05 - 总结

  象棋棋盘绘制主要是在 chessarea.cpp 中的 paintEvent 重绘事件中实现 ,主要用到 QPainter 类的画笔,其次是使用QPalette 类调整了棋盘witget背景色。接下来分析如何把棋子摆放上绘画好的象棋棋盘上,下回见!

  • 01_开发象棋游戏简介
  • 02_绘画象棋棋盘
  • 03_象棋棋子摆放
  • 04_象棋走棋规则——車、炮、士
  • 05_象棋走棋规则——象、马、将、兵
  • 06_象棋游戏法则
  • 07_人机博弈算法开端
  • 08_人机博弈高阶算法
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Qt的绘图功能来画象棋棋盘,以下是一个简单的实现: 1. 在Qt Creator中创建一个新的Qt Widgets应用程序项目。 2. 在主窗口的构造函数中创建一个QGraphicsView和QGraphicsScene。 ```cpp MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { QGraphicsView *view = new QGraphicsView(this); QGraphicsScene *scene = new QGraphicsScene(this); view->setScene(scene); setCentralWidget(view); // TODO: 添加棋盘图形项 } ``` 3. 创建一个棋盘图形项,并将其添加到场景中。 ```cpp // 棋盘格子大小 const int CELL_SIZE = 50; // 棋盘格子行列数 const int ROWS = 10; const int COLS = 9; // 棋盘原点坐标 const int ORIGIN_X = 25; const int ORIGIN_Y = 25; // 棋盘颜色 const QColor BOARD_COLOR = QColor(238, 200, 163); // 棋盘边框宽度 const int BORDER_WIDTH = 2; class ChessBoardItem : public QGraphicsItem { public: QRectF boundingRect() const override { return QRectF(0, 0, CELL_SIZE * COLS, CELL_SIZE * ROWS); } void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override { // 画棋盘背景 painter->setBrush(BOARD_COLOR); painter->drawRect(boundingRect()); // 画棋盘边框 painter->setBrush(Qt::NoBrush); painter->setPen(QPen(Qt::black, BORDER_WIDTH)); painter->drawRect(boundingRect()); // 画棋盘格子 painter->setPen(QPen(Qt::black)); for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { if ((row + col) % 2 == 0) { painter->setBrush(Qt::white); } else { painter->setBrush(Qt::gray); } painter->drawRect(QRectF(col * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE)); } } } }; // 在主窗口构造函数中添加以下代码 ChessBoardItem *boardItem = new ChessBoardItem; scene->addItem(boardItem); boardItem->setPos(ORIGIN_X, ORIGIN_Y); ``` 4. 运行程序,即可看到绘制象棋棋盘。 注意:以上代码只是一个简单的实现,还有很多可以优化的地方,比如使用QPainterPath来绘制棋盘线条,增加棋子图形项等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值