Как мне клонировать объект с целью перемещения чего-либо и проверки правильности этого перемещения?(Ява, Шахматы) - PullRequest
2 голосов
/ 21 февраля 2012

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

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

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

Ответы [ 2 ]

3 голосов
/ 21 февраля 2012

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

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

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

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

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

1 голос
/ 21 февраля 2012

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

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

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

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

...