首页 > 代码库 > 俄罗斯方块

俄罗斯方块

CellLabelRenderer.java

package fangkuai;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.io.Serializable;
import java.util.Date;
import java.util.Random;
import java.util.Timer;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import saolei.TanChiSheTask;
import util.MyAWTEventListener;
/**
 * 俄罗斯方块
 * 
 * @author Stanny Xie
 * @Date 2017-01-20
 */
public class ELuoSiFangKuai extends JFrame implements Serializable {
 /**
  * 
  */
 private static final long serialVersionUID = 5977722980538750979L;
 /**
  * 方块主区域表格
  */
 static JTable table;
 /**
  * 主区域数据模型
  */
 static TableModule tbModule;
 /**
  * 待出现图形显示区域表格
  */
 static JTable tableNext;
 /**
  * 待出现图形显示区域模型
  */
 static TableModule tbModuleNext;
 /**
  * 底层面板
  */
 static JLayeredPane desktop = null;
 /**
  * 主区域行数
  */
 static int ROW_COUNT = 23;
 /**
  * 主区域列数
  */
 static int COL_COUNT = 10;
 /**
  * 游戏开始标记
  */
 static boolean GAME_START = false;
 /**
  * 主区域左起始坐标
  */
 public static int LEFTPOSITION = 40;
 /**
  * 主区域上起始坐标
  */
 public static int TOPPOSITION = 10;
 /**
  * 单元格大小
  */
 static int CELL_SIZE = 22;
 /**
  * 得分
  */
 public static long SCORE = 0L;
 /**
  * 基础分数
  */
 public static long BASE_SCORE = 100L;
 /**
  * 速度级别
  */
 public static long LEVEL = 1L;
 Color color = new Color(232, 232, 232);
 /**
  * 显示得分
  */
 static JLabel jtf_S = new JLabel();
 /**
  * 显示速度级别
  */
 static JLabel jtf_L = new JLabel();
 /**
  * 图形底色渲染器
  */
 CellLabelRenderer tcr = new CellLabelRenderer();
 /**
  * 图形在主区域移动定时器
  */
 static Timer timer;
 /**
  * 游戏继续/暂停状态位
  */
 static boolean STATUS = true;
 /**
  * 随机生成图形
  */
 static Random random = new Random();
 /**
  * 主区域移动图形实例
  */
 static ShapeInstance shapeInstance;
 /**
  * 待出现图形
  */
 static ShapeModule shapeNext;
 public ELuoSiFangKuai() {
  super();
  // 获取显示器分辨率
  Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
  int screenWitdth = screenSize.width;// 显示器宽
  int screenHeight = screenSize.height;// 显示器高
  int width = COL_COUNT * 25 + 200;
  int height = ROW_COUNT * 25 + 100;
  // 设置窗口大小
  setSize(width, height);
  // 设置窗口位置
  setLocation((screenWitdth - width) / 2, (screenHeight - height) / 2);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  // 构建底层区域
  buildFrame();
 }
 public static void main(String[] args) {
  ELuoSiFangKuai myFrame = new ELuoSiFangKuai();
  myFrame.setVisible(true);
 }
 /**
  * 定时器工作方法
  * 
  * @param flag
  *            true/false 开始/暂停
  */
 public static void timerStart(boolean flag) {
  if (flag) {
   if (timer != null) {
    timer.cancel();
   }
   timer = new Timer();
   TanChiSheTask task = new TanChiSheTask() {
    public void run() {
     shapeMoveY(1);
    }
   };
   timer.schedule(task, new Date(), (1000 / LEVEL));// 基础时间间隔1000ms,每升1级时间减少
  } else {
   if (timer != null) {
    timer.cancel();
    timer = null;
   }
  }
 }
 /**
  * 暂停/开始
  */
 public static void pause() {
  if (GAME_START) {
   if (STATUS) {
    STATUS = false;
   } else {
    STATUS = true;
   }
   timerStart(STATUS);
  }
 }
 /**
  * 开始新游戏
  */
 public void newGame() {
  clearTable(table);
  SCORE = 0L;
  LEVEL = 1;
  setScore();
  setLevel();
  GAME_START = true;
  STATUS = true;
  shapeNext = null;
  shapeInstance = null;
  loadNextShape();
  timerStart(true);
  desktop.repaint();
 }
 /**
  * 构建底层区域
  */
 public void buildFrame() {
  // 获取JFrame动态图层
  desktop = this.getLayeredPane();
  // 加载主区域
  desktop.add(loadTable(), new Integer(200));
  // 加载得分展示区域
  desktop.add(loadScorePanel(), new Integer(200));
  // 记载速度级别展示区域
  desktop.add(loadLevelPanel(), new Integer(200));
  // 加载待出现图形区域
  desktop.add(loadNextItemPanel(), new Integer(200));
  // 记载说明区域
  desktop.add(loadDescriptionPanel(), new Integer(200));
  // 添加空区域
  desktop.add(Box.createHorizontalStrut(20));
  // 添加窗口监听事件--键盘事件
  Toolkit.getDefaultToolkit().addAWTEventListener(
    new MyAWTEventListener() {
     public void keyPressed(KeyEvent e) {
      keyEventToolkit(e);
     }
    }, AWTEvent.KEY_EVENT_MASK);
 }
 /**
  * 处理键盘监听事件
  * 
  * @param e
  */
 public void keyEventToolkit(KeyEvent e) {
  // System.out.println(e.getKeyCode() + ":" + e.getKeyChar());
  switch (e.getKeyCode()) {
  case 27:// esc
   break;
  case 32:// space
   transform(1);
   break;
  case 112:// 112 F1
   newGame();
   break;
  case 113:// 113 F2
   pause();
   break;
  case 114:// 113 F3
   shapeNext = null;
   shapeInstance = null;
   clearTable(table);
   loadNextShape();
   break;
  case 37:// 37 left
   shapeMoveX(-1);
   break;
  case 38:// 38 up
   shapeMoveY(-1);
   break;
  case 39:// 39 right
   shapeMoveX(1);
   break;
  case 10:// Enter
   shapeMoveY(99);
   break;
  case 40:// 40 down
   shapeMoveY(1);
   break;
  case 49:// Number 1
  case 97:
   generateNextShape(0);
   break;
  case 50:// Number 2
  case 98:
   generateNextShape(1);
   break;
  case 51:// Number 3
  case 99:
   generateNextShape(2);
   break;
  case 52:// Number 4
  case 100:
   generateNextShape(3);
   break;
  case 53:// Number 5
  case 101:
   generateNextShape(4);
   break;
  case 54:// Number 6
  case 102:
   generateNextShape(5);
   break;
  case 55:// Number 7
  case 103:
   generateNextShape(6);
   break;
  default:
   break;
  }
 }
 /**
  * 清除区域中已有图形
  * 
  * @param jtb
  */
 public static void clearTable(JTable jtb) {
  for (int row = 0; row < jtb.getModel().getRowCount(); row++) {
   for (int col = 0; col < jtb.getModel().getColumnCount(); col++) {
    jtb.setValueAt(null, row, col);
   }
  }
 }
 /**
  * 随机生成待选图形
  */
 public static void randomSquare() {
  int index = 1;
  int rNum = random.nextInt(100);
  if (rNum > 85) {
   index = 6;
  } else if (rNum > 70) {
   index = 5;
  } else if (rNum > 55) {
   index = 4;
  } else if (rNum > 40) {
   index = 3;
  } else if (rNum > 20) {
   index = 2;
  } else if (rNum > 10) {
   index = 1;
  } else {
   index = 0;
  }
  generateNextShape(index);
 }
 /**
  * 根据编号获取图形
  * 
  * @param index
  *            图形编号
  */
 public static void generateNextShape(int index) {
  clearTable(tableNext);// 清除目前的待选图形
  shapeNext = ShapePool.getShape(index, 0);// 加载新的待选图形
  int top = tableNext.getModel().getRowCount()
    - shapeNext.getYArr().length - 1;
  int left = tableNext.getModel().getColumnCount()
    - shapeNext.getXArr().length;
  if (left > 0) {
   left--;
  }
  // 绘制待选图形
  for (int i = 0; i < shapeNext.getSquareList().size(); i++) {
   Position p = shapeNext.getSquareList().get(i);
   tableNext.setValueAt(shapeNext.getShape(), p.y + top, p.x + left);
  }
  tableNext.repaint();
 }
 /**
  * 将待选图形添加到主区域,并生成一个新的待选图形
  */
 public static void loadNextShape() {
  // 如果待选图形是空的,那么随机加载一个
  if (shapeNext == null) {
   randomSquare();
  }
  int left = (table.getModel().getColumnCount() - shapeNext.getXArr().length) / 2;
  int top = 4 - shapeNext.getYArr().length;
  // 实例化待选图形到主区域
  shapeInstance = new ShapeInstance(shapeNext, top, left);
  // 绘制待选图形到主区域
  repaintShape(table);
  // 生成一个新的待选图形
  randomSquare();
 }
 /**
  * 实例化图形横向移动
  * 
  * @param mIndex
  *            -1:左移; 1:右移
  */
 public void shapeMoveX(int mIndex) {
  if (!GAME_START) {
   return;
  }
  // 清除当前坐标的图形
  removeCurrentShape(table);
  // 图形移动
  shapeInstance.moveX(mIndex, tbModule);
  // 在新坐标绘制图形
  repaintShape(table);
 }
 /**
  * 实例化图形纵向移动
  * 
  * @param mIndex
  *            -1:上移; 1:下移; 99:直接到底
  */
 public static void shapeMoveY(int mIndex) {
  if (!GAME_START) {
   return;
  }
  // 清除当前坐标的图形
  removeCurrentShape(table);
  // 图形移动
  boolean downFlag = shapeInstance.moveY(mIndex, tbModule);
  // 在新坐标绘制图形
  repaintShape(table);
  // 判断图形是否已经到达底部,或者刚好压到其他图形上
  if (downFlag) {
   // 判断当前主区域内是否有整行被图形填充,如果过有那么清除该行
   int clLineCount = tbModule.clearFullLine();
   // 如果消除的行>0,分数添加
   if (clLineCount > 0) {
    long addScore = BASE_SCORE * LEVEL;
    for (int i = 1; i < clLineCount; i++) {
     addScore *= 2;
    }
    SCORE += addScore;
    setScore();
   } else {
    SCORE += 10;
    setScore();
   }
   // 判断是否GameOver
   if (tbModule.checkGameOver()) {
    JOptionPane.showMessageDialog(table, "GAME OVER", "提示",
      JOptionPane.INFORMATION_MESSAGE);
    desktop.repaint();
    GAME_START = false;// 游戏结束
    STATUS = false;// 状态位设为停止
    timerStart(false);// 清除定时器
    return;
   }
   // 加载新图形
   loadNextShape();
  }
 }
 /**
  * 实例图形变形
  * 
  * @param cIndex
  *            变形方向 -1:左转90度 1:右转90度
  */
 public void transform(int cIndex) {
  if (!GAME_START) {
   return;
  }
  // 清除当前坐标的图形
  removeCurrentShape(table);
  // 图形移动
  shapeInstance.transform(cIndex, tbModule);
  // 绘制变形后的图形
  repaintShape(table);
 }
 /**
  * 清除制定区域内的图形
  * 
  * @param jtb
  *            绘制区域
  */
 public static void removeCurrentShape(JTable jtb) {
  if (!GAME_START) {
   return;
  }
  ShapeModule shapeM = shapeInstance.getShape();
  for (int i = 0; i < shapeM.getSquareList().size(); i++) {
   Position p = shapeM.getSquareList().get(i);
   jtb.setValueAt(null, p.y + shapeInstance.getTop(), p.x
     + shapeInstance.getLeft());
  }
  jtb.repaint();
 }
 /**
  * 在指定区域内绘制图形
  * 
  * @param jtb
  *            绘制区域
  */
 public static void repaintShape(JTable jtb) {
  if (!GAME_START) {
   return;
  }
  ShapeModule shapeM = shapeInstance.getShape();
  for (int i = 0; i < shapeM.getSquareList().size(); i++) {
   Position p = shapeM.getSquareList().get(i);
   jtb.setValueAt(shapeM.getShape(), p.y + shapeInstance.getTop(), p.x
     + shapeInstance.getLeft());
  }
  jtb.repaint();
 }
 /**
  * 记载主区域
  * 
  * @return
  */
 public JComponent loadTable() {
  JPanel fr1 = new JPanel();
  fr1.setBounds(LEFTPOSITION, TOPPOSITION, COL_COUNT * CELL_SIZE + 20,
    (ROW_COUNT - 3) * CELL_SIZE + 60);
  fr1.setBorder(new TitledBorder("俄罗斯方块"));
  tbModule = new TableModule(ROW_COUNT, COL_COUNT);
  table = new JTable(tbModule);
  table.setDefaultRenderer(Object.class, tcr);
  for (int i = 0; i < table.getColumnCount(); i++) {
   table.getColumnModel().getColumn(i).setPreferredWidth(CELL_SIZE);
  }
  table.setRowHeight(CELL_SIZE);
  table.setRowHeight(0, 1);
  table.setRowHeight(1, 1);
  table.setRowHeight(2, 1);
  Border bor = new BevelBorder(BevelBorder.LOWERED);
  table.setBorder(bor);
  // table.setShowHorizontalLines(false);
  // table.setShowVerticalLines(false);
  Dimension abc = table.getIntercellSpacing();
  abc.setSize(0, 0);
  table.setIntercellSpacing(abc);
  fr1.add(table);
  return fr1;
 }
 /**
  * 加载待选图形区域
  * 
  * @return
  */
 public JComponent loadNextItemPanel() {
  JPanel fr4 = new JPanel();
  fr4.setBounds(LEFTPOSITION + COL_COUNT * CELL_SIZE + 40,
    TOPPOSITION + 140, 100, 120);
  tbModuleNext = new TableModule(5, 3);
  tableNext = new JTable(tbModuleNext);
  tableNext.setDefaultRenderer(Object.class, tcr);
  for (int i = 0; i < tableNext.getColumnCount(); i++) {
   tableNext.getColumnModel().getColumn(i)
     .setPreferredWidth(CELL_SIZE);
  }
  tableNext.setRowHeight(CELL_SIZE);
  tableNext.setRowHeight(4, 1);
//  Border bor = new BevelBorder(BevelBorder.LOWERED);
//  tableNext.setBorder(bor);
//  tableNext.setBackground(color);
  Dimension abc = table.getIntercellSpacing();
  abc.setSize(0, 0);
  tableNext.setIntercellSpacing(abc);
  fr4.add(tableNext);
  return fr4;
 }
 /**
  * 加载分数区域
  * 
  * @return
  */
 public JComponent loadScorePanel() {
  JPanel fr3 = new JPanel();
  TitledBorder bdr = new TitledBorder("分数");
  fr3.setBorder(bdr);
  fr3.setBounds(LEFTPOSITION + COL_COUNT * CELL_SIZE + 40, TOPPOSITION,
    100, 50);
  jtf_S.setPreferredSize(new Dimension(90, 18));
  jtf_S.setFont(new Font("", Font.BOLD, 18));
  jtf_S.setForeground(Color.RED);
  jtf_S.setBackground(Color.BLACK);
  jtf_S.setOpaque(true);
  jtf_S.setHorizontalAlignment(SwingConstants.CENTER);
  fr3.add(jtf_S);
  setScore();
  return fr3;
 }
 /**
  * 加载速度级别区域
  * 
  * @return
  */
 public JComponent loadLevelPanel() {
  JPanel fr4 = new JPanel();
  fr4.setBorder(new TitledBorder("Level"));
  fr4.setBounds(LEFTPOSITION + COL_COUNT * CELL_SIZE + 40,
    TOPPOSITION + 70, 100, 50);
  jtf_L.setPreferredSize(new Dimension(90, 18));
  jtf_L.setFont(new Font("", Font.BOLD, 18));
  jtf_L.setForeground(Color.RED);
  jtf_L.setBackground(Color.BLACK);
  jtf_L.setOpaque(true);
  jtf_L.setHorizontalAlignment(SwingConstants.CENTER);
  fr4.add(jtf_L);
  setLevel();
  return fr4;
 }
 /**
  * 加载描述区域
  * 
  * @return
  */
 public JComponent loadDescriptionPanel() {
  JPanel ljp = new JPanel();
  ljp.setBounds(LEFTPOSITION + COL_COUNT * CELL_SIZE + 40,
    TOPPOSITION + 300, 100, 140);
  ljp.setLayout(new BoxLayout(ljp, BoxLayout.Y_AXIS));
  JLabel j1, j2, j3;
  j1 = new JLabel("F1 - New Game");
  j1.setForeground(Color.BLUE);
  j2 = new JLabel("F2 - Pause");
  j2.setForeground(Color.BLUE);
  j3 = new JLabel("F3 - Cheat");
  j3.setForeground(Color.BLUE);
  ljp.add(j1);
  ljp.add(j2);
  ljp.add(j3);
  return ljp;
 }
 /**
  * 设置得分
  */
 public static void setScore() {
  String SCORE_S = String.valueOf(SCORE);
  for (int i = 8; i > String.valueOf(SCORE).length(); i--) {
   SCORE_S = "0" + SCORE_S;
  }
  jtf_S.setText(SCORE_S);
  jtf_S.repaint();
  if (SCORE >= 4000 * LEVEL * LEVEL) {
   LEVEL++;
   setLevel();
   timerStart(true);
  }
 }
 /**
  * 设置速度
  */
 public static void setLevel() {
  String SCORE_S = String.valueOf(LEVEL);
  jtf_L.setText(SCORE_S);
  jtf_L.repaint();
 }
}

