C # / Unity - нужна помощь в отладке моей шахматной программы - проблема при создании экземпляра класса в другом экземпляре того же класса - PullRequest
0 голосов
/ 14 ноября 2018

Я создаю шахматную программу. Я решил сделать так, чтобы при выборе фигуры отображались все возможные юридические ходы. Чтобы это сработало, у меня должен быть механизм для прогнозирования результатов ходов (потому что вы не можете сделать законный ход, который, например, контролирует вашего короля). Это также будет полезно, когда я начну работать с компьютерными противниками, так как ИИ должен будет уметь видеть несколько ходов заранее, чтобы принимать разумные решения.

С этой целью я сделал так, чтобы в начале каждого хода рассчитывались все возможные ходы для фигур игрока, а затем моделировался каждый из этих возможных ходов, чтобы увидеть, покидает ли он Короля или нет. в проверке. Если это так, эта опция будет удалена. У меня есть основной класс BoardManager, который управляет визуальными элементами и содержит фактическую разметку шахматной доски (в ChessBoardSim), и у меня есть класс ChessBoardSim, каждый из объектов которого содержит одно возможное состояние платы. ChessBoardSim может создавать другие экземпляры ChessBoardSim, позволяя имитировать состояние доски на любое количество ходов заранее.

У меня есть ошибка, с которой я боролся более 5 часов, которая появилась после того, как я попытался реструктурировать большую часть кода. Я в своем уме и мне просто нужна свежая пара глаз. Проблема заключается в том, чтобы при перемещении фигуры не удалялись со своих старых позиций, а расположение некоторых фигур на доске, похоже, сдвигалось на две плитки вверх. На основании отладки я полагаю, что проблема возникает в CalculateAllMovementOptions () в классе ChessBoardSim - по какой-то причине, когда ChessBoardSim имеет дочерний элемент ChessBoardSim и функция CalculateAllMovementOptions () вызывается в дочернем элементе, он изменяет данные в родитель. Я включил полный код ниже и опишу конкретную проблему как можно лучше.

Поток проблемы:

1: закрытый void Start () в BoardManager вызывается.

2: Программа правильно рисует и заполняет игровое поле. ChessBoardSim (называемый ChessPieces) создается для хранения данных о текущем состоянии платы.

3: StartTurn () вызывается в BoardManager, чтобы начать игру.

4: StartTurn () вызывает ChessPieces.CalculateAllMovementOptions (). Предполагаемая функция CalculateAllMovementOptions () - вернуть массив списков. Каждый список в массиве содержит законные ходы одной из фигур игрока. Тем не менее, похоже, что это фактически меняет фактические данные платы, и я не могу понять, почему.

  1. Когда игрок пытается переместить фигуру, игра прерывается, потому что фигуры находятся не там, где они должны быть, и программное обеспечение не справляется с этим. Перемещенная часть не удаляется из своего старого местоположения (несмотря на все мои усилия), и это приводит к тому, что у этого объекта два экземпляра, что приводит к исключению indexoutofrange, когда часть кода пытается получить доступ к 17-му элементу массива с 16 элементами.

Я был бы очень признателен, если бы кто-нибудь мог мне помочь, я чувствую, что уже потратил на это целый день и уверен, что упускаю что-то простое.

Ссылка на мой код https://github.com/FC123321/Chess

1 Ответ

0 голосов
/ 14 ноября 2018

Array.Clone не создает глубокую копию массива, поэтому, когда вы вызываете boardLayout.Clone() в SimulateBoard (и снова в конструкторе ChessBoardSim), вы копируете ссылки из boardLayout вновый массив.Это означает, что части в новом массиве - это один и тот же объект в старом.

Это означает, что когда вы находитесь в MovePiece в SimulateBoard, и вы вызываете piece.SetPosition и так далее для членовВ этом скопированном массиве вы также устанавливаете положение фрагментов в источнике копии.

Вместо использования boardLayout.Clone() вам нужно перебрать весь исходный массив и выполнить newBoardLayout[x,y] = new ChessPiece();а затем скопируйте значения в новый ChessPiece.Кроме того, вы можете создать новый конструктор ChessPiece, который возьмет другую шахматную фигуру и скопирует туда значения:

// ChessPiece copy constructor
public ChessPiece(ChessPiece other) {
    this.Position = new int[2] { other.Position[0], other.Position[1]};
    this.isWhite = other.isWhite;
    this.movementType = other.movementType;
    this.hasMoved = other.hasMoved;
    this.turnDoubleMoved = other.turnDobleMoved;
}

// instead of boardLayout.Clone() in the ChessBoardSim constructor:

for (int x=0 ; x<8;x++){
    for(int y=0; y<8;y++){
        if (boardLayout[x,y] != null)
            this.boardLayout[x,y] = new ChessPiece(boardLayout[x,y]);
    }
}


// In SimulateBoard, take out the redundant Clone call
ChessBoardSim simBoard = new ChessBoardSim(boardLayout, turnNumber);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...