改进 1. 方块旋转修改

2. 实现没达到一个成绩等级进行加速并且保持速度直到下一次加速(使用两个定时器)

3. 实现两个人分别暂停

4. 界面优化

图片大家网上自己搜索一下

--------------------------------------Tetris类---------------------------------


import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.p_w_picpath.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

import javax.p_w_picpathio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
* 俄罗斯方块的游戏执行类,继承于JPanel实现绘制
*
* @author soft01
*
*/
public class Tetris extends JPanel {

/** 版本号*/
private static final long serialVersionUID = 1L;

/** 玩家p1和玩家p2的分数,行数,游戏的墙,生成的方块,下一个方块
* 游戏结束和暂停提示,定时器*/
private int scores_p1;
private int lines_p1;
private int scores_p2;
private int lines_p2;
public Cell[][] walls_p1 = new Cell[20][10];
public Cell[][] walls_p2 = new Cell[20][10];
private Tetromino tetromino_p1;
private Tetromino tetromino_p2;
private Tetromino nextOne_p1;
private Tetromino nextOne_p2;
private boolean pause_p1;
private boolean pause_p2;
private boolean gameOver_p1;
private boolean gameOver_p2;
private Timer timer_p1;
private Timer timer_p2;

/** 行数*/
private static final int ROWS = 20;
/** 列数*/
private static final int COLS = 10;
/** 字体颜色,设置为与方块界面相同的颜色*/
public static final Color FONT_COLOR = new Color(0x667799);
/** 字体大小,设置为25号*/
public static final int FONT_SIZE = 25;
/** 格子的像素,26*/
public static final int CELL_SIZE = 26;
/** 方块下落时间间隔,通过设置定时器的间隔时间实现*/
public static final int INTEVAL = 600;
/** 用于加速的时间间隔值*/
public static final int INTEVALDOWN = 50;
/** 消除行数对应的分数,设置为1 3 9 27*/
public static final int[] SCORE_TABLE = {0, 1, 3, 9, 27};

/** 将程序需要的数据用常量表示,增加代码可读性*/
/** 使用白色作为说明文字的背景颜色*/
public static final Color COLOR_FONTBACKGROUND = new Color(0xffffff);// 白色
/** 窗口框架的宽度和高度*/
public static final int FRAME_WIDTH = 1015;
public static final int FRAME_HEIGHT = 570;

/** 定义一个boolean数组,用于实现成绩分段,速度不同*/
private boolean[] flags_p1 = new boolean[15];
/** 定义一个boolean数组,用于实现成绩分段,速度不同*/
private boolean[] flags_p2 = new boolean[15];

/** 定义为静态的缓冲图片,可以被静态代码块调用加载*/
public static BufferedImage background;
public static BufferedImage gameOverImage;
public static BufferedImage T;
public static BufferedImage S;
public static BufferedImage Z;
public static BufferedImage L;
public static BufferedImage J;
public static BufferedImage I;
public static BufferedImage O;

/** 静态代码块,用于加载一次性资源,主要是,图片*/
static {
try {
ImageIO.read(Tetris.class.getResource("tetris.png"));
gameOverImage = ImageIO.read(Tetris.class.getResource("game-over.png"));
I = ImageIO.read(Tetris.class.getResource("I.png"));
T = ImageIO.read(Tetris.class.getResource("T.png"));
S = ImageIO.read(Tetris.class.getResource("S.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"));
} catch (IOException e) {
e.printStackTrace();
}
}

/** 程序的入口main方法,构建JFrame框架*/
public static void main(String[] args) {

/** 创建Tetris的对象,用于将程序装入JFrame中*/
Tetris tetris = new Tetris();

/** 新建窗口对象并且设置标题为TETRIS*/
JFrame frame = new JFrame("TETRIS");
/** 将画板添加到新建的窗口中*/
frame.add(tetris);
/** 设置窗口的宽度,高度*/
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
/** 窗口关闭(叉)时结束程序*/
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/** 窗口居中*/
frame.setLocationRelativeTo(null);
/** 设置窗口可见(默认的时候是不可见的)*/
frame.setVisible(true);
/** 执行tetris对象的action方法,静态方法不能直接调用非静态
* 方法*/
tetris.action();
}

/** 程序执行的主要方法,设置键盘监听*/
private void action() {
startAction();
repaint();
/** 通过匿名内部类创建键盘监听*/
KeyListener l = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_ESCAPE) {
System.exit(0);// 结束java进程
}
if (gameOver_p1 || gameOver_p2) {
// 游戏结束后,按enter回车重新开始
if (key == KeyEvent.VK_ENTER) {
startAction();
repaint();
}
return;
}
if (pause_p1 || pause_p2) {
// 暂停游戏之后,可以继续游戏
if (key == KeyEvent.VK_S) {
continueActionForP1();
}
if (key == KeyEvent.VK_LEFT) {
continueActionForP2();
}
return;
}
switch (key) {
case KeyEvent.VK_2:// 玩家2的向下
softDropActionForP2();
break;
case KeyEvent.VK_K:// 玩家1的向下
softDropActionForP1();
break;
case KeyEvent.VK_1:// 玩家2的向左
moveLeftAction(tetromino_p2, walls_p2);
break;
case KeyEvent.VK_J:// 玩家1的向左
moveLeftAction(tetromino_p1, walls_p1);
break;
case KeyEvent.VK_3:// 玩家2的向右
moveRightAction(tetromino_p2, walls_p2);
break;
case KeyEvent.VK_L:// 玩家1的向右
moveRightAction(tetromino_p1, walls_p1);
break;
case KeyEvent.VK_5:// 玩家2的旋转
rotateAction(tetromino_p2, walls_p2);
break;
case KeyEvent.VK_I:// 玩家1的旋转
rotateAction(tetromino_p1, walls_p1);
break;
case KeyEvent.VK_0:// 玩家2的快速向下
hardDropActionForP2();
break;
case KeyEvent.VK_SPACE:// 玩家1的快速向下
hardDropActionForP1();
break;
case KeyEvent.VK_RIGHT:// 玩家2的技能
cheatActionForP1();
break;
case KeyEvent.VK_D:// 玩家1的技能
cheatActionForP2();
break;
case KeyEvent.VK_UP:// 玩家2的暂停
pauseActionForP2();
break;
case KeyEvent.VK_A:// 玩家1的暂停
pauseActionForP1();
break;
}
repaint();
}
};
this.addKeyListener(l);// 在当前面板上绑定键盘监听l
this.requestFocus();// 为当前面板请求键盘输入焦点
}