ELuoSiFangKuai.java

package fangkuai;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.TableCellRenderer;
import util.ObjectUtil;
/**
 * 背景渲染器类
 * 
 * @author Stanny Xie
 * @date 2010-01-19
 * 
 */
public class CellLabelRenderer extends JLabel implements TableCellRenderer {
 private static final long serialVersionUID = 7083489923614792312L;
 public CellLabelRenderer() {
  setOpaque(true);
  setHorizontalAlignment(SwingConstants.CENTER);
  setVerticalAlignment(SwingConstants.CENTER);
 }
 /**
  * 底色:灰
  */
 static Color color_gray = new Color(240, 240, 240);
 /**
  * 不同图形背景色
  */
 static Color[] NUMBERCOLOR = { new Color(23, 232, 232),
   new Color(200, 255, 255), new Color(255, 255, 123),
   new Color(50, 255, 255), new Color(255, 123, 255),
   new Color(150, 255, 150), new Color(123, 123, 255),
   new Color(255, 180, 255), new Color(200, 255, 200),
   new Color(0, 0, 0) };
 /**
  * 重写父类方法
  * 
  * @see javax.swing.table.TableCellRenderer#getTableCellRendererComponent(javax.swing.JTable,
  *      java.lang.Object, boolean, boolean, int, int)
  */
 public Component getTableCellRendererComponent(JTable table, Object value,
   boolean isSelected, boolean hasFocus, int row, int column) {
  TableModule tm = (TableModule) table.getModel();
  String oValue = ObjectUtil.getNotNullValue(tm.getBackgourndValue(row,
    column));
  this.setFont(new Font("Arial", Font.BOLD, 28));
  this.setText(ObjectUtil.getNotNullValue(value));
  setVerticalAlignment(CENTER);
  setHorizontalAlignment(CENTER);
  setBackground(color_gray);
  if (!ObjectUtil.checkEmpty(oValue)) {
   setBackground(NUMBERCOLOR[ObjectUtil.getIntValue(oValue)]);
  }
  return this;
 }
}

