import java.awt.*;
import java.awt.event.*;
import javax.swing.*;public class GameMainFrame extends JFrame { private static final long serialVersionUID = 1L; public static void main(String[] args) { 
  new GameMainFrame();
 } public GameMainFrame() {
  Block b = new Block();
  addKeyListener(b);
  add(b); 
  JMenuBar bar = new JMenuBar();
  JMenu game = new JMenu("游戏");
  JMenuItem start = new JMenuItem("开始游戏");
  JMenuItem pause = new JMenuItem("暂停游戏");
  JMenuItem goon = new JMenuItem("继续游戏");
  JMenuItem exit = new JMenuItem("退出");
  game.add(start);
  game.add(pause);
  game.add(goon);
  game.add(exit);
  bar.add(game);
  JMenu help = new JMenu("帮助");
  JMenuItem instr = new JMenuItem("游戏说明");
  JMenuItem about = new JMenuItem("关于");
  help.add(instr);
  help.add(about);
  bar.add(help);
  setJMenuBar(bar);
  setTitle("Tetris");
  setBounds(700, 100, Block.getCOLUMN() * Block.getCELL_LENGTH() + 7,
  Block.getROW() * Block.getCELL_LENGTH() + 58);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  setResizable(false);
  setVisible(true);
  instr.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) {
    JOptionPane.showMessageDialog(null, "控制键:键盘上的四个方向键,上键是变形!"); 
   }  
  });
  
  about.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) {
    JOptionPane.showMessageDialog(null, "设计者: 闫海");   
   }  
  });
 }
}class Block extends JPanel implements KeyListener {
 private static final long serialVersionUID = 1L;
 private static final int ROW = 23, COLUMN = 12;
 private static final int XPOS = 6, YPOS = 1;
 private static final int CELL_LENGTH = 25;
 private int x, y;
 private int type;
 private int status;
 private boolean flag;
 private boolean active = true;
 private int scores = 0;
 private int[][] map = new int[ROW][COLUMN];
 private final int shapes[][][] = new int[][][] {
 // i
   { { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
     { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 } },
   // s
   { { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
     { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 } },
   // z
   { { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
     { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } },
   // j
   { { 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
     { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
     { 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
   // o
   { { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
   // l
   { { 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
     { 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
     { 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
   // t
   { { 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
     { 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } } }; public Block() {
  newBlock();
  drawMap();
  drawWall();
  new Timer(666, new Monitor()).start();
 } public static int getROW() {
  return ROW;
 } public static int getCOLUMN() {
  return COLUMN;
 } public static int getCELL_LENGTH() {
  return CELL_LENGTH;
 } private void newBlock() {
  type = (int) (Math.random() * 1000) % 7;
  status = (int) (Math.random() * 1000) % 3;
  x = XPOS;
  y = YPOS;
  if (!rightful(x, y, type, status)) {
   scores = 0;
   drawMap();
   drawWall();
   JOptionPane.showMessageDialog(null, "GAME OVER");
  }
 } private void left() {
  if (rightful(x - 1, y, type, status) && active) {
   x -= 1;
  }
  repaint();
 } private void right() {
  if (rightful(x + 1, y, type, status) && active) {
   x += 1;
  }
  repaint();
 } private void turn() {
  int tempBlockState = status;
  status = (status + 1) % 4;
  if (!rightful(x, y, type, status) || !active) {
   status = tempBlockState;
  }
  repaint();
 } private void down() {
  if (rightful(x, y + 1, type, status) && active) {
   y += 1;
  }
  if (!rightful(x, y + 1, type, status)) {
   if (flag) {
    add(x, y, type, status);
    deleteLine();
    newBlock();
    flag = false;
   } else {
    flag = true;
   }
  }
  repaint();
 } private void drawMap() {
  for (int i = 0; i < ROW; i++) {
   for (int j = 0; j < COLUMN; j++) {
    map[i][j] = 0;
   }
  }
 } private void drawWall() {
  for (int i = 0; i < COLUMN; i++) {
   map[ROW - 1][i] = 2;
  }
  for (int i = 0; i < ROW; i++) {
   map[i][0] = 2;
   map[i][COLUMN - 1] = 2;
  }
 } private boolean rightful(int x, int y, int blockType, int blockState) {
  for (int a = 0; a < 4; a++) {
   for (int b = 0; b < 4; b++) {
    if (shapes[blockType][blockState][a * 4 + b] == 1
      && (map[y + a][x + b - 1] == 1 || map[y + a][x + b - 1] == 2))
     return false;
   }
  }
  return true;
 } private void add(int x, int y, int blockType, int blockState) {
  for (int a = 0; a < 4; a++) {
   for (int b = 0; b < 4; b++) {
    int temp = shapes[blockType][blockState][a * 4 + b];
    if (temp == 1)
     map[y + a][x + b - 1] = temp;
   }
  }
 } private void deleteLine() {
  for (int a = 0; a < ROW; a++) {
   int c = 0;
   for (int b = 0; b < COLUMN; b++) {
    if (map[a][b] == 1) {
     c += 1;
     if (c == COLUMN - 2) {
      scores += 100;
      int e = a;
      for (int m = e - 1; m >= 0; m--) {
       for (int n = 0; n < 12; n++) {
        map[m + 1][n] = map[m][n];
       }
      }
     }
    }
   }
  }
 } public void keyReleased(KeyEvent e) {
 } public void keyTyped(KeyEvent e) {
 } public void keyPressed(KeyEvent e) {
  int keyCode = e.getKeyCode();
  switch (keyCode) {
  case KeyEvent.VK_LEFT:
   left();
   break;
  case KeyEvent.VK_RIGHT:
   right();
   break;
  case KeyEvent.VK_UP:
   turn();
   break;
  case KeyEvent.VK_DOWN:
   down();
   break;
  case KeyEvent.VK_ENTER:
   active = true;
   break;
  case KeyEvent.VK_SPACE:
   active = false;
   break;
  }
 } public void paintComponent(Graphics g) {
  super.paintComponent(g);
  g.drawString("暂停: 空格键      继续: 回车键      得分: " + scores, COLUMN
    * CELL_LENGTH - 255, 11);
  for (int i = 0; i < shapes[type][status].length; i++) {
   if (shapes[type][status][i] == 1)
    g.fill3DRect((x + i % 4 - 1) * CELL_LENGTH, (y + (int) i / 4)
      * CELL_LENGTH, CELL_LENGTH, CELL_LENGTH, true);
  }
  for (int i = 0; i < ROW; i++) {
   for (int j = 0; j < COLUMN; j++) {
    if (map[i][j] == 1) {
     g.fill3DRect(j * CELL_LENGTH, i * CELL_LENGTH, CELL_LENGTH,
       CELL_LENGTH, true);
    }
    if (map[i][j] == 2) {
     g.drawRect(j * CELL_LENGTH, i * CELL_LENGTH, CELL_LENGTH,
       CELL_LENGTH);
    }
   }
  }
 } private class Monitor implements ActionListener {
  public void actionPerformed(ActionEvent e) {
   if (active)
    down();
  }
 }
}