通过鼠标事件实现棋子移动(还没实现每个棋子的移动规则,所以可以随便移动,随便吃棋子,只要轮到走棋的话)
1、判断鼠标左键点击的位置是否为棋盘合法位置
2、只有在棋盘的行、列交叉点为中心的圆圈(刚好是处于圆形棋子范围内)内才合法
3、如果已经选中了棋子,点击的位置也合法则考虑移动棋子
4、如果没有选中棋子,点击的位置也合法则考虑选择棋子
chessboard.h头文件
#ifndef CHESSBOARD_H
#define CHESSBOARD_H
#include <QWidget>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QPainter>
#include <QPoint>
#include <QRect>
#include <QPen>
#include "chesspieces.h"
class ChessBoard : public QWidget
{
Q_OBJECT
public:
QPoint origin; /*棋盘原点坐标*/
int sideLen; /*棋盘格子边长*/
int selectID; /*被选中的棋子*/
bool redGo; /*是否轮到红方走*/
ChessPieces pieces[32]; /*32颗棋子*/
explicit ChessBoard(QWidget *parent = nullptr); /*构造函数*/
void paintEvent(QPaintEvent *); /*重绘事件,绘制棋盘、棋子等*/
void drawRightAngle(QPainter &pt, QPoint c); /*绘制棋子炮的停靠点(绘制几个直角)*/
void drawPieces(QPainter &pt, int id); /*绘制棋子*/
void mouseReleaseEvent(QMouseEvent *); /*鼠标事件,选中棋子,移动棋子等*/
bool onChessBoard(QPoint c, int &row, int &col); /*判断点击的位置是否合法(是否在棋盘坐标的棋子范围内),同时计算出对应的棋盘行列坐标*/
int getPiecesID(int row, int col); /*获取棋盘行列位置上的棋子*/
void toSelectPieces(int id); /*选择棋子*/
void toMovePieces(int targetid, int row, int col); /*将选中的棋子移动到目标位置*/
bool canSelect(int id); /*棋子是否能被选中*/
bool isSameColor(int id1, int id2); /*判断两个棋子是否为同一方(颜色相同)*/
QPoint center(int row, int col); /*将棋盘行、列坐标转换成像素坐标*/
bool canMove(int moveid, int targetid, int row, int col); /*判断选中的棋子能否移动到目标位置*/
signals:
public slots:
};
#endif // CHESSBOARD_H
chessboard.cpp实现文件
#include "chessboard.h"
ChessBoard::ChessBoard(QWidget *parent) : QWidget(parent)
{
setWindowTitle(tr("中国象棋"));
origin = QPoint(60,60); /*棋盘原点坐标*/
sideLen = 60; /*棋盘格子边长*/
selectID = -1;
redGo = true;
resize(origin.x()*3+sideLen*8, origin.y()*2+sideLen*9);
/*初始化32颗棋子*/
for(int i=0; i<32; i++) {
pieces[i].init(i);
}
}
/*重绘事件*/
void ChessBoard::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QPen pen;
pen.setWidth(3);
painter.setPen(pen);
/*绘制棋盘外廊框*/
painter.drawRect(QRect(origin.x()-5,origin.y()-5, sideLen*8+10, sideLen*9+10));
/*绘制棋盘外围*/
pen.setWidth(1);
painter.setPen(pen);
painter.drawRect(QRect(origin, center(9,8)));
/*绘制剩下的8横7竖*/
for(int i=1; i<=8; i++) {
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(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));
/*绘制楚河、汉界*/
painter.setPen(Qt::gray);
painter.setFont(QFont("system", 24, sideLen/2));
painter.drawText(QRect(center(4,1), center(5,3)), "楚河", QTextOption(Qt::AlignCenter));
painter.drawText(QRect(center(4,5), center(5,7)), "汉界", QTextOption(Qt::AlignCenter));
/*绘制直角(棋子炮的停靠点)*/
drawRightAngle(painter, center(2,1));
drawRightAngle(painter, center(2,7));
drawRightAngle(painter, center(7,1));
drawRightAngle(painter, center(7,7));
/*绘制32颗棋子到棋盘*/
for(int i=0; i<32; i++) {
drawPieces(painter, i);
}
}
/*绘制棋子炮的停靠点(绘制几个直角)*/
void ChessBoard::drawRightAngle(QPainter &pt, QPoint c)
{
int x = c.x();
int y = c.y();
int r = sideLen/10;
pt.drawLine(x-2*r, y-r, x-r, y-r);
pt.drawLine(x-2*r, y+r, x-r, y+r);
pt.drawLine(x+r, y-r, x+2*r, y-r);
pt.drawLine(x+r, y+r, x+2*r, y+r);
pt.drawLine(x-r, y-2*r, x-r, y-r);
pt.drawLine(x-r, y+r, x-r, y+2*r);
pt.drawLine(x+r, y-2*r, x+r, y-r);
pt.drawLine(x+r, y+r, x+r, y+2*r);
}
/*绘制棋子到棋盘*/
void ChessBoard::drawPieces(QPainter &pt, int id)
{
/*假如棋子已死,就不绘制*/
if(pieces[id].isDead) {
return;
}
int r = sideLen/2; /*棋子半径*/
/*获取棋子中心点的像素坐标,根据中心点坐标绘制棋子*/
QPoint c = center(pieces[id].row, pieces[id].col);
/*根据棋子中心点的像素坐标,计算出棋子上面的文字所在的矩形*/
QRect rect = QRect(c.x()-r, c.y()-r, sideLen, sideLen);
/*红方棋子设置文字为红色*/
if(pieces[id].isRed) {
pt.setPen(Qt::red);
} else {
pt.setPen(Qt::black);
}
/*设置棋子背景颜色为黄色,被鼠标选中的设为绿色*/
if(selectID == id) {
pt.setBrush(QBrush(Qt::green));
} else {
pt.setBrush(QBrush(Qt::yellow));
}
/*绘制棋子为圆形*/
pt.drawEllipse(c, r, r);
/*绘制棋子文字*/
pt.drawText(rect, pieces[id].name(),QTextOption(Qt::AlignCenter));
}
/*鼠标事件,选中棋子,移动棋子等*/
void ChessBoard::mouseReleaseEvent(QMouseEvent *ev)
{
/*判断是否为鼠标左键*/
if(ev->button() != Qt::LeftButton) {
return;
}
/*判断点击的位置是否合法(是否在棋盘坐标的棋子范围内),同时计算出对应的棋盘行列坐标*/
int row, col;
if(!onChessBoard(ev->pos(), row, col)) {
return;
}
/*获取当前坐标上的棋子*/
int id = getPiecesID(row, col);
if(selectID == -1) {
/*选择棋子*/
toSelectPieces(id);
} else {
/*移动棋子*/
toMovePieces(id, row, col);
}
}
/*将选中的棋子移动到目标位置*/
void ChessBoard::toMovePieces(int targetid, int row, int col)
{
/*如果目标棋子和被选中的棋子为同一方则重写选中目标棋子*/
if(targetid != -1 && isSameColor(selectID, targetid)) {
toSelectPieces(targetid);
return;
}
/*判断选中的棋子能否移动到目标位置*/
if(!canMove(selectID, targetid, row, col)) {
return;
}
if(targetid != -1) {
pieces[targetid].isDead = true;
}
pieces[selectID].row = row;
pieces[selectID].col = col;
/*棋子移动后切换到另一方走棋*/
selectID = -1;
redGo = !redGo;
update();
}
/*判断两个棋子是否为同一方(颜色相同)*/
bool ChessBoard::isSameColor(int id1, int id2)
{
if(id1 == -1 || id2 == -1) {
return false;
}
return pieces[id1].isRed == pieces[id2].isRed;
}
/*选择棋子*/
void ChessBoard::toSelectPieces(int id)
{
/*判断棋子是否存在*/
if(id == -1) {
return;
}
/*判断棋子是否能够被选中*/
if(!canSelect(id)) {
return;
}
selectID = id;
update();
}
/*棋子是否能被选中*/
bool ChessBoard::canSelect(int id)
{
return redGo == pieces[id].isRed;
}
/*获取棋盘行列位置上的棋子*/
int ChessBoard::getPiecesID(int row, int col)
{
for(int i=0; i<32; i++) {
if(!pieces[i].isDead && pieces[i].row==row && pieces[i].col==col) {
return i;
}
}
return -1;
}
/*判断点击的位置是否合法(是否在棋盘坐标的棋子范围内),同时计算出对应的棋盘行列坐标*/
bool ChessBoard::onChessBoard(QPoint c, int &row, int &col)
{
int r = sideLen/2;
int x = c.x() - origin.x();
int y = c.y() - origin.y();
row = y/sideLen;
col = x/sideLen;
if(y%sideLen > r) {
row++;
}
if(x%sideLen > r) {
col++;
}
int dx = center(row,col).x()-c.x();
int dy = center(row,col).y()-c.y();
if(dx*dx + dy*dy < r*r) {
return true;
}
return false;
}
/*将棋盘行、列坐标转换成像素坐标*/
QPoint ChessBoard::center(int row, int col)
{
return QPoint(origin.x()+sideLen*col, origin.y()+sideLen*row);
}
/*判断选中的棋子能否移动到目标位置*/
bool ChessBoard::canMove(int moveid, int targetid, int row, int col)
{
return true;
}
效果图
转载:https://blog.csdn.net/u010037542/article/details/101036404
查看评论