利用QT实现中国象棋

        这个项目是暑假在校比赛时,参考B站教程编写的,没有像一般的游戏进行导入图片的简单方法来进行游戏界面布局,而是采用画笔来进行操作,包括棋盘绘制和棋子的绘制前期只做了简单的走棋,后来有时间将会尝试联网功能和人工智能走棋操作。本软件版本为QT版本5.14

   希望大家能够加个关注,收藏。以后会完善这个项目的。代码如果编译不过,可以私信我分享源文件。之前私信没看见加一个github地址有点乱,请见谅。地址在这

 

 

一、项目创建

 有QT编程基础的应该会如果不会的话参考一下链接-------->QT项目创建

二、界面样式

aa5f191d9ed24fafbeda3ab96d32bd82.png

三、项目效果

通过画笔实现象棋界面的绘制,其中每一个采用了枚举类,实现相似棋子的定义。采用像素点转化的方法来绘制棋盘。就是划线的方法采用drawLine方法,后来又用画圆的方法绘制棋子,后来再用调整汉字大小的方法来得到汉字。

b949ee6e94a249cd9153f6f08356ac82.png

四、源代码

board.h

主要包含了棋盘绘制函数的实现以及走棋代码函数的定义。

#ifndef BOARD_H
#define BOARD_H

#include <QWidget>
#include <QVector>
#include "stone.h"
#include "step.h"


QT_BEGIN_NAMESPACE
namespace Ui { class Board; }
QT_END_NAMESPACE

class Board : public QWidget
{
    Q_OBJECT

public:
    Board(QWidget *parent = nullptr);
    ~Board();
    //棋盘初始点坐标
    QPoint origin;

    //格子边长
    int d;

    //棋子   
    stone s[32];

    //棋子半径
    int r;

    //记录棋子,是否选中
    int isSelect;

    //返回象棋棋盘行列对应的坐标
    QPoint Center(int row,int col);
    QPoint Center(int id);

    //交换走棋
    bool isTurnRed;
    //绘制棋子
    void DrawStone(QPainter &painter,int id);

    //棋盘绘制(绘图事件)
    void paintEvent(QPaintEvent *);

    //绘制兵炮停靠点
    void drawAngle(QPainter &p,QPoint point);

    //走棋(鼠标点击事件)
    void mouseReleaseEvent(QMouseEvent *);

    //获得棋盘的行列,是否在棋盘内
    bool getRowCol(QPoint pt,int &row,int &col);

    //判读是否能够走棋
    bool canMove(int moveid,int row,int col,int killid);

    bool canMoveCar(int moveid,int row,int col);
    bool canMoveGun(int moveid,int row,int col);
    bool canMoveHorse(int moveid,int row,int col);
    bool canMoveElephant(int moveid,int row,int col);
    bool canMoveMandarins(int moveid,int row,int col);
    bool canMoveGenerals(int moveid,int row,int col);
    bool canMovePawns(int moveid,int row,int col);

    //勾股定理计算棋子应该移动范围
    int Gougu(int moveid,int row,int col);

    //判断某行某位置有没有棋子
    int Havestone(int row,int col);

    //统计直线上棋子个数
    int CountnumLine(int row, int col ,int Row,int Col);

    //人工智能走棋
    void click(QPoint pt);
    void click(int id,int row,int col);

    //获取棋子id
    int getStonID(int row, int col);


private:
    Ui::Board *ui;
};
#endif // BOARD_H

 board.cpp

主要程序界面包含棋盘绘制函数的实现,以及象棋初始界面的定义。走棋的详细操作,走棋遵循传统的中国象棋的规则。

#include "board.h"
#include "ui_board.h"
#include <QPainter>
#include <QMouseEvent>
#include "QDebug"
Board::Board(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Board)
{
    setWindowTitle("中国象棋");
    origin = QPoint(60,60);
    d=80;
    r=d/2;
    resize(origin.x()*3+d*8,origin.y()+d*9);

    for (int i=0;i<32;i++) {
        s[i].init(i);
    }
    isSelect = -1;
    isTurnRed = true;
    ui->setupUi(this);
}

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

//将坐标轴转换为像素坐标点
QPoint Board::Center(int row, int col)
{

    return QPoint(origin.x()+d*col,origin.y()+d*row);
}