/** 玩家1对玩家2的技能释放,就是调用了玩家2的快速下落方法*/
private void cheatActionForP2() {
if (scores_p1 >= 5) {
hardDropActionForP2();
scores_p1 -= 5;
}
}

/** 玩家2对玩家1的技能释放,就是调用了玩家1的快速下落方法*/
private void cheatActionForP1() {
if (scores_p2 >= 5) {
hardDropActionForP1();
scores_p2 -= 5;
}
}

/** 暂停游戏,删除定时器就可以*/
private void pauseActionForP1() {
timer_p1.cancel();
pause_p1 = true;
}

/** 暂停游戏,删除定时器就可以*/
private void pauseActionForP2() {
timer_p2.cancel();
pause_p2 = true;
}

/** 继续游戏,新建相同的定时器和任务就可以*/
private void continueActionForP1() {
pause_p1 = false;
timer_p1 = new Timer();
timer_p1.schedule(new TimerTask(){
public void run() {
softDropActionForP1();
repaint();
}
}, INTEVAL, INTEVAL);
}

/** 继续游戏*/
private void continueActionForP2() {
pause_p2 = false;
timer_p2 = new Timer();
timer_p2.schedule(new TimerTask(){
public void run() {
softDropActionForP2();
repaint();
}
}, INTEVAL, INTEVAL);
}

