Java国际象棋代码报错:无法读取null对象的pieceColor字段
问题描述
运行国际象棋棋盘相关Java代码时,触发空指针异常:
Cannot read field "pieceColor" because "elem" is null
错误出现在Board类的avalia方法中if(elem.pieceColor == pieceColor){这一行。
需求:给定棋子颜色(例如黑色),统计棋盘上该颜色的所有棋子,并根据PieceType枚举计算它们的总价值。
相关代码如下:
Main类
import m2_praticas.xadrez.enums.PieceColor; public class Main { public static void main(String[] args) { Board board = new Board(); System.out.println(board.avalia(PieceColor.BLACK)); } }
Board类
import m2_praticas.xadrez.enums.PieceColor; import m2_praticas.xadrez.enums.PieceType; public class Board { Piece board[][]; public Board(){ board = new Piece[8][8]; // Creates a new board // For loop to set the pieces for (int i = 0; i < board.length; i++){ // columns for (int j = 0; j < board[i].length; j++){ // rows //System.out.println("[" + i + "]" + "[" + j + "]"); if(i == 0 && j >= 0){ // 0, 0 & 0, 1 board[i][j] = new Piece(PieceColor.BLACK, PieceType.ROOK); // 2 black rooks } if(i == 0 && j >= 2){ board[i][j] = new Piece(PieceColor.BLACK, PieceType.KNIGHT); // 2 black knights } if(i == 0 && j >= 4){ board[i][j] = new Piece(PieceColor.BLACK, PieceType.BISHOP); // 2 black bishops } if(i == 0 && j >= 6){ board[i][j] = new Piece(PieceColor.BLACK, PieceType.QUEEN); // 1 black queen } if(i == 0 && j >= 7){ board[i][j] = new Piece(PieceColor.BLACK, PieceType.KING); // 1 black king } if(i == 1 && j >= 0){ board[i][j] = new Piece(PieceColor.BLACK, PieceType.PAWN); // 8 black pawns } // --------------------------------- if(i == 6 && j >= 0){ board[i][j] = new Piece(PieceColor.WHITE, PieceType.PAWN); // 8 white pawns } if(i == 7 && j >= 0){ board[i][j] = new Piece(PieceColor.WHITE, PieceType.ROOK); // 2 white rooks } if(i == 7 && j >= 2){ board[i][j] = new Piece(PieceColor.WHITE, PieceType.KNIGHT); // 2 white knights } if(i == 7 && j >= 4){ board[i][j] = new Piece(PieceColor.WHITE, PieceType.BISHOP); // 2 white bishops } if(i == 7 && j >= 6){ board[i][j] = new Piece(PieceColor.WHITE, PieceType.QUEEN); // 1 white queen } if(i == 7 && j >= 7){ board[i][j] = new Piece(PieceColor.WHITE, PieceType.KING); // 1 white king } } } } public int avalia(PieceColor pieceColor){ int totalValue = 0; for (Piece[] p: board){ for (Piece elem: p){ if(elem.pieceColor == pieceColor){ switch (elem.pieceType){ case PAWN: totalValue = (totalValue + PieceType.PAWN.getPieceValue()); break; case ROOK: totalValue = (totalValue + PieceType.ROOK.getPieceValue()); break; case KNIGHT: totalValue = (totalValue + PieceType.KNIGHT.getPieceValue()); break; case BISHOP: totalValue = (totalValue + PieceType.BISHOP.getPieceValue()); break; case QUEEN: totalValue = (totalValue + PieceType.QUEEN.getPieceValue()); break; case KING: totalValue = (totalValue + PieceType.KING.getPieceValue()); break; } } } } return totalValue; } }
Piece类
import m2_praticas.xadrez.enums.PieceColor; import m2_praticas.xadrez.enums.PieceType; public class Piece { PieceColor pieceColor; PieceType pieceType; public Piece(PieceColor pieceColor, PieceType pieceType) { this.pieceColor = pieceColor; this.pieceType = pieceType; } }
PieceType枚举
public enum PieceType { PAWN(1), ROOK(5), KNIGHT(3), BISHOP(3), QUEEN(9), KING(0); private int pieceValue; PieceType(int pieceValue){ this.pieceValue = pieceValue; } public int getPieceValue() { return pieceValue; } }
PieceColor枚举
public enum PieceColor { BLACK, WHITE; }
问题原因与修复方案
1. 空指针异常原因
- 棋盘初始化时,第2到第5行(i=2至i=5)的所有位置未创建Piece对象,这些位置的元素为null。遍历到null元素时,直接访问
elem.pieceColor必然触发空指针。 - 棋子初始化逻辑错误:使用连续的
if而非else if,导致后面的条件覆盖前面的设置(比如第0行所有列先被设为车,后续又被覆盖为马、象等),棋子位置完全不符合国际象棋规则。
2. 修复步骤
方案1:修正棋盘初始化逻辑
直接按国际象棋规则精确设置每个棋子的位置,避免条件覆盖:
public Board(){ board = new Piece[8][8]; // 初始化黑方棋子 // 第0行:黑方后排 board[0][0] = new Piece(PieceColor.BLACK, PieceType.ROOK); board[0][1] = new Piece(PieceColor.BLACK, PieceType.KNIGHT); board[0][2] = new Piece(PieceColor.BLACK, PieceType.BISHOP); board[0][3] = new Piece(PieceColor.BLACK, PieceType.QUEEN); board[0][4] = new Piece(PieceColor.BLACK, PieceType.KING); board[0][5] = new Piece(PieceColor.BLACK, PieceType.BISHOP); board[0][6] = new Piece(PieceColor.BLACK, PieceType.KNIGHT); board[0][7] = new Piece(PieceColor.BLACK, PieceType.ROOK); // 第1行:黑方兵 for (int j = 0; j < 8; j++) { board[1][j] = new Piece(PieceColor.BLACK, PieceType.PAWN); } // 初始化白方棋子 // 第6行:白方兵 for (int j = 0; j < 8; j++) { board[6][j] = new Piece(PieceColor.WHITE, PieceType.PAWN); } // 第7行:白方后排 board[7][0] = new Piece(PieceColor.WHITE, PieceType.ROOK); board[7][1] = new Piece(PieceColor.WHITE, PieceType.KNIGHT); board[7][2] = new Piece(PieceColor.WHITE, PieceType.BISHOP); board[7][3] = new Piece(PieceColor.WHITE, PieceType.QUEEN); board[7][4] = new Piece(PieceColor.WHITE, PieceType.KING); board[7][5] = new Piece(PieceColor.WHITE, PieceType.BISHOP); board[7][6] = new Piece(PieceColor.WHITE, PieceType.KNIGHT); board[7][7] = new Piece(PieceColor.WHITE, PieceType.ROOK); }
方案2:遍历前判空并简化价值计算
在avalia方法中先检查元素是否为null,再访问属性,同时省去冗余的switch逻辑:
public int avalia(PieceColor pieceColor){ int totalValue = 0; for (Piece[] row : board){ for (Piece elem : row){ // 先判空,再判断颜色 if(elem != null && elem.pieceColor == pieceColor){ // 直接调用枚举的getValue计算价值 totalValue += elem.pieceType.getPieceValue(); } } } return totalValue; }
内容的提问来源于stack exchange,提问作者OrlandoVSilva
相关产品推荐
相关产品推荐

