Qt中国象棋之棋子规则

中国象棋中各棋子的规则

一、车(車)

此棋子是中国象棋中棋力最强的棋子,每行一步棋可以上、下直线行走(进、退);左、右横走(中间不隔棋子),且行棋步数不限,但不可以走对角线。不过车吃棋的话没有其他条件限制,只要在他的行走范围之内就可以被他吃掉。

车能否移动到目标位置(坐标)

bool ChessBoard::canMoveCHE(int moveid, int targetid, int row, int col)
{
    if(getPiecesCountAtLine(moveid, row, col) == 0) {
        return true;
    }
    return false;
}

计算棋子到目标位置(坐标)之间有多少个棋子,用于车和炮的移动

/*计算被选中棋子到目标坐标之间棋子个数*/
int ChessBoard::getPiecesCountAtLine(int id, int row, int col)
{
    int row1 = pieces[id].row;
    int col1 = pieces[id].col;
    /*判断两个坐标是否在一起*/
    if(row1 == row && col1 == col) {
        return -1;
    }
    /*判断两个棋盘上的坐标是否在同一条直线上(同一行或者同一列)*/
    if(row1 != row && col1 != col) {
        return -1;
    }
    /*记录两坐标中间棋子个数*/
    int count = 0;
    /*两个坐标在同一行*/
    if(row1 == row) {
        int min = col1 < col ? col1 : col;
        int max = col1 < col ? col : col1;
        for(int i=min+1; i<max; i++) {
            if(getPiecesID(row,i) != -1) {
                count++;
            }
        }
    } else {
        /*两个坐标在同一列*/
        int min = row1 < row ? row1 : row;
        int max = row1 < row ? row : row1;
        for(int i=min+1; i<max; i++) {
            if(getPiecesID(i,col) != -1) {
                count++;
            }
        }
    }
    return count;
}

二、马(馬)

使用中国的日字来形容马的行走方式比较贴切,“马走日”这是我们通俗的叫法,理解起来也就是马必须走两个小格子的对角线。但如果有其他棋子挡住的话(蹩马腿),则不能行走。马的行走范围无限制,可以穿过河界,而且可进可退。

bool ChessBoard::canMoveMA(int moveid, int targetid, int row, int col)
{
    /*马走日*/
    int r = qAbs(pieces[moveid].row-row)*10 + qAbs(pieces[moveid].col-col);
    if(r != 12 && r != 21) {
        return false;
    }
    /*有没蹩马腿*/
    if(r == 12) {
        if(getPiecesID(pieces[moveid].row, (pieces[moveid].col+col)/2) != -1) {
            return false;
        }
    } else {
        if(getPiecesID((pieces[moveid].row+row)/2, pieces[moveid].col) != -1) {
            return false;
        }
    }
    return true;
}

三、象(相)

此棋子不能越过河界走入对方的领地,“象走田‘这是我们另一个通俗的叫法,理解起也就是象必须走四个小格子的对角线,但如果四个小格子的中间有其他的棋子,象则不能走。象的主要任务是防守,所以不能越过河界,只能在己方这边行走。

bool ChessBoard::canMoveXIANG(int moveid, int targetid, int row, int col)
{
    /*象走田*/
    int r = qAbs(pieces[moveid].row-row)*10 + qAbs(pieces[moveid].col-col);
    if(r != 22) {
        return false;
    }
    /*象眼是否有棋子*/
    int rEye = (pieces[moveid].row+row)/2;
    int cEye = (pieces[moveid].col+col)/2;
    if(getPiecesID(rEye, cEye) != -1) {
        return false;
    }
    /*象不能过河*/
    if(pieces[moveid].isRed) {
        if(row>4) {
            return false;
        }
    } else {
        if(row<5) {
            return false;
        }
    }
    return true;
}

四、士(仕)

士(仕)是帅(将)的贴身保卫,只能在九宫(画了斜线的四个小格子)之内行走,而且它每步只能走一个小格子的对角线,不能平移,可进可退。

bool ChessBoard::canMoveSHI(int moveid, int targetid, int row, int col)
{
    /*士只能在九宫内走斜线*/
    int r = qAbs(pieces[moveid].row-row)*10 + qAbs(pieces[moveid].col-col);
    if(r != 11) {
        return false;
    }
    if(col<3 || col>5) {
        return false;
    }
    if(pieces[moveid].isRed) {
        if(row>2) {
            return false;
        }
    } else {
        if(row<7) {
            return false;
        }
    }
    return true;
}

五、将(帅)

虽然名称不同,但它们这都是对垒双方的最高统帅,对垒的目的就是通过运用各自的棋子,想方设法将对方的首领将死,方为己方胜利。这两位棋子的最高统帅,只能在九宫内行走,不得走出九宫外。行走的步法为:左、右横走,上、下竖走都行,但每次只能行走一格。将和帅不准在同一直线上直接对面(中间无棋子),如一方已先占据位置,则另一方必须回避,否则就算输了。

bool ChessBoard::canMoveJIANG(int moveid, int targetid, int row, int col)
{
    /*双方将碰面可以直接吃对方的将*/
    if(targetid != -1 && pieces[targetid].type == JIANG) {
        if(getPiecesCountAtLine(moveid,row,col) == 0) {
            return true;
        }
    }
    /*将在九宫内一步一步走*/
    int r = qAbs(pieces[moveid].row-row)*10 + qAbs(pieces[moveid].col-col);
    if(r != 1 && r != 10) {
        return false;
    }
    if(col<3 || col>5) {
        return false;
    }
    if(pieces[moveid].isRed) {
        if(row>2) {
            return false;
        }
    } else {
        if(row<7) {
            return false;
        }
    }
    return true;
}

六、炮(砲)

此棋的行棋规则和车(車)类似,横平、竖直,只要前方没有棋子的地方都能行走。但是,它的吃棋规则很特别,必须跳过一个棋子(无论是己方的还是对方的)去吃掉对方的一个棋子。

bool ChessBoard::canMovePAO(int moveid, int targetid, int row, int col)
{
    /*不吃棋子*/
    if(targetid == -1 && getPiecesCountAtLine(moveid, row, col) == 0) {
        return true;
    }
    /*吃棋子*/
    if(targetid != -1 && getPiecesCountAtLine(moveid, row, col) == 1) {
        return true;
    }
    return false;
}

七、兵(卒)

兵、卒是永远不能后退的。在没过河界之前,兵、卒只能一步一步往前走;过了河界之后,兵、卒可以选择往前、左以及右行走。记住,兵卒每次只能行走一步。

bool ChessBoard::canMoveBING(int moveid, int targetid, int row, int col)
{
    /*兵只能一步一步走,只能前进不能倒退(列),过河之前不能左右走(行)*/
    int r = qAbs(pieces[moveid].row-row)*10 + qAbs(pieces[moveid].col - col);
    if(r != 1 && r != 10) {
        return false;
    }
    if(pieces[moveid].isRed) {
        if(pieces[moveid].row > row) {
            return false;
        }
        /*没过河不能左右走*/
        if(pieces[moveid].row < 5 && pieces[moveid].row == row) {
            return false;
        }
    } else {
        if(pieces[moveid].row < row) {
            return false;
        }
        if(pieces[moveid].row > 4 && pieces[moveid].row == row) {
            return false;
        }
    }
    return true;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值