/** 玩家1的快速下落方法*/
private void hardDropActionForP1() {
while (canDrop(tetromino_p1, walls_p1)) {
tetromino_p1.softDrop();
}
landToWall(tetromino_p1, walls_p1);
destroyLinesForP1();
checkGameOverForP1();
tetromino_p1 = nextOne_p1;
nextOne_p1 = Tetromino.randomOne();
}

/** 玩家2的快速下落方法*/
private void hardDropActionForP2() {
while (canDrop(tetromino_p2, walls_p2)) {
tetromino_p2.softDrop();
}
landToWall(tetromino_p2, walls_p2);
destroyLinesForP2();
checkGameOverForP2();
tetromino_p2 = nextOne_p2;
nextOne_p2 = Tetromino.randomOne();
}

/** 玩家1正常下落一步的方法*/
private void softDropActionForP1() {
if (canDrop(tetromino_p1, walls_p1)) {
tetromino_p1.softDrop();
} else {
landToWall(tetromino_p1, walls_p1);
destroyLinesForP1();
checkGameOverForP1();
tetromino_p1 = nextOne_p1;
nextOne_p1 = Tetromino.randomOne();
}
}

/** 玩家2正常下落一步的方法*/
private void softDropActionForP2() {
if (canDrop(tetromino_p2, walls_p2)) {
tetromino_p2.softDrop();
} else {
landToWall(tetromino_p2, walls_p2);
destroyLinesForP2();
checkGameOverForP2();
tetromino_p2 = nextOne_p2;
nextOne_p2 = Tetromino.randomOne();
}
}

/** 玩家1判断游戏是否结束的方法*/
private void checkGameOverForP1() {
if (walls_p1[0][4] != null) {
tetromino_p1 = null;
nextOne_p1 = null;
gameOver_p1 = true;
timer_p1.cancel();
}
}

/** 玩家2判断游戏是否结束的方法*/
private void checkGameOverForP2() {
if (walls_p2[0][4] != null) {
tetromino_p2 = null;
nextOne_p2 = null;
gameOver_p2 = true;
timer_p2.cancel();
}
}

/** 玩家1消除行的方法*/
private void destroyLinesForP1() {
int lines = 0;
for (int i = 0; i < 20; i++) {
if (fullCells(i, walls_p1)) {
removeLine(i, walls_p1);
lines++;
System.out.println(i + " " + lines);
}
}
scores_p1 += SCORE_TABLE[lines];
lines_p1 += lines;
/** 游戏每过30分降低一次速度,可以说,30分提高一个等级*/
int level = scores_p1 / 30;
/** flags_p1数组默认都是flase,可以按分数(等级)
* 来决定是否加速*/
while(! flags_p1[level]) {
if(level > 11) {
break;// 11级别是最快速度
}
checkScoreForP1(level);
break;
}
}

/** 玩家2消除行的方法*/
private void destroyLinesForP2() {
int lines = 0;
for (int i = 0; i < 20; i++) {
if (fullCells(i, walls_p2)) {
removeLine(i, walls_p2);
lines++;
}
}
scores_p2 += SCORE_TABLE[lines];
lines_p2 += lines;
/** 游戏每过30分降低一次速度,可以说,30分提高一个等级*/
int level = scores_p2 / 30;
/** flags_p1数组默认都是flase,可以按分数(等级)
* 来决定是否加速*/
while(! flags_p2[level]) {
if(level > 11) {
break;
}
checkScoreForP2(level);
break;
}

}

/** 判断玩家当前所处的等级,根据等级来决定是否加速
* 也就是,时间间隔减小*/
private void checkScoreForP1(int level) {
switch (level) {
case 1 :
case 2 :
case 3 :
case 4 :
case 5 :
case 6 :
case 7 :
case 8 :
case 9 :
case 10 :
case 11 :
intevalDownForP1(level);
break;
default : return;
}
}

