Cocos2d-X开发中国象棋《九》走棋规则

Cocos2d-X开发中国象棋《九》走棋规则,第1张

概述在上一节中实现了走棋,这篇博客将介绍中国象棋中的走棋规则 在写博客前先可能一下象棋的走棋规则: 1)将 将的坐标关系:横坐标相等,纵坐标相减绝对值等于1,或者纵坐标相等,横坐标相减绝对值等于1 将的特殊要求:目标坐标坐落于九宫内 将的例外情况:如果两个老将面对面而中间没有棋子阻拦,老将可以直接飞到对方九宫吃对方老将 2)士 士的坐标关系:纵坐标和横坐标相减的绝对值都是1, 士的特殊要求:目标坐标坐

在上一节中实现了走棋,这篇博客将介绍中国象棋中的走棋规则


在写博客前先可能一下象棋的走棋规则:

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 y){    //获得选中的棋子    Stone* s = _s[moveID];    //棋子的类型    switch(s->getType())    {        //将的走棋规则        case Stone::JIANG:        {            return canMoveJiang(moveID,killID,x,y);        }        break;        //士的走棋规则        case Stone::SHI:        {            return canMoveShi(moveID,y);        }        break;        //相的走棋规则        case Stone::XIANG:        {            return canMoveXiang(moveID,y);        }        break;               //车的走棋规则        case Stone::CHE:        {            return canMoveChe(moveID,y);        }        break;               //马的走棋规则        case Stone::MA:        {            return canMoveMa(moveID,y);        }        break;            //炮的走棋规则        case Stone::PAO:        {            return canMovePao(moveID,y);        }        break;             //兵的走棋规则        case Stone::BING:        {            return canMoveBing(moveID,y);        }        break;        default:        {            break;        }    }    return false;}


然后针对不同的棋子定义成员函数,实现走棋规则

canMoveJiang(int moveID,int y)实现将的走棋规则

//将的走棋规则bool SceneGame::canMoveJiang(int moveID,int y){   Stone* skill = _s[killID];      //将的走棋规则:    //1、一次走一格    //2、不能出九宫格     //cclog("x=%d,y=%d",y);     //cclog("moveID=%d,killID=%d",moveID,killID);    //将的对杀    if(skill->getType() == Stone::JIANG)    {        return canMoveChe(moveID,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 y)实现士的走棋规则

//士的走棋规则bool SceneGame::canMoveShi(int moveID,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 y)实现相的走棋规则

//相的走棋规则bool SceneGame::canMoveXiang(int moveID,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 y)实现车的走棋规则

//车的走棋规则bool SceneGame::canMoveChe(int moveID,int y){    //通过棋子的ID得到棋子    Stone* s = _s[moveID];    //获得车走棋前的位置    int xo = s->getX();    int yo = s->getY();    //当两点之间有棋子的时候车不能走    if(getStoneCount(xo,yo,y) != 0)    {        return false;    }    return true;}

canMoveMa(int moveID,int y)实现马的走棋规则

//马的走棋规则bool SceneGame::canMoveMa(int moveID,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 y)实现炮的走棋规则

//炮的走棋规则bool SceneGame::canMovePao(int moveID,int y){    //通过棋子的ID得到棋子    Stone* s = _s[moveID];    //获得炮走棋前的位置    int xo = s->getX();    int yo = s->getY();    //当触摸点上有一个棋子    //而且两点之间只有一个棋子的时候    //炮吃掉触摸点上的棋子    if(killID != -1 && this->getStoneCount(xo,y) == 1)    {        return true;    }    if(killID == -1 && this->getStoneCount(xo,y) == 0)     {        return true;    }    return false;}


canMoveBing(int moveID,int y)实现兵的走棋规则

//兵的走棋规则bool SceneGame::canMoveBing(int moveID,int y){     //兵的走棋规则:    //1、一次走一格    //2、前进一格后不能后退    //3、过河后才可以左右移动    //通过棋子的ID得到棋子    Stone* s = _s[moveID];    //获得将当前的位置    int xo = s->getX();    int yo = s->getY();    //获得兵走的格数    //(x,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 y)判断两个棋子之间棋子的个数,用于车和炮以及将的对杀

///计算(xo,yo)和(x,y)之间的棋子数//如果棋子数为-1,表示(xo,y)不在一条直线上int SceneGame::getStoneCount(int xo,int y){    int ret = 0;//记录两点之间的棋子的个数    //(xo,y)不在同一条直线上    if(xo != x && yo != y)    {        return -1;    }    //(xo,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://www.jb51.cc/article/p-rnaiduep-q.html

 总结

以上是内存溢出为你收集整理的Cocos2d-X开发中国象棋《九》走棋规则全部内容,希望文章能够帮你解决Cocos2d-X开发中国象棋《九》走棋规则所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/web/1014571.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存