QPoint Board::Center(int id)
{
    return Center(s[id].row,s[id].col);
}

//绘制棋子
void Board::DrawStone(QPainter &painter, int id)
{
  QPen pen;
  pen.setWidth(1);
  painter.setPen(pen);
  //求中心点
  QPoint c = Center(id);
  //构造图像
  QRect rect = QRect(c.rx()-r,c.ry()-r,r*2,r*2);
  //棋子不存在
  if(s[id].isdead)
      return;
  //如果棋子被选中
  if(id == isSelect)
     painter.setBrush(QBrush(Qt::gray));
  else
     painter.setBrush(QBrush(QColor(234,173,26)));

   //绘制椭圆函数DrawEllipse
  painter.drawEllipse(Center(s[id].row,s[id].col),r, r);
  painter.drawEllipse(Center(s[id].row,s[id].col),r-3, r-3);
  //绘制棋子颜色
  if(s[id].isblack)
  {
       painter.setPen(Qt::black);

  }
   else  painter.setPen(Qt::red);



  //写字,参数说明draw(对象,字,对齐方式)
  painter.setFont(QFont("楷体",r,700));
  painter.drawText(rect,s[id].getclass(),QTextOption(Qt::AlignCenter));


}

//创建棋盘雏形,利用坐标点原理
void Board::paintEvent(QPaintEvent *)
{

    QPainter painter(this);
    //设置画笔
    QPen pen;
    pen.setWidth(3);
    painter.setPen(pen);
    //绘制棋盘外围边框
    painter.drawRect(QRect(origin.x()-4,origin.y()-4,d*8+10,d*9+10));
    //绘制棋盘内线
    pen.setWidth(1);
    painter.setPen(pen);
    painter.drawRect(QRect(origin,Center(9,8)));

//   //画10条横线
//    for (int i=0;i<11;++i)
//    {
//        //drawline函数就是两点之间画直线,电脑左上角为坐标轴起点,QPoint(d,d)点坐标
//        painter.drawLine(QPoint(d,i*d),QPoint(9*d,i*d));
//    }
//   //画9条竖线
//    for (int i=0;i<10;i++)
//    {
//        //楚河汉界空白处不划线
//        if(i==1 || i==9)
//            painter.drawLine(QPoint(i*d,d),QPoint(i*d,10*d));
//        else
//        {
//            painter.drawLine(QPoint(i*d,d),QPoint(i*d,5*d));
//            painter.drawLine(QPoint(i*d,6*d),QPoint(i*d,10*d));
//        }
//    }
    //绘制8横7竖
    for (int i=1;i<=8;i++)
    {
        //drawline函数就是两点之间画直线,电脑左上角为坐标轴起点,QPoint(d,d)点坐标
        painter.drawLine(Center(i,0),Center(i,8));
        if(i<8)
        {
            painter.drawLine(Center(0,i),Center(4,i));
            painter.drawLine(Center(5,i),Center(9,i));
        }
    }

   //九宫格
//   painter.drawLine(QPoint(4*d,d),QPoint(6*d,3*d));
//   painter.drawLine(QPoint(6*d,d),QPoint(4*d,3*d));

//   painter.drawLine(QPoint(4*d,8*d),QPoint(6*d,10*d));
//   painter.drawLine(QPoint(6*d,8*d),QPoint(4*d,10*d));
    painter.drawLine(Center(0,3),Center(2,5));
    painter.drawLine(Center(2,3),Center(0,5));
    painter.drawLine(Center(7,3),Center(9,5));
    painter.drawLine(Center(9,3),Center(7,5));
   //绘制楚河汉界
 //   QTransform transfrom;
//    transfrom.rotate(180);
//    painter.setTransform(transfrom);
    QPainterPath s;
    painter.setPen(Qt::gray);
    painter.setFont(QFont("楷体",35,r));
    painter.drawText(QRect(Center(4,1),Center(5,3)),"楚河",QTextOption(Qt::AlignCenter));
    painter.drawText(QRect(Center(4,5),Center(5,7)),"漢界",QTextOption(Qt::AlignCenter));

    //绘制棋子炮的停靠点
    drawAngle(painter,Center(2,1));
    drawAngle(painter,Center(2,7));
    drawAngle(painter,Center(7,1));
    drawAngle(painter,Center(7,7));
    //中间6个兵停靠点
    drawAngle(painter,Center(3,2));
    drawAngle(painter,Center(3,4));
    drawAngle(painter,Center(3,6));
    drawAngle(painter,Center(6,2));
    drawAngle(painter,Center(6,4));
    drawAngle(painter,Center(6,6));

    drawAngle(painter,Center(3,0));
    drawAngle(painter,Center(3,8));
    drawAngle(painter,Center(6,0));
    drawAngle(painter,Center(6,8));


   //绘制32个棋子
   for (int i=0;i<32;i++)
   {
       DrawStone(painter,i);
       }
}

