用JAVA写一个俄罗斯方块游戏程序
时间: 2023-09-03 11:16:33 浏览: 109
好的,以下是一个简单的俄罗斯方块游戏程序的JAVA代码:
```java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class Tetris extends JFrame implements ActionListener {
private final int BOARD_WIDTH = 10;
private final int BOARD_HEIGHT = 22;
private Timer timer;
private boolean isFallingFinished = false;
private boolean isStarted = false;
private boolean isPaused = false;
private int numLinesRemoved = 0;
private int curX = 0;
private int curY = 0;
private JLabel statusbar;
private Shape curPiece;
private Shape.Tetrominoes[] board;
public Tetris() {
initUI();
}
private void initUI() {
Board board = new Board(this);
add(board);
statusbar = new JLabel(" 0");
add(statusbar, BorderLayout.SOUTH);
setSize(200, 400);
setTitle("Tetris");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public JLabel getStatusBar() {
return statusbar;
}
public boolean isStarted() {
return isStarted;
}
public boolean isPaused() {
return isPaused;
}
public Shape.Tetrominoes[] getBoard() {
return board;
}
public void start() {
if (isPaused)
return;
isStarted = true;
isFallingFinished = false;
numLinesRemoved = 0;
clearBoard();
newPiece();
timer.start();
}
public void pause() {
if (!isStarted)
return;
isPaused = !isPaused;
if (isPaused) {
timer.stop();
statusbar.setText("paused");
} else {
timer.start();
statusbar.setText(String.valueOf(numLinesRemoved));
}
repaint();
}
private void clearBoard() {
for (int i = 0; i < BOARD_HEIGHT * BOARD_WIDTH; i++) {
board[i] = Shape.Tetrominoes.NoShape;
}
}
private void newPiece() {
curPiece = new Shape();
curX = BOARD_WIDTH / 2 + 1;
curY = BOARD_HEIGHT - 1 + curPiece.minY();
if (!tryMove(curPiece, curX, curY)) {
curPiece.setShape(Shape.Tetrominoes.NoShape);
timer.stop();
isStarted = false;
statusbar.setText("game over");
}
}
private boolean tryMove(Shape 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 >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT)
return false;
if (shapeAt(x, y) != Shape.Tetrominoes.NoShape)
return false;
}
curPiece = newPiece;
curX = newX;
curY = newY;
repaint();
return true;
}
private void oneLineDown() {
if (!tryMove(curPiece, curX, curY - 1))
pieceDropped();
}
private void pieceDropped() {
for (int i = 0; i < 4; i++) {
int x = curX + curPiece.x(i);
int y = curY - curPiece.y(i);
board[(y * BOARD_WIDTH) + x] = curPiece.getShape();
}
removeFullLines();
if (!isFallingFinished)
newPiece();
}
private void removeFullLines() {
int numFullLines = 0;
for (int i = BOARD_HEIGHT - 1; i >= 0; i--) {
boolean lineIsFull = true;
for (int j = 0; j < BOARD_WIDTH; j++) {
if (shapeAt(j, i) == Shape.Tetrominoes.NoShape) {
lineIsFull = false;
break;
}
}
if (lineIsFull) {
numFullLines++;
for (int k = i; k < BOARD_HEIGHT - 1; k++) {
for (int j = 0; j < BOARD_WIDTH; j++)
board[(k * BOARD_WIDTH) + j] = shapeAt(j, k + 1);
}
}
}
if (numFullLines > 0) {
numLinesRemoved += numFullLines;
statusbar.setText(String.valueOf(numLinesRemoved));
isFallingFinished = true;
curPiece.setShape(Shape.Tetrominoes.NoShape);
}
}
private Shape.Tetrominoes shapeAt(int x, int y) {
return board[(y * BOARD_WIDTH) + x];
}
@Override
public void actionPerformed(ActionEvent e) {
if (isFallingFinished) {
isFallingFinished = false;
newPiece();
} else {
oneLineDown();
}
}
private void startGame() {
isPaused = false;
isStarted = true;
isFallingFinished = false;
numLinesRemoved = 0;
clearBoard();
newPiece();
timer.start();
}
public static void main(String[] args) {
Tetris game = new Tetris();
game.setVisible(true);
game.startGame();
}
private class Board extends JPanel {
private final int SQUARE_SIZE = 20;
public Board(ActionListener listener) {
setPreferredSize(new Dimension(BOARD_WIDTH * SQUARE_SIZE,
BOARD_HEIGHT * SQUARE_SIZE));
setBackground(Color.BLACK);
setFocusable(true);
addKeyListener(new TAdapter());
timer = new Timer(400, listener);
board = new Shape.Tetrominoes[BOARD_WIDTH * BOARD_HEIGHT];
clearBoard();
}
private void drawSquare(Graphics g, int x, int y, Shape.Tetrominoes 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()];
g.setColor(color);
g.fillRect(x + 1, y + 1, SQUARE_SIZE - 2, SQUARE_SIZE - 2);
g.setColor(color.brighter());
g.drawLine(x, y + SQUARE_SIZE - 1, x, y);
g.drawLine(x, y, x + SQUARE_SIZE - 1, y);
g.setColor(color.darker());
g.drawLine(x + 1, y + SQUARE_SIZE - 1,
x + SQUARE_SIZE - 1, y + SQUARE_SIZE - 1);
g.drawLine(x + SQUARE_SIZE - 1, y + SQUARE_SIZE - 1,
x + SQUARE_SIZE - 1, y + 1);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension size = getSize();
int boardTop = (int) size.getHeight() - BOARD_HEIGHT * SQUARE_SIZE;
for (int i = 0; i < BOARD_HEIGHT; i++) {
for (int j = 0; j < BOARD_WIDTH; j++) {
Shape.Tetrominoes shape = shapeAt(j, BOARD_HEIGHT - i - 1);
if (shape != Shape.Tetrominoes.NoShape)
drawSquare(g, j * SQUARE_SIZE,
boardTop + i * SQUARE_SIZE, shape);
}
}
if (curPiece.getShape() != Shape.Tetrominoes.NoShape) {
for (int i = 0; i < 4; i++) {
int x = curX + curPiece.x(i);
int y = curY - curPiece.y(i);
drawSquare(g, x * SQUARE_SIZE,
boardTop + (BOARD_HEIGHT - y - 1) * SQUARE_SIZE,
curPiece.getShape());
}
}
}
}
private class TAdapter extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
if (!isStarted || curPiece.getShape() == Shape.Tetrominoes.NoShape) {
return;
}
int keycode = e.getKeyCode();
if (keycode == 'p' || keycode == 'P') {
pause();
return;
}
if (isPaused)
return;
switch (keycode) {
case KeyEvent.VK_LEFT:
tryMove(curPiece, curX - 1, curY);
break;
case KeyEvent.VK_RIGHT:
tryMove(curPiece, curX + 1, curY);
break;
case KeyEvent.VK_DOWN:
tryMove(curPiece.rotateRight(), curX, curY);
break;
case KeyEvent.VK_UP:
tryMove(curPiece.rotateLeft(), curX, curY);
break;
case KeyEvent.VK_SPACE:
dropDown();
break;
case 'd':
oneLineDown();
break;
case 'D':
oneLineDown();
break;
}
}
}
private void dropDown() {
int newY = curY;
while (newY > 0) {
if (!tryMove(curPiece, curX, newY - 1))
break;
newY--;
}
pieceDropped();
}
}
class Shape {
public enum Tetrominoes {NoShape, ZShape, SShape, LineShape, TShape, SquareShape, LShape, MirroredLShape}
private Tetrominoes pieceShape;
private int coords[][];
private int[][][] coordsTable;
public Shape() {
coords = new int[4][2];
setShape(Tetrominoes.NoShape);
}
public void setShape(Tetrominoes 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 Tetrominoes getShape() {
return pieceShape;
}
public void setRandomShape() {
Random r = new Random();
int x = Math.abs(r.nextInt()) % 7 + 1;
Tetrominoes[] values = Tetrominoes.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 Shape rotateLeft() {
if (pieceShape == Tetrominoes.SquareShape)
return this;
Shape result = new Shape();
result.pieceShape = pieceShape;
for (int i = 0; i < 4; ++i) {
result.setX(i, y(i));
result.setY(i, -x(i));
}
return result;
}
public Shape rotateRight() {
if (pieceShape == Tetrominoes.SquareShape)
return this;
Shape result = new Shape();
result.pieceShape = pieceShape;
for (int i = 0; i < 4; ++i) {
result.setX(i, -y(i));
result.setY(i, x(i));
}
return result;
}
}
```
这个程序使用了 Java Swing 框架来创建游戏界面和用户交互,实现了俄罗斯方块的基本功能。
阅读全文