我有一个有趣的个人项目,我在一个盒子舞台上移动一个“机器人”,如果他撞到一堵墙,游戏就结束了。它具有自动行走模式,可以在不使用有限状态机击打墙壁的情况下在竞技场周围移动。竞技场使用Strings和Java Swing UI打印,一切都由摇摆事件控制。
我正试图让他开枪。由于子弹行为非常类似于机器人行为,我创建了一个具有所有类似方法和属性(如位置坐标和方向)的超类命名实体,然后扩展了机器人和子弹类。
问题是:当我移动(改变机器人的位置属性)时,子弹位置也会改变。 我的UI显示了两个对象的当前位置,当我移动机器人时,子弹移动。子弹位置仅用于按下拍摄按钮时设置。射击按钮将子弹位置设置到机器人,然后沿相同方向移动子弹,直到它达到框限制。
拍摄时发生的事情与机器人的动作相同:当子弹移动时,机器人移动到子弹的墙壁上。
就像它们是同一个对象,但我很确定我正在使用正确的对象调用move方法。
据我所知,我在下面制作了MCVE版本:
实体超级
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(重置)按钮移动机器人时,它也会移动子弹。这意味着即使不使用移动方法,子弹也在移动!!!
因此,作为要求的直接问题, “机器人对象正在将其位置属性的变化复制到子弹位置,反之亦然,如何阻止这种行为?”
答案 0 :(得分:1)
Robot和Bala共享完全相同的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);
}
}
顺便说一句,您可能不希望使用字符来表示方向,而是使用方向枚举,因为这会为您的程序添加编译时类型安全性。