void Board::drawAngle(QPainter &p, QPoint point)
{
    QPen pen;
    pen.setWidth(2);
    p.setPen(pen);
    int X = point.x();
    int Y = point.y();
    float R = d/9.5;
    if(point.x() == 60)
     {

        p.drawLine(X+R,Y-R,X+2*R,Y-R);
        p.drawLine(X+R,Y+R,X+2*R,Y+R);
        p.drawLine(X+R,Y-2*R,X+R,Y-R);
        p.drawLine(X+R,Y+R,X+R,Y+2*R);

    }
    else if(point.x() == 700)
    {
        p.drawLine(X-2*R,Y-R,X-R,Y-R);
        p.drawLine(X-2*R,Y+R,X-R,Y+R);
        p.drawLine(X-R,Y-2*R,X-R,Y-R);
        p.drawLine(X-R,Y+R,X-R,Y+2*R);
    }

    else
    {
        p.drawLine(X-2*R,Y-R,X-R,Y-R);
        p.drawLine(X-2*R,Y+R,X-R,Y+R);
        p.drawLine(X+R,Y-R,X+2*R,Y-R);
        p.drawLine(X+R,Y+R,X+2*R,Y+R);

        p.drawLine(X-R,Y-2*R,X-R,Y-R);
        p.drawLine(X-R,Y+R,X-R,Y+2*R);
        p.drawLine(X+R,Y-2*R,X+R,Y-R);
        p.drawLine(X+R,Y+R,X+R,Y+2*R);
    }

}

void Board::mouseReleaseEvent(QMouseEvent *ev)
{
   QPoint pt = ev->pos();
   //将pt转换成象棋的行列值
   //判断行列值上面有没有棋子
   int row,col;
   bool bret = getRowCol(pt,row,col);
   if(bret == false) return; //点在棋盘外
   int i;
   int clickid = -1;
   for(i=0;i<32;++i)
   {
       if(s[i].row == row && s[i].col == col && s[i].isdead == false)
       {
           break;
       }

   }
   if(i<32)
   {
       clickid = i;

   }
   //
   if(isSelect == -1)
   {
      if(clickid != -1)
      {
          if(isTurnRed == !s[clickid].isblack)
          isSelect = clickid;
          update();
      }
   }
   else
   {
       //走棋
       if(canMove(isSelect,row,col,clickid))
       {
           s[isSelect].row = row;
           s[isSelect].col =col;
           if(clickid != -1)
           {
               s[clickid].isdead = true;
           }
           isSelect = -1;
           isTurnRed = !isTurnRed;
           update();
       }

   }

}

bool Board::getRowCol(QPoint pt, int &row, int &col)
{
    for (row = 0;row<=9;row++)
    {
        for (col = 0;col<=8;col++)
        {
            QPoint c=Center(row,col);
            //勾股定理 //效率不高
            int dx = c.x() - pt.x();
            int dy = c.y() - pt.y();
            int dist = dx*dx+dy*dy;
            if(dist < r*r)
                return true;
        }
    }
    return false;
}

