2014-02-17 46 views
2

我在這裏收到一個空指針異常,我不知道爲什麼。在我的Java應用程序中需要幫助找到Nullpointer異常

import cs251.lab2.GomokuGUI; 
import cs251.lab2.GomokuModel; 

public class Gomoku implements GomokuModel { 

public Square[][] gameBoard; 

public static void main(String[] args) { 
    Gomoku game = new Gomoku(); 
    if (args.length > 0) { 
     game.setComputerPlayer(args[0]); 
    } 
    GomokuGUI.showGUI(game);//This calls newGame(). 
    } 

@Override 
public void newGame() {  //Generic constant values. 
    this.gameBoard = new Square[NUM_HSQUARES][NUM_VSQUARES]; 

    // For every block 
    for (Square[] s : gameBoard) 
     // And every element of that block 
     for (Square ss : s) 
      // Reset to empty. 
      {ss = Square.EMPTY;} 

} 

@Override 
public String boardString() { 
    String output = ""; 

    //This is where the problem is!! 
    for (Square[] s : this.gameBoard) // For every block 
    { 
     //output appends either " ", "x" or "o" accordingly. 
     for (Square ss : s)//For every element of the block. 
      {output += ss.toChar();} 

     // Must be time for a new row already! 
     output += "\n"; 
    } 

    //output should now be some big nasty string of love xoxo\n baby. 
    return output; 
} 
} 

調用newGame()

以下各行存在,並通過GomokuGUI.class

public static void showGUI(final GomokuModel model) { 
     // For thread safety, invoke GUI code on event-dispatching thread 
     SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        new GomokuGUI(model); 
       } 
      }); 
    } 

..... 稱爲.....

 private GomokuGUI (GomokuModel gomokuModel) { 
     model = gomokuModel; 
     model.newGame (); 
     //Buncha GUI code... 
     } 

如果我刪除了這個。參考我仍然收到錯誤。也許我誤解了這個?我想通過在newGame()內創建大小來創建一個與這個遊戲實例關聯的獨特對象gameBoard,並且通過調用game.gameBoard(這是函數內部的this.gameBoard),我可以查看它的元素。

全GomokuGUI.class文件

package cs251.lab2; 

import java.awt.*; 
import java.awt.event.*; 

import javax.swing.*; 

/** 
* This is the graphical user interface for the Gomoku game. 
*/ 
public class GomokuGUI { 

    /** 
    * Class used to display the Gomoku game board 
    */ 
    private class BoardPanel extends JPanel { 

     /** Used to shut up the compiler */ 
     private static final long serialVersionUID = 1L; 

     /** 
     * Draws the x's and o's on the game board in the right places. 
     * @param g Graphics context for the component 
     */ 
     public void drawBoard (Graphics2D g) { 

      // Read the string from the model so I know what to draw, 
      // convert to lowercase just in case. 
      String s = model.boardString().toLowerCase(); 

      // Split board into rows 
      String[] rowStrings = s.split("\\n"); 

      // Figure out number of rows and columns 
      int numRows = rowStrings.length; 
      int numCols = rowStrings[0].length(); 

      // Use a somewhat wide pen based on size of box 
      int offset = SQUARE_SIZE/5; 
      int x2offset = 2 * offset; 
      g.setStroke (new BasicStroke (offset)); 

      // Draw the signs on the board (within the squares) 
      for (int row = 0; row < numRows; row++) { 
       for (int col = 0; col < numCols; col++) { 

        // Choose what to do depending on the character in the string I got 
        switch (rowStrings[row].charAt(col)) { 

        case 'o': // Draw a ring 
         g.setColor (Color.BLUE); 
         g.drawOval (col * SQUARE_SIZE + offset, 
            row * SQUARE_SIZE + offset, 
            SQUARE_SIZE - x2offset, 
            SQUARE_SIZE - x2offset); 
         break; 

        case 'x': // Draw an X 
         g.setColor (Color.RED); 
         g.drawLine (col * SQUARE_SIZE + offset, 
            row * SQUARE_SIZE + offset, 
            (col + 1) * SQUARE_SIZE - offset, 
            (row + 1) * SQUARE_SIZE - offset); 
         g.drawLine ((col + 1) * SQUARE_SIZE - offset, 
            row * SQUARE_SIZE + offset, 
            col * SQUARE_SIZE + offset, 
            (row + 1) * SQUARE_SIZE - offset); 
         break; 
        } 
       } 
      } 
     } 

     /** 
     * Mainly used to redraw the grid on the board, so that it's always there. 
     */ 
     @Override 
     public void paintComponent (Graphics g) { 
      g.setColor (Color.BLACK); 
      int width = getWidth (); 
      int height = getHeight (); 
      for (int row = 0; row <= GomokuModel.NUM_VSQUARES; row++) { 
       int line = row * SQUARE_SIZE; 

       // Draw the vertical lines 
       g.drawLine (0, line, width, line); 

       // Draw the horizontal lines 
       g.drawLine (line, 0, line, height); 
      } 

      // Then draw the contents 
      drawBoard ((Graphics2D) g); 
     } 
    } 

