C++ QT开发人机象棋(棋子走法)

目录

 

1:选择下棋的棋子:

2:尝试着下棋:

3:移动棋子:

4.规则

1.将:

2.士:

3.象:

4.马:

5.车:

6.炮:

7.兵:


 

1:选择下棋的棋子:

    void Board::trySelectStone(int id)

    {

        if(id == -1)

            return;

        if(!canSelect(id)) return;

        _selectid = id;

        update();

    }

2:尝试着下棋:

 

分为两种情况,第一种情况是点击的是自己的棋子,这个时候转移下棋的棋子,第二种情况是点击的不是自己的棋子,这个时候就要判断能不能移动过去,_selectid是当前选定的棋子的id,killid代表的是用鼠标第二次点击的要去的位置的id,刚才说的瞻前顾后就是在这里进行判断的,killid如果不等于-1,代表的是当前的位置有棋子,如果两个棋子的颜色相同的话,就转移操作的棋子,

这里的canMove()函数里面包含了我们在下棋的时候的各种规则,关于这个规则我将会在下面进行展示。当我们判断完能够下棋之后就是下棋了,我们下棋的时候只需要把原来的位置的棋子给删去,然后把这个棋子移动到我们的目标位置就行了。

   

 void Board::tryMoveStone(int killid, int row, int col)

    {

        if(killid != -1 && sameColor(killid, _selectid))

        {

            trySelectStone(killid);

            return;

        }

        bool ret = canMove(_selectid, row, col ,killid);

        if(ret)

        {

            moveStone(_selectid, row, col ,killid);

            _selectid = -1;

            update();

        }

}

 

3:移动棋子:

 

移动棋子的时候要瞻前顾后,既要把这个棋子给走过去,同时又要把原来位置上面的棋子给删去,这样才能保证棋盘的正确性。

首先是删除原来位置的棋子:使用killStone()函数

void Board::killStone(int id)

{

    if(id==-1) return;

    _s[id]._dead = true;

}

然后就是把这个棋子给移动过去,使用的是moveStone(int moveid,int row,int col)函数

void Board::moveStone(int moveid, int row, int col)

{

    _s[moveid]._row = row;

    _s[moveid]._col = col;

_bRedTurn = !_bRedTurn;

}

这里出现了_bRedTurn = !_bRedTurn;它的作用是改变下棋方

 

4.规则

 

1.将:

将只能在九宫格内上下左右移动,那么我们只需要判断边界就行了。

bool Board::canMove1(int moveid,int row,int col,int killid)

{

    //将

       if(_s[moveid]._id==5&&_s[killid]._id==21||_s[moveid]._id==21&&_s[killid]._id==5)

            {

         if(getCountAtLine(_s[moveid]._row,_s[moveid]._col,_s[killid]._row,_s[killid]._col)==0)

               {

                  //现在代表的是打照面了,当前位置的棋子直接胜利。

                  return true;

               }

            }



    //对于棋盘来说,上红下黑的话进行类型的判断

    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 rr=_s[moveid]._col-col;

    int rc=_s[moveid]._row-row;

    //移动一个单位的棋子,那么横竖肯定有一个是0,并且另一个应该是1或者-1

    //那么使用绝对值进行操作的时候,可以简化判断的过程.



    int number=abs(rc)*10+abs(rr);

    if(number==1||number==10)

       return true;



   return false;

}

2.士:

士只能斜着在九宫格里面移动,跟前面的将的判断方法类似,我们只需要计算士的位置和鼠标点击位置的横坐标的绝对值乘以10加上纵坐标的绝对值,并判断这个数是不是11就好了。

bool Board::canMove2(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 rr=_s[moveid]._col-col;

    int rc=_s[moveid]._row-row;

    //移动一个单位的棋子,那么横竖肯定有一个是0,并且另一个应该是1或者-1

    //那么使用绝对值进行操作的时候,可以简化判断的过程.



    int number=abs(rr)*10+abs(rc);

    if(number==11)

       return true;



   return false;

}

