<span style="font-size:18px;"><strong>package com.chen.Tetris;
import java.util.Random;
/**
*方块类,每个方块类有四个格子,分别表示(T,L,J,Z,I,O,S)方块的类型
*/
public abstract class Tetromino {
Cell[] cells = new Cell[4];
/**定义一个存储状态的变量*/
protected State[] states ;
/**定义一个旋转序号*/
protected int index = 10;
/**
* 创建一个内部类,用来实现存储旋转的状态
*/
protected class State{
int row0,col0,row1,col1,row2,col2,row3,col3;
public State(int row0, int col0, int row1, int col1, int row2,
int col2, int row3, int col3) {
super();
this.row0 = row0;
this.col0 = col0;
this.row1 = row1;
this.col1 = col1;
this.row2 = row2;
this.col2 = col2;
this.row3 = row3;
this.col3 = col3;
}
}
/**方块向右移*/
public void moveRigth(){
for(int i=0; i<cells.length; i++)
cells[i].moveRigth();
}
/**方块向左移*/
public void moveLeft(){
for(int i=0; i<cells.length; i++){
cells[i].moveLeft();
}
}
/**随机生成一个方块*/
public static Tetromino randomOne(){
Random random = new Random();
int key = random.nextInt(7);
switch (key) {
case 1:return new T();
case 2:return new L();
case 3:return new J();
case 4:return new Z();
case 5:return new I();
case 6:return new O();
case 0:return new S();
default :return null;
}
}
/**向下移动*/
public void moveDown() {
for(int i=0; i<cells.length; i++){
cells[i].moveDown();
}
}
public void rotateRigth(){
index ++;
int n = index % states.length;
State aState = states[n];
Cell o = cells[0];
int row = o.getRow();
int col = o.getCol();
cells[1].setRow(row+aState.row1);
cells[1].setCol(col+aState.col1);
cells[2].setRow(row+aState.row2);
cells[2].setCol(col+aState.col2);
cells[3].setRow(row+aState.row3);
cells[3].setCol(col+aState.col3);
}
public void rotateLeft(){
index--;
int n = index % states.length;//求出下一步旋转的状态
Cell o = cells[0];//把第0个方格取出来作为轴
int row = o.getRow();
int col = o.getCol();//取出轴的坐标
State aState = states[n];//取出状态数
cells[1].setRow(row+aState.row1);
cells[1].setCol(col+aState.col1);
cells[2].setRow(row+aState.row2);
cells[2].setCol(col+aState.col2);
cells[3].setRow(row+aState.row3);
cells[3].setCol(col+aState.col3);
}
}
class I extends Tetromino{
public I(){
cells[0] = new Cell(0, 4, Tetris.I);
cells[1] = new Cell(0, 3, Tetris.I);
cells[2] = new Cell(0, 5, Tetris.I);
cells[3] = new Cell(0, 6, Tetris.I);
states = new State[2];
states[0] = new State(0,0,0,-1,0,1,0,2);
states[1] = new State(0,0,-1,0,1,0,2,0);
}
}
class L extends Tetromino{
public L(){
cells[0] = new Cell(0, 4, Tetris.L);
cells[1] = new Cell(0, 3, Tetris.L);
cells[2] = new Cell(0, 5, Tetris.L);
cells[3] = new Cell(1, 3, Tetris.L);
states = new State[4];
states[0] = new State(0,0,0,1,0,-1,-1,1);
states[1] = new State(0,0,1,0,-1,0,1,1);
states[2] = new State(0,0,0,-1,0,1,1,-1);
states[3] = new State(0,0,-1,0,1,0,-1,-1);
}
}
class S extends Tetromino{
public S(){
cells[0] = new Cell(0, 4, Tetris.S);
cells[1] = new Cell(0, 5, Tetris.S);
cells[2] = new Cell(1, 3, Tetris.S);
cells[3] = new Cell(1, 4, Tetris.S);
states = new State[2];
states[0] = new State(0,0,0,-1,-1,0,-1,1);
states[1] = new State(0,0,-1,0,0,1,1,1);
}
}
class T extends Tetromino{
public T(){
cells[0] = new Cell(0, 4, Tetris.T);
cells[1] = new Cell(0, 3, Tetris.T);
cells[2] = new Cell(0, 5, Tetris.T);
cells[3] = new Cell(1, 4, Tetris.T);
states = new State[4];
states[0] = new State(0,0,0,-1,0,1,1,0);
states[1] = new State(0,0,-1,0,1,0,0,-1);
states[2] = new State(0,0,0,1,0,-1,-1,0);
states[3] = new State(0,0,1,0,-1,0,0,1);
}
}
class Z extends Tetromino{
public Z(){
cells[0] = new Cell(1, 4, Tetris.Z);
cells[1] = new Cell(0, 3, Tetris.Z);
cells[2] = new Cell(0, 4, Tetris.Z);
cells[3] = new Cell(1, 5, Tetris.Z);
states = new State[2];
states[0] = new State(0,0,-1,-1,-1,0,0,1);
states[1] = new State(0,0,-1,1,0,1,1,0);
}
}
class J extends Tetromino{
public J(){
cells[0] = new Cell(0, 4, Tetris.J);
cells[1] = new Cell(0, 3, Tetris.J);
cells[2] = new Cell(0, 5, Tetris.J);
cells[3] = new Cell(1, 5, Tetris.J);
states = new State[4];
states[0] = new State(0,0,0,-1,0,1,1,1);
states[1] = new State(0,0,-1,0,1,0,1,-1);
states[2] = new State(0,0,0,1,0,-1,-1,-1);
states[3] = new State(0,0,1,0,-1,0,-1,1);
}
}
class O extends Tetromino{
public O(){
cells[0] = new Cell(0, 4, Tetris.O);
cells[1] = new Cell(0, 5, Tetris.O);
cells[2] = new Cell(1, 4, Tetris.O);
cells[3] = new Cell(1, 5, Tetris.O);
states = new State[2];
states[0] = new State(0,0,0,1,1,0,1,1);
states[1] = new State(0,0,0,1,1,0,1,1);
}
}
<pre name="code" class="java">package com.chen.Tetris;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.net.Inet4Address;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.RepaintManager;
/**
* 俄罗斯方块游戏的主窗口类
*/
public class Tetris extends JPanel{
/**得分*/
private int score;
private static int[] scores = {0,5,10,20,40};
/**销毁的行数*/
private int lines;
/**正在下落的方块*/
private Tetromino tetromino;
/**下一个准备下落的方块*/
private Tetromino tetrominoNxet;
/**墙*/
private Cell[][] walls;
/**定义定时器的参数*/
private int index ;
private int speed ;
private int level;
private static final int ROWS = 20;
private static final int COLS = 10;
private static final int CELL_SIZE = 26;
/**添加游戏状态的参数*/
private int state;
private static final int RUNNING = 0;
private static final int PAUSE = 1;
private static final int GAMEOVER = 2;
/**初始化数据*/
public Tetris(){
lines = 0;
score = 0;
state = 0;
walls = new Cell[ROWS][COLS];
}
/***
* 创建静态代码块,将磁盘里面的图片,读取到内存中成为静态对象
*/
private static BufferedImage tetris;
public static BufferedImage I;
public static BufferedImage S;
public static BufferedImage T;
public static BufferedImage Z;
public static BufferedImage L;
public static BufferedImage J;
public static BufferedImage O;
private static BufferedImage game_over;
private static BufferedImage pause;
static{
try{
tetris = ImageIO.read(Tetris.class.getResource("tetris.png"));
T = ImageIO.read(Tetris.class.getResource("T.png"));
S = ImageIO.read(Tetris.class.getResource("S.png"));
I = ImageIO.read(Tetris.class.getResource("I.png"));
Z = ImageIO.read(Tetris.class.getResource("Z.png"));
L = ImageIO.read(Tetris.class.getResource("L.png"));
J = ImageIO.read(Tetris.class.getResource("J.png"));
O = ImageIO.read(Tetris.class.getResource("O.png"));
game_over = ImageIO.read(Tetris.class.getResource("game-over.png"));
pause = ImageIO.read(Tetris.class.getResource("pause.png"));
}catch(Exception e ){
}
}
/**重写paint方法*/
public void paint(Graphics g){
g.drawImage(tetris, 0, 0, null);
g.translate(15, 15);
printWall(g);
printTetromino(g);
printTetrominoNext(g);
printScore(g);
printState(g);
}
/**绘制游戏当前状态*/
private void printState(Graphics g){
switch (state) {
case GAMEOVER:
g.drawImage(game_over, -15, -15, null);
break;
case PAUSE:
g.drawImage(pause, -15, -15,null);
break;
}
}
/**绘制墙*/
public void printWall(Graphics g){
for(int row = 0;row < ROWS;row++){
for(int col = 0;col < COLS;col++){
if(walls[row][col] == null){
g.drawRect(col*26, row*26, 26, 26);
}else {
g.drawImage(walls[row][col].getImage(), col*26, row*26,null );
}
}
}
}
/**打印正在下落的方块*/
private void printTetromino(Graphics g){
Cell[] cells = tetromino.cells;
for(int i = 0 ;i<cells.length;i++){
int x =cells[i].getCol()*26;
int y = cells[i].getRow()*26;
BufferedImage image = cells[i].getImage();
g.drawImage(image, x, y, null);
}
}
/**打印下一个要下落的方块*/
private void printTetrominoNext(Graphics g){
Cell[] cells = tetrominoNxet.cells;
for(int i= 0 ;i<cells.length;i++){
Cell cell = cells[i];
int x = (cell.getCol()+10)*CELL_SIZE;
int y = (cell.getRow()+1)*CELL_SIZE;
g.drawImage(cell.getImage(), x, y, null);
}
}
/**打印分数和销毁的行数*/
private void printScore(Graphics g){
int x =297, y = 160;
Font font = new Font(Font.SANS_SERIF, Font.BOLD, 30);
g.setFont(font);
g.setColor(new Color(0x667799));
g.drawString("SCORE:"+score, x+2, y+2);
y += 56;
g.drawString("LINES:"+lines, x+2, y+2);
y += 56;
g.drawString("LEVEL:"+level, x+2, y+2);
x = 297; y = 160;
g.drawString("SCORE:"+score, x, y);
y += 56;
g.drawString("LINES:"+lines, x, y);
y += 56;
g.drawString("LEVEL:"+level, x, y);
}
/**创建键盘接受监听器,监听从键盘的操作, 匿名内部类*/
KeyListener listener = new KeyListener() {
@Override
/**输入某个键的时候,执行该方法*/
public void keyTyped(KeyEvent e) {
}
@Override
/**按键按下起来后,执行该方法*/
public void keyReleased(KeyEvent e) {
}
@Override
/**按键一按下就执行该方法*/
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch(state){
case PAUSE:
pauseAction(key);
break;
case GAMEOVER:
game_overAction(key);
break;
case RUNNING:
runningAction(key);
break;
}
repaint();//执行完该方法以后,立刻调用paint方法,重新打印
}
};
/**pause状态时*/
public void pauseAction(int key){
switch(key){
case KeyEvent.VK_Q :
System.exit(0);
break;
case KeyEvent.VK_P :
state = RUNNING;
index = 0;
break;
}
}
/**game_over状态时*/
public void game_overAction(int key){
switch(key){
case KeyEvent.VK_Q :
System.exit(0);
break;
case KeyEvent.VK_S:
restartGame();
break;
}
}
/**running状态时*/
private void runningAction(int key){
switch(key){
case KeyEvent.VK_Q :
System.exit(0);
break;
case KeyEvent.VK_P :
state = PAUSE;
break;
case KeyEvent.VK_RIGHT :
moveRigthAction();
break;
case KeyEvent.VK_LEFT:
moveLeftAction();
break;
case KeyEvent.VK_DOWN:
moveDownAction();
break;
case KeyEvent.VK_SPACE:
hardDownAction();
break;
case KeyEvent.VK_UP:
roateRigthAction();
break;
}
}
/**重新开始游戏*/
private void restartGame(){
this.score = 0;
this.index = 0;
this.lines = 0;
this.walls = new Cell[ROWS][COLS];
this.tetromino = Tetromino.randomOne();
this.tetrominoNxet = Tetromino.randomOne();
this.state = RUNNING;
}
//添加定时器,匿名内部类
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
index ++;
level = (score/500+1);
speed = 41 - level;
if(index % speed ==0 && state == RUNNING)
moveDownAction();
repaint();
}
};
/**启动方法*/
public void action(){
tetromino = Tetromino.randomOne();
tetrominoNxet = Tetromino.randomOne();
//在当前面板上将监听器注册进去
addKeyListener(listener);
//为当前面板获取输入焦点,以便获取键盘输入的信息
setFocusable(true);
//等待键盘输入信息
requestFocus();
Timer timer = new Timer();
timer.schedule(timerTask, 0,10);
}
/**当前方块向右移动的方法
* 算法描述:先将方块向右移,如果有重合或者越界,则返回即再向左移
* */
private void moveRigthAction(){
tetromino.moveRigth();
if(outOfBound() || coincidence())
tetromino.moveLeft();
}
/**当前放开向左移的方法*/
private void moveLeftAction(){
tetromino.moveLeft();
if (outOfBound() || coincidence()) {
tetromino.moveRigth();
}
}
/**outOfBound判断是否出界
* 算法描述:取出当前方块的每一个格子,与边界参数进行比较
* true代表已越界
*/
public boolean outOfBound(){
Cell[] cells = tetromino.cells;
for(int i=0; i<cells.length; i++){
Cell cell = cells[i];
int row = cell.getRow();
int col = cell.getCol();
if(col<0 || col>=COLS || row<0 || row>=ROWS)
return true;
}
return false;
}
/**判断与其它格子是不是有重合的地方,如有重合则不能移动
* 算法描述:取出当前方块中的每一个格子,然后将它的位置与墙
* 的位置进行比较。true代表返回有重合
* */
public boolean coincidence(){
Cell[] cells = tetromino.cells;
for(int i=0; i<cells.length; i++){
Cell cell = cells[i];
int row = cell.getRow();
int col = cell.getCol();
if(walls[row][col] != null)
return true;
}
return false;
}
/**方块软下落的方法
* 1、先判断方块是否能下落,能下落即下落
* 2.如果不能下落,则将当前方块打进墙里面,然后再销毁行数
* 3.销毁完行数之后再判断游戏是否接束,如果没有结束则替换
* 掉当前方块和下一个下落的方块
* */
public void moveDownAction(){
if(isCanDown())
tetromino.moveDown();
else {
putInToWall();
int line = dropLine();
lines += line;
score += scores[line];
if(isGameOver())
state = GAMEOVER ;
else {
tetromino = tetrominoNxet;
tetrominoNxet = Tetromino.randomOne();
}
}
}
/**方块硬下落的方法*/
public void hardDownAction(){
while(isCanDown())
tetromino.moveDown();
putInToWall();
int line = dropLine();
score += scores[line];
lines += line;
if(isGameOver())
state = GAMEOVER;
else {
tetromino = tetrominoNxet;
tetrominoNxet = Tetromino.randomOne();
}
}
/**判断是否能下落 true代表能下落,算法描述,如果方块中有任何一个
格子超过界限或者下一个格子不为空的话,就不能下落*/
private boolean isCanDown(){
Cell[] cells = tetromino.cells;
for(int i=0; i<cells.length; i++){
Cell cell = cells[i];
int row = cell.getRow();
if(row==ROWS-1){return false;}
}
for (int i = 0; i < cells.length; i++) {
Cell cell = cells[i];
int row =cell.getRow();
int col =cell.getCol();
if(walls[row+1][col]!=null){return false;}
}
return true;
}
/**将方块打进墙里面*/
private void putInToWall(){
Cell[] cells = tetromino.cells;
for(int i=0; i<cells.length; i++){
Cell cell = cells[i];
int row = cell.getRow();
int col = cell.getCol();
walls[row][col] = cell;
}
}
/**销毁已满的行
* 算法描述:先判断该行是否为满,如满则消除,并lines+1;
*/
private int dropLine(){
int line = 0;
for(int row=0; row<ROWS; row++)
if(isFull(row)){
deleteLine(row);
line++;
}
return line;
}
/**判断行是否满*/
private boolean isFull(int row){
Cell[] cells = walls[row];
for(int i=0; i<cells.length; i++)
if(cells[i] == null)
return false;
return true;
}
/**销毁已满的行,算法描述:利用数组复制将已满的行覆盖掉, 最后再将第一个清除*/
private void deleteLine(int row){
for(int i=row; i>=1; i--) {
Cell[] src = walls[i-1];
Cell[] des = walls[i];
System.arraycopy(src, 0, des, 0, COLS);
}
Arrays.fill(walls[0], null);
}
/**判断游戏是否结束,算法描述,取出下一个要下落的方块,将方块的初始位置
与墙进行比较,不为空则到达了顶端,则游戏结束*/
private boolean isGameOver(){
Cell[] cells = tetrominoNxet.cells;
for (int i = 0; i < cells.length; i++) {
Cell cell = cells[i];
int row = cell.getRow();
int col = cell.getCol();
if(walls[row][col] != null){
return true;
}
}
return false;
}
/**定义一个方块旋转的方法*/
private void roateRigthAction(){
if(tetromino == null)
return ;
tetromino.rotateRigth();
if(outOfBound() || coincidence())
tetromino.rotateLeft();
}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setSize(535,585);
Tetris tetris = new Tetris();
frame.add(tetris);
frame.setVisible(true);//窗口可见
frame.setBackground(Color.BLUE);//设置背景颜色
frame.setLocationRelativeTo(null);//把窗口移到屏幕中心
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//点击关闭时会直接关闭窗口
tetris.action();
//待打印界面时,会自动调用paint的方法,然后再绘制出界面
}
}