/** 玩家2的等级判断*/
private void checkScoreForP2(int level) {
switch (level) {
case 1 :
case 2 :
case 3 :
case 4 :
case 5 :
case 6 :
case 7 :
case 8 :
case 9 :
case 10 :
case 11 :
intevalDownForP2(level);
break;
default : return;
}
}

/** 改变玩家1的速度,创建新的定时器*/
private void intevalDownForP1(int level) {
timer_p1.cancel();
flags_p1[level] = true;
// System.out.println(level);// 测试用
timer_p1 = new Timer();
int inteval = INTEVAL - INTEVALDOWN * level;
timer_p1.schedule(new TimerTask(){
public void run(){
softDropActionForP1();
repaint();
}
}, inteval, inteval);
}

/** 改变玩家1的速度,创建新的定时器*/
private void intevalDownForP2(int level) {
timer_p2.cancel();
flags_p2[level] = true;
// System.out.println(level);// 测试用
timer_p2 = new Timer();
int inteval = INTEVAL - INTEVALDOWN * level;
timer_p2.schedule(new TimerTask(){
public void run(){
softDropActionForP2();
repaint();
}
}, inteval, inteval);
}

/** 判断给定的行是否为满,消行内调用的方法*/
private boolean fullCells(int row, Cell[][] wall) {
Cell[] line = wall[row];
for (Cell cell : line) {
if (cell == null) {
return false;
}
}
return true;
}

/** 消除满行,消行内调用的方法*/
private void removeLine(int row, Cell[][] wall) {
for (int i = row; i > 0; i--) {
System.arraycopy(wall[i - 1], 0, wall[i], 0, COLS);
}
Arrays.fill(wall[0], null);
}

/** 方块着陆到墙的方法,玩家1 2 共有的*/
private void landToWall(Tetromino tetromino, Cell[][] wall) {
Cell[] cells = tetromino.cells;
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
wall[row][col] = cell;
}
}

/** 判断是否可以下落的方法,玩家12 共有*/
private boolean canDrop(Tetromino tetromino, Cell[][] wall) {
Cell[] cells = tetromino.cells;
for (Cell cell : cells) {
if (cell.getRow() == ROWS - 1) {
// cell有0-19,行数是20
return false;
// 如果方块走到底部,则不可以再下落了
}
int row = cell.getRow();
int col = cell.getCol();
if (wall[row + 1][col] != null) {
return false;
}
}
return true;
}

/** 向左移动的方法,玩家1 2 是一样的*/
private void moveLeftAction(Tetromino tetromino, Cell[][] wall) {
tetromino.moveLeft();
if (coincide(tetromino, wall) || outOfBounds(tetromino, wall)) {
tetromino.moveRight();
}
}

/** 向右移动的方法,玩家1 2 是一样的*/
private void moveRightAction(Tetromino tetromino, Cell[][] wall) {
tetromino.moveRight();
if (coincide(tetromino, wall) || outOfBounds(tetromino, wall)) {
tetromino.moveLeft();
}
}

/** 旋转的方法,玩家1和玩家2是一样的*/
private void rotateAction(Tetromino tetromino, Cell[][] wall) {
tetromino.rotate();
if (coincide(tetromino, wall) || outOfBounds(tetromino, wall)) {
tetromino.rotateBack();// 转回来
}
}

/** 判断方块移动之后之否与原有的格子重合*/
private boolean coincide(Tetromino tetromino, Cell[][] wall) {
for(Cell cell:tetromino.cells){
int row=cell.getRow();
int col=cell.getCol();
if(row>=0&&row<ROWS&&col<COLS&&col>=0
&&wall[row][col]!=null){
return true;
}
}
return false;
}