3.象:

象只能在以河界为分割线的自己的这一边走田,并且在移动的时候田的中间如果有棋子的话象是过不去的。

 

这里的判断同上,不过这里的值应该是22,相较于前面的来说,这一步多了一个判断是否过河的条件。

bool Board::canMove3(int moveid,int row,int col,int killid)

{

    //象

    getrowcol(row1,col1,moveid);

    int number=relation(row1,col1,row,col);

    if(number!=22) return false;



    int halfrow=(row1+row)/2;

    int halfcol=(col1+col)/2;

    if(getStone(halfrow,halfcol)!=-1) return false;

    //判断不能过河

    if(isBottomSide(moveid))//代表颜色方向

    {

        if(row>5) return false;

    }

    else

    {

        if(row<4) return false;

    }

    return true;

}

4.马:

在象棋里面,马走日,按照前面的方法,我们计算的值应该是21或者12,不过对于马来说,我们还要考虑蹩马腿的情况。

 

也就是说当前的马的位置是(x1,y1),鼠标点击的位置是(x2,y2)(已经满足计算的值为12或者21了),那么我们只需分别在值为12和21的基础上判断是否蹩马腿就行了,首先分析12这种情况,12代表的是向右边走两格,这个时候蹩马腿位置的横坐标与马的横坐标相同,纵坐标为两个棋子的纵坐标的和的一半,就下来分析21这种情况,21代表的是向右边走一格棋子,这个时候蹩马腿位置的纵坐标与马的横坐标相同,横坐标为两个棋子的纵坐标的和的一半。

bool Board::canMove4(int moveid,int row,int col,int killid)

{

    //马

    getrowcol(row1,col1,moveid);

    int ret=relation(row1,col1,row,col);

    if(ret!=12&&ret!=21) return false;

    if(ret==12)

    {

        if(getStone(row1,(col1+col)/2)!=-1)

        {

            return false;

        }

    }

    else if(ret==21)

    {

        if(getStone((row1+row)/2,col1)!=-1)

        {

            return false;

        }

    }

    return true;

}

5.车:

车只能走直线,并且不能跳子,那么我们只需要计算原本的车的位置和鼠标点击的位置之间的棋子的个数就行了。

bool Board::canMove5(int moveid,int row,int col,int killid)

{

    //车



    //判断是否在同一条直线上

    getrowcol(row1,col1,moveid);

    int ret=0;

    ret=getCountAtLine(row1,col1,row,col);

    if(ret==0)

    return true;

    else

       return false;

}

6.炮:

炮走棋分为两种情况

1:跳棋,这个时候需要吃棋。

2:不跳棋,这个时候只能移动,不能吃棋,这个时候就可以当车来处理。

bool Board::canMove6(int moveid,int row,int col,int killid)

{

    //炮

    getrowcol(row1,col1,moveid);

    int ret=getCountAtLine(row1, col1, row, col);

    if(killid!=-1)

    {

       if(ret==1)

       {

           if(getStone(row1,col1)!=-1)

              return true;

           else

               false;

       }

    }

    else

    {

        if(ret==0)

            return true;

    }

    return false;

}

7.兵:

在玩象棋的时候,我们都知道兵在没有过河界的时候只能往前走,而当兵过了河界之后不但能够往后走,而且还能左右走,现在我们需要判断的是兵是否过河和兵是否向前走或者左右走,并且一次只能走一格。

bool Board::canMove7(int moveid,int row,int col,int killid)

{

    //兵

    getrowcol(row1,col1,moveid);

    int number=relation(row1,col1,row,col);

    if(number!=1&&number!=10) return false;

    if(!isBottomSide(moveid))

    {

        if(row1<row) return false;

        if(row1>=5&&row1==row) return false;

    }

    else

    {

        if(row1>row) return false;

        if(row1<=4&&row1==row) return false;

    }

    return true;

}

 

  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值