2014-10-03 102 views
0

你好,我相对较新的Java和我正在写一个俄罗斯方块风格的程序。我目前得到这样一个nullpointerException:在Java俄罗斯方块游戏中的空指针异常

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
at tetris2.GameBoard.drawSquare(Tetris.java:359) 
at tetris2.GameBoard.paint(Tetris.java:250) 

我已经标出了异常指向的行。我理解NulPointerException是什么,但我不能工作了,而不在这里创造 ,我引用一下班是我的代码:

public class Tetris { 

public static void createGUI() 
{ 
    final JFrame frame = new JFrame("159.235 - A2"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    final JPanel contentPane = new JPanel(new BorderLayout()); 
    frame.setContentPane(contentPane); 

    final GameBoard gameBoard = new GameBoard(); 
    contentPane.add(gameBoard, BorderLayout.CENTER); 

    frame.addKeyListener(new KeyListener() { 

     @Override 
     public void keyTyped(KeyEvent e) 
     { 
      gameBoard.keyTyped(e); 

     } 

     @Override 
     public void keyReleased(KeyEvent e) 
     { 
      gameBoard.keyReleased(e); 
     } 

     @Override 
     public void keyPressed(KeyEvent e) 
     { 
      switch (e.getKeyChar()) { 
      case KeyEvent.VK_ESCAPE: 
       gameBoard.pauseGame(); 
       System.exit(0); 
       break; 
      default: 
       gameBoard.keyPressed(e); 
      } 
     } 
    }); 

    frame.pack(); 
    frame.setResizable(false); 
    frame.setVisible(true); 

    // Note: you might want to add a button to start, pause, or resume the 
    // game instead of automatically starting it here 
    gameBoard.startGame(); 
} 

public static void main(String[] args) 
{ 
    SwingUtilities.invokeLater(new Runnable() { 

     @Override 
     public void run() 
     { 
      createGUI(); 
     } 
    }); 
} 
} 


class GameBoard extends JPanel implements KeyListener { 

private static final long serialVersionUID = 1L; 

// the number of rows and columns on the game board 
public static final int NUM_COLS = 10; 
public static final int NUM_ROWS = 20; 

// the size of each cell in pixels 
public static final int CELL_SIZE = 20; 

// the game board size in pixels 
public final int GAME_FIELD_WIDTH = NUM_COLS * CELL_SIZE; 
public final int GAME_FIELD_HEIGHT = NUM_ROWS * CELL_SIZE; 

// the interval between game state updates 
private int m_updateInterval = 500; 







// the game timer initiates an update to the game state 
private final Timer m_gameTimer = new Timer(m_updateInterval, 
     new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       if(isFallingFinished) { 
        isFallingFinished = false; 
        newPiece();; 
       } else { 
        oneLineDown(); 
       } 
      } 
     }); 

// the game board, with [0][0] being the bottom left cell 
//private final Block[][] m_cells = new Block[NUM_ROWS][NUM_COLS]; 

// the currently active shape 
private Shapes m_currentShape = new Shapes(); 



public int curX = 0; 
public int curY = 0; 
tetrisPieces[] board; 
boolean isFallingFinished = false; 
boolean isStarted = false; 
boolean isPaused = false; 
int numLinesRemoved = 0; 

// //////////////////////////////////////////////////////////////////// 
public GameBoard() 
{ 
    setMinimumSize(new Dimension(GAME_FIELD_WIDTH + 1, GAME_FIELD_HEIGHT)); 
    setPreferredSize(new Dimension(GAME_FIELD_WIDTH + 1, GAME_FIELD_HEIGHT)); 
    setOpaque(true); 

    // set-up the timer for the render loop 
    m_gameTimer.setInitialDelay(m_updateInterval); 
    m_gameTimer.setRepeats(true); 
    board = new tetrisPieces[GAME_FIELD_WIDTH * GAME_FIELD_HEIGHT]; 
    clearBoard(); 
    newPiece(); 



} 



int squareWidth() { return (int) getSize().getWidth()/GAME_FIELD_WIDTH;} 
int squareHeight() { return (int) getSize().getHeight()/GAME_FIELD_HEIGHT; } 
tetrisPieces shapeAt(int x, int y) { return board[(y * GAME_FIELD_WIDTH) + x]; } 

@Override 
public void keyPressed(KeyEvent e) 
{ 
    switch (e.getKeyCode()) { 
    case KeyEvent.VK_UP: 
     m_currentShape.rotateShape(); 
     break; 
    case KeyEvent.VK_DOWN: // move down 
     oneLineDown(); 
     break; 
    case KeyEvent.VK_LEFT: // move left 
     tryMove(m_currentShape, curX - 1, curY); 
     break; 
    case KeyEvent.VK_RIGHT: // move right 
     tryMove(m_currentShape, curX + 1, curY); 
     break; 
    case KeyEvent.VK_SPACE: // toggle pause/resume 
     if (m_gameTimer.isRunning()) pauseGame(); 
     else startGame(); 
     break; 
    } 
} 