/**检查方块是否越界,也就是方块的所有格子都在列数范围内*/
private boolean outOfBounds(Tetromino tetromino, Cell[][] wall){
for(Cell cell:tetromino.cells){
int col=cell.getCol();
if(col<0||col>=COLS){
return true;
}
}
for(Cell cell:tetromino.cells){
int row=cell.getRow();
int col=cell.getCol();
if(!(row>=0&&row<ROWS&&col<COLS&&col>=0
)){
return true;
}
}
return false;
}

/** 用于开始程序以及重新开始程序的方法*/
private void startAction() {
pause_p1 = false;
pause_p2 = false;
gameOver_p1 = false;
gameOver_p2 = false;
scores_p1 = 0;
scores_p2 = 0;
lines_p1 = 0;
lines_p2 =0;
Arrays.fill(flags_p1, false);
Arrays.fill(flags_p2, false);
for (Cell[] line : walls_p1) {
Arrays.fill(line, null);
}
for (Cell[] line : walls_p2) {
Arrays.fill(line, null);
}
tetromino_p1 = Tetromino.randomOne();
nextOne_p1 = Tetromino.randomOne();
tetromino_p2 = Tetromino.randomOne();
nextOne_p2 = Tetromino.randomOne();
timer_p1 = new Timer();
timer_p1.schedule(new TimerTask(){
public void run() {
softDropActionForP1();
repaint();
}
}, INTEVAL, INTEVAL);
timer_p2 = new Timer();
timer_p2.schedule(new TimerTask(){
public void run() {
softDropActionForP2();
repaint();
}
}, INTEVAL, INTEVAL);
}

/** 重写paint方法,设置画板,并且实现画画*/
public void paint(Graphics g) {
/** 将背景图画三张
* 此处顺序不能改变,不然界面就错了*/
g.drawImage(background, 246, 0, null);
g.drawImage(background, 0, 0, null);
g.drawImage(background, 720, 0, null);
g.translate(15, 15);// 坐标系平移
paintWall(g);
paintTetromino(g);
paintNextOne(g);
paintScore(g);
if (gameOver_p1 || gameOver_p2) {
g.drawImage(gameOverImage, -12, -13, null);
g.drawImage(gameOverImage, 512, -13, null);
Font font = getFont();
font = new Font(font.getName(), font.PLAIN, 150);
g.setFont(font);
String str1 = "WIN!";
String str2 = "回车开始";
if (gameOver_p1) {
g.drawString(str1, 515, 150);
g.drawString(str2, 0, 350);
} else {
g.drawString(str1, 0, 150);
g.drawString(str2, 0, 350);
}
}
}

/** 分数等信息的绘制*/
private void paintScore(Graphics g) {
int x1 = 289;
int x2 = 535;
int y = 160;
g.setColor(FONT_COLOR);
Font font = getFont();
font = new Font(font.getName(), Font.BOLD, FONT_SIZE);
g.setFont(font);
String str1 = "SCORE:" + scores_p1;
String str2 = "SCORE:" + scores_p2;
g.drawString(str1, x1, y);
g.drawString(str2, x2, y);
y += 56;
str1 = "LINES:" + lines_p1;
g.drawString(str1, x1, y);
str2 = "LINES:" + lines_p2;
g.drawString(str2, x2, y);
y += 56;
str1 = str2 = "[A/UP]PAUSE";
if (pause_p1 || pause_p2) {
str1 = str2 = "[S/LEFT]CONTINUE";
x1 -= 15;
x2 -= 15;
}
g.drawString(str1, x1, y);
g.drawString(str2, x2, y);
font = new Font(font.getName(), Font.BOLD, 18);
g.setFont(font);
g.drawString("1玩家 I转 K下 J左 L右 空格快落", 280, 313);
g.drawString("玩家可以减去5分," +
"使用技能[D]/[右方向键][ESC]退出", 280, 340);
g.drawString("2玩家 5转 2下 1左 3右 0快落", 280, 367);

}

