你好,我相對較新的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;
}
}
哪條線是359?在這行之前在代碼中放置一個斷點,啓動調試器並檢查變量的狀態...... – MadProgrammer 2014-10-03 05:24:34
那麼'形狀'和'tetrisPieces'在哪裏?考慮提供一個[可運行的示例](https://stackoverflow.com/help/mcve),它可以證明你的問題。這會減少混淆和更好的反應。您可能希望閱讀[Java TM編程語言的代碼約定](http://www.oracle.com/technetwork/java/codeconvtoc-136057.html),它將使人們更容易閱讀代碼和你閱讀其他人 – MadProgrammer 2014-10-03 05:29:05
@MadProgrammer好吧抱歉,我忘了放在我的形狀類。我會通讀公約,謝謝,這些都是基於講師給我們提供的骨架代碼。 – 2014-10-03 05:31:15