java游戏实战chess-3.Piece类之knight

本文介绍了如何在棋盘游戏中实现骑士的合法移动算法。具体包括创建Piece抽象类,定义Knight类继承Piece,并实现calculateLegalMoves方法来计算骑士的合法走法。在计算过程中,考虑了棋子的移动规则、边界检查以及棋盘上的其他棋子占用情况。同时,将判断棋子位置是否有效的功能重构到BoardUtils类中,提高了代码的复用性和可读性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.Piece类

Piece代表棋子类,每一枚棋子都有对应的位置坐标和对应的阵营(Alliance)(黑子或者白子)。
我们需要限制棋子的移动位置,限制因素有很多,比如它所属阵营,它的本身属性,移动的位置处是否有其他子占用等等。所以我们需要定义棋子的合法移动抽象方法(calculateLegalMoves)来计算合法移动。
棋子所对应的英文解释

public class abstract Piece{
	protected final int piecePosition;
	protected final Alliance pieceAlliance; //导入枚举类型Alliance
	Piece(final int piecePosition, final ALLiance pieceAlliance) {
		this.pieceAlliance = pieceAlliance;
		this.piecePosition = piecePosition;
	}
	public Alliance getPieceAlliance(){
		return this.pieceAlliance;
	}
	public abstract List<Move> calculateLegalMoves(final Board board);
}
public enum Alliance {
	WHITE,
	BLACK;
}

二.Knight类

Knight是骑士,即为棋子马🐎。它的走法规则如图所示:
图片来自维基百科
例如这个棋盘,骑士的位置在棋盘的位置坐标是d4。它的合法位置分别是c6,e6,b5,f5,b3,c2,e2,f3,一共八个坐标。我们的算法是将棋盘映射到格子编号,第一行从左往右数分别是0,1,2,3,4,5,6,7,对应的骑士位置即为35,其中合法位置f5即为29。但是我们还需要考虑两种情况:第一种是合法位置被敌方占据从而变成不合法位置,第二种合法位置超出棋盘范围(例如骑士在b8,它的合法位置只有一个为d7。考虑到整个棋盘的对称性,我们把当前骑士的位置编号记为0,从右向左编号依次增大。所有的合法位置编号即为:-17,-15,-10,-6,6,10,15,17。
然后循环遍历所有偏移位置,候选目的地坐标等于当前位置加上偏移量。循环过程中需要加入判断,除去那些不在棋盘内的候选目的地坐标,还需判断候选目的地坐标受否被其他棋子占用。
最后我们需要考虑边缘情况,

public class Knight extends Piece {
	private final static int[] CANDIDATE_MOVE_COORDINATES = {-17,-15,-10,-6,6,10,15,17}//候选的合法位置编号列表(编号为相对于当前位置的偏移量)
	Knight(final int piecePosition, final Alliance pieceAlliance){
		super(piecePosition,pieceAlliance);
	}
	@Override
	public List<Move>calculateLegalMoves(Board board){
		int candidateDestinationCoorainate; //候选目的地坐标
		final List<Move> legalMoves = new ArratList<>();
		for(final int currentCandidate : CANDIDATE_MOVE_COORDINATES) { //for循环依次筛选列表中的位置是否真正合法
			candidateDestinationCoorainate = this.piecePosition + currentCandidate; //目标位置是当前位置加上偏移量
			//如果是有效的位置
			if(isValidTileCoordinate(candidateDestination)){
				final Tile candidateDestinationTile = board.getTile(candidateDestinationCoordinate);//目标位置和所选的位置一致
				if(!candidateDestinationTile.isTileOccupied()){//所选的位置没有被棋子占领
					legalMoves.add(new Move());//Move类,后续会提到
				}
				//如果选中的位置被占领
				else{
					final Piece pieceAtDestination = candidateDestinationTile.getPiece();
					final Alliance pieceAlliance = pieceAtDestination.getPieceAlliance();
					if(this.pieceAlliance != pieceAlliance){//判断是否为敌方占领该位置
						legalMoves.add(new Move());
					}
				}
			}
		}
		return ImmutableList.copyOf(legalMoves);
	}

将判断是否超出棋盘范围重构到BoardUtils类中:

public class BoardUtils{
	public static final boolean[] FIRST_COLUMN = null;
	//抛出运行时异常,防止被实例化
	private BoardUtils(){
		throw new 
	private boolean isValidTileCoordinate(int coordinate){ //是否超出棋盘
		return coordinate >=0 && coordinate < 64;
	}
}

判断骑士的合法位置这种算法其实可以用到所有棋子上,只需要按照游戏的规则将不同编号的格子放到列表中。需要充分考虑边界合法问题以及是否被其他棋子占领,若敌方棋子占领需要考虑是否进行攻击吃掉对方棋子自己独自占领目标位置。
由于代码量比较多,只是放了部分关键代码,后期还会不断完善修正。

原视频出处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值