@Override 
public void keyReleased(KeyEvent e) 
{ 
    switch (e.getKeyCode()) { 
    case KeyEvent.VK_DOWN: // disable down key 
     break; 
    case KeyEvent.VK_LEFT: // disable left key 
     break; 
    case KeyEvent.VK_RIGHT: // disable right key 
     break; 
    } 
} 

@Override 
public void keyTyped(KeyEvent e) 
{} 

public void startGame() 
{ 
    if(isPaused) 
     return; 

    isStarted = true; 
    isFallingFinished = false; 
    numLinesRemoved = 0; 
    clearBoard(); 

    board = new tetrisPieces[getWidth() * getHeight()]; 
    newPiece(); 
    m_gameTimer.start(); 
} 

public void pauseGame() 
{ 
    if (!isStarted) 
      return; 

     isPaused = !isPaused; 
     if(isPaused) { 
      m_gameTimer.stop(); 
      //statusbar.setText("paused"); 
     } else { 
      m_gameTimer.start(); 
      //statusbar.setText(String.valueOf(numLinesRemoved)); 
      } 
      repaint(); 
} 


public void paint(Graphics g) 
{ 
    super.paint(g); 

    Dimension size = getSize(); 
    int boardTop = (int) size.getHeight() - GAME_FIELD_HEIGHT * squareHeight(); 

    for (int i = 0; i < GAME_FIELD_HEIGHT; ++i) { 
     for (int j = 0; j < GAME_FIELD_WIDTH; ++j) { 
      tetrisPieces shapes = shapeAt(j, GAME_FIELD_HEIGHT - i -1); 
      if (shapes != tetrisPieces.noPiece) 
       drawSquare(g, 0 + j * squareWidth(),boardTop + i * squareHeight(), shapes); 
       //**This line above** 
     } 
    } 

    if(m_currentShape.getShape() != tetrisPieces.noPiece) { 
     for(int i = 0; i <4; ++i) { 
      int x = curX + + m_currentShape.x(i); 
      int y = curY - m_currentShape.y(i); 
      drawSquare(g, 0 + x * squareWidth(), 
          boardTop + (GAME_FIELD_HEIGHT - y - 1) * squareHeight(), 
          m_currentShape.getShape()); 
     } 
    } 
} 




private void oneLineDown() 
{ 
    if(!tryMove(m_currentShape, curX, curY - 1)) 
     pieceDropped(); 
} 

private void clearBoard() { 
    for (int i = 0; i <GAME_FIELD_HEIGHT * GAME_FIELD_WIDTH; ++i) 
     board[i] = tetrisPieces.noPiece; 
} 


private boolean tryMove(Shapes newPiece, int newX, int newY) { 
    for(int i = 0; i< 4; ++i) { 
     int x = newX + newPiece.x(i); 
     int y = newY - newPiece.y(i); 
     if(x < 0 || x >= GAME_FIELD_WIDTH || y < 0 || y >= GAME_FIELD_HEIGHT) 
      return false; 
     if(shapeAt(x, y) != tetrisPieces.noPiece) 
      return false; 
    } 

    m_currentShape = newPiece; 
    curX = newX; 
    curY = newY; 
    repaint(); 
    return true; 
} 

private void pieceDropped() { 
    for (int i =0; i < 4; ++i) { 
     int x = curX + m_currentShape.x(i); 
     int y = curY - m_currentShape.y(i); 
     board[(y * GAME_FIELD_WIDTH) + x] = m_currentShape.getShape(); 
    } 

    removeFullLines(); 

    if(!isFallingFinished) 
     newPiece(); 
} 

private void removeFullLines() { 

    int numFullLines = 0; 

    for(int i = GAME_FIELD_HEIGHT -1; i >= 0; --i) { 
     boolean lineIsFull = true; 

     for(int j = 0; j < GAME_FIELD_WIDTH; ++j) { 
      if(shapeAt(j, i) == tetrisPieces.noPiece) { 
       lineIsFull = false; 
       break; 
      } 
     } 
     if(lineIsFull) { 
      ++numFullLines; 
      for(int k = i; k < GAME_FIELD_HEIGHT - 1; ++k) { 
       for(int j = 0; j < GAME_FIELD_WIDTH; ++j) 
        board[(k* GAME_FIELD_WIDTH) + j] = shapeAt(j, k + 1); 
      } 
     } 
    } 
} 

private void newPiece() { 
    m_currentShape.setRandomShape(); 
    curX = GAME_FIELD_WIDTH/2 + 1; 
    curY = GAME_FIELD_HEIGHT - 1 + m_currentShape.minY(); 

    if(!tryMove(m_currentShape, curX, curY)) { 
     m_currentShape.setShape(tetrisPieces.noPiece); 
     m_gameTimer.stop(); 
     isStarted = false; 

    } 
} 



