You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()时触发空指针异常。

修复方案

  1. 初始化矩阵:在main方法中Visual[][] visual = new Visual[3][3];代码行后,添加调用初始化方法的代码:
start(visual);
  1. 补充逻辑优化(可选):
  • 修正胜负判断逻辑:现有代码中if(victory.equals(""))逻辑反向,应改为if(!victory.equals(""))才会在有玩家获胜时触发结束逻辑。
  • 优化落子切换逻辑:只有当whoPlays()返回true(落子成功)时,才切换当前玩家符号,避免玩家选中已落子位置时误切换玩家。

内容的提问来源于stack exchange,提问作者Pedro Y

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 11:00:01