значения защищенных массивов в суперклассе неожиданно меняются - PullRequest
2 голосов
/ 14 июля 2020

Я кодирую шахматный движок, используя битовые доски, и я хочу создать расширяемый 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 - это два поля stati c final, используемых в качестве индексов массива, чтобы избежать несогласованности. white = 0, black = 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;
    }
}

Проблема в том, что, вызывая любой метод получения суперкласса, я получаю двоичный код 1000 для белого (индекс 0) и 10000000000000000000000000000000000000000000000000000000 для черного (индекс 1) вместо назначенных значений

Мы будем очень признательны за объяснение этого странного поведения, заранее спасибо.

1 Ответ

3 голосов
/ 14 июля 2020

Проблема в конструкторе 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();
}
...