Java井字棋开发中Visual矩阵未初始化引发NullPointerException如何解决
井字棋开发空指针异常问题解决
问题背景
开发井字棋游戏时,使用Visual类型二维矩阵存储落子信息,调用drawGame方法渲染界面时抛出NullPointerException,推测与矩阵初始化相关。
错误信息
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.company.Visual.getSymbol()" because "visual[0][0]" is null at com.company.Main.drawGame(Main.java:48) at com.company.Main.main(Main.java:21)
相关代码
Main.java主类
package com.company; import java.util.Scanner; public class Main { public static void main(String[] args){ //variables Visual[][] visual = new Visual[3][3]; //public static Visual[3][3] visual = {{' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}}; char symbol='X'; boolean game = true; String victory=""; Scanner scan = new Scanner(System.in); //int line=0,colunm=0; //game while(game){ if(visual!=null)drawGame(visual); //drawGame(visual); victory = verifyVictory(visual); if(victory.equals("")){ System.out.printf("Player %s won!", victory); break; } try { whoPlays(visual, play(scan, symbol), symbol); if(symbol=='X'){ symbol='O'; }else{ symbol='X'; } } catch (Exception e) { System.out.println("Error!"); } } System.out.println("End"); } //function to call the Visual class and show the visual of tactoe public static void drawGame(Visual[][] visual){ System.out.printf(" 0 1 2\n"); System.out.printf("0 %c | %c | %C \n", visual[0][0].getSymbol(),visual[0][1].getSymbol(),visual[0][2].getSymbol()); System.out.printf(" --------------\n"); System.out.printf("1 %c | %c | %C \n",visual[1][0].getSymbol(),visual[1][1].getSymbol(),visual[1][2].getSymbol()); System.out.printf(" --------------\n"); System.out.printf("2 %c | %c | %C \n",visual[2][0].getSymbol(),visual[2][1].getSymbol(),visual[2][2].getSymbol()); } //clean the old drawGame() public static void clean(){ for(int i=0;i<50;i++){ System.out.println(""); } } //coords to play public static int[] play(Scanner scan, char symbol){ int p[] = new int[2]; System.out.printf("%s %c\n", "Who plays: ", symbol); System.out.print("Line: "); p[0] = scan.nextInt(); System.out.print("Colunm: "); p[1] = scan.nextInt(); return p; } //who is playing public static boolean whoPlays(Visual[][] visual, int p[], char symbol){ if(visual[p[0]][p[1]].getSymbol()==' '){ visual[p[0]][p[1]].setSymbol(symbol); return true; }else{ return false; } } //this is an attempt to inicialize the array visual, since I saw this might be the problem public static void start(Visual[][] visual){ for(int i=0;i<3;i++){ for(int c=0;c<3;c++){ visual[i][c] = new Visual(); } } } //still doing this, useless by now public static String verifyVictory(Visual[][] visual){ return ""; } }
Visual.java辅助类
package com.company; public class Visual { private char symbol; public Visual(){ this.symbol=' '; } public char getSymbol(){ return this.symbol; } public void setSymbol(char symbol){ if(this.symbol==' '){ this.symbol=symbol; }else{ System.out.println("Error"); } } }
问题原因
Java创建引用类型二维数组时,仅会为数组本身分配内存空间,数组内的所有元素默认值为null,你虽然已经编写了start()初始化方法为每个数组元素实例化Visual对象,但在main方法中声明二维数组后没有调用该初始化方法,导致访问visual[0][0].getSymbol()时触发空指针异常。
修复方案
- 初始化矩阵:在main方法中
Visual[][] visual = new Visual[3][3];代码行后,添加调用初始化方法的代码:
start(visual);
- 补充逻辑优化(可选):
- 修正胜负判断逻辑:现有代码中
if(victory.equals(""))逻辑反向,应改为if(!victory.equals(""))才会在有玩家获胜时触发结束逻辑。 - 优化落子切换逻辑:只有当
whoPlays()返回true(落子成功)时,才切换当前玩家符号,避免玩家选中已落子位置时误切换玩家。
内容的提问来源于stack exchange,提问作者Pedro Y
相关产品推荐
相关产品推荐