Position.java

package fangkuai;
/**
 * 坐标模块
 * 
 * @author Stanny Xie
 * @date 2010-01-19
 * 
 */
public class Position {
 int y;// 纵坐标
 int x;// 横坐标
 public Position(int y, int x) {
  this.y = y;
  this.x = x;
 }
}

ShapeInstance.java

package fangkuai;
import util.ObjectUtil;
/**
 * 实例化图形类
 * 
 * @author Stanny Xie
 * @date 2010-01-19
 * 
 */
public class ShapeInstance {
 public ShapeInstance(ShapeModule shape, int top, int left) {
  this.shape = shape;
  this.top = top;
  this.left = left;
 }
 /**
  * 图形类
  */
 private ShapeModule shape;
 /**
  * 纵坐标开始位
  */
 private int top;
 /**
  * 横坐标开始为
  */
 private int left;
 /**
  * 纵坐标修正位
  */
 int yMove = 0;
 /**
  * 横坐标修正位
  */
 int xMove = 0;
 /**
  * 图形变形
  * 
  * @param cIndex
  *            变形方式 -1:左转90度 1:右转90度
  * @param tbModule
  *            数据模型
  */
 public void transform(int cIndex, TableModule tbModule) {
  // 根据变形方式获取变形图形
  ShapeModule newSM = ShapePool.changeSquare(this.shape, cIndex);
  // 之前是否有过修正,如果有那么清除修正位,恢复先前纵坐标开始位
  if (yMove < 0) {
   yMove = 0;
   if (getTop() < tbModule.getRowCount() - newSM.getYArr().length) {
    top++;
   }
  }
  // 之前是否有过修正,如果有那么清除修正位,恢复先前纵坐标开始位
  if (xMove < 0) {
   xMove = 0;
   if (getLeft() < tbModule.getColumnCount() - newSM.getXArr().length
     - 1) {
    left++;
   }
  }
  // 根据变形图形判断位置有没有被占用
  for (Position posi : newSM.getSquareList()) {
   // 如果纵坐标溢出,那么修正-1
   if (posi.y + getTop() >= tbModule.getRowCount()) {
    top--;
    yMove = -1;
   }
   // 如果横坐标溢出,那么修正-1
   if (posi.x + getLeft() >= tbModule.getColumnCount()) {
    left--;
    xMove = -1;
   }
   // 根据坐标获取数据模型中设置的值
   Object oValue = tbModule.getBackgourndValue(posi.y + getTop(),
     posi.x + getLeft());
   // 已经被占用
   if (!ObjectUtil.checkEmpty(oValue)) {
    return;
   }
  }
  // 新图形可用,返回展示
  this.shape = newSM;
 }
 /**
  * 图形横向移动
  * 
  * @param xIndex
  *            -1:左移; 1:右移
  * @param tbModule
  *            数据模型
  */
 public void moveX(int xIndex, TableModule tbModule) {
  int validX = getLeft() + xIndex;// 新坐标
  if (xIndex == -1) {// -1:左移
   // 到达左边界,图形不可移动,直接返回
   if (getLeft() == 0) {
    return;
   }
   // 迭代图形纵向坐标
   for (SubModule sm : shape.getYArr()) {
    int col = getLeft() + sm.minC + xIndex;// 需加上对应纵坐标的最小x坐标
    // 判断主区域坐标有没有被占用
    if (!ObjectUtil.checkEmpty(tbModule.getBackgourndValue(sm.p
      + getTop(), col))) {
     validX = left;
     break;
    }
   }
  } else if (xIndex == 1) {// 1:右移
   // 到达右边界,图形不可移动,直接返回
   if (getLeft() + shape.getXArr().length >= tbModule.getColumnCount()) {
    return;
   }
   // 迭代图形纵向坐标
   for (SubModule sm : shape.getYArr()) {
    int col = getLeft() + sm.maxC + xIndex;// 需加上对应纵坐标的最大x坐标
    if (!ObjectUtil.checkEmpty(tbModule.getBackgourndValue(sm.p
      + getTop(), col))) {
     validX = left;
     break;
    }
   }
  }
  this.left = validX;
 }
 /**
  * 图形纵向移动
  * 
  * @param yIndex
  *            -1:上移; 1:下移; 99:直接到底
  * @param tbModule
  *            数据模型
  * @return true:图形已经到底,或者已经与区域中已有图形接触,如果是那么需要将待选图形添加到主区域
  */
 public boolean moveY(int yIndex, TableModule tbModule) {
  int validY = getTop() + yIndex;
  int oldTop = getTop();
  if (yIndex == -1) {// -1:上移
   // 到达上边界,图形不可移动,直接返回
   if (getTop() == 0) {
    return false;
   }
   // 迭代图形横向坐标
   for (SubModule sm : shape.getXArr()) {
    int row = getTop() + sm.minC + yIndex;// 需加上对应横坐标的最小y坐标
    if (!ObjectUtil.checkEmpty(tbModule.getBackgourndValue(row,
      sm.p + getLeft()))) {
     validY = getTop();
    }
   }
   this.top = validY;
  } else if (yIndex == 1) {// 1:下移
   // 到达下边界,图形不可移动,直接返回
   if (getTop() + shape.getYArr().length >= tbModule.getRowCount()) {
    return true;// 已经到底
   }
   // 迭代图形横向坐标
   for (SubModule sm : shape.getXArr()) {
    int row = getTop() + sm.maxC + yIndex;// 需加上对应横坐标的最大y坐标
    if (!ObjectUtil.checkEmpty(tbModule.getBackgourndValue(row,
      sm.p + getLeft()))) {
     validY = getTop();
    }
   }
   this.top = validY;
   // 判断新坐标是不是到底了,如果到底或者与主区域其他图形接触了
   // for (SubModule sm : shape.getXArr()) {
   // int row = getTop() + sm.maxC + 1;
   // if (row >= tbModule.getRowCount()
   // || !ObjectUtil.checkEmpty(tbModule.getBackgourndValue(
   // row, sm.p + getLeft()))) {
   // return true;// 已经到底或者与主区域其他图形接触
   // }
   // }
  } else {// 99:直接到底
   validY = tbModule.getRowCount() - shape.getYArr().length;// 初始化为最大总坐标处
   // 迭代图形横向坐标
   for (SubModule sm : shape.getXArr()) {
    // 纵坐标从低到高判断
    for (int row = getTop() + shape.getYArr().length; row < tbModule
      .getRowCount(); row++) {
     // 坐标是不是已经被占用
     if (!ObjectUtil.checkEmpty(tbModule.getBackgourndValue(row,
       sm.p + getLeft()))) {
      if (validY == tbModule.getRowCount()
        - shape.getYArr().length) {// 新坐标如果是最大总坐标,那么需要重新赋值
       validY = row - sm.maxC - 1;
       if(validY>tbModule.getRowCount() - shape.getYArr().length){
        validY = tbModule.getRowCount() - shape.getYArr().length;
       }
      } else {// 比较新坐标,取最小坐标
       validY = validY > (row - sm.maxC - 1) ? (row
         - sm.maxC - 1) : validY;
      }
      break;
     }
    }
   }
   this.top = validY;
   return true;// 已经到底
  }
  if (oldTop == getTop()) {
   return true;
  }
  return false;
 }
 public int getLeft() {
  return left;
 }
 public ShapeModule getShape() {
  return shape;
 }
 public void setShape(ShapeModule shape) {
  this.shape = shape;
 }
 public int getTop() {
  return top;
 }
}

