Cocos2d-X开发中国象棋《九》走棋规则
在上一节中实现了走棋,这篇博客将介绍中国象棋中的走棋规则
在写博客前先可能一下象棋的走棋规则:
1)将
将的坐标关系:横坐标相等,纵坐标相减绝对值等于1,或者纵坐标相等,横坐标相减绝对值等于1
将的特殊要求:目标坐标坐落于九宫内
将的例外情况:假设两个老将面对面而中间没有棋子阻拦。老将能够直接飞到对方九宫吃对方老将
2)士
士的坐标关系:纵坐标和横坐标相减的绝对值都是1,
士的特殊要求:目标坐标坐落于九宫内
3)象
象的坐标关系:纵坐标和横坐标相减的绝对值都是2
象的特殊要求:象眼不能有棋子,不能过河
4)车
车的坐标关系:横坐标或者纵坐标相等
车的特殊要求:两个坐标之间不能有棋子存在
5)马
马的坐标关系:横坐标相减等于1且纵坐标相减等于2,或者反过来
马的特殊要求:马腿不能憋着
6)炮
炮的坐标关系:与车同样
炮的特殊要求:假设目标坐标没有棋子,则与车一样,否则要求中间有一个棋子
7)兵
过河前:
兵的坐标关系:纵坐标相差1,并且仅仅能前进
兵的特殊要求:没有
过河后:
兵的坐标关系:纵坐标相差1或者横坐标相差1。不能后退
兵的特殊要求:没有
实现代码:
首先在在SceneGame类中定义一个成员函数canMove(int moveid, int killid, int x, int y)用于实现走棋规则
//走棋规则
bool SceneGame::canMove(int moveid, int killid, int x, int y)
{
//获得选中的棋子
Stone* s = _s[moveid]; //棋子的类型
switch(s->getType())
{
//将的走棋规则
case Stone::JIANG:
{
return canMoveJiang(moveid, killid, x, y);
}
break; //士的走棋规则
case Stone::SHI:
{
return canMoveShi(moveid, x, y);
}
break; //相的走棋规则
case Stone::XIANG:
{
return canMoveXiang(moveid, x, y);
}
break; //车的走棋规则
case Stone::CHE:
{
return canMoveChe(moveid, x, y);
}
break; //马的走棋规则
case Stone::MA:
{
return canMoveMa(moveid, x, y);
}
break; //炮的走棋规则
case Stone::PAO:
{
return canMovePao(moveid, killid, x, y);
}
break; //兵的走棋规则
case Stone::BING:
{
return canMoveBing(moveid, x, y);
}
break; default:
{
break;
}
} return false;
}
然后针对不同的棋子定义成员函数。实现走棋规则
canMoveJiang(int moveid, int killid, int x, int y)实现将的走棋规则
//将的走棋规则
bool SceneGame::canMoveJiang(int moveid, int killid, int x, int y)
{
Stone* skill = _s[killid]; //将的走棋规则:
//1、一次走一格
//2、不能出九宫格 //CCLog("x=%d, y=%d", x, y);
//CCLog("moveid=%d, killid=%d", moveid, killid); //将的对杀
if(skill->getType() == Stone::JIANG)
{
return canMoveChe(moveid, x, y);
} //通过棋子的ID得到棋子
Stone* s = _s[moveid]; //获得将当前的位置
int xo = s->getX();
int yo = s->getY(); //获得将走的格数
//(x,y)表示将走到的位置
int xoff = abs(xo - x);
int yoff = abs(yo - y); int d = xoff*10 + yoff; //走将的时候有两种情况
//xoff=1, yoff=0:将向左或向右
//xoff=0, yoff=1:将向前或向后
if(d != 1 && d != 10)
{
return false;
} //推断将是否出了九宫
//红色的将和黑色的将的x坐标的范围都是3<=x<=5
if(x<3 || x>5)
{
return false;
} //假设玩家的棋子是红棋
if(_redSide == s->getRed())
{
//推断将是否出了九宫
if(y<0 || y>2)
{
return false;
}
}
else//推断黑色的将的范围
{
//推断将是否出了九宫
if(y>9 || y<7)
{
return false;
}
} return true;
}
canMoveShi(int moveid, int x, int y)实现士的走棋规则
//士的走棋规则
bool SceneGame::canMoveShi(int moveid, int x, int y)
{
//士的走棋规则:
//1、一次走一格
//2、不能出九宫格
//3、斜着走 //通过棋子的ID得到棋子
Stone* s = _s[moveid]; //获得相走棋前的位置
int xo = s->getX();
int yo = s->getY(); //获得相走的格数
//(x,y)表示将走到的位置
int xoff = abs(xo - x);
int yoff = abs(yo - y); int d = xoff*10 + yoff; //士每走一步x方向走1格,y方向走1格
//当走的格数大于1格时
//返回false
if(d != 11)
{
return false;
} //推断士是否出了九宫
//红色的士和黑色的士的x坐标的范围都是3<=x<=5
if(x<3 || x>5)
{
return false;
} //假设玩家的棋子是红棋
if(_redSide == s->getRed())
{
//推断士是否出了九宫
if(y<0 || y>2)
{
return false;
}
}
else//推断黑色的士的范围
{
//推断士是否出了九宫
if(y>9 || y<7)
{
return false;
}
} return true;
}
canMoveXiang(int moveid, int x, int y)实现相的走棋规则
//相的走棋规则
bool SceneGame::canMoveXiang(int moveid, int x, int y)
{
//相的走棋规则:
//每走一次x移动2格,y移动2格
//不能过河 //通过棋子的ID得到棋子
Stone* s = _s[moveid]; //获得相走棋前的位置
int xo = s->getX();
int yo = s->getY(); //获得相走的格数
//(x,y)表示将走到的位置
int xoff = abs(xo - x);
int yoff = abs(yo - y); int d = xoff*10 + yoff; //相每一次x方向走2格子,y方向走2格
//当走的格数大于2格时
//返回false
if(d != 22)
{
return false;
} //计算两个坐标的中点坐标
int xm = (xo + x) / 2;
int ym = (yo + y) / 2; //得到(xm,ym)上的棋子
int id = getStone(xm, ym); //当(xm,ym)上有棋子的时候
if(id != -1)
{
//不能走相
return false;
} //限制相不能过河
//假设玩家的棋子是红棋
if(_redSide == s->getRed())
{
//推断相是否过了河
if(y > 4)
{
return false;
}
}
else//推断黑色的相的范围
{
//推断相是否过了河
if(y < 5)
{
return false;
}
} return true;
}
canMoveChe(int moveid, int x, int y)实现车的走棋规则
//车的走棋规则
bool SceneGame::canMoveChe(int moveid, int x, int y)
{
//通过棋子的ID得到棋子
Stone* s = _s[moveid]; //获得车走棋前的位置
int xo = s->getX();
int yo = s->getY(); //当两点之间有棋子的时候车不能走
if(getStoneCount(xo,yo,x,y) != 0)
{
return false;
} return true;
}
canMoveMa(int moveid, int x, int y)实现马的走棋规则
//马的走棋规则
bool SceneGame::canMoveMa(int moveid, int x, int y)
{
//通过棋子的ID得到棋子
Stone* s = _s[moveid]; //获得马走棋前的位置
int xo = s->getX();
int yo = s->getY(); //CCLog("xo=%d", xo);
//CCLog("yo=%d", yo); //获得马走的格数
//(x,y)表示马走到的位置
//马有两种情况:
//第一种情况:马先向前或向后走1步,再向左或向右走2步
//另外一种情况:马先向左或向右走1不,再向前或向后走2步
int xoff = abs(xo-x);
int yoff = abs(yo-y); //CCLog("x=%d", x);
//CCLog("y=%d", y); int d = xoff*10 + yoff; //CCLog("d=%d", d); if(d != 12 && d != 21)
{
return false;
} int xm, ym;//记录绑脚点坐标 if(d == 12)//当马走的是第一种情况
{
xm = xo;//绑脚点的x坐标为走棋前马的x坐标
ym = (yo + y) / 2;//绑脚点的y坐标为走棋前马的y坐标和走棋后马的y坐标的中点坐标
}
else//当马走的是另外一种情况
{
xm = (xo + x) / 2;//绑脚点的x坐标为走棋前马的x坐标和走棋后马的x坐标的中点坐标
ym = yo;;//绑脚点的y坐标为走棋前马的y坐标
} //CCLog("xm=%d", xm);
//CCLog("ym=%d", ym); //当绑脚点有棋子时,不能走
if(getStone(xm, ym) != -1)
{
return false;
} return true;
}
canMovePao(int moveid, int killid, int x, int y)实现炮的走棋规则
//炮的走棋规则
bool SceneGame::canMovePao(int moveid, int killid, int x, int y)
{
//通过棋子的ID得到棋子
Stone* s = _s[moveid]; //获得炮走棋前的位置
int xo = s->getX();
int yo = s->getY(); //当触摸点上有一个棋子
//并且两点之间仅仅有一个棋子的时候
//炮吃掉触摸点上的棋子
if(killid != -1 && this->getStoneCount(xo,yo,x,y) == 1)
{
return true;
} if(killid == -1 && this->getStoneCount(xo, yo, x, y) == 0)
{
return true;
} return false;
}
canMoveBing(int moveid, int x, int y)实现兵的走棋规则
//兵的走棋规则
bool SceneGame::canMoveBing(int moveid, int x, int y)
{
//兵的走棋规则:
//1、一次走一格
//2、前进一格后不能后退
//3、过河后才干够左右移动 //通过棋子的ID得到棋子
Stone* s = _s[moveid]; //获得将当前的位置
int xo = s->getX();
int yo = s->getY(); //获得兵走的格数
//(x,y)表示将走到的位置
int xoff = abs(xo - x);
int yoff = abs(yo - y); int d = xoff*10 + yoff; //走将的时候有两种情况
//xoff=1, yoff=0:将向左或向右
//xoff=0, yoff=1:将向前或向后
if(d != 1 && d != 10)
{
return false;
} //假设玩家的棋子是红棋
if(_redSide == s->getRed())
{
//限制红色的兵不能后退
if(y < yo)
{
return false;
} //红色的兵没有过河不能左右移动
if(yo <= 4 && y == yo)
{
return false;
}
}
else//推断黑色的兵
{
//限制黑色的兵不能后退
if(y > yo)
{
return false;
} //黑色的兵没有过河不能左右移动
if(yo >= 5 && y == yo)
{
return false;
}
} return true;
}
getStoneCount(int xo, int yo, int x, int y)推断两个棋子之间棋子的个数,用于车和炮以及将的对杀
///计算(xo,yo)和(x,y)之间的棋子数
//假设棋子数为-1,表示(xo,yo)和(x,y)不在一条直线上
int SceneGame::getStoneCount(int xo, int yo, int x, int y)
{
int ret = 0;//记录两点之间的棋子的个数 //(xo,yo)和(x,y)不在同一条直线上
if(xo != x && yo != y)
{
return -1;
} //(xo,yo)和(x,y)在同一点上
if(xo == x && yo == y)
{
return -1;
} //两点在同一条竖线上
if(xo == x)
{
//min为两个点中y坐标最小的点的y坐标
int min = yo < y ? yo : y; //max为两个点中y坐标最大的点的y坐标
int max = yo > y ? yo : y; //查找同一条竖线上两点之间的棋子数
for(int yy=min+1; yy<max; yy++)
{
//当两点之间有棋子的时候
if(getStone(x,yy) != -1)
{
++ret;//棋子数加1
}
}
}
else//两点在同一条横线上yo == y
{
//min为两个点中x坐标最小的点的x坐标
int min = xo < x ? xo : x; //max为两个点中x坐标最大的点的x坐标
int max = xo > x ? xo : x; //查找同一条竖线上两点之间的棋子数
for(int xx=min+1; xx<max; xx++)
{
//当两点之间有棋子的时候
if(getStone(xx,y) != -1)
{
++ret;//棋子数加1
}
}
} //返回两点之间的棋子数
return ret;
}
參考文章:http://blog.csdn.net/itcastcpp/article/details/17673393
Cocos2d-X开发中国象棋《九》走棋规则的更多相关文章
- Cocos2d-X开发中国象棋《二》project文件概述
我在上一篇博客中介绍了象棋的功能.在接下来的博客中将向大家介绍使用Cocos2d-X怎样一步一步开发中国象棋 开发工具: Cocos2d-X2.2.3 VS2012 项目的文件夹: Classes:存 ...
- Cocos2d-X开发中国象棋《八》走棋
在上一节中实现了新局,至此中国象棋的准备工作差点儿相同都完毕了,在接下来的博客中将介绍玩家的走棋和一些游戏属性的设置,今天先介绍走棋和走棋规则 老规则,先看走棋的效果图,然后依据效果图一步一步分析游戏 ...
- Cocos2d-X开发中国象棋《三》開始场景的实现
在前面两节(第一节.第二节)中介绍了中国象棋的功能和project文件.在这篇博客中将介绍中国象棋的開始场景的实现 在写代码前先理清一下实现開始场景的思路: 1.打开游戏后进入開始场景,场景上显示一个 ...
- Python开发中国象棋实战(附源码)
Pygame 做的中国象棋,一直以来喜欢下象棋,写了 python 就拿来做一个试试,水平有限,电脑走法水平低,需要在下次版本中更新电脑走法,希望源码能帮助大家更好的学习 python.总共分 ...
- cocos2d-x游戏开发系列教程-中国象棋06-游戏规则
前情回顾 上一个博文我们提到象棋运动的函数dealWithChess,但是只是说该函数完成了棋子的选择和移动功能 其实在这个函数里,在移动棋子之前,是要对棋子的移动是否合法进行判断的,我们一起来看看如 ...
- Cocos2d-X开发中国象棋《四》设计游戏场景
设计完開始界面后就要设计游戏界面了 为了理清设计思路先看一张游戏界面效果图 游戏界面设计思路: 1.在窗体上放一张桌子 2.在桌子上放一个棋盘 3.在棋盘右边加入新局button,暂不实现详细的功能 ...
- 【原创】使用HTML5+canvas+JavaScript开发的原生中国象棋游戏及源码分享
目前已经实现的功能: V1.0 : 实现棋子的布局,画布及游戏场景的初始化V2.0 : 实现棋子的颜色改变V3.0 :实现所有象棋的走棋规则V4.0 : 实现所有棋子的吃子功能 GItHub源码下载地 ...
- 【JavaScript游戏开发】使用HTML5 canvas开发的网页版中国象棋项目
//V1.0 : 实现棋子的布局,画布及游戏场景的初始化 //V2.0 : 实现棋子的颜色改变 //V3.0 :实现所有象棋的走棋规则 //V4.0 : 实现所有棋子的吃子功能 完整的项目源码已经开源 ...
- 中国象棋游戏Chess(3) - 实现走棋规则
棋盘的绘制和走棋参看博文:中国象棋游戏Chess(1) - 棋盘绘制以及棋子的绘制,中国象棋游戏Chess(2) - 走棋 现在重新整理之前写的代码,并且对于每个棋子的走棋规则都进行了限制,不像之前那 ...
随机推荐
- weight initilzation
1. pytorch提供接口 method 1 torch.nn.init里面有很多初始化分布 import torch.nn.init as init self.conv1 = nn.Conv2d ...
- hosts文件中同一个域名两个IP的解析顺序
比如: 192.168.0.2 www.easonjim.com 192.168.0.3 www.easonjim.com 那么解析顺序就只有最开头的IP,即:192.168.0.2 经过测试,相同域 ...
- Eclipse的调试功能(转)(让Eclipse也能有VS的即时窗口那样的即时代码调试功能)
前言:可以很明确的说明,eclipse也有像vs那样的即时窗口来运行即时代码的功能. 调试的界面如下: 如果要像vs那样的即时调试功能,需要做一些设置,就是Expressions功能. 开通步骤:Wi ...
- Jenkins配置git进行构建失败:Error cloning remote repo 'origin'的解决思路
说明:这个没有实际的解决方法,只提供一个思路去解决. 操作系统:windows 背景:在配置的节点之后,由于是windows的系统,运行git克隆地址,使用的是SSH协议地址.出现如下的错误: Err ...
- 矩阵快速幂计算hdu1575
矩阵快速幂计算和整数快速幂计算相同.在计算A^7时,7的二进制为111,从而A^7=A^(1+2+4)=A*A^2*A^4.而A^2可以由A*A得到,A^4可以由A^2*A^2得到.计算两个n阶方阵的 ...
- mac 下mysql常用命令
是那种单独安装的mysql 启动: /usr/local/mysql/bin/mysql -u root -p
- HDU 5360 Hiking(优先队列)
Hiking Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total S ...
- window脚本命令学习(转)
批处理文件是无格式的文本文件,它包含一条或多条命令.它的文件扩展名为 .bat 或 .cmd.在命令提示下键入批处理文件的名称,或者双击该批处理文件,系统就会调用Cmd.exe按照该文件中各个命令出现 ...
- 2016.7.14 如何在浏览器中查看jsp文件
参考资料: http://jingyan.baidu.com/article/ed15cb1b10f1241be36981ab.html 1.复制jsp文件地址 2.写在浏览器里 E:/lyh/tas ...
- haifeng
[root@localhost 桌面]# yum list|grep wubi ibus-table-chinese-wubi-haifeng.noarch -.el7 base ibus-table ...