java - 为类的一个实例设置成员变量会覆盖其他类实例的相同成员变量
问题描述
因此,我正在制作一个简单的战舰游戏(我对 java 还很陌生……),当将“舰船”的位置分配给 7x7 的虚拟网格时,我得到了意想不到的结果。我将从显示测试代码和该代码的输出开始:
Ship[] ships = new Ship[2];
for (int i = 0; i < ships.length; i++) {
ships[i] = new Ship();
ships[i].setLocationCells(ShipLocations.createLocations());
System.out.println(Arrays.deepToString(ships[i].getLocationCells()));
}
for (int i = 0; i < ships.length; i++) {
System.out.println(Arrays.deepToString(ships[i].getLocationCells()));
}
System.out.println(Arrays.deepToString(ShipLocations.getUsedLocations()));
所以我只是初始化一个包含两个 Ship 对象的数组。我循环并创建这些对象。ShipLocations.createCells() 返回随机唯一位置的 3x2 2D 数组。Set 和 get 方法是相当标准的。这段代码的输出是这样的:
[[1, 3], [1, 4], [1, 5]]
[[4, 5], [5, 5], [6, 5]]
[[4, 5], [5, 5], [6, 5]]
[[4, 5], [5, 5], [6, 5]]
[[1, 3], [1, 4], [1, 5], [4, 5], [5, 5], [6, 5]}
因此,由此看来,当它最初设置时,位置确实是唯一的,但在我返回检查位置的第二个 for 循环中,似乎两个对象的位置单元格都已设置为从 ShipLocations 生成的最后一个值。创建位置单元()。最后一个打印显示由 ShipLocations 创建和存储的所有位置(您可以看到这些值不受影响并且仍然是唯一的)。那么这里发生了什么?为什么最后一次调用 setLocationCells() 会重置两个 Ship() 实例的成员变量?我想知道这里是否存在我只是以某种方式丢失的引用指针问题......船舶引用变量是否指向同一个对象,这就是正在发生的事情?如果这有助于解决任何澄清问题,这是 Ship 类:
import java.util.Arrays;
public class Ship {
private int len = 3;
private int[][] locationCells = new int[3][2];
private int numOfHits = 0;
public String check(int[] g) {
// compare user guess to location cell
for (int i = 0; i < locationCells.length; i++) {
//look for hit, if guess is a location...
if (locationCells[i][0] == g[0] && locationCells[i][1] == g[1]) {
// increase num of hits
numOfHits++;
// shrink locationsCells and remove the hit location
shrinkLocations(g);
if (locationCells.length == 0) {
return "kill";
}
else {
return "hit";
}
}
}
return "miss";
}
public void shrinkLocations(int[] guess) {
int[][] temp = new int[locationCells.length - 1][2];
int currentPos = 0;
for (int i = 0; i < locationCells.length; i++) {
if (!(locationCells[i][0] == guess[0] && locationCells[i][1] == guess[1])) {
temp[currentPos] = locationCells[i];
currentPos++;
}
}
setLocationCells(temp);
}
public void setLocationCells(int[][] locations) {
this.locationCells = locations;
}
public int[][] getLocationCells() {
return this.locationCells;
}
public void setLen(int len) {
this.len = len;
}
public int getLen() {
return len;
}
public int getNumOfHits() {
return numOfHits;
}
}
这是 ShipLocations 类(根据要求):
mport java.util.Random;
public class ShipLocations {
// array that holds the nine total ship locations
private static int len = 3;
private static int[][] usedLocations = new int[9][2];
private static int[][] shipLocations = new int[len][2];
public static int[][] createLocations(){
// need to know if you are going to position ship up or down.
Random randint = new Random();
// control boolean for do-while loop below
boolean locationsHaveBeenUsed = false;
boolean placementIsValid = false;
int xLoc;
int yLoc;
int direction = randint.nextInt(2);
// generate locations until the initial location isnt already used
do {
// x location starts at 1 and goes to a point where it will still fit on the board
xLoc = randint.nextInt(8 - len) + 1;
// y location starts at 1 and goes to a point where it will still fit on the board
yLoc = randint.nextInt(8 - len) + 1;
locationsHaveBeenUsed = hasBeenUsed(xLoc, yLoc);
//generate new direction and try again.
direction = randint.nextInt(2);
placementIsValid = validPlacement(xLoc, yLoc, direction);
// only place if the locations have not been NOT been used
if (placementIsValid && !locationsHaveBeenUsed) {
//make a call to place at those locations.
placeShipLocations(xLoc, yLoc, direction);
}
// stop once both the locations haven't been used and the placement is not valid
} while (locationsHaveBeenUsed || !placementIsValid);
// current shipLocations array has been altered, return.
return shipLocations;
}
public static boolean hasBeenUsed(int xLoc, int yLoc) {
for (int[] loc : usedLocations) {
// if the randomly generated location has already been used, generate again.
if (loc[0] == xLoc && loc[1] == yLoc) {
return true;
}
}
// if not found in usedLocaations return false
return false;
}
public static void placeInNonEmpty(int xLoc, int yLoc) {
// add the location to used locations in the slot that is first available (non-double zeros)
for (int j = 0; j < usedLocations.length; j++) {
if (usedLocations[j][0] == 0 && usedLocations[j][1] == 0) {
usedLocations[j][0] = xLoc;
usedLocations[j][1] = yLoc;
break;
}
}
}
public static void placeShipLocations(int x, int y, int direction) {
for (int i = 0; i < len; i++) {
// place in UsedLocations array
placeInNonEmpty(x, y);
// place in current shipLocations
shipLocations[i][0] = x;
shipLocations[i][1] = y;
if (direction == 1) {
// moving location up and down
y++;
}
else {
// moving location left and right
x++;
}
}
}
public static boolean validPlacement(int x, int y, int direction) {
for (int i = 1; i < len; i++) {
if (direction == 1) {
// moving location up and down
y++;
}
else {
// moving location left and right
x++;
}
for (int[] loc : usedLocations) {
// check through each location in usedLocations
if (loc[0] == x && loc[1] == y) {
// moving in that direction is not compatible return false and try again
return false;
}
}
}
// if it makes it through that checking minefield return true.
return true;
}
public static int[][] getUsedLocations() {
return usedLocations;
}
}
解决方案
推荐阅读
- python - 为什么通过从另一个模块调用函数来显示来自不同模块中不同 GUI 的图像时会出现问题?
- google-cloud-platform - 如何使用我们付费但无法访问的 GCP 项目
- php - 如何在 codeIgniter 的 heredoc 中显示图像
- android - 无法恢复活动:不允许启动服务 Intent,应用程序在后台
- node.js - NodJS 本地数据存储 GAE Whit UI
- java - Kafka Stream - 只有一个实例从分区读取
- java - JavaFX + GraalVM + Gluon
- ruby-on-rails - 删除功能不适用于 Rails 应用程序中的 Active Storage 映像
- node.js - npm run build 返回未找到模块:错误:无法在我的 NuxtJS 应用程序中的 docker 容器中解析
- java - android studio中的矢量路径数据