ShapeModule.java

package fangkuai;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import util.ObjectUtil;
/**
 * 图形模型
 * 
 * @author Stanny Xie
 * @date 2010-01-19
 * 
 */
public class ShapeModule {
 public ShapeModule(String positionC, int shape, int type) {
  squareList.clear();
  this.initSquareList(positionC);
  this.shape = shape;
  this.type = type;
 }
 /**
  * 组成图形的小方块坐标
  */
 private List<Position> squareList = new ArrayList<Position>();
 /**
  * 存储图形横坐标集合
  */
 private SubModule[] xArr;
 /**
  * 存储图形纵坐标集合
  */
 private SubModule[] yArr;
 /**
  * 图形编号
  */
 private int shape = -1;
 /**
  * 图形变种编号
  */
 private int type = -1;
 /**
  * 根据坐标字符串解析图形及其附属属性
  * 
  * @param positionC
  */
 private void initSquareList(String positionC) {
  // 传入坐标集不为空
  if (ObjectUtil.checkEmpty(positionC)) {
   return;
  }
  Map<Integer, Integer> yMap = new HashMap<Integer, Integer>();// 横坐标对应高度度集合
  Map<Integer, Integer> minYMap = new HashMap<Integer, Integer>();// 横坐标对应最小纵坐标集合
  Map<Integer, Integer> maxYMap = new HashMap<Integer, Integer>();// 横坐标对应最大纵坐标集合
  Map<Integer, Integer> xMap = new HashMap<Integer, Integer>();// 纵坐标对应宽度集合
  Map<Integer, Integer> minXMap = new HashMap<Integer, Integer>();// 纵坐标对应最小横坐标集合
  Map<Integer, Integer> maxXMap = new HashMap<Integer, Integer>();// 纵坐标对应最小横坐标集合
  Set<Integer> xSet = new TreeSet<Integer>();// 横坐标集合
  Set<Integer> ySet = new TreeSet<Integer>();// 纵坐标集合
  String[] pArr = positionC.split("#");// 分割小方块
  for (int i = 0; i < pArr.length; i++) {
   String[] p = pArr[i].split(":");// 分割横纵坐标
   int y = Integer.valueOf(p[0]);// 纵坐标
   int x = Integer.valueOf(p[1]);// 横坐标
   initMap(yMap, y);
   Integer ySize = yMap.get(y);
   ySize++;
   yMap.put(y, ySize);
   ySet.add(y);
   initMap(xMap, x);
   Integer xSize = xMap.get(x);
   xSize++;
   xMap.put(x, xSize);
   xSet.add(x);
   addSquareList(y, x);
   putMinMap(minYMap, y, x);
   putMaxMap(maxYMap, y, x);
   putMinMap(minXMap, x, y);
   putMaxMap(maxXMap, x, y);
  }
  Iterator<Integer> xIter = xSet.iterator();
  xArr = new SubModule[xSet.size()];
  int i = 0;
  while (xIter.hasNext()) {
   Integer x = xIter.next();
   SubModule sm = new SubModule(x, xMap.get(x), minXMap.get(x),
     maxXMap.get(x));
   xArr[i++] = sm;
  }
  Iterator<Integer> yIter = ySet.iterator();
  yArr = new SubModule[ySet.size()];
  int j = 0;
  while (yIter.hasNext()) {
   Integer y = yIter.next();
   SubModule sm = new SubModule(y, yMap.get(y), minYMap.get(y),
     maxYMap.get(y));
   yArr[j++] = sm;
  }
 }
 /**
  * 设置最小坐标
  * 
  * @param map
  *            xmap/ymap
  * @param key
  *            x/y
  * @param num
  *            y/x
  */
 public void putMinMap(Map<Integer, Integer> map, int key, int num) {
  Integer minN = map.get(key);
  if (minN == null || minN > num) {
   map.put(key, num);
  }
 }
 /**
  * 设置最大坐标
  * 
  * @param map
  *            xmap/ymap
  * @param key
  *            x/y
  * @param num
  *            y/x
  */
 public void putMaxMap(Map<Integer, Integer> map, int key, int num) {
  Integer maxN = map.get(key);
  if (maxN == null || maxN < num) {
   map.put(key, num);
  }
 }
 /**
  * map 初始化
  * 
  * @param map
  * @param key
  */
 public void initMap(Map<Integer, Integer> map, int key) {
  if (map.get(key) == null) {
   map.put(key, new Integer(0));
  }
 }
 private void addSquareList(int y, int x) {
  squareList.add(new Position(y, x));
 }
 /**
  * 模型初始化
  */
 public void clear() {
  squareList.clear();
  shape = -1;
  type = -1;
 }
 public int getShape() {
  return shape;
 }
 public void setShape(int shape) {
  this.shape = shape;
 }
 public List<Position> getSquareList() {
  return squareList;
 }
 public void setSquareList(List<Position> squareList) {
  this.squareList = squareList;
 }
 public int getType() {
  return type;
 }
 public void setType(int type) {
  this.type = type;
 }
 /**
  * 获取最大横坐标
  * 
  * @return
  */
 public int getMaxX() {
  if (xArr == null || xArr.length == 0) {
   return 0;
  }
  return xArr[xArr.length - 1].p;
 }
 /**
  * 获取最到纵坐标
  * 
  * @return
  */
 public int getMaxY() {
  if (yArr == null || yArr.length == 0) {
   return 0;
  }
  return yArr[yArr.length - 1].p;
 }
 public SubModule[] getXArr() {
  return xArr;
 }
 public SubModule[] getYArr() {
  return yArr;
 }
 /**
  * 判断对应坐标有无组成图形的小方块
  * 
  * @param p
  * @return
  */
 public boolean checkPositionExists(Position p) {
  if (squareList == null || squareList.size() == 0 || p == null) {
   return false;
  }
  for (Position sp : squareList) {
   if (sp.y == p.y && sp.x == p.x) {
    return true;
   }
  }
  return false;
 }
}

