Какой шаблон я использую для взаимозависимого класса - PullRequest
0 голосов
/ 06 июня 2019

Я читал из других источников, что для объектов не очень хорошая идея знать друг о друге, особенно те, которые находятся на одном уровне.Это должно быть больше похоже на иерархию.

Моя проблема совершенно уникальна, так как я не нашел пути ее решения.Кроме того, мне не повезло встретить любую тему, которая конкретно касается моей проблемы.

Проблема Я создаю шахматное приложение и создаю модель приложения.Прямо сейчас у меня есть абстрактные объекты, такие как, например, Piece, от которых другие части, такие как Queen, Knight, и остальные будут наследоваться.У меня также есть класс Board, который обрабатывает все модели доски и состояние игры.Теперь у каждого из моих фигур есть метод generateMove() для расчета возможных ходов с их позиции, и для этого им нужно знать состояние доски.Также Части были созданы Правлением при запуске.

Вопрос. Могу ли я пойти дальше и создать экземпляр Pieces, например,

public class ChessBoard{
   Boardbit = 64bit
   Knight = new Knight(start_position, this) 

  //calculate

}

, а затем в методе класса Найта

public long generateMove(ChessBoard);

Если нет, то какими еще способами я могу воспользоваться?Это?

Ответы [ 2 ]

1 голос
/ 06 июня 2019

Заставить Chessboard узнать Knight и наоборот не элегантно.Я согласен с вами в этом пункте.Правильное соблюдение правила «Не спрашивай» заставляет элемент «более высокого уровня», в данном случае шахматную доску, указывать фигуре двигаться, предоставляя всю необходимую информацию.Сам по себе Chessboard не знает, какая фигура движется (в этом случае предсказывает возможные ходы для всех фигур), но наверняка никогда не узнает никаких подробностей о том, как фигура может двигаться или как она может двигаться.Это только одно из возможных решений с использованием своего рода паттерна стратегии.(Посетитель или другой подобный шаблон также может быть использован здесь):

Main() {
    chessboard = new Chessboard()
    PiecesCollection = new PiecesCollection(new Knight(KnightStrategy, Color.Black))
    chessboard.AddPieces(PiecesCollection)

    CollectionOfAllPossibleMoveCollections = chessBoard.CallculateAllPossibleMoves()

    Move selectedMove = ShowOrSelectMove(CollectionOfAllPossibleMoveCollections)
    chessboard.ExecuteMove(selectedMove)
}

public class Chessboard{
   // fields
   PiecesCollectionWhite
   // where 'PiecesCollectionWhite' is a collection of `Piece`

   PiecesCollectionBlack
   // where 'PiecesCollectionBlack' is a collection of `Piece`

   CurrentlyVisitedPositionsCollection
   // where 'CurrentlyVisitedPositionsCollection' is a collection of `Position`

   // methods
   AddPieces(PiecesCollection, Color)

   CallculateAllPossibleMoves(Color) {
     CollectionOfPossibleMoveCollections = 
         FOREACH Piece IN PiecesCollection OF Color
             DO Piece.CalculateMoves(this.CurrentlyVisitedPositionsCollection)
     return CollectionOfAllPossibleMoveCollections // where 'CollectionOfAllPossibleMoveCollections ' is a collection that holds a collection of `Move` of which each nested collection represents the possible moves of a chess piece.
   }

   ExecuteMove(Move) {
       RemovePieceFromBoardIfNecessary(Move.ToPosition)
   }
} 

public class Piece 
{
   // fields
   Strategy
   Position
   Color

   // methods
   CallculateMoves(CurrentlyVisitedPositionsCollection) {
       PossibleMovesCollection = this.Strategy.Execute(CurrentlyVisitedPositionsCollection, this.Position)
       return PossibleMovesCollection where `PossibleMovesCollection` is a collection of `Move`
   }
}

public class Knight extends Piece
{
   ctor(Strategy, Color)
}

public class Stragtegy
{
  abstract Execute(currentPosition, allPiecesPositions) : PossibleMovesCollection 
}

public class KnightStrategy extends Strategy
{
  Execute(currentPosition, allPiecesPositions) {
      PossibleMovesCollection = ApplyKnightMoveAlgorithm()
      return PossibleMovesCollection 
  }

  private ApplyKnightMoveAlgorithm() : PossibleMovesCollection 
}

public class Move
{
  Position fromPosition
  Position toPosition
}

public class Color
{
  Black
  White
}

public class Position
{
  Color
  xCoordinate
  yCoordinate
}

Это всего лишь эскиз, а не полный пример.Некоторая информация о состоянии или операции отсутствуют.Например, возможно, вам придется хранить Color, который был перемещен последним на шахматной доске.

Поскольку Chessboard возвращает все возможные ходы (информацию обо всех посещенных в данный момент координатах), вы можете легко улучшить алгоритм, реализовавнекоторый интеллект, чтобы предсказать лучшие возможные шаги от этой информации.Поэтому, прежде чем контроллер или в этом случае Main() вызовет Chessboard.ExecuteMove(Move), он может сделать вызов PredictionEngine.PredictBestMove(CollectionOfAllPossibleMoveCollections).

1 голос
/ 06 июня 2019

Намного лучше иметь метод generateMove(boardState), поэтому ваша доска должна вызывать любую фигуру, которую вы имеете, и передавать им необходимую информацию для выполнения этой задачи. Его можно использовать даже для некоторой оптимизации, поскольку доска может генерировать какую-то полезную структуру каждый раунд только один раз, а затем передавать ее всем кусочкам (например, в некоторый 2d массив).

...