超类上受保护数组的值意外更改
values of protected arrays on superclass get changed unexpectedly
我正在使用位板对国际象棋引擎进行编码,我想为位板初始化程序制作一个可扩展的 API,这将允许我在将来添加更多变体,例如 chess960。
所以我想出了下面的抽象超类,它为所有类型的初始化程序提供了一个统一的接口:它分配用于存储位板的数组,然后调用抽象方法 init() 必须由任何子类,应该在其中创建位板并将其分配给相应的数组
public abstract class BitboardInitializer {
private static final int NUMBER_OF_PLAYERS = 2;
protected long[] pawnsPositions, knightsPositions, bishopsPositions,
rooksPositions, queenPositions, kingPositions;
protected BitboardInitializer() {
pawnsPositions = knightsPositions = bishopsPositions =
rooksPositions = queenPositions = kingPositions = new long[NUMBER_OF_PLAYERS];
init();
}
protected abstract void init();
public long getPawnsPositionsAs(int side) {
return pawnsPositions[side];
}
public long getKnightsPositionsAs(int side) {
return knightsPositions[side];
}
public long getBishopsPositionsAs(int side) {
return bishopsPositions[side];
}
public long getRooksPositionsAs(int side) {
return rooksPositions[side];
}
public long getQueenPositionsAs(int side) {
return queenPositions[side];
}
public long getKingPositionsAs(int side) {
return kingPositions[side];
}
}
一种初始化标准国际象棋位板的实现,它只是分配硬编码的位板值,因为标准国际象棋总是以一种方式开始。 Side.White 和 Side.Black 是两个用作数组索引以避免不一致的静态最终字段。白色 = 0,黑色 = 1:
public final class StandardChessInitializer extends BitboardInitializer {
public StandardChessInitializer() {
super();
}
protected void init() {
pawnsPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_11111111_00000000L;
pawnsPositions[Side.BLACK] =
0b00000000_11111111_00000000_00000000_00000000_00000000_00000000_00000000L;
knightsPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_01000010L;
knightsPositions[Side.BLACK] =
0b01000010_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
bishopsPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00100100L;
bishopsPositions[Side.BLACK] =
0b00100100_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
rooksPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_10000001L;
rooksPositions[Side.BLACK] =
0b10000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
queenPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00010000L;
queenPositions[Side.BLACK] =
0b00010000_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
kingPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00001000L;
kingPositions[Side.BLACK] =
0b00001000_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
}
}
问题是,通过调用任何超类的 getter 方法,我得到白色(索引 0)的二进制 1000 和 1000000000000000000000000000000000000000000000000000000000000 用于黑色(索引 1)而不是分配的值
在此先感谢对这种奇怪行为的解释。
问题出在 BitboardInitializer
构造函数中,您在其中初始化所有数组引用以指向 相同的数组:
protected BitboardInitializer() {
pawnsPositions = knightsPositions = bishopsPositions =
rooksPositions = queenPositions = kingPositions = new long[NUMBER_OF_PLAYERS];
init();
}
应该是:
protected BitboardInitializer() {
pawnsPositions = new long[NUMBER_OF_PLAYERS];
knightsPositions = new long[NUMBER_OF_PLAYERS];
bishopsPositions = new long[NUMBER_OF_PLAYERS];
rooksPositions = new long[NUMBER_OF_PLAYERS];
queenPositions = new long[NUMBER_OF_PLAYERS];
kingPositions = new long[NUMBER_OF_PLAYERS];
init();
}
我正在使用位板对国际象棋引擎进行编码,我想为位板初始化程序制作一个可扩展的 API,这将允许我在将来添加更多变体,例如 chess960。
所以我想出了下面的抽象超类,它为所有类型的初始化程序提供了一个统一的接口:它分配用于存储位板的数组,然后调用抽象方法 init() 必须由任何子类,应该在其中创建位板并将其分配给相应的数组
public abstract class BitboardInitializer {
private static final int NUMBER_OF_PLAYERS = 2;
protected long[] pawnsPositions, knightsPositions, bishopsPositions,
rooksPositions, queenPositions, kingPositions;
protected BitboardInitializer() {
pawnsPositions = knightsPositions = bishopsPositions =
rooksPositions = queenPositions = kingPositions = new long[NUMBER_OF_PLAYERS];
init();
}
protected abstract void init();
public long getPawnsPositionsAs(int side) {
return pawnsPositions[side];
}
public long getKnightsPositionsAs(int side) {
return knightsPositions[side];
}
public long getBishopsPositionsAs(int side) {
return bishopsPositions[side];
}
public long getRooksPositionsAs(int side) {
return rooksPositions[side];
}
public long getQueenPositionsAs(int side) {
return queenPositions[side];
}
public long getKingPositionsAs(int side) {
return kingPositions[side];
}
}
一种初始化标准国际象棋位板的实现,它只是分配硬编码的位板值,因为标准国际象棋总是以一种方式开始。 Side.White 和 Side.Black 是两个用作数组索引以避免不一致的静态最终字段。白色 = 0,黑色 = 1:
public final class StandardChessInitializer extends BitboardInitializer {
public StandardChessInitializer() {
super();
}
protected void init() {
pawnsPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_11111111_00000000L;
pawnsPositions[Side.BLACK] =
0b00000000_11111111_00000000_00000000_00000000_00000000_00000000_00000000L;
knightsPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_01000010L;
knightsPositions[Side.BLACK] =
0b01000010_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
bishopsPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00100100L;
bishopsPositions[Side.BLACK] =
0b00100100_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
rooksPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_10000001L;
rooksPositions[Side.BLACK] =
0b10000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
queenPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00010000L;
queenPositions[Side.BLACK] =
0b00010000_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
kingPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00001000L;
kingPositions[Side.BLACK] =
0b00001000_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
}
}
问题是,通过调用任何超类的 getter 方法,我得到白色(索引 0)的二进制 1000 和 1000000000000000000000000000000000000000000000000000000000000 用于黑色(索引 1)而不是分配的值
在此先感谢对这种奇怪行为的解释。
问题出在 BitboardInitializer
构造函数中,您在其中初始化所有数组引用以指向 相同的数组:
protected BitboardInitializer() {
pawnsPositions = knightsPositions = bishopsPositions =
rooksPositions = queenPositions = kingPositions = new long[NUMBER_OF_PLAYERS];
init();
}
应该是:
protected BitboardInitializer() {
pawnsPositions = new long[NUMBER_OF_PLAYERS];
knightsPositions = new long[NUMBER_OF_PLAYERS];
bishopsPositions = new long[NUMBER_OF_PLAYERS];
rooksPositions = new long[NUMBER_OF_PLAYERS];
queenPositions = new long[NUMBER_OF_PLAYERS];
kingPositions = new long[NUMBER_OF_PLAYERS];
init();
}