bool Board::canMove(int moveid, int row, int col, int killid)
{
    if((s[moveid].isblack == s[killid].isblack)&&killid != -1)
    {

        isSelect = killid;
        update();
        return false;
    }

    switch(s[moveid].type)
    {
        case stone::Car: return canMoveCar(moveid, row,  col); break;
        case stone::Gun: return canMoveGun(moveid, row,  col);break;
        case stone::Horse: return canMoveHorse(moveid, row,  col); break;
        case stone::Elephant: return canMoveElephant(moveid, row,  col);break;
        case stone::Premier: return canMoveElephant(moveid, row,  col);break;
        case stone::Mandarins: return canMoveMandarins(moveid, row,  col);break;
        case stone::Soldier: return canMoveMandarins(moveid, row,  col);break;
        case stone::Generals: return canMoveGenerals(moveid, row,  col);break;
        case stone::King:return canMoveGenerals(moveid, row,  col);break;
        case stone::Pawns: return canMovePawns(moveid, row,  col); break;
        case stone::Arms: return canMovePawns(moveid, row,  col);break;
    }

    return true;
}
//車直行
bool Board::canMoveCar(int moveid, int row, int col)
{
    if(CountnumLine(row,col,s[moveid].row,s[moveid].col) == 0)
     {
        return true;
    }
    return false;
}
//隔山打牛炮
bool Board::canMoveGun(int moveid, int row, int col)
{
    //移动
  if(Havestone(row,col) == -1 && CountnumLine(row,col,s[moveid].row,s[moveid].col)==0)
  {
      return true;
  }
  //隔山打牛吃子
  if(Havestone(row,col) != -1 && CountnumLine(row,col,s[moveid].row,s[moveid].col)==1)
  {
       return true;
  }
  return false;
}
//马走日
bool Board::canMoveHorse(int moveid, int row, int col)
{
    //勾股定理 
    int dis = Gougu(moveid, row, col);
    if(dis == 12 && Havestone(s[moveid].row,(col+s[moveid].col)>>1)==-1) //没有拐脚
    {
        return true;
    }
    else if(dis == 21 && Havestone((row+s[moveid].row)>>1,s[moveid].col)==-1)
    {
        return true;
    }
    return false;
}
 //士的移动范围在九宫格内,移动的步长是斜线
bool Board::canMoveMandarins(int moveid, int row, int col)
{

    //黑棋 士
    if(s[moveid].isblack)
    {
        if(row > 2)
            return false;
    }
    //红棋 士
    else
    {
       if(row < 7)
          return false;
    }

    if(col < 3)
        return false;
    if(col >5)
        return false;
    //勾股定理
    int dis = Gougu(moveid, row, col);
    if(dis == 11)
    {
        return true;
    }
    return false;
}
 //相或者象的移动范围楚河汉界的一边不能越界,象飞田
bool Board::canMoveElephant(int moveid, int row, int col)
{
    //黑棋 象
    if(s[moveid].isblack)
    {
        if(row > 4)
            return false;

    }
    //红棋 相
    else
    {
       if(row < 5)
          return false;

    }
    //勾股定理
    int dis = Gougu(moveid, row, col);
    if(dis == 22 && Havestone((row+s[moveid].row)>>1,(col+s[moveid].col)>>1) == -1)
    {
        return true;
    }
    return false;
}
 //将军的移动范围在九宫格内,移动的步长是一个格子
bool Board::canMoveGenerals(int moveid, int row, int col)
{

    //黑棋 将
    if(s[moveid].isblack)
    {
        if(row > 2)
            return false;
    }
    //红棋 帅
    else
    {
       if(row < 7)
          return false;
    }
    if(col < 3)
        return false;
    if(col >5)
        return false;
    //勾股定理
    int dis = Gougu(moveid, row, col);
    if(dis == 1 || dis ==10)
    {
        return true;
    }
    return false;
}
 //小兵的移动是一直向前,移动的步长是一个格子
bool Board::canMovePawns(int moveid, int row, int col)
{

    //黑棋 卒
    if(s[moveid].isblack)
    {
        if(s[moveid].row>row)
            return false;
//        else if(s[moveid].row<4)
//            return false;
    }
    //红棋 兵
    else
    {
       if(s[moveid].row<row)
          return false;
//       else if(s[moveid].row>5)
//           return false;
    }
    //勾股定理
    int dis = Gougu(moveid, row, col);
    if(dis ==10)
    {
        return true;
    }
    else if(dis == 1&&s[moveid].isblack&&s[moveid].row>4)
    {
        return true;
    }
    else if(dis == 1&&!s[moveid].isblack&&s[moveid].row<5)
    {
         return true;
    }

    return false;
}

 //勾股定理计算棋子应该移动范围
int Board::Gougu(int moveid, int row, int col)
{
    int Row = s[moveid].row-row;
    int Col = s[moveid].col-col;
    //勾股定理
    return abs(Row)*10+abs(Col);
}

