Stone.h
#ifndef STONE_H
#define STONE_H
#include <QString>
class Stone
{
public:
Stone();
//定义棋子的所有类型
enum TYPE{JIANG,CHE,PAO,MA,BING,SHI,XIANG};
//棋子所处的行
int _row;
//棋子所处的列
int _col;
//棋子的id
int _id;
//棋子是否已死
bool _dead;
//棋子是否为红子
bool _red;
//棋子类型
TYPE _type;
//初始化棋子
void init(int id);
//获取棋子的类型名
QString getText();
};
#endif // STONE_H
Stone.cpp
#include "Stone.h"
Stone::Stone()
{
}
void Stone::init(int id)
{
// 总共有16种棋子
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},
};
_id = id;
_dead = false;
_red = id<16;
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;
}
}
QString Stone::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 "Wrong";
}
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]; // 32个棋子
int _r; // r棋子的半径,格子一半的宽度
int _selectid; // 被选中的棋子
bool _bRedTurn; // 是否轮到红方走
// 根据行和列获取棋子的id
int getStoneId(int row, int col);
//计算即将行走的棋子与某一坐标之间有几颗棋子
int num_of_Stone(int moveid,int row,int col);
//输入行列坐标判断该坐标上有没有棋子
bool beStone(int row,int col);
// 判断棋子的颜色是否相同
bool sameColor(int moveid,int killid);
// 由点击坐标转化为棋子的行列编号
bool getRowCol(QPoint pt, int &row, int &col);
bool canSelect(int id);
//最基本的能不能走的判断判断
bool canMove(int moveid,int row,int col,int killid);
//判断将能不能走
bool canMoveJIANG(int moveid,int row,int col,int killid);
//判断士能不能走
bool canMoveSHI(int moveid,int row,int col,int killid);
//判断象能不能走
bool canMoveXIANG(int moveid,int row,int col,int killid);
//判断车能不能走
bool canMoveCHE(int moveid,int row,int col,int killid);
//判断马能不能走
bool canMoveMA(int moveid,int row,int col,int killid);
//判断炮能不能走
bool canMovePAO(int moveid,int row,int col,int killid);
//判断兵能不能走
bool canMoveBING(int moveid,int row,int col,int killid);
virtual void paintEvent(QPaintEvent *);
//与显示到窗口中有关的函数
void drawStone(QPainter& painter,int id);
//输入行列坐标 返回像素坐标
QPoint center(int row,int col);
//输入棋子的id 返回像素坐标
QPoint center(int id);
void trySelectStone(int id);
void tryMoveStone(int id,int row,int col);
void click(QPoint pt);
void click(int id, int row, int col);
void moveStone(int _selectid, int killid, int row, int col);
void mouseReleaseEvent(QMouseEvent *);
//void click(QPoint pt);
~Board();
};
#endif // BOARD_H
Board.cpp
#include "Board.h"
#include <QPainter>
#include <QMouseEvent>
Board::Board(QWidget *parent)
: QWidget(parent)
{
for(int i=0;i<32;i++)
{
_s[i].init(i);
}
_selectid = -1;
_bRedTurn = true;
}
Board::~Board()
{
}
void Board::paintEvent(QPaintEvent *)
{
QPainter painter(this);
int d=40;
// 画10条横线
_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(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));
}
}
// 九宫格
painter.drawLine(QPoint(4*d,1*d),QPoint(6*d,3*d));
painter.drawLine(QPoint(6*d,1*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));
// 绘制32个棋子
for(int i=0;i<32;i++)
{
drawStone(painter,i);
}
}
QPoint Board::center(int row, int col)
{
return QPoint((col+1)*_r*2,(row+1)*_r*2);
}
QPoint Board::center(int id)
{
return center(_s[id]._row, _s[id]._col);
}
void Board::drawStone(QPainter & painter, int id)
{
if(_s[id]._dead)
return;
QPoint c=center(id);
QRect rect = QRect(c.x()-_r,c.y()-_r,_r*2,_r*2);
if(id == _selectid)
painter.setBrush(QBrush(Qt::gray));
else
painter.setBrush(QBrush(Qt::yellow));
painter.setPen(Qt::black);
painter.drawEllipse(c,_r,_r);
if(_s[id]._red)
painter.setPen(Qt::red);
painter.setFont(QFont("system",_r,700));
painter.drawText(rect,_s[id].getText(),QTextOption(Qt::AlignCenter));
}
/*确定某个行列位置上是否有棋子*/
bool Board::beStone(int row,int col)
{
for(int i=0;i<32;i++)
if(_s[i]._row==row&&_s[i]._col==col&&!_s[i]._dead)
return true;
return false;
}
//计算即将行走的棋子与某一坐标之间有几颗棋子 默认返回值为-1
int Board::num_of_Stone(int moveid,int row,int col)
{
int i;
int sum=0;
if(_s[moveid]._row==row)
{
if(col-_s[moveid]._col>0)
for(i=_s[moveid]._col+1;i<col;i++)
{
if(beStone(_s[moveid]._row,i)==true)
sum++;
}
else
for(i=_s[moveid]._col-1;i>col;i--)
{
if(beStone(_s[moveid]._row,i)==true)
sum++;
}
return sum;
}
else if(_s[moveid]._col==col)
{
if(row-_s[moveid]._row>0)
for(i=_s[moveid]._row+1;i<row;i++)
{
if(beStone(i,_s[moveid]._col)==true)
sum++;
}
else
for(i=_s[moveid]._row-1;i>row;i--)
{
if(beStone(i,_s[moveid]._col)==true)
sum++;
}
return sum;
}
//两个棋子不在一条直线上
return -1;
}
bool Board::sameColor(int moveid, int killid)
{
return _s[moveid]._red == _s[killid]._red;
}
// 总的逻辑判断函数
// 总的逻辑判断函数
bool Board::canMove(int moveid, int killid, int row, int col)
{
if(killid==-1||!sameColor(moveid,killid))
{
switch(_s[moveid]._type)
{
case Stone::JIANG:
return canMoveJIANG(moveid,row,col,killid);
break;
case Stone::SHI:
return canMoveSHI(moveid,row,col,killid);
break;
case Stone::XIANG:
return canMoveXIANG(moveid,row,col,killid);
break;
case Stone::CHE:
return canMoveCHE(moveid,row,col,killid);
break;
case Stone::MA:
return canMoveMA(moveid,row,col,killid);
break;
case Stone::PAO:
return canMovePAO(moveid,row,col,killid);
break;
case Stone::BING:
return canMoveBING(moveid,row,col,killid);
break;
default: break;
}
}
//move的棋子和kill的棋子是相同颜色的
if(sameColor(moveid,killid))
{
/*换选择*/
_selectid=killid;
update();
return false;
}
return true;
}
bool Board::canMoveSHI(int moveid,int row,int col,int killid)
{
if(_s[moveid]._red)
{
//判断红方士的纵向行走是否超出米字格范围
if(row>2) return false;
}
else
{
//判断黑方士的纵向行走是否超出米字格范围
if(row<7) return false;
}
//判断红黑双方方士的横向行走是否超出米字格范围
if(col<3) return false;
if(col>5) return false;
//判断是否为沿着对角线斜着行走
int dr=_s[moveid]._row-row;
int dc=_s[moveid]._col-col;
if(abs(dr)==1&&abs(dc)==1)
return true;
return false;
}
bool Board::canMoveBING(int moveid,int row,int col,int killid)
{
/*兵的走棋规则*/
int dr=_s[moveid]._row-row;
int dc=_s[moveid]._col-col;
//红棋
if(_s[moveid]._red)
{
//过河前
if(_s[moveid]._row>=3&&_s[moveid]._row<=4)
{
//竖着走
if(dr==-1&&dc==0)
return true;
//横着走
else
return false;
}
//过河后
else
{
if(abs(dr)==1&&abs(dc)==0||(abs(dc)==1&&abs(dr)==0))
{
//竖着走
if(dr==1)
//竖着走走了回头路就要返回错误
return false;
//横着走
else
return true;
}
else
return false;
}
}
//黑棋
else
{
//过河前
if(_s[moveid]._row>=5&&_s[moveid]._row<=6)
{
//竖着走
if(dr==1&&dc==0)
return true;
//横着走
else
return false;
}
//过河后
else
{
//竖着走
if(abs(dr)==1&&abs(dc)==0||(abs(dc)==1&&abs(dr)==0))
{
//竖着走走了回头路就要返回错误
if(dr==-1)
return false;
//横着走
else
return true;
}
else
return false;
}
}
return true;
}
bool Board::canMoveXIANG(int moveid,int row,int col,int killid)
{
//不能过河
if(_s[moveid]._red)
{
if(row>4) return false;
}
else
{
if(row<5) return false;
}
//走田字格
int dr=_s[moveid]._row-row;
int dc=_s[moveid]._col-col;
int medium_r=(_s[moveid]._row+row)/2;
int medium_c=(_s[moveid]._col+col)/2;
if(abs(dr)==2&&abs(dc)==2)
//别象眼检验
if(!beStone(medium_r,medium_c))
return true;
return false;
}
bool Board::canMoveMA(int moveid,int row,int col,int killid)
{
int dr=_s[moveid]._row-row;
int dc=_s[moveid]._col-col;
int medium_r=(_s[moveid]._row+row)/2;
int medium_c=(_s[moveid]._col+col)/2;
if(abs(dr)==1&&abs(dc)==2||(abs(dr)==2&&abs(dc)==1))
{
if(abs(dr)==2)
{
//别马腿检验
if(beStone(medium_r,_s[moveid]._col)==false)
return true;
}
else
{
//别马腿检验
if(beStone(_s[moveid]._row,medium_c)==false)
return true;
}
}
return false;
}
bool Board::canMoveJIANG(int moveid, int row, int col, int killid)
{
if(_s[moveid]._red)
{
if(row > 2)
return false;
}
else
{
if(row < 7)
return false;
}
if(col < 3)
return false;
if(col > 5)
return false;
int dr = _s[moveid]._row - row;
int dc = _s[moveid]._col - col;
int d = abs(dr)*10 + abs(dc);
if(d==1||d==10)
return true;
return false;
}
bool Board::canMovePAO(int moveid,int row,int col,int killid)
{
int ret = num_of_Stone(moveid,row,col);
if(killid!=-1 && ret == 1)
return true;
else if(killid==-1 && ret ==0)
return true;
else
return false;
}
bool Board::canMoveCHE(int moveid,int row,int col,int killid)
{
int ret = num_of_Stone(moveid,row,col);
return !ret;
}
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;
}
int Board::getStoneId(int row, int col)
{
for(int i=0;i<32;i++){
if(_s[i]._row == row && _s[i]._col == col)
return i;
}
return -1;
}
void Board::click(int id, int row, int col)
{
if(this->_selectid == -1) // 如果没有选择到棋子,选择棋子
trySelectStone(id);
else // 选择到棋子,移动棋子
tryMoveStone(id,row,col);
}
void Board::click(QPoint pt)
{
int row, col;
bool bClicked = getRowCol(pt, row, col);
if(!bClicked) // 点击地方不合理
return;
int id = getStoneId(row,col);
click(id,row,col);
}
void Board::trySelectStone(int id)
{
if(_bRedTurn == _s[id]._red){
_selectid = id;
update();
}
}
// 尝试走棋
void Board::tryMoveStone(int killid, int row, int col)
{
// 如果尝试吃颜色相同的棋子,那么重新选择棋子
if(killid!=-1 && sameColor(killid, _selectid)){
trySelectStone(killid);
return;
}
// 如果可以移动棋子,那么移动棋子
if(canMove(_selectid, killid, row, col)){
moveStone(_selectid, killid, row, col);
_selectid = -1;
update();
}
}
void Board::moveStone(int _selectid, int killid, int row, int col)
{
_s[_selectid]._row = row;
_s[_selectid]._col = col;
if(killid!=-1)
{
_s[killid]._dead = true;
}
_selectid = -1;
_bRedTurn = !_bRedTurn; // 对方回合
}
void Board::mouseReleaseEvent(QMouseEvent *ev)
{
QPoint pt = ev->pos();
click(pt);
}