意外复制其他对象的行为

时间:2014-09-28 18:07:31

标签: java swing object attributes

我有一个有趣的个人项目,我在一个盒子舞台上移动一个“机器人”,如果他撞到一堵墙,游戏就结束了。它具有自动行走模式,可以在不使用有限状态机击打墙壁的情况下在竞技场周围移动。竞技场使用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(重置)按钮移动机器人时,它也会移动子弹。这意味着即使不使用移动方法,子弹也在移动!!!

因此,作为要求的直接问题, “机器人对象正在将其位置属性的变化复制到子弹位置,反之亦然,如何阻止这种行为?”

1 个答案:

答案 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);
   }
}

顺便说一句,您可能不希望使用字符来表示方向,而是使用方向枚举,因为这会为您的程序添加编译时类型安全性。