ShapePool.java

package fangkuai;
/**
 * 俄罗斯方块图形池
 * 
 * @author Stanny Xie
 * @date 2010-01-19
 * 
 */
public class ShapePool {
 /**
  * 各类方块图形集合
  */
 private static ShapeModule[][] squareTypeArr = null;
 public ShapePool() {
  init();
 }
 public static ShapeModule getShape(int shape, int type) {
  init();
  return squareTypeArr[shape][type];
 }
 // 7中图形,每种四种变化
 private static void init() {
  if (squareTypeArr != null) {
   return;
  }
  squareTypeArr = new ShapeModule[7][4];
  // Shape 1 竖条
  loadLine();
  // Shape 2 四方
  loadBlock();
  // Shape 3 7形
  loadSeven();
  // Shape 4 反7形
  loadContrarySeven();
  // Shape 5 Z形
  loadZ();
  // Shape 6 反Z形
  loadContraryZ();
  // Shape 7 山形
  loadM();
 }
 /**
  * 图形变形
  * 
  * @param spm
  *            图形模型
  * @param changeFlag
  *            变形方式 -1:左转90度 1:右转90度
  * @return
  */
 public static ShapeModule changeSquare(ShapeModule spm, int changeFlag) {
  init();
  int shape = spm.getShape();
  int type = spm.getType();
  int newType = (type + changeFlag) % 4;
  if (newType < 0) {
   newType = 3;
  }
  return squareTypeArr[shape][newType];
 }
 /**
  * type 1 竖条形方块
  */
 private static void loadLine() {
  squareTypeArr[0][0] = new ShapeModule("0:0#1:0#2:0#3:0", 0, 0);
  squareTypeArr[0][1] = new ShapeModule("0:0#0:1#0:2#0:3", 0, 1);
  squareTypeArr[0][2] = new ShapeModule("0:0#1:0#2:0#3:0", 0, 2);
  squareTypeArr[0][3] = new ShapeModule("0:0#0:1#0:2#0:3", 0, 3);
 }
 /**
  * type 2 四方形方块
  */
 private static void loadBlock() {
  squareTypeArr[1][0] = new ShapeModule("0:0#0:1#1:0#1:1", 1, 0);
  squareTypeArr[1][1] = new ShapeModule("0:0#0:1#1:0#1:1", 1, 1);
  squareTypeArr[1][2] = new ShapeModule("0:0#0:1#1:0#1:1", 1, 2);
  squareTypeArr[1][3] = new ShapeModule("0:0#0:1#1:0#1:1", 1, 3);
 }
 /**
  * type 3 7形方块
  */
 private static void loadSeven() {
  squareTypeArr[2][0] = new ShapeModule("0:0#1:0#2:0#2:1", 2, 0);
  squareTypeArr[2][1] = new ShapeModule("0:2#1:0#1:1#1:2", 2, 1);
  squareTypeArr[2][2] = new ShapeModule("0:0#0:1#1:1#2:1", 2, 2);
  squareTypeArr[2][3] = new ShapeModule("0:0#0:1#0:2#1:0", 2, 3);
 }
 /**
  * 反7形方块
  */
 private static void loadContrarySeven() {
  squareTypeArr[3][0] = new ShapeModule("0:1#1:1#2:0#2:1", 3, 0);
  squareTypeArr[3][1] = new ShapeModule("0:0#0:1#0:2#1:2", 3, 1);
  squareTypeArr[3][2] = new ShapeModule("0:0#0:1#1:0#2:0", 3, 2);
  squareTypeArr[3][3] = new ShapeModule("0:0#1:0#1:1#1:2", 3, 3);
 }
 /**
  * Z形方块
  */
 private static void loadZ() {
  squareTypeArr[4][0] = new ShapeModule("0:0#0:1#1:1#1:2", 4, 0);
  squareTypeArr[4][1] = new ShapeModule("0:1#1:0#1:1#2:0", 4, 1);
  squareTypeArr[4][2] = new ShapeModule("0:0#0:1#1:1#1:2", 4, 2);
  squareTypeArr[4][3] = new ShapeModule("0:1#1:0#1:1#2:0", 4, 3);
 }
 /**
  * 反Z形方块
  */
 private static void loadContraryZ() {
  squareTypeArr[5][0] = new ShapeModule("0:1#0:2#1:0#1:1", 5, 0);
  squareTypeArr[5][1] = new ShapeModule("0:0#1:0#1:1#2:1", 5, 1);
  squareTypeArr[5][2] = new ShapeModule("0:1#0:2#1:0#1:1", 5, 2);
  squareTypeArr[5][3] = new ShapeModule("0:0#1:0#1:1#2:1", 5, 3);
 }
 /**
  * 山形方块
  */
 private static void loadM() {
  squareTypeArr[6][0] = new ShapeModule("0:1#1:0#1:1#1:2", 6, 0);
  squareTypeArr[6][1] = new ShapeModule("0:1#1:0#1:1#2:1", 6, 1);
  squareTypeArr[6][2] = new ShapeModule("0:0#0:1#0:2#1:1", 6, 2);
  squareTypeArr[6][3] = new ShapeModule("0:0#1:0#1:1#2:0", 6, 3);
 }
}

