Java 替换二维对象数组的元素
我目前正在尝试用Java实现国际象棋,我想我会被一些非常琐碎的事情挂住,但我无法为自己的生活调试这个问题 假设我有一个二维数组中的'Piece'子类(Pawn、Rook、Knight等),简单的“=”符号赋值不足以将一个元素替换为另一个元素,对吗?因为,它只创建对原始对象的引用 例如,假设“field[][]”是一个8x8的实例化棋子数组,表示我将迭代的棋盘,以绘制到JLayeredPane上Java 替换二维对象数组的元素,java,arrays,object,multidimensional-array,chess,Java,Arrays,Object,Multidimensional Array,Chess,我目前正在尝试用Java实现国际象棋,我想我会被一些非常琐碎的事情挂住,但我无法为自己的生活调试这个问题 假设我有一个二维数组中的'Piece'子类(Pawn、Rook、Knight等),简单的“=”符号赋值不足以将一个元素替换为另一个元素,对吗?因为,它只创建对原始对象的引用 例如,假设“field[][]”是一个8x8的实例化棋子数组,表示我将迭代的棋盘,以绘制到JLayeredPane上 field[dst_y][dst_x] = field[src_y][src_x];
field[dst_y][dst_x] = field[src_y][src_x];
field[src_y][src_x] = null;
field[dst_y][dst_x].setPosition(dst_y, dst_x);
// setPosition(int, int) just sets instance variables of the piece subclasses
这是否只是在[src_y][src_x]字段创建对元素的引用,将其放置在[dst_y][dst_x]字段中,并立即将它们都设置为null?我发现,当我试图以这种方式更新电路板时,会出现一个空指针异常,但所有确定的解决方案都涉及我完全更改数据表示,这将是不幸的,因为我对我已经在各个工件类型中实现的逻辑感到满意,以从(x,y)角度验证它们的移动
这可能与浅层复制有关吗
我怎样才能改善这一点?如果唯一的答案是重构大量的代码,我接受它,但我觉得我错过了一些令人尴尬的简单的东西
Board.java
public class Board {
private static final Board INSTANCE = new Board();
private static Piece[][] field = new Piece[8][8];
private Board() {}
public static Board getInstance() {
init();
return INSTANCE;
}
public static Piece[][] getField(){
return field;
}
public static void movePiece(int src_y, int src_x, int dst_y, int dst_x) {
if(src_y != dst_y || src_x != dst_x) {
field[dst_y][dst_x] = field[src_y][src_x];
field[src_y][src_x] = null;
field[dst_y][dst_x].setPosition(dst_y, dst_x);
}
}
public static void init() {
field[0][0] = new Rook(0, 0, true);
field[0][1] = new Knight(0, 1, true);
field[0][2] = new Bishop(0, 2, true);
field[0][3] = new Queen(0, 3, true);
field[0][4] = new King(0, 4, true);
field[0][5] = new Bishop(0, 5, true);
field[0][6] = new Knight(0, 6, true);
field[0][7] = new Rook(0, 7, true);
field[1][0] = new Pawn(1, 0, true);
field[1][1] = new Pawn(1, 1, true);
field[1][2] = new Pawn(1, 2, true);
field[1][3] = new Pawn(1, 3, true);
field[1][4] = new Pawn(1, 4, true);
field[1][5] = new Pawn(1, 5, true);
field[1][6] = new Pawn(1, 6, true);
field[1][7] = new Pawn(1, 7, true);
for(int i = 2; i < 6; i++) {
for(int j = 0; j < 7; j++) {
field[i][j] = null;
}
}
field[7][0] = new Rook(7, 0, false);
field[7][1] = new Knight(7, 1, false);
field[7][2] = new Bishop(7, 2, false);
field[7][3] = new Queen(7, 3, false);
field[7][4] = new King(7, 4, false);
field[7][5] = new Bishop(7, 5, false);
field[7][6] = new Knight(7, 6, false);
field[7][7] = new Rook(7, 7, false);
field[6][0] = new Pawn(6, 0, false);
field[6][1] = new Pawn(6, 1, false);
field[6][2] = new Pawn(6, 2, false);
field[6][3] = new Pawn(6, 3, false);
field[6][4] = new Pawn(6, 4, false);
field[6][5] = new Pawn(6, 5, false);
field[6][6] = new Pawn(6, 6, false);
field[6][7] = new Pawn(6, 7, false);
}
}
import java.lang.Math;
import javax.swing.ImageIcon;
import java.awt.*;
public abstract class Piece implements MoveStrategy{
private int x;
private int y;
private boolean white;
public abstract ImageIcon getIcon();
public Piece(int pos_y, int pos_x, boolean white) {
setPosition(pos_y, pos_x);
setColor(white);
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public void setPosition(int dst_y, int dst_x) {
this.x = dst_x;
this.y = dst_y;
}
public boolean isWhite() {
return this.white;
}
private void setColor(boolean white) {
this.white = white;
}
}
import javax.swing.ImageIcon;
public class Pawn extends Piece {
public Pawn(int pos_y, int pos_x, boolean white) {
super(pos_y, pos_x, white);
}
public ImageIcon getIcon() {
ImageIcon icon = (this.isWhite() == true) ? new ImageIcon("WhitePawn.png") : new ImageIcon("BlackPawn.png");
return icon;
}
public boolean validateMove(int dst_x, int dst_y, Piece[][] field) {
int x = this.getX();
int y = this.getY();
boolean iw = this.isWhite();
// If either dst_x/y param is out of array bounds return false
if(dst_x > 7 || dst_y > 7 || dst_x < 0 || dst_y < 0) {
return false;
}
// Logic if the piece is white
if(iw) {
// Can move two
if(y == 1) {
// If not moving horizontally, not moving more than 2 vertically, moving at least one space, and moving
// into an open square, return true.
if(x == dst_x && dst_y - y <= 2 && dst_y - y > 0 && field[dst_x][dst_y] == null) return true;
// If moving one diagonally into a spot occupied by the other team's piece, return true.
if(Math.abs(x - dst_x) == 1 && dst_y == y + 1 && field[dst_x][dst_y] != null && field[dst_x][dst_y].isWhite() == false) return true;
}
else {
if(dst_x == x + 1 && dst_y == y + 1 && field[dst_x][dst_y] != null && field[dst_x][dst_y].isWhite() == false) return true;
if(Math.abs(x - dst_x) == 1 && dst_y == y + 1 && field[dst_x][dst_y] != null && field[dst_x][dst_y].isWhite() == false) return true;
}
}
// Logic if the piece is black
else {
// Calculations same as above but for black pieces
if(y == 6) {
if(x == dst_x && y - dst_y <= 2 && y - dst_y > 0 && field[dst_x][dst_y] == null) return true;
if(Math.abs(dst_x - x) == 1 && dst_y - y == 1 && field[dst_x][dst_y] != null && field[dst_x][dst_y].isWhite() == true) return true;
}
else {
if(x == dst_x && y - dst_y == 1 && field[dst_x][dst_y] == null) return true;
if(Math.abs(dst_x - x) == 1 && dst_y - y == 1 && field[dst_x][dst_y] != null && field[dst_x][dst_y].isWhite() == true) return true;
}
}
return false;
}
public String toString() {
String s = "Type: Pawn" + " Position (" + this.getX() + ", " + this.getY() + ")";
return s;
}
}
Pawn.java
public class Board {
private static final Board INSTANCE = new Board();
private static Piece[][] field = new Piece[8][8];
private Board() {}
public static Board getInstance() {
init();
return INSTANCE;
}
public static Piece[][] getField(){
return field;
}
public static void movePiece(int src_y, int src_x, int dst_y, int dst_x) {
if(src_y != dst_y || src_x != dst_x) {
field[dst_y][dst_x] = field[src_y][src_x];
field[src_y][src_x] = null;
field[dst_y][dst_x].setPosition(dst_y, dst_x);
}
}
public static void init() {
field[0][0] = new Rook(0, 0, true);
field[0][1] = new Knight(0, 1, true);
field[0][2] = new Bishop(0, 2, true);
field[0][3] = new Queen(0, 3, true);
field[0][4] = new King(0, 4, true);
field[0][5] = new Bishop(0, 5, true);
field[0][6] = new Knight(0, 6, true);
field[0][7] = new Rook(0, 7, true);
field[1][0] = new Pawn(1, 0, true);
field[1][1] = new Pawn(1, 1, true);
field[1][2] = new Pawn(1, 2, true);
field[1][3] = new Pawn(1, 3, true);
field[1][4] = new Pawn(1, 4, true);
field[1][5] = new Pawn(1, 5, true);
field[1][6] = new Pawn(1, 6, true);
field[1][7] = new Pawn(1, 7, true);
for(int i = 2; i < 6; i++) {
for(int j = 0; j < 7; j++) {
field[i][j] = null;
}
}
field[7][0] = new Rook(7, 0, false);
field[7][1] = new Knight(7, 1, false);
field[7][2] = new Bishop(7, 2, false);
field[7][3] = new Queen(7, 3, false);
field[7][4] = new King(7, 4, false);
field[7][5] = new Bishop(7, 5, false);
field[7][6] = new Knight(7, 6, false);
field[7][7] = new Rook(7, 7, false);
field[6][0] = new Pawn(6, 0, false);
field[6][1] = new Pawn(6, 1, false);
field[6][2] = new Pawn(6, 2, false);
field[6][3] = new Pawn(6, 3, false);
field[6][4] = new Pawn(6, 4, false);
field[6][5] = new Pawn(6, 5, false);
field[6][6] = new Pawn(6, 6, false);
field[6][7] = new Pawn(6, 7, false);
}
}
import java.lang.Math;
import javax.swing.ImageIcon;
import java.awt.*;
public abstract class Piece implements MoveStrategy{
private int x;
private int y;
private boolean white;
public abstract ImageIcon getIcon();
public Piece(int pos_y, int pos_x, boolean white) {
setPosition(pos_y, pos_x);
setColor(white);
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public void setPosition(int dst_y, int dst_x) {
this.x = dst_x;
this.y = dst_y;
}
public boolean isWhite() {
return this.white;
}
private void setColor(boolean white) {
this.white = white;
}
}
import javax.swing.ImageIcon;
public class Pawn extends Piece {
public Pawn(int pos_y, int pos_x, boolean white) {
super(pos_y, pos_x, white);
}
public ImageIcon getIcon() {
ImageIcon icon = (this.isWhite() == true) ? new ImageIcon("WhitePawn.png") : new ImageIcon("BlackPawn.png");
return icon;
}
public boolean validateMove(int dst_x, int dst_y, Piece[][] field) {
int x = this.getX();
int y = this.getY();
boolean iw = this.isWhite();
// If either dst_x/y param is out of array bounds return false
if(dst_x > 7 || dst_y > 7 || dst_x < 0 || dst_y < 0) {
return false;
}
// Logic if the piece is white
if(iw) {
// Can move two
if(y == 1) {
// If not moving horizontally, not moving more than 2 vertically, moving at least one space, and moving
// into an open square, return true.
if(x == dst_x && dst_y - y <= 2 && dst_y - y > 0 && field[dst_x][dst_y] == null) return true;
// If moving one diagonally into a spot occupied by the other team's piece, return true.
if(Math.abs(x - dst_x) == 1 && dst_y == y + 1 && field[dst_x][dst_y] != null && field[dst_x][dst_y].isWhite() == false) return true;
}
else {
if(dst_x == x + 1 && dst_y == y + 1 && field[dst_x][dst_y] != null && field[dst_x][dst_y].isWhite() == false) return true;
if(Math.abs(x - dst_x) == 1 && dst_y == y + 1 && field[dst_x][dst_y] != null && field[dst_x][dst_y].isWhite() == false) return true;
}
}
// Logic if the piece is black
else {
// Calculations same as above but for black pieces
if(y == 6) {
if(x == dst_x && y - dst_y <= 2 && y - dst_y > 0 && field[dst_x][dst_y] == null) return true;
if(Math.abs(dst_x - x) == 1 && dst_y - y == 1 && field[dst_x][dst_y] != null && field[dst_x][dst_y].isWhite() == true) return true;
}
else {
if(x == dst_x && y - dst_y == 1 && field[dst_x][dst_y] == null) return true;
if(Math.abs(dst_x - x) == 1 && dst_y - y == 1 && field[dst_x][dst_y] != null && field[dst_x][dst_y].isWhite() == true) return true;
}
}
return false;
}
public String toString() {
String s = "Type: Pawn" + " Position (" + this.getX() + ", " + this.getY() + ")";
return s;
}
}
您能发布一个最小的可运行示例吗?当然,我现在就要发布,虽然它包含大量代码,因为它包含一个抽象类及其子类(片段的类型)。我真的很感激,不<代码>字段[dst_y][dst_x]=字段[src_y][src_x]代码>只需设置
字段[dst_y][dst_x]
,这样它现在引用的内容与字段[src_y][src_x]
引用的内容相同。然后字段[src_y][src_x]=null
只需将字段[src_y][src_x]
设置为null
,字段[dst_y][dst_x]
继续引用它之前引用的任何内容(即之前引用的字段[src_y][src_y]
)<代码>字段[dst_y][dst_x]=字段[src_y][src_x]并没有以某种方式使字段[dst_y][dst_x]
成为字段{src_y][src_x]的同义词
@KevinAnderson好的,太好了!感谢您的回复和澄清。我对您忽视我的问题表示歉意。因此,问题一定存在于我尝试访问空值的其他地方?堆栈跟踪非常有用,并且尝试在发生错误但无法找到任何类型的错误的地方进行调试根本原因还没有。好吧,好吧……别担心;)这是猎人最初的挫折感。堆叠的痕迹引导你去祈祷,在指定的位置是……什么都没有