/** 绘制下一个下落的方块*/
private void paintNextOne(Graphics g) {
if (nextOne_p1 == null) {
return;
}
Cell[] cells = nextOne_p1.cells;
for (int i = 0; i < cells.length; i++) {
Cell cell = cells[i];
int x = (cell.getCol()-1) * CELL_SIZE;
int y = cell.getRow() * CELL_SIZE;
g.drawImage(cell.getImage(), x + 260, y + 30, null);
}
if (nextOne_p2 == null) {
return;
}
cells = nextOne_p2.cells;
for (int i = 0; i < cells.length; i++) {
Cell cell = cells[i];
int x = (cell.getCol()-1) * CELL_SIZE;
int y = cell.getRow() * CELL_SIZE;
g.drawImage(cell.getImage(), x + 500, y + 30, null);
}

}

private void paintTetromino(Graphics g) {
if (tetromino_p1 == null) {
// 如果没有正在下落的方块,就不绘制
return;
}
for(Cell cell:tetromino_p1.cells){
g.drawImage(cell.getImage(), CELL_SIZE*cell.getCol()-1, CELL_SIZE*cell.getRow()-1, null);
}
if (tetromino_p2 == null) {
// 如果没有正在下落的方块,就不绘制
return;
}
g.translate(720, 0);
for(Cell cell:tetromino_p2.cells){
g.drawImage(cell.getImage(), CELL_SIZE*cell.getCol()-1, CELL_SIZE*cell.getRow()-1, null);
}
g.translate(-720, 0);
}

private void paintWall(Graphics g) {
for (int row = 0; row < walls_p1.length; row++) {
Cell[] line = walls_p1[row];
for (int col = 0; col < line.length; col++) {
Cell cell = line[col];
int x = col * CELL_SIZE;
int y = row * CELL_SIZE;
if (cell == null) {
g.setColor(new Color(0));// 黑色
g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
} else {
g.drawImage(cell.getImage(), x - 1, y - 1, null);
}
}
}
for (int row = 0; row < walls_p2.length; row++) {
Cell[] line = walls_p2[row];
for (int col = 0; col < line.length; col++) {
Cell cell = line[col];
int x = col * CELL_SIZE + 720;
int y = row * CELL_SIZE;
if (cell == null) {
g.setColor(new Color(0));// 黑色
g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
} else {
g.drawImage(cell.getImage(), x - 1, y - 1, null);
}
}
}
g.setColor(new Color(0xffffff));
g.fillRect(267 , 293, CELL_SIZE * 17, CELL_SIZE * 3);
}
}

/----------------------------Cell类-----------------------------



import java.awt.p_w_picpath.BufferedImage;

/**
* 俄罗斯方块的格子类,包含格子属性,行列 图片
* 添加读取设置方法
* 添加移动的方法,还有toString方法
*
* @author soft01
*
*/
public class Cell {

private int row;
private int col;
private BufferedImage p_w_picpath;

public Cell() {

}

public Cell(int row, int col, BufferedImage p_w_picpath) {
super();
this.row = row;
this.col = col;
this.p_w_picpath = p_w_picpath;
}

public int getRow() {
return row;
}

public void setRow(int row) {
this.row = row;
}

public int getCol() {
return col;
}

public void setCol(int col) {
this.col = col;
}

public BufferedImage getImage() {
return p_w_picpath;
}

public void setImage(BufferedImage p_w_picpath) {
this.p_w_picpath = p_w_picpath;
}

public void drop() {
row ++;
}

public void moveRight() {
col ++;
}

public void moveLeft() {
col --;
}

public String toString() {
return row + "," + col;
}

}

/-----------------------Tetromino类--------------


import java.util.Arrays;
import java.util.Random;