private void drawSquare(Graphics g, int x, int y, tetrisPieces shape) 
{ 
    Color colors[] = { new Color(0, 0, 0), new Color(204, 102, 102), 
          new Color(102, 204, 102), new Color(102, 102, 204), 
          new Color(204, 204, 102), new Color(204, 102, 204), 
          new Color(102, 204, 204), new Color(218, 170, 0) 
     }; 

Color color = colors[shape.ordinal()]; //**This line here** 

g.setColor(color); 
g.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2); 

g.setColor(color.brighter()); 
g.drawLine(x, y + squareHeight() - 1, x, y); 
g.drawLine(x, y, x + squareWidth() - 1, y); 

g.setColor(color.darker()); 
     g.drawLine(x + 1, y + squareHeight() - 1, 
        x + squareWidth() - 1, y + squareHeight() - 1); 
     g.drawLine(x + squareWidth() - 1, y + squareHeight() - 1, 
         x + squareWidth() - 1, y + 1); 
} 
} 

形状类:

public class Shapes { 

enum tetrisPieces { noPiece, ZShape, SSHape, TShape, LShape, SquareShape, 
        ReverseLShape} 

private tetrisPieces pieceShape; 
private int coords[][]; 
private int coordsTable[][][]; 


public Shapes() { 

    coords = new int[4][2]; 
    setShape(tetrisPieces.noPiece); 

} 

public void setShape(tetrisPieces shape) { 

    coordsTable = new int[][][] { 
     { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 
     { { 0, -1 }, { 0, 0 }, { -1, 0 }, { -1, 1 } }, 
     { { 0, -1 }, { 0, 0 }, { 1, 0 }, { 1, 1 } }, 
     { { 0, -1 }, { 0, 0 }, { 0, 1 }, { 0, 2 } }, 
     { { -1, 0 }, { 0, 0 }, { 1, 0 }, { 0, 1 } }, 
     { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }, 
     { { -1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } }, 
     { { 1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } } 
    }; 

    for(int i = 0; i < 4; i++) { 
     for(int j = 0; j<2; ++j) { 
      coords[i][j] = coordsTable[shape.ordinal()][i][j]; 
     } 
    } 
    pieceShape = shape; 

} 

private void setX(int index, int x) { coords[index][0] = x; } 
private void setY(int index, int y) { coords[index][1] = y; } 
public int x(int index) { return coords[index][0]; } 
public int y(int index) { return coords[index][1]; } 
public tetrisPieces getShape() { return pieceShape; } 

public void setRandomShape() 
{ 
    Random r = new Random(); 
    int x = Math.abs(r.nextInt()) % 6 + 1; 
    tetrisPieces[] values = tetrisPieces.values(); 
    setShape(values[x]); 
} 

public int minX() { 
    int m =coords[0][0]; 
    for (int i = 0; i < 4; i++) { 
     m = Math.min(m, coords[i][0]); 
    } 
    return m; 
} 

public int minY() { 
    int m = coords[0][1]; 
    for (int i =0; i <4; i++) { 
     m = Math.min(m, coords[i][1]); 
    } 
    return m; 
} 



public Shapes rotateShape() { 
    if(pieceShape == tetrisPieces.SquareShape) 
     return this; 

    Shapes result = new Shapes(); 
    result.pieceShape = pieceShape; 

    for(int i = 0; i <4; ++i) { 
     result.setX(i, -y(i)); 
     result.setY(i, x(i)); 
    } 
    return result; 
    } 
} 
+1

哪条线是359?在这行之前在代码中放置一个断点,启动调试器并检查变量的状态...... – MadProgrammer 2014-10-03 05:24:34

+1

那么'形状'和'tetrisPieces'在哪里?考虑提供一个[可运行的示例](https://stackoverflow.com/help/mcve),它可以证明你的问题。这会减少混淆和更好的反应。您可能希望阅读[Java TM编程语言的代码约定](http://www.oracle.com/technetwork/java/codeconvtoc-136057.html),它将使人们更容易阅读代码和你阅读其他人 – MadProgrammer 2014-10-03 05:29:05

+0

@MadProgrammer好吧抱歉,我忘了放在我的形状类。我会通读公约,谢谢,这些都是基于讲师给我们提供的骨架代码。 – 2014-10-03 05:31:15

回答

0
Color color = colors[shape.ordinal()]; 

唯一令可以为空,因为颜色在以前的行是iniyialized的,因此这行是shape

形状从哪里来?从行

tetrisPieces shapes = shapeAt(j, GAME_FIELD_HEIGHT - i -1); 

shapeAt()返回什么?

tetrisPieces shapeAt(int x, int y) { return board[(y * GAME_FIELD_WIDTH) + x]; } 

在执行该行之前是否初始化了board数组的元素?可能不会。调试器会确认。什么是越野车大概是这几行:

clearBoard(); 
board = new tetrisPieces[getWidth() * getHeight()]; 

第一个初始化板阵列的每一个元素,但第二扔掉初始化板阵列和一个新的空一个替换它。

+0

好的,谢谢删除该行删除了该问题,再次非常感谢! – 2014-10-03 05:43:11