2012-02-20 1 views
2

Я пишу простую шахматную игру. Я не буду публиковать его здесь, но я дам вам необходимые данные.Как клонировать объект для перемещения чего-либо и видеть, действительно ли это действие? (Java, Chess)

Я перемещаюсь, щелкая квадрат с куском на нем, затем квадрат выбирается, а затем щелкает, где я хочу кусочек, чтобы двигаться. Иногда в шахматах ход может не отвечать на проверку или создавать чек на своего собственного короля и, следовательно, является незаконным. Лучший способ, я обнаружил, решить, является ли движение незаконным, - это сделать переход на «ifBoard» (клон доски), и если я считаю, что закон закончен, установите реальный совет равным ifBoard.

Вот фрагмент коды мне реагировать на щелчки мышей (плата реальной платы, назначение является кликой квадрата, selectedSquare является квадратом ранее выбранным (если не нулевой))

public void mousePressed(MouseEvent e){ 
      Square selectedSquare = board.selectedSquare(); 
      Square destination = board.getSquare(e.getX(), e.getY()); 
      board.deselect(); 
      if(destination == null){ 
       repaint(); 
       return; 
      } 

      if(selectedSquare == null){ 
       System.out.println("SelectedSquare is null"); 
       if(destination.occupiedByTeam(turn)){ 
        System.out.println("destination is occupied by right team and is null"); 
        board.select(destination); 
       } 
      } 
      else{ 
       if(!selectedSquare.occupiedByTeam(turn)){ 
        System.out.println("SelectedSquare not occupied by correct team"); 
        repaint(); 
        return; 
       } 

       if(destination.occupiedByTeam(turn)){ 
        System.out.println("ChosenSquare occupied by same team"); 
        board.select(destination); 
        repaint(); 
        return; 
       } 

       //move on a dummy board and check for conflicts 
       Board ifBoard = (Board)board.clone(); 

       System.out.println(ifBoard.toString()); 
       System.out.println(board.toString()); 
       //check if you can't move due to piece movement limitations 
//.place() is a coordinate of the square on the tile system (A-H and 1-8) 
       if(
       !ifBoard.move((int)selectedSquare.place().getX(), (int)selectedSquare.place().getY(), (int)destination.place().getX(), (int)destination.place().getY()) 
       ){ 
        repaint(); 
        return; 
       } 

       //if moving results in self-check 
       if(ifBoard.check(turn)){ 
        //don't move 
        repaint(); 
        return; 
       } 
       else{ 
        //move 
        System.out.println("Board moved!"); 
        board = new Board(ifBoard); 
        cycleTurns(); 
       } 
      } 

      repaint(); 
     } 

В ToString звонков регистрируются по-разному, но я сузил проблему до вызова ifBoard.move(), фактически перемещая реальную доску.

Это класс платы или ее часть.

import java.awt.Color; 
import java.lang.Cloneable; 
import java.awt.geom.*; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 

public class Board implements Cloneable{ 
    private Square[][] squares; 

    private Rectangle2D squareWrap; 
    private Rectangle2D boardBorder; 

    private Square selectedSquare; 

    public Board(){ 
     squares = new Square[8][8]; 
     for(int i = 0; i < 8; i++){ 
      for(int j = 0; j < 8; j++){ 
       squares[i][j] = new Square(new Point2D.Double(i, j)); 
      } 
     } 

     boardBorder = new Rectangle2D.Double(Constants.boardX, 
              Constants.boardY, 
              Constants.borderWidth * 2 + Constants.boardSide, 
              Constants.borderHeight * 2 + Constants.boardSide); 

     squareWrap = new Rectangle2D.Double(Constants.boardX + Constants.borderWidth, 
              Constants.boardY + Constants.borderHeight, 
              Constants.boardSide, 
              Constants.boardSide); 

     selectedSquare = null; 
    } 

    public Object clone() { 
     Board obj = new Board(); 
     obj.setSquares(this.squares); 
     obj.setSelectedSquare(this.selectedSquare); 

     return obj; 
    }... 

Я неправильно клонирую? Есть ли способ лучше? Заранее спасибо.

ответ

3

Я неправильно клонирую? Есть ли способ лучше?

Метод клонирования всегда должен начинаться с вызова super.clone() по причинам, по которым я не буду входить в этот пост.

Кроме того, вы не клонируете атрибуты объекта (вы делаете мелкую копию вместо глубокой копии). Таким образом, клонированная Правление делится той же ссылкой на структуру squares. (Изменение клонированного совета изменит оригинальный совет.)

(Многие люди утверждают, что вы должны избегать clone и Cloneable все вместе, хотя.)

Если бы я тебя, я бы настоятельно рекомендую сделать класс Board неизменны и, возможно, запустите механизм копирования на запись. Думаю, это сэкономит вам много головной боли.

+0

Спасибо, я понимаю разницу между мелкой и глубокой копиями. Также мне нравится идея, что Совет неизменен, и я рассмотрю, как реализовать механизм копирования на запись. –

+0

Не могли бы вы случайно указать на хорошую реализацию Java-копирования на запись, чтобы я мог научиться ее создавать? Кажется, я не могу найти. –

1

Возможно, проблема заключается в том, что ваша реализация clone() не создает глубокую копию. Клонированный объект разделяет хотя бы некоторое состояние с экземпляром, из которого он клонирован. Под этим я имею в виду, они ссылаются на одни и те же объекты:

public Object clone() { 
    Board obj = new Board(); 
    obj.setSquares(this.squares); // Square instances are the same for both boards 
    return obj; 
} 

Если изменить состояние на клоне - например, на квадрате - вы также меняете его на реальной доске.

От того, что вы опубликовали, вы звоните ifBoard.move(). Если этот метод влияет на часть «общего состояния», это повлияет на оба экземпляра платы.

+0

Спасибо.Это было также правильно, но, учитывая, что я должен был выбрать ответ, я выбрал более подробный (и более ранний) ниже. –

+0

правильно;) - и удачи в вашей шахматной игре! – alex

 Смежные вопросы

  • Нет связанных вопросов^_^