    /** 
    * Handles a mouse click on the board. 
    * @param x X position of the click 
    * @param y Y position of the click 
    */ 
    private void doMouseClick(int x, int y) { 
     int row = y/SQUARE_SIZE; 
     int col = x/SQUARE_SIZE; 

     boolean gameOver = true; 

     // Check current status and decide what to do 
     GomokuModel.Outcome outcome = model.doClick (row, col); 

     // Better repaint so that the latest move shows up 
     boardFrame.repaint (); 

     // If necessary present a dialog box 
     switch (outcome) { 
     case DRAW: 
      JOptionPane.showMessageDialog (null, "Draw Game!", "Game Over", 
              JOptionPane.INFORMATION_MESSAGE); 
      break; 
     case CROSS_WINS: 
      JOptionPane.showMessageDialog (null, "Cross Wins!", "Game Over", 
              JOptionPane.INFORMATION_MESSAGE); 
      break; 
     case RING_WINS: 
      JOptionPane.showMessageDialog (null, "Ring Wins!", "Game Over", 
              JOptionPane.INFORMATION_MESSAGE); 
      break; 
     default: 
      // No action to take. Either game is over or someone clicked on the wrong spot. 
      gameOver = false; 
      break; 
     } 

     if (gameOver) { 
      // Question user about another game, and either quit or restart 
      int choice = JOptionPane.showConfirmDialog (null, "Play again?", "Play again?", 
                 JOptionPane.YES_NO_OPTION); 
      if (choice == JOptionPane.NO_OPTION) { 
       System.exit (0); 
      } else { 
       model.newGame(); 
      } 
     } 

     // Repaint after user choose a new game as otherwise we'll still see the old 
     // contents of the board, and that's no fun. 
     boardFrame.repaint(); 
    } 

    /** Size in pixels of each square */ 
    public static final int SQUARE_SIZE = 20; 

    /** Reference to the model class */ 
    private final GomokuModel model; 

    /** Reference to my board */ 
    private final JFrame boardFrame; 

    /** 
    * Constructor for the GUI. 
    * @param gomokuModel Reference to a model that correctly 
    * implements the interface, so that I know that all methods are 
    * there. 
    */ 
    private GomokuGUI (GomokuModel gomokuModel) { 
     model = gomokuModel; 
     model.newGame (); 

     // Create the frame 
     boardFrame = new JFrame (); 
     boardFrame.setTitle ("Gomoku"); 

     // Create the board 
     BoardPanel boardPanel = new BoardPanel (); 
     boardPanel.setPreferredSize (new Dimension (
             GomokuModel.NUM_HSQUARES * SQUARE_SIZE + 1, 
             GomokuModel.NUM_VSQUARES * SQUARE_SIZE + 1)); 
     boardPanel.addMouseListener (new MouseAdapter() { 

       @Override 
       public void mouseClicked (MouseEvent e) { 

        int x = e.getX (); 
        int y = e.getY (); 
        doMouseClick(x, y); 
       } 
      }); 

     // Create status panel for new game and quit buttons 
     JPanel statusPanel = new JPanel (new FlowLayout ()); 
     statusPanel.setPreferredSize (new Dimension (
             GomokuModel.NUM_HSQUARES * SQUARE_SIZE, 50)); 

     // Create a new New Game Button 
     JButton newGameButton = new JButton ("New Game"); 
     newGameButton.addActionListener (new ActionListener () { 
       public void actionPerformed (ActionEvent e) { 
        model.newGame (); 
        boardFrame.repaint (); 
       } 
      }); 
     statusPanel.add (newGameButton); 

     // Create a nice quit button 
     JButton quitButton = new JButton ("Quit"); 
     quitButton.addActionListener (new ActionListener () { 
       public void actionPerformed (ActionEvent e) { 
        System.exit (0); 
       } 
      }); 
     statusPanel.add (quitButton); 

     // Add the panels to the frame 
     boardFrame.add (statusPanel, BorderLayout.NORTH); 
     boardFrame.add (boardPanel, BorderLayout.CENTER); 

     // Make sure it looks good 
     boardFrame.pack (); 
     boardFrame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
     boardFrame.setLocationRelativeTo (null); 
     boardFrame.setResizable (false); 
     boardFrame.setVisible (true); 
    } 

    /** 
    * Construct and display GUI for a Gomoku game 
    * @param model Reference to a model that correctly 
    * implements the interface, so that I know that all methods are 
    * there. 
    */ 
    public static void showGUI(final GomokuModel model) { 
     // For thread safety, invoke GUI code on event-dispatching thread 
     SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        new GomokuGUI(model); 
       } 
      }); 
    } 
} 
+0

你調用'newGame()'?我想看一看。 「Foo」是爲了「Gomoku」嗎? –

+0

是Foo == Gomoku(我改變了這一點,它是從修剪評論和枯木代碼剩下的)。我已經包含了調用newGame()的行。 – user1695505

+0

在'newGame()'之前調用'boardString()'是否可能? –

回答

3
// For every block 
for (Square[] s : gameBoard) 
    for (Square ss : s) 
     // Reset to empty. 
     {ss = Square.EMPTY;} 

這個循環沒有做任何事情。這相當於:

// For every block 
for (Square[] s : gameBoard) { 
    for(int i = 0; i < s.length; i++) { 
     Square ss; 
     ss = s[i]; 
     ss = Square.EMPTY; 
    } 
} 

你可以看到它並沒有真正改變電路板。

相反,這樣做:

for(Square[] s : gameBoard) 
    for(int i = 0; i < s.length; i++) 
     s[i] = Square.EMPTY; 

或這樣的:(和進口java.util.Arrays中)

for(Square[] s : gameBoard) 
    Arrays.fill(s, Square.EMPTY); 
+0

正是這個問題!對我而言,這是一個非常大的誤解,關於我如何使用該循環。你的回答是富有洞察力和教育性的,謝謝! – user1695505