俄羅斯方塊

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;
 }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章