У меня есть небольшой интересный персональный проект, в котором я перемещаю "робота" на арене коробки, если он ударяет по стене, игра окончена. Он имеет автоматический режим ходьбы, где он перемещается по арене, не нажимая стены, используя конечный автомат. Арена печатается с использованием Strings и Java Swing UI, и все контролируется событиями качания.
Я пытаюсь заставить его стрелять. Поскольку поведение пули довольно похоже на поведение робота, я создал объект класса Super Class с похожими методами и атрибутами (например, координаты местоположения и направление), а затем расширил класс робота и пули.
Проблема в том, что когда я перемещаюсь (изменяю атрибут позиции робота), позиция маркера тоже изменяется. Мой пользовательский интерфейс показывает текущую позицию обоих объектов, и когда я перемещаю робота, пуля перемещается. Положение пули предназначалось для установки только при нажатии кнопки съемки. Кнопка съемки устанавливает положение пули роботу, а затем перемещает пулю в том же направлении, пока она не попадет в рамки.
То, что происходит, когда я стреляю, - это то же самое, что и движение робота: когда пуля перемещается, робот перемещается, суицируя в стене пулю.
Это похоже на тот же объект, но я уверен, что я вызываю метод move, используя правильный объект.
Как я уже сказал, я сделал версию MCVE ниже:
Суперкласс класса Entity
public abstract class Entity {
protected int[] position = new int[2];
protected char direction;
public int getPosI() {
// System.out.println("i: " + position[0]);
return position[0];
}
public int getPosJ() {
// System.out.println("j: " + position[1]);
return position[1];
}
public int[] getPosition() {
return position;
}
public void setPosition(int[] position) {
this.position = position;
}
public char getDirection() {
return direction;
}
public void setDirection(char direction) {
this.direction = direction;
}
public boolean move() {
switch (direction) {
case 'u':
if (this.position[0] != 0) {
this.position[0]--;
return true;
} else
return false;
case 'r':
if (this.position[1] != 3) {
this.position[1]++;
return true;
} else
return false;
case 'd':
if (this.position[0] != 3) {
this.position[0]++;
return true;
} else
return false;
case 'l':
if (this.position[1] != 0) {
this.position[1]--;
return true;
} else
return false;
default:
return false;
}
}
}
Класс робота
public class Robot extends Entity {
public Robot(int[] position) {
super();
this.position = position;
this.direction = 'u';
}
public void resetPos() {
this.position[0] = this.position[1] = 1;
}
}
Класс пули
public class Bala extends Entity{
public Bala(int[] position, char direction) {
this.position = position;
this.direction = direction;
}
}
Основной класс
public class Main {
private static final int[] start = new int[] { 1, 1 };
public static void main(String[] args) {
Robot robot = new Robot(start);
robot.setDirection('d');
Bala bala = new Bala(robot.getPosition(), robot.getDirection());
for (int i = 0; i < 3; i++) {
System.out.println("MOVING ONLY THE ROBOT...");
robot.move();
System.out.println("Robot position: "
+ String.valueOf(robot.getPosI()) + ", "
+ String.valueOf(robot.getPosJ()));
System.out.println("Bullet position: "
+ String.valueOf(bala.getPosI()) + ", "
+ String.valueOf(bala.getPosJ()));
}
System.out.println("but the bullet moves to!!!");
System.out.println("reseting position of robot and lets see what happens to bullet...");
robot.resetPos();
System.out.println("Robot position: "
+ String.valueOf(robot.getPosI()) + ", "
+ String.valueOf(robot.getPosJ()));
System.out.println("Bullet position: "
+ String.valueOf(bala.getPosI()) + ", "
+ String.valueOf(bala.getPosJ()));
System.out.println("bullet moves too...");
}
}
ВАЖНОЕ ВЕЩАНИЕ: Когда я перемещаю робота с помощью кнопки R (сброс), он также перемещает пулю. Это означает, что пуля движется, даже если она не использует метод перемещения !!!
Итак, в качестве прямого вопроса по запросу: "Объект робота реплицирует изменения своего атрибута положения на позицию пули и наоборот, как остановить это поведение?"
Оба робота и Балы разделяют один и тот же массив int, и в этом и заключается ваша проблема: здесь присутствует код вины:
Bala bala = new Bala(robot.getPosition(), robot.getDirection());
Одно из возможных решений: getPosition()
возвращает копию массива, или другое - создать новый массив в конструкторе, который копирует значения в параметре.
В стороне, ваш опубликованный код был довольно близок к стандарту MCVE и требовал лишь нескольких изменений, чтобы сделать его ближе. Для чего это стоит, так я изменил свой код, чтобы сделать его MCVE и исправить:
public class Main {
private static final int[] start = new int[] { 1, 1 };
public static void main(String[] args) {
Robot robot = new Robot(start);
robot.setDirection('d');
Bala bala = new Bala(robot.getPosition(), robot.getDirection());
for (int i = 0; i < 3; i++) {
System.out.println("MOVING ONLY THE ROBOT...");
robot.move();
System.out.println("Robot position: "
+ String.valueOf(robot.getPosI()) + ", "
+ String.valueOf(robot.getPosJ()));
System.out.println("Bullet position: "
+ String.valueOf(bala.getPosI()) + ", "
+ String.valueOf(bala.getPosJ()));
}
System.out.println("but the bullet moves to!!!");
System.out.println("reseting position of robot and lets see what happens to bullet...");
robot.resetPos();
System.out.println("Robot position: " + String.valueOf(robot.getPosI())
+ ", " + String.valueOf(robot.getPosJ()));
System.out.println("Bullet position: " + String.valueOf(bala.getPosI())
+ ", " + String.valueOf(bala.getPosJ()));
System.out.println("bullet moves too...");
}
}
abstract class Entity {
protected int[] position = new int[2];
protected char direction;
public Entity(int[] position) {
System.arraycopy(position, 0, this.position, 0, position.length);
}
public Entity(int[] position, char direction) {
this(position);
this.direction = direction;
}
public int getPosI() {
// System.out.println("i: " + position[0]);
return position[0];
}
public int getPosJ() {
// System.out.println("j: " + position[1]);
return position[1];
}
public int[] getPosition() {
return position;
}
public void setPosition(int[] position) {
this.position = position;
}
public char getDirection() {
return direction;
}
public void setDirection(char direction) {
this.direction = direction;
}
public boolean move() {
switch (direction) {
case 'u':
if (this.position[0] != 0) {
this.position[0]--;
return true;
} else
return false;
case 'r':
if (this.position[1] != 3) {
this.position[1]++;
return true;
} else
return false;
case 'd':
if (this.position[0] != 3) {
this.position[0]++;
return true;
} else
return false;
case 'l':
if (this.position[1] != 0) {
this.position[1]--;
return true;
} else
return false;
default:
return false;
}
}
}
class Robot extends Entity {
public Robot(int[] position) {
super(position, 'u');
}
public void resetPos() {
this.position[0] = this.position[1] = 1;
}
}
class Bala extends Entity {
public Bala(int[] position, char direction) {
super(position, direction);
}
}
В стороне, вы, вероятно, не захотите использовать символы для представления направления, а скорее перечисления Direction, так как это добавит безопасность типа компиляции в вашу программу.