之前的文章请看:中国象棋游戏Chess(1) - 棋盘绘制以及棋子的绘制
现在实现走棋的功能。
首先需要获取点击到的棋子,用QWidget中的函数
mouseReleaseEvent
实现函数:
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]._dead == false) {
break;
}
}
if (i < 32) {
clickid = i;
}
if (_selectid == -1) { // 如果点中的棋子之前未被选中
if (clickid != -1) {
_selectid = clickid;
update();
}
}
else {
_s[_selectid]._row = row;
_s[_selectid]._col = col;
if (clickid != -1) {
_s[clickid]._dead = true;
}
_selectid = -1;
update();
}
}
这里涉及到点击位置的有效性,写了一个函数,根据点击得到的位置判断是否属于所在矩形四个顶点中的某个圆内。
// 判断点击位置是否在某个顶点的圆内
// 返回值为bool类型是为了处理点击在棋盘外的情况
bool Board::getRowCol(QPoint pt, int &row, int &col)
{
row = pt.y() / (2 * _r) - 1;
col = pt.x() / (2 * _r) - 1;
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;
}
row += 1;
c = center(row, col);
dx = c.x() - pt.x();
dy = c.y() - pt.y();
dist = dx * dx + dy * dy; // 和鼠标所处矩形左下顶点的距离
if (dist < _r * _r) {
return true;
}
row -= 1;
col += 1;
c = center(row, col);
dx = c.x() - pt.x();
dy = c.y() - pt.y();
dist = dx * dx + dy * dy; // 和鼠标所处矩形右上顶点的距离
if (dist < _r * _r) {
return true;
}
row += 1;
c = center(row, col);
dx = c.x() - pt.x();
dy = c.y() - pt.y();
dist = dx * dx + dy * dy; // 和鼠标所处矩形右下顶点的距离
if (dist < _r * _r) {
return true;
}
return false;
}
注意更改drawStone函数中的绘制棋子部分。
if (id == _selectid) {
painter.setBrush(QBrush(Qt::gray));
}
else {
painter.setBrush(QBrush(QColor(255, 228, 181))); // 将棋子底色设置为鹿皮色
}
如果是被选中的,把底色设置成灰色。
最终就实现了棋子的选中和走棋,效果为:
此时走棋可以随意走,可以随意吃,还没规则的限制,下一篇中再实现。
完整代码:Github