SubModule.java

package fangkuai;
/**
 * 图形横/纵子模型
 * 
 * @author Stanny Xie
 * @date 2010-01-19
 * 
 * @Example
 * <p>
 * 如果p存储的为纵坐标,那么size对应的就是宽度,即横坐标个数<br/> minC为最小横坐标,maxC为最大横坐标;
 * </p>
 * 
 * <p>
 * 如果p存储的为横坐标,那么size对应的就是高度,即纵坐标个数<br/> minC为最小纵坐标,maxC为最大纵坐标
 * </p>
 */
public class SubModule {
 /**
  * 横/总坐标
  */
 public int p;
 /**
  * 高度/宽度
  */
 public int size;
 /**
  * 最小横/总坐标
  */
 public int minC;
 /**
  * 最大横/总坐标
  */
 public int maxC;
 public SubModule(int p, int size) {
  super();
  this.p = p;
  this.size = size;
 }
 public SubModule(int p, int size, int minC, int maxC) {
  super();
  this.p = p;
  this.size = size;
  this.minC = minC;
  this.maxC = maxC;
 }
}

TableModule.java

package fangkuai;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import util.ObjectUtil;
/**
 * 表格数据模型
 * 
 * @author Stanny Xie
 * @date 2010-01-19
 * 
 */