/**
* 四格方块的类
*
* @author soft01
*
*/
public class Tetromino {

/** 用四个格子,对应四格方块*/
protected Cell[] cells = new Cell[4];
// /** c用于接收四格方块构造器的字符,可以进行测试,查看方块是否正常生成*/
// char c;
// /** */
// int index = 0;
/** 用于实现旋转的State数组*/
protected State[] states;
/** 通过取余运算来实现周期性,遍历格子1 2 3*/
protected int index = 10000;

/** 私有构造器*/
private Tetromino() {

}

/** State内部类,一共六个属性,对应方块除了轴以外的三个格子,行列坐标*/
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) {
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 softDrop() {
for (int i = 0; i < cells.length; i ++) {
cells[i].drop();
}
}

/** 左移一步的方法*/
public void moveLeft() {
for (int i = 0; i < cells.length; i ++) {
cells[i].moveLeft();
}
}

/** 右移一步的方法*/
public void moveRight() {
for (int i = 0; i < cells.length; i ++) {
cells[i].moveRight();
}
}

/** 旋转的方法
* 旋转的实现,
* 1 获得当前的轴
* 2 获得下一个状态的数据变化(相对于轴的数据变化)
* 3 利用加法来实现数据变化*/
public void rotate() {
Cell o = cells[0];
int row = o.getRow();
int col = o.getCol();
index++;
State s = states[index % states.length];

cells[1].setRow(row + s.row1);
cells[1].setCol(col + s.col1);
cells[2].setRow(row + s.row2);
cells[2].setCol(col + s.col2);
cells[3].setRow(row + s.row3);
cells[3].setCol(col + s.col3);
}

/** 旋转方法的返回,也就是,判断是否越界或者重合时,旋转之后再转回来*/
public void rotateBack() {
Cell o = cells[0];
int row = o.getRow();
int col = o.getCol();
index--;
State s = states[index % states.length];

cells[1].setRow(row + s.row1);
cells[1].setCol(col + s.col1);
cells[2].setRow(row + s.row2);
cells[2].setCol(col + s.col2);
cells[3].setRow(row + s.row3);
cells[3].setCol(col + s.col3);
}

/** 重写toString方法*/
public String toString() {
return Arrays.toString(cells);
}

/** 创建四格方块的实例的方法,随机生成方块*/
public static Tetromino randomOne() {
Random r = new Random();
int type = r.nextInt(7);
switch (type) {
case 0 : return new T();
case 1 : return new L();
case 2 : return new J();
case 3 : return new I();
case 4 : return new O();
case 5 : return new Z();
case 6 : return new S();
}
return null;
}

/** 静态方法中只能使用静态内部类*/
private static 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[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);
states[0]=new State(0,0,0,-1,0,1,1,0);

}


}

private static 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[] { new State(0, 0, 0, 1, 0, -1, 0, -2),
new State(0, 0, -1, 0, 1, 0, 2, 0) };
}
}

private static 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[] { new State(0, 0, 0, 1, 1, -1, 1, 0),
new State(0, 0, -1, 0, 1, 1, 0, 1) };
}
}

private static 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[] { new State(0, 0, -1, -1, -1, 0, 0, 1),
new State(0, 0, -1, 1, 0, 1, 1, 0) };
}
}

private static 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[] { new State(0, 0, 0, -1, 0, 1, 1, -1),
new State(0, 0, -1, 0, 1, 0, -1, -1),
new State(0, 0, 0, 1, 0, -1, -1, 1),
new State(0, 0, 1, 0, -1, 0, 1, 1) };
}
}

private static 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[] { new State(0, 0, 0, -1, 0, 1, 1, 1),
new State(0, 0, -1, 0, 1, 0, 1, -1),
new State(0, 0, 0, 1, 0, -1, -1, -1),
new State(0, 0, 1, 0, -1, 0, -1, 1) };
}
}

private static 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[] { new State(0, 0, 0, 1, 1, 0, 1, 1),
new State(0, 0, 0, 1, 1, 0, 1, 1) };
}
}

}