//判断某行某位置有没有棋子
int Board::Havestone(int row, int col)
{
    for (int i =0;i < 32;i++)
    {

        if((row == s[i].row && col ==s[i].col)&&!s[i].isdead)
        {
           return i;
        }


    }
    return -1;
}

 //统计直线上棋子个数
int Board::CountnumLine(int row, int col, int Row, int Col)
{
    int max,min,count=0;
    if(row != Row && col !=Col)
    {
        return -1;
    }
    if(row == Row)
    {
        if(col < Col)
        {
            max = Col;
            min = col;
        }
        else
        {
            max = col;
            min = Col;
        }
        for (int i = min+1;i < max;i++)
        {
            if(Havestone(row,i)>=0)
            {
                count++;
            }          
        }
    }

    else if (col == Col)
    {
       if(row < Row)
       {
           max = Row;
           min = row;
       }
       else
       {
           max = row;
           min = Row;
       }
       for (int i = min+1;i < max;i++)
       {
           if(Havestone(i,col)>=0)
           {
               count++;
           }
        }
    }
    return count;
}

//点击坐标点
void Board::click(QPoint pt)
{
    int row,col;
    bool isClicked = getRowCol(pt,row,col);
    if(!isClicked)
    {
        return ;
    }
    int id = getStonID(row,col);
  // click(id,row,col);

}

int Board::getStonID(int row, int col)
{
    for(int i=0;i<32;i++)
    {
        if(s[i].row==row && s[i].col == col)
        {
            return i;
        }

        else
            return 0;
    }

}



stone.h

#ifndef STONE_H
#define STONE_H

#include <QString>

class stone
{
public:
    stone();

    enum TYPE{Car,Gun,Horse,Premier,Elephant,Soldier,Mandarins,Arms,Pawns,King,Generals};
    int row;        //横坐标
    int col;        //纵坐标
    int id;         //编号
    bool isdead;      //是否死亡
    bool isblack;     //颜色
    TYPE type;      //种类

    //初始化棋子
    void init(int ID)
    {
       struct
       {
           int row, col;
           stone::TYPE type;
       }

       chess[32]=
       {
       //黑棋
       {0,0,stone::Car},
       {0,1,stone::Horse},
       {0,2,stone::Elephant},
       {0,3,stone::Mandarins},
       {0,4,stone::Generals},
       {0,5,stone::Mandarins},
       {0,6,stone::Elephant},
       {0,7,stone::Horse},
       {0,8,stone::Car},

       {2,1,stone::Gun},
       {2,7,stone::Gun},
       {3,0,stone::Pawns},
       {3,2,stone::Pawns},
       {3,4,stone::Pawns},
       {3,6,stone::Pawns},
       {3,8,stone::Pawns},

       //红棋

       {9,0,stone::Car},
       {9,1,stone::Horse},
       {9,2,stone::Premier},
       {9,3,stone::Soldier},
       {9,4,stone::King},
       {9,5,stone::Soldier},
       {9,6,stone::Premier},
       {9,7,stone::Horse},
       {9,8,stone::Car},

       {7,1,stone::Gun},
       {7,7,stone::Gun},
       {6,0,stone::Arms},
       {6,2,stone::Arms},
       {6,4,stone::Arms},
       {6,6,stone::Arms},
       {6,8,stone::Arms},
       };
        id = ID;
        isdead = false;
        if(ID<16)
        {
            isblack = true;
        }

        else  isblack = false;

        if(ID<16){
          row =  chess[ID].row;
          col =  chess[ID].col;
          type = chess[ID].type;
        }
        else{
          row = chess[ID].row;
          col = chess[ID].col;
          type = chess[ID].type;
        }
    }

    //判断棋子的种类
    QString getclass()
    {
        switch (this->type)
        {
            case Car: return "車";
            case Gun: return "炮";
            case Horse: return "马";
            case Premier: return "相";
            case Elephant: return "象";
            case Soldier: return "仕";
            case Mandarins: return "士";
            case Arms: return "兵";
            case Pawns: return "卒";
            case King: return "帥";
            case Generals: return "将";
        }

        return "ERROR";
    }

};

#endif // STONE_H

 

stone.cpp

#include "stone.h"

stone::stone()
{

}

singlegame.h

#ifndef SINGLEGAME_H
#define SINGLEGAME_H
#include "board.h"

