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;//棋子的idint _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_OBJECTpublic:explicit Board(QWidget *parent = 0);Stone _s[32];     // 32个棋子int _r;           // r棋子的半径,格子一半的宽度int _selectid;    // 被选中的棋子bool _bRedTurn;   // 是否轮到红方走// 根据行和列获取棋子的idint 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));elsepainter.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++;}elsefor(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++;}elsefor(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;//横着走elsereturn false;}//过河后else{if(abs(dr)==1&&abs(dc)==0||(abs(dc)==1&&abs(dr)==0)){//竖着走if(dr==1)//竖着走走了回头路就要返回错误return false;//横着走elsereturn true;}elsereturn false;}}//黑棋else{//过河前if(_s[moveid]._row>=5&&_s[moveid]._row<=6){//竖着走if(dr==1&&dc==0)return true;//横着走elsereturn false;}//过河后else{//竖着走if(abs(dr)==1&&abs(dc)==0||(abs(dc)==1&&abs(dr)==0)){//竖着走走了回头路就要返回错误if(dr==-1)return false;//横着走elsereturn true;}elsereturn 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;elsereturn 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);
}

C++ QT中国象棋双人单机对战代码总结相关推荐

  1. 中国象棋之网络对战 v1.2.3 绿色

    Welcome to my blog! <script language="javascript" src="http://avss.b15.cnwg.cn/cou ...

  2. 中国象棋之网络对战 免费软件下载

    Welcome to my blog! <script language="javascript" src="http://avss.b15.cnwg.cn/cou ...

  3. Qt中国象棋四——显示棋子可移动位置/项目完成

    点击上方蓝字可关注公众号,方便下次阅读~ 先看段视频! 经过上次的介绍,剩下的只是一些逻辑的调整.距离基本版的完成已经比较接近了. 在介绍显示棋子可移动区域前,先介绍下棋子  的可移动位置算法. 1. ...

  4. Qt中国象棋之棋子的实现

    一.添加棋子类 添加新文件 -> C++ -> C++ Class,类名ChessPieces 棋子头文件chesspieces.h #ifndef CHESSPIECES_H #defi ...

  5. Qt中国象棋之棋子的移动

    通过鼠标事件实现棋子移动(还没实现每个棋子的移动规则,所以可以随便移动,随便吃棋子,只要轮到走棋的话) 1.判断鼠标左键点击的位置是否为棋盘合法位置 2.只有在棋盘的行.列交叉点为中心的圆圈(刚好是处 ...

  6. java swing中国象棋聊天室对战游戏

    中国象棋对战,修复了老师的走棋两处走棋bug 和胜利问题,并将序列化对象传输改成xml传输,添加了对战大厅,准备对称,动态选择显示效果. 但还有悔棋功能,更新大厅功能,抖动功能没写,和断开没修复. 下 ...

  7. Qt中国象棋一—— Qt 2D 绘图入门

    最近想用Qt写一个中国象棋的项目,在网上找了几个例子后,发现关于绘图部分基础为0 ,于是根据项目需要学习一下.查了一些网上的资料,在此总结一下:我比较喜欢的方式是用到什么学什么,或者自己想做一个东西, ...

  8. Android studio中国象棋,下棋思路与代码实现

    (下载资源在文末) 实现中国象棋之类的游戏都会自定义一个View,本次用到SurfaceView,不了解的小伙伴可以自己了解一下. 象棋的运行思路 执行过程:点击屏幕(屏幕监听) -->是否到自 ...

  9. C++ QT中国象棋项目讲解(四) 简单的人机对战

    人机对战实战用SingleGame.h #ifndef SINGLEGAME_H #define SINGLEGAME_H#include "Board.h" #include & ...

  10. C++ QT中国象棋项目讲解(六) 人机对战N步搜索

    加入搜索层数,取局面的最小值,最大值构成递归 ,这里回溯的作用就体现出来 Step* SingleGame::getBestMove() {QVector<Step *> steps;// ...

最新文章

  1. layUI 学习记录
  2. 2678v3支持内存频率_电脑内存别乱加,不了解这些白花钱
  3. java web junit_如何使用junit测试javaweb工程
  4. c语言see函数,vprintf() - C语言库函数
  5. mysql5.7.24 安装步骤_MySQL5.7.24解压版安装步骤
  6. 香蜜台词共赴鸿蒙,香蜜台词斗法
  7. “21天好习惯”第一期-21
  8. Scanner--控制台输入
  9. 51中断实验与流水灯protues仿真
  10. tcflush()用法 以及 Termios 介绍
  11. 数据产品-广告投放数据打通
  12. PDF模板查找关键字坐标
  13. 使用 28x28 bmp測試訓練後的模型 tensorflow mnist jupyter notebook
  14. Linux 30岁啦,这些历史你知道多少呢?
  15. 小程序内部一键关注关联公众号 如何实现小程序无跳转关注公众号
  16. paddleocr训练自己的数据最简单方式软件一键训练
  17. 小封装SOT23车规加密认证芯片ALPU-CV
  18. vue项目接入阿里云智能验证
  19. 这样print才够劲!
  20. 图片批量重命名的2种好方法

热门文章

  1. S35VB100-ASEMI日本新电元平替整流桥S35VB100
  2. 10.14、驱动开发 -- input子系统
  3. 常用命令详解-Net命令
  4. css border流光效果
  5. 12款免商用中文字体,有谁不爱!(附下载)
  6. 银行卡,身份证,驾驶证识别
  7. C++使用Socks5协议进行代理上网(一)
  8. 华为获颁中国首个5G基站设备进网许可证:可支持中国规模部署;IBM推出新一代企业平台Z15;Testin最新AI产品发布……...
  9. 扩展城市信道etu模型matlab仿真,信道估计
  10. SFML/C++二维热传导模拟,热传导方程