初始化棋子,首先,得有棋子,先定义一个棋子类。Stone.h。棋子需要有坐标,也就是行列,序号,是否被吃,颜色等属性。
#ifndef STONE_H
#define STONE_H
class Stone
{
public:
Stone();
~Stone();
enum TYPE {jiang, bing, pao, shi, che, ma, xiang};
int _row;
int _col;
int _id;
bool _dead;
bool _red;
TYPE type;
};
#endif // STONE_H
然后需要在棋盘中声明32个棋子。
Stone _s[32];
定义好棋子后,画在棋盘上。但是画棋子很复杂,需要定义一个函数来画。用drawStone(int id);思考?画棋子,需要画些什么,看以前 的图片知道,棋子是有一个圆圈组成,上面写着字。所以,我们需要的画的就是一个圆,还有一个字。画32个棋子就行。
//绘制棋子
for(int i=0;i<32;i++)
{
drawStone(painter,i);
}
先声明函数void drawStone(QPainter &painter,int id);画棋子画在哪?肯定是画在棋盘上,所以还需要有一个以前定义的painter。这里用的是引用,因为绘制的棋子需要和窗口关联。
void drawStone(QPainter &painter,int id);
现在来写drawStone函数,
函数的第一步就是画圆圈。画圆圈需要知道半径以及圆心坐标。但是,棋盘的坐标和窗口的坐标是不一样的。需要就行转换。这里用一个center函数来将窗口的坐标转化为棋盘坐标。半径就根据前面的画棋盘,半径是整个代码中都需要的属性,就直接加在棋盘的成员变量中。还要声明center函数。
int _r;//棋子半径
//返回棋盘对应的窗口坐标
QPoint center(int row,int col);
然后实现center函数。根据窗口和棋盘坐标关系很容易实现函数。
QPoint Board::center(int row,int col)
{
QPoint ret;
ret.rx()=(col+1)*_r*2;
ret.ry()=(row+1)*_r*2;
return ret;
}
写完,发现center函数的参数比较多,麻烦,所以再写一个函数center函数,也就是函数重载。这样的话,在花圈的时候直接传入id就行了。
QPoint Board::center(int id)
{
return center(_s[id].row,_s[id].col);
}
painter.drawEllipse(center(id),_r,_r);
花完圈后,还需要在上面写字。写字的话需要根据象棋的类型来写,在棋子类中加个函数,根据棋子的类型写字。
QString getText()()
{
switch(this->_type)
{
case CHE:
return "车";
case MA:
return "马";
case PAO:
return "炮";
case BING:
return "兵";
case JIANG:
return "将";
case SHI:
return "士";
case XIANG:
return "相";
}
return "错误";
}
写字也需要面临一个问题,就是写在哪。也就是需要坐标,根据函数drawText()知道,可以指定一个矩形,然后指定一个字符串,以及对齐方式。首先,要有一个矩形,然后就是字符串也就是函数getText()上面的函数,再就是对齐方式。
矩形怎么弄?用QRect()函数,这个函数,需要知道左上角的点的坐标还有就是边长。
QPoint c=center(id);
QRect rect=QRect(c.rx()-_r,c.ry(-_r),_r*2,_r*2);
目前,画好了,运行以下试试,看一下情况。发现,棋子好像没有初始化。也就是在棋盘中只定义了一个数组,但是没有出初始化。
Stone _s[32];
现在需要对32个棋子初始化。用一个init函数,在构造函数中初始化。
void init(int id)
{
struct {
int row, col;
Stone::TYPE type;
} pos[16] = {
{0, 0, Stone::CHE},
{0, 1, Stone::MA},
{0, 2, Stone::XIANG},
{0, 3, Stone::SHI},
{0, 4, Stone::JIANG},
{0, 5, Stone::SHI},
{0, 6, Stone::XIANG},
{0, 7, Stone::MA},
{0, 8, Stone::CHE},
{2, 1, Stone::PAO},
{2, 7, Stone::PAO},
{3, 0, Stone::BING},
{3, 2, Stone::BING},
{3, 4, Stone::BING},
{3, 6, Stone::BING},
{3, 8, Stone::BING},
};
if(id<16)
{
_row=pos[id].row;
_col=pos[id].col;
_type=pos[id].type;
}
else
{
_row=9-pos[id-16].row;
_col=8-pos[id-16].col;
_type=pos[id-16].type;
}
_id=id;
_dead=false;
_red=id<16;
}
运行:
现字棋子初始化,但是不够美观,还有颜色美分。
在绘制的时候注意下一,首先绘制圆形,加入黄色的背景。再就是区别棋子是红的还是黑的。还有就是字体。
painter.setBrush(QBrush(QColor(255,255,0))); //背景颜色
painter.setPen(Qt::black); //画黑色矩形框
if(_s[id]._red)
painter.setPen(Qt::red); //红色棋子,默认的黑色棋子,也就是上面黑色矩形框
painter.setFont(QFont("system", _r, 700)); //字体
今日代码:
Board.cpp
#include "Board.h"
#include<QPainter>
Board::Board(QWidget *parent) : QWidget(parent)
{
for(int i=0;i<32;i++)
{
_s[i].init(i);
}
}
void Board::paintEvent(QPaintEvent*)
{
QPainter painter(this);
int d=40; //棋子直径
_r=d/2;
//十条横线
for(int i=1;i<=10;i++)
{
painter.drawLine(QPoint(d,i*d),QPoint(9*d,i*d));
}
//九条竖线
for(int i=1;i<=9;i++)
{
if(i==1||i==9)
painter.drawLine(QPoint(d*i,d),QPoint(i*d,10*d));
else
{
painter.drawLine(QPoint(d*i,d),QPoint(i*d,5*d));
painter.drawLine(QPoint(d*i,6*d),QPoint(i*d,10*d));
}
}
//九宫格
painter.drawLine(QPoint(d*4,d),QPoint(6*d,3*d));
painter.drawLine(QPoint(d*6,d),QPoint(4*d,3*d));
painter.drawLine(QPoint(d*4,10*d),QPoint(6*d,8*d));
painter.drawLine(QPoint(d*6,10*d),QPoint(4*d,8*d));
//绘制棋子
for(int i=0;i<32;i++)
{
drawStone(painter,i);
}
}
QPoint Board::center(int row,int col)
{
QPoint ret;
ret.rx()=(col+1)*_r*2;
ret.ry()=(row+1)*_r*2;
return ret;
}
QPoint Board::center(int id)
{
return center(_s[id]._row,_s[id]._col);
}
void Board::drawStone(QPainter &painter,int id)
{
QPoint c=center(id);
QRect rect=QRect(c.rx()-_r,c.ry()-_r,_r*2,_r*2);
painter.setBrush(QBrush(QColor(255,255,0))); //背景颜色
painter.setPen(Qt::black); //画黑色矩形框
if(_s[id]._red)
painter.setPen(Qt::red); //红色棋子,默认的黑色棋子,也就是上面黑色矩形框
painter.setFont(QFont("system", _r, 700)); //字体
painter.drawEllipse(center(id),_r,_r);
painter.drawText(rect,_s[id].getText(),QTextOption(Qt::AlignCenter));
}
Board.h
#ifndef BOARD_H
#define BOARD_H
#include <QWidget>
#include"Stone.h"
class Board : public QWidget
{
Q_OBJECT
public:
explicit Board(QWidget *parent = 0);
Stone _s[32];
int _r;//棋子半径
//返回棋盘对应的窗口坐标
QPoint center(int row,int col);
QPoint center(int id);
void drawStone(QPainter &painter,int id);
void paintEvent(QPaintEvent *);
signals:
public slots:
};
#endif // BOARD_H
Stone.h
#ifndef STONE_H
#define STONE_H
#include<QString>
class Stone
{
public:
Stone();
~Stone();
enum TYPE {JIANG,CHE,MA,PAO,SHI,BING,XIANG};
int _row;
int _col;
int _id;
bool _dead;
bool _red;
TYPE _type;
void init(int id)
{
struct {
int row, col;
Stone::TYPE type;
} pos[16] = {
{0, 0, Stone::CHE},
{0, 1, Stone::MA},
{0, 2, Stone::XIANG},
{0, 3, Stone::SHI},
{0, 4, Stone::JIANG},
{0, 5, Stone::SHI},
{0, 6, Stone::XIANG},
{0, 7, Stone::MA},
{0, 8, Stone::CHE},
{2, 1, Stone::PAO},
{2, 7, Stone::PAO},
{3, 0, Stone::BING},
{3, 2, Stone::BING},
{3, 4, Stone::BING},
{3, 6, Stone::BING},
{3, 8, Stone::BING},
};
if(id<16)
{
_row=pos[id].row;
_col=pos[id].col;
_type=pos[id].type;
}
else
{
_row=9-pos[id-16].row;
_col=8-pos[id-16].col;
_type=pos[id-16].type;
}
_id=id;
_dead=false;
_red=id<16;
}
QString getText()
{
switch(this->_type)
{
case CHE:
return "车";
case MA:
return "马";
case PAO:
return "炮";
case BING:
return "兵";
case JIANG:
return "将";
case SHI:
return "士";
case XIANG:
return "相";
}
return "错误";
}
};
#endif // STONE_H