class SingleGame:public Board
{
public:
    //纯虚函数与抽象类,纯虚函数没有函数体,只有函数名,因此不能被调用,徒有其名,而无其实留在派生类中带定义,只有派生类定义后才能使用
    virtual void click(int id, int row, int col);
    //电脑走棋
    void  computerMove();
    void getAllstep();

};

#endif // SINGLEGAME_H

singlegame.cpp

#include "singlegame.h"

void SingleGame::click(int id, int row, int col)
{
//    Board::click(id,row,col);
//    if(this->isTurnRed)
//    {
//        computerMove();
//    }
}
void SingleGame::computerMove()
{
    //1.看看有哪些步骤可以走
    //2.试着走一下
    //3.评估走的结果
    //4.取最好结果作为参考

}

step.h

#ifndef STEP_H
#define STEP_H

#include <QObject>

class Step : public QObject
{
    Q_OBJECT
public:
    explicit Step(QObject *parent = nullptr);

    ~Step();

    int _moveid;
    int _killid;
    int _rowFrom;
    int _colFrom;
    int _rowTo;
    int _colTo;

signals:

public slots:
};

#endif // STEP_H

step.cpp

#include "step.h"

Step::Step(QObject *parent) : QObject(parent)
{

}

Step::~Step()
{

}

mian.cpp

#include "board.h"
#include "singlegame.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    SingleGame w;

    w.show();
    return a.exec();
}

QPainter函数详解

QPainter类在窗口和其他绘制设备上执行低级绘制。

QPainter提供高度优化的功能来完成大多数图形用户界面程序所需的工作。它能画出从简单线条到复杂形状如饼图和弦等一切图形。它还可以绘制对齐的文本和像素图。通常,它绘制一个“自然”坐标系,但它也可以进行视图和世界变换。QPainter可以对继承QPaintDevice类的任何对象进行操作。

QPainter的常见用法是在窗口的绘制事件中:构造和自定义(例如设置笔或画笔)绘制器。然后画。记住在绘制后销毁QPainer对象。例如:

QPainter的核心功能是绘图。但是类还提供了几个功能,允许您自定义QPainter的设置及其渲染质量,以及其他启用剪辑的功能。此外,还可以通过指定绘制者的合成模式来控制不同形状合并在一起的方式。

函数QPainter::isActive()的作用是:指示绘制程序是否处于活动状态。painter由begin()函数和接受QPaintDevice参数的构造函数激活,end()函数和析构函数将停用它

与QPaintDevice和QPaintEngine类一起,QPainter构成了qt绘图系统的基础。QPainter是用于执行绘图操作的类。QPaintDevice表示可以使用QPainter绘制的设备。QPaintEngine提供了一个接口,绘图使用它来绘制不同类型的设备。如果绘图处于活动状态,则device()返回及绘图在其上进行绘图的绘图设备,paintEngine()返回绘图当前正在使用的绘图引擎。有关详细信息,请参见绘图系统。

QPainer支持一个静态函数来执行此操作,setRedirected()。

警告:当paintdevice是一个窗口时,QPainter只能在paintEvent()函数或paintEvent()调用的函数中使用。

设置属性
可以根据自己的喜好自定义多个设置以使QPainer绘制:

font()用于绘制文本的字体。如果painter为isActive(),则可以分别使用fontInfo()和fontMetrics()函数检索有关当前设置的字体及其度量的信息。
brush()定义用于填充形状的颜色或图案。
pen()定义用于绘制线条或边界的颜色或点画。
backgroundMode()定义是否有background(),即它是Qt::OpaqueMode或Qt::TransparentMode。
background()是Qt::OpaqueMode,pen()是点画时,background()才适用。在这种情况下,它描述点画中背景像素的颜色。
brushOrigin()定义平铺画笔的原点,通常是小部件背景的原点。
viewport()、window()、worldTransform()构成了painter的坐标转换系统。有关详细信息,请参见“坐标变换”部分和坐标系文档。
hasClipping()告诉画师是否剪辑。(绘制设备也会被保存)如果painter被截取,它会被保存到clipRegion()。
layoutDirection()定义绘制文本时画家使用的布局方向。
worldMatrixEnabled()指示是否启用世界转换。
viewTransformEnabled()指示是否启用视图转换。

 

  • 10
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 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
发出的红包

打赏作者

开开心累兮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值