public class TableModule extends AbstractTableModel implements Serializable {
 /**
  * 
  */
 private static final long serialVersionUID = 1978547795796513859L;
 private int rowCount = 1;
 private int columnCount = 1;
 public Object[][] dataArr = null;
 public TableModule(int rowCount, int columnCount) {
  if (columnCount > 1) {
   this.columnCount = columnCount;
  } else {
   this.columnCount = 1;
  }
  if (rowCount > 1) {
   this.rowCount = rowCount;
  } else {
   this.rowCount = 1;
  }
  dataArr = new Object[rowCount][columnCount];
 }
 public Class<?> getColumnClass(int columnIndex) {
  if (getValueAt(0, columnIndex) != null) {
   return getValueAt(0, columnIndex).getClass();
  } else {
   return String.class;
  }
 }
 public String getColumnName(int columnIndex) {
  return " 第" + columnIndex + "列";
 }
 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
  if (rowIndex >= rowCount) {
   new Exception("Row Index Outbound!").printStackTrace();
  }
  if (columnIndex >= columnCount) {
   new Exception("Column Index Outbound!").printStackTrace();
  }
  if (dataArr == null) {
   dataArr = new Object[rowCount][columnCount];
  }
  dataArr[rowIndex][columnIndex] = aValue;
  fireTableCellUpdated(rowIndex, columnIndex);
 }
 public Object getValueAt(int rowIndex, int columnIndex) {
  if (dataArr == null) {
   dataArr = new Object[rowCount][columnCount];
  }
  // return dataArr[rowIndex][columnIndex];
  // if(columnIndex==columnCount-1){
  // return rowIndex;
  // }
  // if (rowIndex == 9) {
  // return columnIndex;
  // }
  return "";
 }
 public Object getBackgourndValue(int rowIndex, int columnIndex) {
  if (dataArr == null) {
   dataArr = new Object[rowCount][columnCount];
  }
  return dataArr[rowIndex][columnIndex];
 }
 public boolean isCellEditable(int rowIndex, int columnIndex) {
  return false;
 }
 public int getRowCount() {
  return rowCount;
 }
 public int getColumnCount() {
  return columnCount;
 }
 /**
  * 清空被图形完全填充的行
  * 
  * @return 返回删除行数
  */
 public int clearFullLine() {
  List<Integer> clearLineList = new ArrayList<Integer>();
  for (int row = rowCount - 1; row >= 0; row--) {
   boolean flag = true;
   for (int col = 0; col < columnCount; col++) {
    if (ObjectUtil.checkEmpty(dataArr[row][col])) {
     flag = false;
    }
   }
   if (flag) {
    clearLineList.add(row);// 将该行添加到待删除行集合
   }
  }
  if (clearLineList.size() != 0) {// 待删除行集合不为空
   int rowIndex = rowCount;
   Object[][] dataArrTemp = new Object[rowCount][columnCount];
   // 重新绘制表格,删除待删行数据
   for (int row = rowCount - 1; row > 0; row--) {
    if (!clearLineList.contains(row)) {
     rowIndex--;
     for (int col = 0; col < columnCount; col++) {
      dataArrTemp[rowIndex][col] = dataArr[row][col];
     }
    }
   }
   dataArr = dataArrTemp;
  }
  return clearLineList.size();
 }
 // 判断有没有空
 public boolean checkEmpty(int row) {
  for (int col = 0; col < columnCount; col++) {
   if (!ObjectUtil.checkEmpty(dataArr[row][col])) {
    return false;
   }
  }
  return true;
 }
 public boolean checkGameOver() {
  for (int row = 2; row >= 0; row--) {
   if (!checkEmpty(row)) {
    return true;
   }
  }
  return false;
 }
}


俄罗斯方块