使用idea
完整也可以在这下载:
https://yadi.sk/d/iKnQi4EtXF4pBw
Block .java
记录各种形状的方块
package com.company;
public class Block {
static final boolean[][][] Shape = {
// I
{
{ false, false, false, false },
{ true, true, true, true },
{ false, false, false, false },
{ false, false, false, false }
},
// J
{
{ true, false, false },
{ true, true, true },
{ false, false, false }
},
// L
{
{ false, false, true },
{ true, true, true },
{ false, false, false }
},
// O
{
{ true, true },
{ true, true }
},
// S
{
{ false, true, true },
{ true, true, false },
{ false, false, false }
},
// T
{
{ false, true, false },
{ true, true, true },
{ false, false, false }
},
// Z
{
{ true, true, false },
{ false, true, true },
{ false, false, false }
}
};
}
Tetris .java 从JPanel继承而来,实现主要功能
package com.company;
import com.sun.corba.se.spi.servicecontext.ServiceContextRegistry;
import sun.misc.Cleaner;
import javax.swing.*;
import java.awt.*;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.sql.Time;
import java.util.concurrent.BlockingDeque;
public class Tetris extends JPanel {
private static final int BlockSize = 10;//方块大小
private static final int BlockWidth = 16;//地图宽度
private static final int BlockHeight = 26;
private static final int TimeDelay = 1000;//刷新时间
private static final String[] AuthorInfo = {
"Author:","TEST"
};
private boolean[][] BlockMap = new boolean[BlockHeight][BlockWidth];
private int Score = 0;
private boolean IsPause = false;
static boolean[][][] Shape = Block.Shape;
private Point NowBlockPos;//记录下落方块位置
//注意Pos坐标是以左上角为零点,y为纵轴,x为横轴
private boolean[][] NowBlockMap,NextBlockMap;
private int NowBlockState,NextBlockState;
private Timer timer;
public Tetris() {
this.Init();
timer = new Timer(Tetris.TimeDelay,this.TimerListener);
timer.start();
this.addKeyListener(this.KeyAdapter);
}
private void getNextBlock() {
this.NowBlockState = this.NextBlockState;
this.NowBlockMap = this.NextBlockMap;
this.NextBlockState = this.CreateNewBlockState();
this.NextBlockMap = this.getBlockMap(NextBlockState);
this.NowBlockPos = this.CalNewBlockInitPos();
}
/**
*
* @param SrcNextBlockMap
* @param SrcNextBlockPos
* @return
*/
private boolean IsTouch(boolean[][] SrcNextBlockMap,Point SrcNextBlockPos) {
for (int i = 0; i < SrcNextBlockMap.length; i++) {
for (int j = 0; j < SrcNextBlockMap[i].length; j++) {
if (SrcNextBlockMap[i][j]) {
if (SrcNextBlockPos.y+i>=BlockHeight || SrcNextBlockPos.x+j>=BlockWidth || SrcNextBlockPos.x+j<0) {
return true;
} else {
if (SrcNextBlockPos.y+i<0) continue;
else if (this.BlockMap[SrcNextBlockPos.y+i][SrcNextBlockPos.x+j])
return true;
}
}
}
}
return false;
}
/**
* 固定方块到地图
*/
private boolean FixBlock() {
for (int i = 0; i < NowBlockMap.length; i++) {
for (int j = 0; j < NowBlockMap[i].length; j++) {
if (NowBlockMap[i][j]) {
//System.out.println(""+i+" "+j+"\n");
if (NowBlockPos.y+i < 0) {
return false;
} else {
BlockMap[NowBlockPos.y+i][NowBlockPos.x+j] = true;
}
}
}
}
return true;
}
private Point CalNewBlockInitPos() {
return new Point(BlockWidth/2-NowBlockMap[0].length/2,-NowBlockMap.length);
}
/**
* 初始化地图
*/
public void Init() {
for (int i = 0 ; i < BlockMap.length; i++)
for (int j = 0; j < BlockMap[i].length; j++)
BlockMap[i][j] = false;
Score = 0;
NowBlockState = CreateNewBlockState();
NowBlockMap = getBlockMap(NowBlockState);
NextBlockState = CreateNewBlockState();
NextBlockMap = getBlockMap(NextBlockState);
NowBlockPos = CalNewBlockInitPos();
repaint();
}
public void SetPause(boolean value) {
IsPause = value;
if (IsPause) {
timer.stop();
} else {
timer.restart();
}
this.repaint();
}
boolean GetPause() {
return this.IsPause;
}
private int CreateNewBlockState() {
int Sum = Shape.length*4;//一共有lenght种方块,每个方块通过旋转有四种状态
return (int) (Math.random()*1000)%Sum;
}
private boolean[][] getBlockMap(int BlockState) {
return RotateBlock(Shape[BlockState/4],BlockState%4);
}
private boolean[][] RotateBlock(boolean[][] shape,int time) {
time = (time%4+4)%4;
if (time == 0) {
return shape;
}
int height = shape[0].length;
int width = shape.length;
boolean[][] NextShape = new boolean[height][width];
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
NextShape[i][j] = shape[width-1-j][i];
return RotateBlock(NextShape,time-1);
}
/**
* 图形部分
*/
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//边界
for (int i = 0; i < BlockHeight+1; i++) {
g.drawRect(0,i*BlockSize,BlockSize,BlockSize);
g.drawRect((BlockWidth+1)*BlockSize,i*BlockSize,BlockSize,BlockSize);
}
for (int i = 0; i < BlockWidth; i++) {
g.drawRect((i + 1) * BlockSize, BlockHeight * BlockSize, BlockSize, BlockSize);
}
//fangkuan
for (int i = 0; i < NowBlockMap.length; i++) {
for (int j = 0; j < NowBlockMap[i].length; j++) {
if (NowBlockMap[i][j]) {
g.fillRect((1+NowBlockPos.x+j)*BlockSize,(NowBlockPos.y+i)*BlockSize,BlockSize,BlockSize);
System.out.println(""+i+" "+j+"\n");
}
}
}
for (int i = 0; i < BlockHeight; i++)
for (int j = 0; j < BlockWidth; j++)
if (BlockMap[i][j])
g.fillRect((1+j)*BlockSize,i*BlockSize,BlockSize,BlockSize);
for (int i = 0; i < NextBlockMap.length; i++) {
for (int j = 0; j < NextBlockMap[i].length; j++) {
if (NextBlockMap[i][j])
//g.fillRect((NextBlockPos.x+j)*BlockSize,(NowBlockPos.y+i)*BlockSize,BlockSize,BlockSize);
g.fillRect(190+j*Tetris.BlockSize, 30+i*BlockSize, BlockSize, BlockSize);
}
}
g.drawString("Score"+Score,190,10);
for (int i = 0; i < AuthorInfo.length; i++) {
g.drawString(AuthorInfo[i],190,100+i*20);
}
if (IsPause) {
g.setColor(Color.WHITE);
g.fillRect(70,100,50,20);
g.setColor(Color.BLACK);
g.drawString("PAUSE",75,113);
}
}
/**
* @return
*/
private int ClearLines() {
int lines = 0;
for (int i = 0; i < BlockMap.length; i++) {
boolean IsLine = true;
for (int j = 0; j < BlockMap[i].length; j++) {
if (!BlockMap[i][j]) {
IsLine = false;
break;
}
}
if (IsLine) {
for (int k = i; k > 0; k--) {
BlockMap[k] = BlockMap[k-1];
}
BlockMap[0] = new boolean[BlockWidth];
lines++;
}
}
return lines;
}
//
ActionListener TimerListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (IsTouch(NowBlockMap,new Point(NowBlockPos.x,NowBlockPos.y+1))) {
if (FixBlock()) {
Score += ClearLines();
getNextBlock();
} else {
JOptionPane.showMessageDialog(Tetris.this.getParent(),"GAME OVER");
Init();
}
} else {
NowBlockPos.y++;
}
repaint();
}
};
/*
按键操作
**/
void UpAction() {
boolean [][] DesBlockMap = RotateBlock(NowBlockMap,1);
if (!IsTouch(DesBlockMap,NowBlockPos)) {
NowBlockMap = DesBlockMap;
}
repaint();
}
void LeftAction() {
Point DesPoint;
DesPoint = new Point(NowBlockPos.x-1,NowBlockPos.y);
if (!IsTouch(NowBlockMap,DesPoint)) {
NowBlockPos = DesPoint;
}
repaint();
}
void RightAction() {
Point DesPoint;
DesPoint = new Point(NowBlockPos.x+1,NowBlockPos.y);
if (!IsTouch(NowBlockMap,DesPoint)) {
NowBlockPos = DesPoint;
}
repaint();
}
java.awt.event.KeyAdapter KeyAdapter = new java.awt.event.KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
System.out.println("GREGEGERG");
if (IsPause) {
return;
}
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN:
Point DesPoint;
DesPoint = new Point(NowBlockPos.x,NowBlockPos.y+1);
while (!IsTouch(NowBlockMap,DesPoint)) {
NowBlockPos = DesPoint;
DesPoint = new Point(NowBlockPos.x,NowBlockPos.y+1);
}
repaint();
break;
case KeyEvent.VK_UP:
UpAction();
break;
case KeyEvent.VK_LEFT:
LeftAction();
break;
case KeyEvent.VK_RIGHT:
RightAction();
break;
}
}
};
}
Main.java 主界面
updata:解决按键失效问题
package com.company;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.*;
class TetrisApp {
JFrame frame;
Tetris tetris;
JMenuBar menuBar;
JMenu gameMenu,helpMenu;
JMenuItem newGameItem,pauseItem,continueItem,exitItem;
JButton pauseButton,newGameButton;
TetrisApp() {
frame = new JFrame("Tetris Game");
menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
tetris = new Tetris();
tetris.setFocusable(true);
frame.add(tetris,BorderLayout.CENTER);
gameMenu = new JMenu("GAME");
newGameItem = new JMenuItem("新游戏");
pauseItem = new JMenuItem("暂停");
continueItem = new JMenuItem("继续");
exitItem = new JMenuItem("退出");
newGameItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tetris.Init();
}
});
pauseItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tetris.SetPause(true);
}
});
continueItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tetris.SetPause(false);
}
});
exitItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
gameMenu.add(newGameItem);
gameMenu.add(pauseItem);
gameMenu.add(continueItem);
gameMenu.add(exitItem);
menuBar.add(gameMenu);
// menuBar.add(pauseItem);
helpMenu = new JMenu("帮助");
JMenuItem helpItem = new JMenuItem("HELP");
helpItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(frame,"上:旋转 \n左右键:移动位置 \n下:加速","游戏帮助", JOptionPane.INFORMATION_MESSAGE);
}
});
helpMenu.add(helpItem);
menuBar.add(helpMenu);
JPanel panel = new JPanel();
newGameButton = new JButton("新游戏");
newGameButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tetris.Init();
tetris.requestFocus();
}
});
pauseButton = new JButton("暂停");
pauseButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boolean isPause = tetris.GetPause();
if (isPause) {
// System.out.println("开开开开");
pauseButton.setText("暂停");
tetris.SetPause(false);
} else {
// System.out.println("停停停停停");
pauseButton.setText("开始");
tetris.SetPause(true);
}
tetris.requestFocus();
}
});
JButton upButton,rightButton,leftButton;
upButton = new JButton("旋转");
leftButton = new JButton("<-");
rightButton = new JButton("->");
upButton.addActionListener(e -> {tetris.UpAction();tetris.requestFocus();});
leftButton.addActionListener(e -> {tetris.LeftAction();tetris.requestFocus();});
rightButton.addActionListener(e -> {tetris.RightAction();tetris.requestFocus();});
panel.add(upButton);
panel.add(leftButton);
panel.add(rightButton);
panel.add(newGameButton);
panel.add(pauseButton);
frame.add(panel,BorderLayout.SOUTH);
frame.setSize(320,370);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
public class Main {
public static void main(String[] args) {
new TetrisApp();
}
}