完全用自己的思路实现, 不过目前还有很多BUG, 懒得改了. 思路已经实现了,分享出来大家研究学习.
 

解决方案 »

  1.   


    /**
     * 
     */
    package cross.pauliuyou.block.api;/**
     * @author 刘优
     *
     */
    public interface Drawable
    {
    public void clearMe();
    public void drawMe();
    }/**
     * 
     */
    package cross.pauliuyou.block.api;/**
     * @author 刘优
     *
     */
    public interface Movable
    {
    public void moveUp();
    public void moveDown();
    public void moveLeft();
    public void moveRight();

    public void moveUp(int step);
    public void moveDown(int step);
    public void moveLeft(int step);
    public void moveRight(int step);

    public void moveAngle(double angle);
    public void moveAngle(int step,double angle);

    public void wander();

    }/**
     * 
     */
    package cross.pauliuyou.block.api;/**
     * @author 刘优
     *
     */
    public interface Rotatable
    {
    public void clockRotate();
    public void deClockRotate();
    }/**
     * 
     */
    package cross.pauliuyou.block.common;import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.util.HashMap;
    import java.util.Iterator;import cross.pauliuyou.block.graph.MsgBox;/**
     * @author 刘优
     *
     */
    public class ConfigUtil
    {
    private static final String CONFIG_FILE_NAME = "BlockConfig";

    public static final int FRAME_TITLE_PANEL_HEIGHT = 65;

    public static int FRAME_MENU_PANEL_HEIGHT = 65;

    public static final int RECTANGLE_STANDARD_ROWS = 4; public static final int RECTANGLE_STANDARD_COLS = 4; public static final String STRING_FONT = "Courier New";

    public static int blockWidth = 10;

    public static int blockHeight = 10;

    private static HashMap<String,String> parametersMap = new HashMap<String,String>();

    public static int blockCountOfX = 10; public static int blockCountOfY = 20;

    public static int initSpeed = 30;

    /**
     * 
     */
    public static HashMap<String,String> readConfigFile(String configFileName)
    {
    HashMap<String,String> parametersMap = new HashMap<String,String>();
    BufferedReader fileReader = null;
    try 
    {
    fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(configFileName)));

    String line = fileReader.readLine();
    int lineIndex = 1;

    while (line != null)
    {
    line = line.trim();
    // 略过注释 if (!line.equals("") && !line.startsWith("//") && !line.startsWith("#")) 
    {
    int equalPos = line.indexOf("=");
    String name = line;
    String value = line;
    if (equalPos != -1) 
    {
    name = line.substring(0,equalPos).trim();
    value = line.substring(equalPos + 1).trim();

    if (value != null && !value.equals(""))
    {
    parametersMap.put(name, value);
    }
    }
    lineIndex++;
    }
    line = fileReader.readLine();
    }

    fileReader.close();

    catch (Exception e) 
    {
    MsgBox.error("未找到配置文件[" + configFileName + "]!");
    }
    return parametersMap;
    } /**
     * @param configFileName
     * @param parametersMap
     */
    public static void writeConfigFile(String configFileName, HashMap<String, String> parametersMap)
    {
    if (parametersMap == null)
    {
    return;
    }
    try
    {
    PrintWriter fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(configFileName)));

    Iterator<String> it = parametersMap.keySet().iterator();
    while (it.hasNext())
    {
    String key = it.next();
    String value = parametersMap.get(key);
    if (value == null)
    {
    value = "";
    }
    fileWriter.println(key + " = " + value);
    }
    fileWriter.close();
    }
    catch (Exception ex)
    {
    ex.printStackTrace();
    }
    }

    /**
     * 
     */
    public static void config()
    {
    File configFile = new File(CONFIG_FILE_NAME);
    if (!configFile.exists() || configFile.length() == 0)
    {
    try
    {
    configFile.createNewFile();

    String name = "blockCountOfX";
    parametersMap.put(name,blockCountOfX + "");

    name = "blockCountOfY";
    parametersMap.put(name,blockCountOfY + "");

    name = "initSpeed";
    parametersMap.put(name,initSpeed + "");

    name = "blockWidth";
    parametersMap.put(name,blockWidth + "");

    blockHeight = 10;
    name = "blockHeight";
    parametersMap.put(name,blockHeight + "");

    writeConfigFile(CONFIG_FILE_NAME,parametersMap);
    }
    catch (IOException e)
    {
    e.printStackTrace();
    }
    }
    else
    {
    parametersMap = readConfigFile(CONFIG_FILE_NAME);

    String name = "blockCountOfX";
    try
    {
    blockCountOfX = Integer.parseInt(parametersMap.get(name));
    }
    catch (Exception ex)
    {
    MsgBox.alert("配置文件中的参数[" + name + "]应该为整数");
    }

    name = "blockCountOfY";
    try
    {
    blockCountOfY = Integer.parseInt(parametersMap.get(name));
    }
    catch (Exception ex)
    {
    MsgBox.alert("配置文件中的参数[" + name + "]应该为整数");
    }

    name = "initSpeed";
    try
    {
    initSpeed = Integer.parseInt(parametersMap.get(name));
    }
    catch (Exception ex)
    {
    MsgBox.alert("配置文件中的参数[" + name + "]应该为整数");
    }

    name = "blockWidth";
    try
    {
    blockWidth = Integer.parseInt(parametersMap.get(name));
    }
    catch (Exception ex)
    {
    MsgBox.alert("配置文件中的参数[" + name + "]应该为整数");
    }

    name = "blockHeight";
    try
    {
    blockHeight = Integer.parseInt(parametersMap.get(name));
    }
    catch (Exception ex)
    {
    MsgBox.alert("配置文件中的参数[" + name + "]应该为整数");
    }
    }
    }
    }
    /**
     * 
     */
    package cross.pauliuyou.block.common;import java.util.Random;/**
     * @author 刘优
     *
     */
    public class RandomProducer
    {
    private static long seed = System.currentTimeMillis();

    private Random random;

    private int max;

    private int begin;

    public RandomProducer(int max)
    {
    this(max,0);
    }

    public RandomProducer(int max,int begin)
    {
    this.max = max;
    this.begin = begin;
    random = new Random(++seed);
    }
    /**
     * @param i
     * @return
     */
    public int getInt()
    {
    int randNum = random.nextInt() % (max - begin) + begin;
    if (randNum < 0)
    {
    randNum *= -1;
    }
    return randNum;
    }

    public double getDouble()
    {
    int randNum = (int)(random.nextDouble() * (max + begin) * 100);

    double rs = randNum / 100d + begin;

    if (rs < 0)
    {
    rs *= -1;
    }
    return rs;
    }
    }
      

  2.   


    /**
     * 
     */
    package cross.pauliuyou.block.graph;import java.awt.Color;
    import java.awt.Graphics;/**
     * @author 刘优
     *
     */
    public class WorkArea
    {
    private static Color areaColor = Color.black;

    protected int x;
    protected int y;
    protected int width;
    protected int height;

    protected int innerX;
    protected int innerY;
    protected int innerWidth;
    protected int innerHeight; public boolean drawed;

    public WorkArea(int x,int y,int width,int height)
    {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;

    innerX = x;
    innerY = y;
    innerWidth = width;
    innerHeight = height;
    }
    /**
     * @return the height
     */
    public int getHeight()
    {
    return height;
    }
    /**
     * @param height the height to set
     */
    public void setHeight(int height)
    {
    this.height = height;
    }
    /**
     * @return the width
     */
    public int getWidth()
    {
    return width;
    }
    /**
     * @param width the width to set
     */
    public void setWidth(int width)
    {
    this.width = width;
    }
    /**
     * @return the x
     */
    public int getX()
    {
    return x;
    }
    /**
     * @param x the x to set
     */
    public void setX(int x)
    {
    this.x = x;
    }
    /**
     * @return the y
     */
    public int getY()
    {
    return y;
    }
    /**
     * @param y the y to set
     */
    public void setY(int y)
    {
    this.y = y;
    }
    /**
     * @param graph
     */
    public void drawArea(Graphics graph)
    {
    graph.setColor(areaColor );
    graph.drawRect(x,y,width,height);
    drawed = true;
    }
    /**
     * @param graph
     */
    public void clearArea(Graphics graph)
    {
    graph.clearRect(innerX,innerY,innerWidth,innerHeight);
    }
    }package cross.pauliuyou.block.graph;import java.awt.Component;
    import java.util.Date;
    import java.util.HashMap;import javax.swing.JOptionPane;/**
     * 弹出报警窗口.同一标题的窗口只能弹出一次,关闭以后才可以再弹出
     * @author 刘优
     * @version 1.0
     */
    public class MsgBox {

    private static HashMap<String,Boolean> isWindowShowingMap = new HashMap<String,Boolean>();

    public static String msgBoxTitleHead = "";

    /**
     * 弹出消息窗口
     * @param msgBody 消息体
     */
    public static void msg(Object msgBody)
    {
    show(null,msgBody,"消息窗口",1,false);
    }

    /**
     * 弹出消息窗口
     * @param msgBody 消息体
     */
    public static void msg(Object msgBody,boolean create)
    {
    show(null,msgBody,"消息窗口",1,false);
    }

    /**
     * 弹出消息窗口
     * @param msgBody 消息体
     */
    public static void msg(Component parentWindow,String msgBody)
    {
    show(parentWindow,msgBody,"消息窗口",1,false);
    }

    /**
     * 弹出消息窗口
     * @param msgBody 消息体
     */
    public static void msg(Component parentWindow,String msgBody,boolean createNew)
    {
    show(parentWindow,msgBody,"消息窗口",1,createNew);
    }

    /**
     * 弹出消息窗口
     * @param msgBody 消息体
     * @param title 消息标题
     */
    public static void msg(String msgBody,String title)
    {
    show(null,msgBody,title,1,false);
    }

    /**
     * 弹出消息窗口
     * @param msgBody 消息体
     * @param title 消息标题
     */
    public static void msg(String msgBody,String title,boolean createNew)
    {
    show(null,msgBody,title,1,createNew);
    }

    public static void msg(Component parentWindow,String msgBody,String title)
    {
    show(parentWindow,msgBody,title,1,false);
    }

    public static void msg(Component parentWindow,String msgBody,String title,boolean createNew)
    {
    show(parentWindow,msgBody,title,1,createNew);
    }

    /**
     * 弹出警告窗口
     * @param msgBody 警告消息
     */
    public static void alert(Object msgBody)
    {
    show(null,msgBody,"警告窗口",2,false);
    }

    public static void alert(Object msgBody,boolean createNew)
    {
    show(null,msgBody,"警告窗口",2,createNew);
    }

    /**
     * 弹出警告窗口
     * @param msgBody 警告消息
     */
    public static void alert(Component parentWindow,String msgBody)
    {
    show(parentWindow,msgBody,"警告窗口",2,false);
    }

    public static void alert(Component parentWindow,String msgBody,boolean createNew)
    {
    show(parentWindow,msgBody,"警告窗口",2,createNew);
    }

    /**
     * 弹出警告窗口
     * @param msgBody 警告消息体
     * @param title 警告标题
     */
    public static void alert(String msgBody,String title)
    {
    show(null,msgBody,title,2,false);
    }

    public static void alert(String msgBody,String title,boolean createNew)
    {
    show(null,msgBody,title,2,createNew);
    }

    /**
     * 弹出警告窗口
     * @param msgBody 警告消息体
     * @param title 警告标题
     */
    public static void alert(Component parentWindow,Object msgBody,String title)
    {
    show(parentWindow,msgBody,title,2,false);
    }

    public static void alert(Component parentWindow,Object msgBody,String title,boolean createNew)
    {
    show(parentWindow,msgBody,title,2,createNew);
    }

    /**
     * 弹出问题窗口
     * @param msgBody 问题消息体
     */
    public static void question(Object msgBody)
    {
    show(null,msgBody,"问题窗口",3,false);
    }

    public static void question(Object msgBody,boolean createNew)
    {
    show(null,msgBody,"问题窗口",3,createNew);
    }

    /**
     * 弹出问题窗口
     * @param msgBody 问题消息体
     */
    public static void question(Component parentWindow,String msgBody)
    {
    show(parentWindow,msgBody,"问题窗口",3,false);
    }

    public static void question(Component parentWindow,String msgBody,boolean createNew)
    {
    show(parentWindow,msgBody,"问题窗口",3,createNew);
    }

    /**
     * 弹出问题窗口
     * @param msgBody 问题消息体
     * @param title 问题标题
     */
    public static void question(String msgBody,String title)
    {
    show(null,msgBody,title,3,false);
    }

    public static void question(String msgBody,String title,boolean createNew)
    {
    show(null,msgBody,title,3,createNew);
    }

    /**
     * 弹出问题窗口
     * @param msgBody 问题消息体
     * @param title 问题标题
     */
    public static void question(Component parentWindow,String msgBody,String title)
    {
    show(parentWindow,msgBody,title,3,false);
    }

    public static void question(Component parentWindow,String msgBody,String title,boolean createNew)
    {
    show(parentWindow,msgBody,title,3,createNew);
    }

    /**
     * 弹出错误窗口
     * @param msgBody 误消息体
     */
    public static void error(Object msgBody)
    {
    show(null,msgBody,"错误窗口",0,false);
    }

    public static void error(Object msgBody,boolean createNew)
    {
    show(null,msgBody,"错误窗口",0,createNew);
    }

    /**
     * 弹出错误窗口
     * @param msgBody 误消息体
     */
    public static void error(Component parentWindow,String msgBody)
    {
    show(parentWindow,msgBody,"错误窗口",0,false);
    }

    public static void error(Component parentWindow,String msgBody,boolean createNew)
    {
    show(parentWindow,msgBody,"错误窗口",0,createNew);
    }

    /**
     * 弹出错误窗口
     * @param msgBody 错误消息体
     * @param title 错误标题
     */
    public static void error(String msgBody,String title)
    {
    show(null,msgBody,title,0,false);
    }

    public static void error(String msgBody,String title,boolean createNew)
    {
    show(null,msgBody,title,0,createNew);
    }

    /**
     * 弹出错误窗口
     * @param msgBody 错误消息体
     * @param title 错误标题
     */
    public static void error(Component parentWindow,String msgBody,String title)
    {
    show(parentWindow,msgBody,title,0,false);
    }

    public static void error(Component parentWindow,String msgBody,String title,boolean createNew)
    {
    show(parentWindow,msgBody,title,0,createNew);
    }

    /**
     * 弹出提示窗口
     * @param msgBody 提示消息体
     * @param title 提示标题
     * @param windowType 提示窗口类型(3-问题窗口,2-警告窗口,1-消息窗口,0-错误窗口)
     */
    public static void show(Component parentWindow,Object msgBody,String title,int windowType,boolean createNew)
    {
    String titleInfor = msgBoxTitleHead + title;
    boolean isShowing = false;

    Object obj = isWindowShowingMap.get(titleInfor);
    if (obj != null)
    {
    isShowing = (Boolean)obj;
    }
    if (!isShowing || createNew)
    {
    new ShowBoxThread(parentWindow,msgBody,title,windowType,createNew).start();
    }
    }

    private static class ShowBoxThread extends Thread
    {
    private Component parentWindow;
    private String infor;
    private String titleInfor;
    private int theType;
    private boolean createNew;

    public ShowBoxThread(Component parentWindow,Object msgBody,String title,int windowType,boolean createNew)
    {
    this.parentWindow = parentWindow;
    this.infor = msgBody.toString();
    this.titleInfor = msgBoxTitleHead + title;
    this.theType = windowType;
    this.createNew = createNew;
    }

    public void run()
    {
    setName("MsgBox<" + titleInfor + ">");
    if (!createNew)
    {
    isWindowShowingMap.put(titleInfor,true);
    try
    {
    JOptionPane.showMessageDialog(parentWindow,new Date() + " > " + infor,titleInfor,theType);
    }
    catch (Exception e) 
    {
    error("消息窗口的类型参数不正确.(3-问题窗口,2-警告窗口,1-消息窗口,0-错误窗口)");
    }
    isWindowShowingMap.put(titleInfor,false);
    }
    else
    {
    try
    {
    JOptionPane.showMessageDialog(parentWindow,new Date() + " > " + infor,titleInfor,theType);
    }
    catch (Exception e) 
    {
    error("消息窗口的类型参数不正确.(3-问题窗口,2-警告窗口,1-消息窗口,0-错误窗口)");
    }
    }
    }
    }

    }
      

  3.   


    package cross.pauliuyou.block.graph;import java.awt.Dimension;
    import java.awt.Frame;
    import java.awt.GraphicsEnvironment;
    import java.awt.Rectangle;
    import java.awt.Toolkit;
    import java.awt.Window;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.lang.reflect.Method;import javax.swing.JDialog;
    import javax.swing.JFrame;/**
     * 窗口显示调整工具
     * @author 刘优
     * @version 1.0
     */public class WindowUtil {
    /**
         * Positions the specified frame in the middle of the screen.
         *
         * @param frame  the frame to be centered on the screen.
         */
        public static void centerFrameOnScreen(final Window frame) {
            positionFrameOnScreen(frame, 0.5, 0.5);
        }    /**
         * Positions the specified frame at a relative position in the screen, where 50% is considered
         * to be the center of the screen.
         *
         * @param frame  the frame.
         * @param horizontalPercent  the relative horizontal position of the frame (0.0 to 1.0,
         *                           where 0.5 is the center of the screen).
         * @param verticalPercent  the relative vertical position of the frame (0.0 to 1.0, where
         *                         0.5 is the center of the screen).
         */
        public static void positionFrameOnScreen(final Window frame,
                                                 final double horizontalPercent,
                                                 final double verticalPercent) {        final Rectangle s = getMaximumWindowBounds();
            final Dimension f = frame.getSize();
            final int w = Math.max(s.width - f.width, 0);
            final int h = Math.max(s.height - f.height, 0);
            final int x = (int) (horizontalPercent * w) + s.x;
            final int y = (int) (verticalPercent * h) + s.y;
            frame.setBounds(x, y, f.width, f.height);    }
        
        /**
         * Computes the maximum bounds of the current screen device. If this method is called on JDK 1.4, Xinerama-aware
         * results are returned. (See Sun-Bug-ID 4463949 for details).
         *
         * @return the maximum bounds of the current screen.
         */
      public static Rectangle getMaximumWindowBounds ()
      {
      final GraphicsEnvironment localGraphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
      try
      {
      final Method method = GraphicsEnvironment.class.getMethod("getMaximumWindowBounds", (Class[]) null);
      return (Rectangle) method.invoke(localGraphicsEnvironment, (Object[]) null);
      }
      catch(Exception e)
      {
      // ignore ... will fail if this is not a JDK 1.4 ..
      }

      final Dimension s = Toolkit.getDefaultToolkit().getScreenSize();
      return new Rectangle (0, 0, s.width, s.height);
    } public static void fullScreenFrame(Window window)
    {
    java.awt.Dimension dimension = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
    window.setSize(dimension.width, dimension.height - 30);
    if (window instanceof Frame)
    ((Frame)window).setExtendedState(Frame.MAXIMIZED_BOTH); 
    window.setLocation(0, 0);
    }

    /**
     * 居中显示窗口
     * @param w
     */
        public static void doView(Window w) {
        
    w.setSize(w.getToolkit().getScreenSize().width,w.getToolkit().getScreenSize().height - 40);
    w.setLocation(0,0);
    w.setVisible(true);
    if (w.getClass() == JFrame.class) {
        ((JFrame)w).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ((JFrame)w).setResizable(false);
    }
    if (w.getClass() == JDialog.class) {
    ((JDialog)w).setDefaultCloseOperation(JDialog.EXIT_ON_CLOSE);
    ((JDialog)w).setResizable(false);
    }
    }
        
        /**
         * 居中显示窗口
         * @param w
         * @param width
         * @param height
         */
    public static void doView(Window w,int width,int height) {
    w.setSize(width,height);
    int width2 = w.getToolkit().getScreenSize().width;
    width2 = (width2 - w.getWidth()) / 2;
    int height2 = w.getToolkit().getScreenSize().height;
    height2 = (height2 - w.getHeight()) / 2;
    w.setLocation(width2,height2);
    w.setVisible(true);
    if (w.getClass() == JFrame.class) {
        ((JFrame)w).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ((JFrame)w).setResizable(false);
    }
    /*
    if (w.getClass() == JDialog.class) {
    ((JDialog)w).setDefaultCloseOperation(JDialog.EXIT_ON_CLOSE);
    ((JDialog)w).setResizable(false);
    }
    */
    }
    /**
     * 设置窗口关闭
     * @param w 窗口
     */
    public static void doClose(Window w) {
    final Window w2 = w;
    w.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent we) {
        w2.dispose();
    }
    });
    }
    }
      

  4.   


    /**
     * 
     */
    package cross.pauliuyou.block.graph;import java.awt.Color;
    import java.awt.Graphics;import cross.pauliuyou.block.api.Drawable;
    import cross.pauliuyou.block.api.Movable;
    import cross.pauliuyou.block.common.ConfigUtil;
    import cross.pauliuyou.block.common.RandomProducer;/**
     * 方块类, 是组成矩阵的基本元素,每个方块都可以移动并自我绘制
     * @author 刘优
     *
     */
    public class Block implements Drawable,Movable
    {
    /**
     * 方块宽度
     */
    public static final int BLOCK_WIDTH = ConfigUtil.blockWidth;

    /**
     * 方块高度
     */
    public static final int BLOCK_HEIGHT = ConfigUtil.blockHeight;

    /**
     * 向上移动
     */
    public static final int MOVE_UP = 0;

    /**
     * 向下移动 
     */
    public static final int MOVE_DOWN = 1;
    public static final int MOVE_LEFT = 2;
    public static final int MOVE_RIGHT = 3;

    protected static int defaultXStep = BLOCK_WIDTH;
    protected static int defaultYStep = BLOCK_HEIGHT;

    protected int x;
    protected int y;

    protected Graphics graphics;
    protected Color blockColor;
    protected Color displayColor;
    protected WorkArea workArea;

    protected RandomProducer countRandom = new RandomProducer(8,3);
    protected RandomProducer directionRandom = new RandomProducer(4);
    protected int stepCount;
    protected int moveDirection;

    protected int[] tableIndex;

    protected boolean visible = true;

    protected boolean toMoveUp = true;
    protected boolean toMoveDown = true;
    protected boolean toMoveLeft = true;
    protected boolean toMoveRight = true;

    private int upStep = defaultXStep;
    private int downStep = defaultXStep;
    private int leftStep = defaultYStep;
    private int rightStep = defaultYStep;

    private int top;
    private int buttom;
    private int left;
    private int right;

    private BlockMartix owner;

    public void setBlockTableIndexes(int[] tableIndexes)
    {
    this.tableIndex = tableIndexes;
    }

    public Block(Graphics graphics,WorkArea workArea,Color blockColor,int x,int y)
    {
    this.blockColor = blockColor;
    displayColor = blockColor;
    this.graphics = graphics;
    this.workArea = workArea;
    this.x = x;
    this.y = y;

    top = workArea.y + 2;
    buttom = workArea.height - 2 - BLOCK_HEIGHT + ConfigUtil.FRAME_TITLE_PANEL_HEIGHT;
    left = workArea.x + 2;
    right = workArea.x + workArea.width - 2 - BLOCK_WIDTH; 

    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Drawable#clearMe()
     */
    public void clearMe()
    {
    if (visible)
    {
    //graphics.clearRect(x, y, BLOCK_WIDTH, BLOCK_HEIGHT);
    }
    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Drawable#drawMe()
     */
    public void drawMeNoRect()
    {
    if (visible)
    {
    graphics.setColor(displayColor);
    graphics.fillRect(x, y, BLOCK_WIDTH, BLOCK_HEIGHT);
    }
    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Drawable#drawMe()
     */
    public void drawMe()
    {
    if (visible)
    {
    graphics.setColor(Color.gray);
    graphics.drawRect(x, y, BLOCK_WIDTH, BLOCK_HEIGHT);
    graphics.setColor(displayColor);
    graphics.fillRect(x + 1, y + 1, BLOCK_WIDTH - 1, BLOCK_HEIGHT - 1);
    }

    }

    public void setVisible(boolean visible)
    {
    this.visible = visible;
    if (visible)
    {
    displayColor = blockColor;
    }
    else
    {
    displayColor = null;
    }
    }

    public boolean isVisible()
    {
    return visible;
    }

    public void moveUp()
    {
    moveUp(defaultYStep);
    }
    public void moveDown()
    {
    moveDown(defaultYStep);
    }
    public void moveLeft()
    {
    moveLeft(defaultXStep);
    }
    public void moveRight()
    {
    moveRight(defaultXStep);
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveUp(int)
     */
    public void moveUp(int step)
    {
    if (!toMoveUp)
    {
    toMoveDown = true;
    return;
    }

    upStep = step;
    clearMe();
    if (willOverTop())
    {
    y = buttom;
    }
    else
    {
    y -= step;
    }
    drawMe();
    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveDown(int)
     */
    public void moveDown(int step)
    {
    if (!toMoveDown)
    {
    toMoveUp = true;
    return;
    }
    downStep = step;
    clearMe();
    if (willOverButtom())
    {
    y = top;
    }
    else
    {
    y += step;
    }
    drawMe();
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveLeft(int)
     */
    public void moveLeft(int step)
    {
    if (!toMoveLeft)
    {
    toMoveRight = true;
    return;
    }
    leftStep = step;
    clearMe();
    if (willOverLeft())
    {
    x = right;
    }
    else
    {
    x -= step;
    }
    drawMe();
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveRight(int)
     */
    public void moveRight(int step)
    {
    if (!toMoveRight)
    {
    toMoveLeft = true;
    return;
    }
    rightStep = step;
    clearMe();
    if (willOverRight())
    {
    x = left;
    }
    else
    {
    x += step;
    }
    drawMe();
    }

    public boolean willOverTop()
    {
    if (y - upStep < workArea.y - 2)
    {
    return true;
    }
    return false;
    }

    public boolean willOverButtom()
    {
    if (y + downStep > workArea.height + ConfigUtil.FRAME_TITLE_PANEL_HEIGHT - BLOCK_HEIGHT)
    {
    return true;
    }
    return false;
    }

    public boolean willOverLeft()
    {
    if (x - leftStep < workArea.x + 2)
    {
    return true;
    }
    return false;
    }

    public boolean willOverRight()
    {
    if (x + rightStep > workArea.x + workArea.width - 2 - BLOCK_WIDTH)
    {
    return true;
    }
    return false;
    } public void wander()
    {
    int theCount = countRandom.getInt();
    if (stepCount++ >= theCount)
    {
    moveDirection = directionRandom.getInt();
    stepCount = 0;
    }

    //System.out.println(moveDirection);

    switch (moveDirection)
    {
    case MOVE_UP :
    if (willOverTop())
    {
    moveDirection = MOVE_DOWN;
    moveDown();
    }
    else
    {
    moveUp();
    }
    break;
    case MOVE_DOWN :
    if (willOverButtom())
    {
    moveDirection = MOVE_UP;
    moveUp();
    }
    else
    {
    moveDown();
    }
    break;
    case MOVE_LEFT :
    if (willOverLeft())
    {
    moveDirection = MOVE_RIGHT;
    moveRight();
    }
    else
    {
    moveLeft();
    }
    break;
    case MOVE_RIGHT:
    if (willOverRight())
    {
    moveDirection = MOVE_LEFT;
    moveLeft();
    }
    else
    {
    moveRight();
    }
    break;
    }
    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveAngle(int, double)
     */
    public void moveAngle(double angle)
    {
    moveAngle(defaultXStep,angle);

    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveAngle(int, double)
     */
    public void moveAngle(int step, double angle)
    {
    // TODO Auto-generated method stub

    }
      

  5.   


    /**
     * @return the blockColor
     */
    public Color getBlockColor()
    {
    return blockColor;
    } /**
     * @param blockColor the blockColor to set
     */
    public void setBlockColor(Color blockColor)
    {
    this.blockColor = blockColor;
    } /**
     * @return the graphics
     */
    public Graphics getGraphics()
    {
    return graphics;
    } /**
     * @param graphics the graphics to set
     */
    public void setGraphics(Graphics graphics)
    {
    this.graphics = graphics;
    } /**
     * @return the workArea
     */
    public WorkArea getWorkArea()
    {
    return workArea;
    } /**
     * @param workArea the workArea to set
     */
    public void setWorkArea(WorkArea workArea)
    {
    this.workArea = workArea;
    } /**
     * @return the x
     */
    public int getX()
    {
    return x;
    } /**
     * @param x the x to set
     */
    public void setX(int x)
    {
    this.x = x;
    } /**
     * @return the y
     */
    public int getY()
    {
    return y;
    } /**
     * @param y the y to set
     */
    public void setY(int y)
    {
    this.y = y;
    } /**
     * @return the displayColor
     */
    public Color getDisplayColor()
    {
    return displayColor;
    } /**
     * @param displayColor the displayColor to set
     */
    public void setDisplayColor(Color displayColor)
    {
    this.displayColor = displayColor;
    } /**
     * @return the moveDirection
     */
    public int getMoveDirection()
    {
    return moveDirection;
    } /**
     * @param moveDirection the moveDirection to set
     */
    public void setMoveDirection(int moveDirection)
    {
    this.moveDirection = moveDirection;
    } /**
     * @return the stepCount
     */
    public int getStepCount()
    {
    return stepCount;
    } /**
     * @param stepCount the stepCount to set
     */
    public void setStepCount(int stepCount)
    {
    this.stepCount = stepCount;
    } /**
     * @return the tableIndexes
     */
    public int[] getTableIndexes()
    {
    return tableIndex;
    } /**
     * @param tableIndexes the tableIndexes to set
     */
    public void setTableIndexes(int[] tableIndexes)
    {
    this.tableIndex = tableIndexes;
    } /**
     * @return the toMoveDown
     */
    public boolean isToMoveDown()
    {
    return toMoveDown;
    } /**
     * @param toMoveDown the toMoveDown to set
     */
    public void setToMoveDown(boolean toMoveDown)
    {
    this.toMoveDown = toMoveDown;
    } /**
     * @return the toMoveLeft
     */
    public boolean isToMoveLeft()
    {
    return toMoveLeft;
    } /**
     * @param toMoveLeft the toMoveLeft to set
     */
    public void setToMoveLeft(boolean toMoveLeft)
    {
    this.toMoveLeft = toMoveLeft;
    } /**
     * @return the toMoveRight
     */
    public boolean isToMoveRight()
    {
    return toMoveRight;
    } /**
     * @param toMoveRight the toMoveRight to set
     */
    public void setToMoveRight(boolean toMoveRight)
    {
    this.toMoveRight = toMoveRight;
    } /**
     * @return the toMoveUp
     */
    public boolean isToMoveUp()
    {
    return toMoveUp;
    } /**
     * @param toMoveUp the toMoveUp to set
     */
    public void setToMoveUp(boolean toMoveUp)
    {
    this.toMoveUp = toMoveUp;
    } /**
     * @return the owner
     */
    public BlockMartix getOwner()
    {
    return owner;
    } /**
     * @param owner the owner to set
     */
    public void setOwner(BlockMartix owner)
    {
    this.owner = owner;
    }
    }
      

  6.   


    /**
     * 
     */
    package cross.pauliuyou.block.graph;import java.awt.Color;
    import java.awt.Graphics;/**
     * @author Administrator
     *
     */
    public class RectangleBlock extends Block
    {
    /**
     * @param graphics
     * @param workArea
     * @param blockColor
     * @param x
     * @param y
     */
    public RectangleBlock(Graphics graphics, WorkArea workArea, Color blockColor, int x, int y)
    {
    super(graphics, workArea, blockColor, x, y);
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Drawable#drawMe()
     */
    @Override
    public void drawMeNoRect()
    {
    if (visible)
    {
    graphics.setColor(displayColor);
    graphics.fillRect(x, y, BLOCK_WIDTH, BLOCK_HEIGHT);
    }
    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Drawable#drawMe()
     */
    public void drawMe()
    {
    if (visible)
    {
    graphics.setColor(Color.gray);
    graphics.drawRect(x, y, BLOCK_WIDTH, BLOCK_HEIGHT);
    graphics.setColor(displayColor);
    graphics.fillRect(x + 1, y + 1, BLOCK_WIDTH - 1, BLOCK_HEIGHT - 1);
    }
    }
    }
      

  7.   


    /**
     * 
     */
    package cross.pauliuyou.block.graph;import java.awt.Color;
    import java.awt.Graphics;import cross.pauliuyou.block.api.Drawable;
    import cross.pauliuyou.block.api.Movable;
    import cross.pauliuyou.block.api.Rotatable;
    import cross.pauliuyou.block.common.ConfigUtil;
    import cross.pauliuyou.block.common.RandomProducer;/**
     * @author 刘优
     *
     */
    public class BlockMartix implements Movable,Drawable,Rotatable
    {
    protected int rows = ConfigUtil.RECTANGLE_STANDARD_ROWS;
    protected int cols = ConfigUtil.RECTANGLE_STANDARD_COLS;

    protected Block[][] blockTable = new Block[rows][cols];

    private RandomProducer random0 = new RandomProducer(230,5);

    private RandomProducer random1 = new RandomProducer(8,5);

    private RandomProducer random2 = new RandomProducer(4);

    protected WorkArea workArea;

    protected Color color;

    protected int stepCount;
    protected int moveDirection; protected int initX;
    protected int initY;
    protected Block leftTopBlock;
    protected Graphics graphics;

    protected static Color[] colors = {Color.red,Color.green,Color.blue,Color.black,Color.gray,Color.yellow};

    protected boolean stopped;

    public BlockMartix(Graphics graphics,WorkArea workArea)
    {
    this(graphics,workArea,null);
    }

    public BlockMartix(Graphics graphics,WorkArea workArea,Color color)
    {
    this.graphics = graphics;
    this.workArea = workArea;
    this.color = color;
    initX = workArea.x + ((workArea.width / 2) - ((cols / 2) * Block.BLOCK_WIDTH));
    initY = workArea.y + 2;
    createMatrix(color);
    }

    /**
     * 
     */
    protected void createMatrix(Color color)
    {
    int x = initX;
    int y = initY;

    int blue = 10;
    int green = 10;
    int red = 10;
    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    Color tmpColor = color;
    if (color == null)
    {
    tmpColor = new Color(red,green,blue);
    }
    Block block = new RectangleBlock(graphics,workArea,tmpColor,x,y);
    block.setOwner(this);
    block.tableIndex = new int[]{i,j};

    blockTable[i][j] = block;

    blue = random0.getInt();
    green = random0.getInt();
    red = random0.getInt();

    x += Block.BLOCK_WIDTH;
    }
    x = initX;
    y += Block.BLOCK_HEIGHT;
    }
    leftTopBlock = blockTable[0][0];
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveUp()
     */
    public void moveUp()
    {
    moveUp(Block.defaultYStep);

    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveDown()
     */
    public void moveDown()
    {
    moveDown(Block.defaultYStep);

    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveLeft()
     */
    public void moveLeft()
    {
    moveLeft(Block.defaultXStep);

    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveRight()
     */
    public void moveRight()
    {
    moveRight(Block.defaultXStep);

    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveUp(int)
     */
    public void moveUp(int step)
    {
    if (stopped)
    {
    return;
    }
    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    if (blockTable[i][j] != null)
    {
    blockTable[i][j].moveUp(step);
    }
    }
    }
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveDown(int)
     */
    public void moveDown(int step)
    {
    if (stopped)
    {
    return;
    }
    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    if (blockTable[i][j] != null)
    {
    blockTable[i][j].moveDown(step);
    }
    }
    }
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveLeft(int)
     */
    public void moveLeft(int step)
    {
    if (stopped)
    {
    return;
    }
    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    if (blockTable[i][j] != null)
    {
    blockTable[i][j].moveLeft(step);
    }
    }
    }

    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveRight(int)
     */
    public void moveRight(int step)
    {
    if (stopped)
    {
    return;
    }
    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    if (blockTable[i][j] != null)
    {
    blockTable[i][j].moveRight(step);
    }
    }
    }

    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveAngle(int, double)
     */
    public void moveAngle(double angle)
    {
    moveAngle(Block.defaultXStep,angle);

    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveAngle(int, double)
     */
    public void moveAngle(int step, double angle)
    {
    if (stopped)
    {
    return;
    }
    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    if (blockTable[i][j] != null)
    {
    blockTable[i][j].moveAngle(step,angle);
    }
    }
    }

    }

    public void wander()
    {
    if (stopped)
    {
    return;
    }
    int theCount = random1.getInt();
    if (stepCount++ >= theCount)
    {
    moveDirection = random2.getInt();
    stepCount = 0;
    }

    //System.out.println(moveDirection);

    switch (moveDirection)
    {
    case Block.MOVE_UP :
    if (blockTable[0][0].willOverTop())
    {
    moveDirection = Block.MOVE_DOWN;
    moveDown();
    }
    else
    {
    moveUp();
    }
    break;
    case Block.MOVE_DOWN :
    if (blockTable[rows - 1][0].willOverButtom())
    {
    moveDirection = Block.MOVE_UP;
    moveUp();
    }
    else
    {
    moveDown();
    }
    break;
    case Block.MOVE_LEFT :
    if (blockTable[0][0].willOverLeft())
    {
    moveDirection = Block.MOVE_RIGHT;
    moveRight();
    }
    else
    {
    moveLeft();
    }
    break;
    case Block.MOVE_RIGHT:
    if (blockTable[0][cols - 1].willOverRight())
    {
    moveDirection = Block.MOVE_LEFT;
    moveLeft();
    }
    else
    {
    moveRight();
    }
    break;
    }
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Drawable#drawMe()
     */
    public void drawMe()
    {
    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    if (blockTable[i][j] != null)
    {
    blockTable[i][j].drawMe();
    }
    }
    }

    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Drawable#clearMe()
     */
    public void clearMe()
    {
    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    if (blockTable[i][j] != null)
    {
    blockTable[i][j].clearMe();
    }
    }
    }

    }
      

  8.   

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Rotatable#clockRotate()
     */
    public void clockRotate()
    {
    if (stopped)
    {
    return;
    }
    Block[][] tempTable = new Block[cols][rows];

    int headX = blockTable[0][0].x;
    int headY = blockTable[0][0].y;

    for (int i = 0; i < cols; i++)
    {
    Block[] newXLine = new Block[rows];
    for (int j = 0; j < rows; j++)
    {
    newXLine[j] = blockTable[rows - 1 - j][i];
    }
    tempTable[i] = newXLine;
    }

    int temp = rows;
    rows = cols;
    cols = temp;

    int x = headX;
    int y = headY;

    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    tempTable[i][j].tableIndex = new int[]{i,j};
    tempTable[i][j].x = x;
    tempTable[i][j].y = y;
    x += Block.BLOCK_WIDTH;
    }
    y += Block.BLOCK_HEIGHT;
    x = headX;
    }
    blockTable = tempTable;
    drawMe();
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Rotatable#deClockRotate()
     */
    public void deClockRotate()
    {
    if (stopped)
    {
    return;
    }
    Block[][] tempTable = new Block[cols][rows];

    int headX = blockTable[0][0].x;
    int headY = blockTable[0][0].y;

    for (int i = 0; i < cols; i++)
    {
    Block[] newXLine = new Block[rows];
    for (int j = 0; j < rows; j++)
    {
    newXLine[j] = blockTable[j][cols - 1 - i];
    }
    tempTable[i] = newXLine;
    }

    int temp = rows;
    rows = cols;
    cols = temp;

    int x = headX;
    int y = headY;

    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    tempTable[i][j].tableIndex = new int[]{i,j};
    tempTable[i][j].x = x;
    tempTable[i][j].y = y;
    x += Block.BLOCK_WIDTH;
    }
    y += Block.BLOCK_HEIGHT;
    x = headX;
    }
    blockTable = tempTable;
    drawMe();
    }

    public int getX()
    {
    return this.leftTopBlock.x;
    }

    public int getY()
    {
    return this.leftTopBlock.y;
    }
    }
      

  9.   


    /**
     * 
     */
    package cross.pauliuyou.block.graph;import java.awt.Color;
    import java.awt.Graphics;
    import java.util.Vector;/**
     * @author 刘优
     *
     */
    public class Shape extends BlockMartix
    {
    private byte[][] shapeDesc;

    private Block topBlock;
    private Block buttomBlock;
    private Block leftBlock;
    private Block rightBlock;

    private boolean atTop;
    private boolean atButtom;
    private boolean atLeft;
    private boolean atRight;

    private boolean moved;

    private Vector<Block> visibleBlocks = new Vector<Block>();

    /**
     * @return the atButtom
     */
    public boolean isAtButtom()
    {
    return atButtom;
    } /**
     * @return the atLeft
     */
    public boolean isAtLeft()
    {
    return atLeft;
    } /**
     * @return the atRight
     */
    public boolean isAtRight()
    {
    return atRight;
    } /**
     * @return the atTop
     */
    public boolean isAtTop()
    {
    return atTop;
    } /**
     * @param window
     * @param color
     */
    public Shape(Graphics graphics,WorkArea workArea,Color color,byte[][]shapeDesc)
    {
    super(graphics,workArea, color);
    this.shapeDesc = shapeDesc;
    rebuildShape();
    this.shapeDesc = new byte[shapeDesc.length][shapeDesc[0].length];
    for (int i = 0; i < shapeDesc.length; i++)
    {
    for (int j = 0; j < shapeDesc[i].length; j++)
    {
    this.shapeDesc[i][j] = shapeDesc[i][j];
    }
    }
    }

    protected void rebuildShape()
    {
    for (int i = 0; i < shapeDesc.length; i++)
    {
    if (i < super.blockTable.length)
    {
    for (int j = 0; j < shapeDesc[i].length; j++)
    {
    if (j < super.blockTable[i].length)
    {
    if (shapeDesc[i][j] == 0)
    {
    super.blockTable[i][j].setVisible(false);
    }
    else
    {
    visibleBlocks.add(blockTable[i][j]);
    }
    }
    }
    }
    }
    findEdge();
    }

    private void findEdge()
    {
    topBlock = null;
    int lx = shapeDesc.length - 1;
    int ly = shapeDesc.length - 1;
    int rx = 0;
    int ry = 0;
    int bx = 0;
    int by = 0;
    for (int i = 0; i < blockTable.length; i++)
    {
    for (int j = 0; j < blockTable[i].length; j++)
    {
    if (blockTable[i][j].isVisible())
    {
    if (topBlock == null)
    {
    topBlock = blockTable[i][j];
    }
    if (j < ly)
    {
    lx = i;
    ly = j;
    }
    if (j > ry)
    {
    rx = i;
    ry = j;
    }
    if (i > bx)
    {
    bx = i;
    by = j;
    }
    }
    }
    }
    buttomBlock = blockTable[bx][by];
    leftBlock = blockTable[lx][ly];
    rightBlock = blockTable[rx][ry];
    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveUp(int)
     */
    @Override
    public void moveUp(int step)
    {
    if (!topBlock.willOverTop())
    {
    super.moveUp(step);
    moved = true;
    }
    else
    {
    atTop = true;
    drawMe();
    }
    atButtom = false;
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveDown(int)
     */
    @Override
    public void moveDown(int step)
    {
    if (!buttomBlock.willOverButtom())
    {
    super.moveDown(step);
    moved = true;
    }
    else
    {
    atButtom = true;
    drawMe();
    }
    atTop = false;
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveLeft(int)
     */
    @Override
    public void moveLeft(int step)
    {
    if (!leftBlock.willOverLeft())
    {
    super.moveLeft(step);
    moved = true;
    }
    else
    {
    atLeft = true;
    drawMe();
    }
    atRight = false;
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveRight(int)
     */
    @Override
    public void moveRight(int step)
    {
    if (!rightBlock.willOverRight())
    {
    super.moveRight(step);
    moved = true;
    }
    else
    {
    atRight = true;
    drawMe();
    }
    atLeft = false;
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveAngle(int, double)
     */
    @Override
    public void moveAngle(double angle)
    {
    moveAngle(Block.defaultXStep,angle);

    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Movable#moveAngle(int, double)
     */
    @Override
    public void moveAngle(int step, double angle)
    {
    super.moveAngle(step,angle);
    moved = true;
    }

    /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Rotatable#clockRotate()
     */
    @Override
    public void clockRotate()
    {
    super.clockRotate();

    int oldRow = shapeDesc.length;
    int oldCol = shapeDesc[0].length;

    byte[][] tempDesc = new byte[oldCol][oldRow];

    for (int i = 0; i < oldCol; i++)
    {
    byte[] newXLine = new byte[oldRow];
    for (int j = 0; j < oldRow; j++)
    {
    newXLine[j] = shapeDesc[oldRow - 1 - j][i];
    }
    tempDesc[i] = newXLine;
    }
    shapeDesc = tempDesc;

    findEdge();

    /*
    Block tmp = topBlock;
    topBlock = leftBlock;
    leftBlock = buttomBlock;
    buttomBlock = rightBlock;
    rightBlock = tmp;
    */
    } /* (non-Javadoc)
     * @see cross.pauliuyou.block.api.Rotatable#deClockRotate()
     */
    @Override
    public void deClockRotate()
    {
    super.deClockRotate();

    int oldRow = shapeDesc.length;
    int oldCol = shapeDesc[0].length;

    byte[][] tempDesc = new byte[oldCol][oldRow];

    for (int i = 0; i < oldCol; i++)
    {
    byte[] newXLine = new byte[oldRow];
    for (int j = 0; j < oldRow; j++)
    {
    newXLine[j] = shapeDesc[j][oldCol - 1 - i];
    }
    tempDesc[i] = newXLine;
    }
    shapeDesc = tempDesc;

    findEdge();

    /*
    Block tmp = topBlock;
    topBlock = rightBlock;
    rightBlock = buttomBlock;
    buttomBlock = leftBlock;
    leftBlock = tmp;
    */
    } /**
     * @return the buttomBlock
     */
    public Block getButtomBlock()
    {
    return buttomBlock;
    } /**
     * @return the leftBlock
     */
    public Block getLeftBlock()
    {
    return leftBlock;
    } /**
     * @return the rightBlock
     */
    public Block getRightBlock()
    {
    return rightBlock;
    } /**
     * @return the topBlock
     */
    public Block getTopBlock()
    {
    return topBlock;
    } /**
     * @return
     */
    public boolean isAllInvisible()
    {
    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    if (blockTable[i][j].isVisible())
    {
    return false;
    }
    }
    }
    return true;
    }
      

  10.   


    /**
     * @param currentLeftBlock
     * @return
     */
    public boolean blockTouchedMe(Block block)
    {
    for (int i = visibleBlocks.size() - 1; i >= 0; i--)
    {
    Block theBlock = visibleBlocks.get(i);
    if (theBlock.isVisible() && theBlock.x == block.x && (block.y + Block.BLOCK_HEIGHT == theBlock.y))
    {
    return true;
    }
    }
    return false;
    }

    public boolean isMoved()
    {
    return moved;
    }

    public boolean notMoved()
    {
    int x = getX();
    int y = getY();
    return (x == initX && y == initY);
    } /**
     * @param y1
     */
    public void moveDownBlocksUponAtY(int y)
    {
    for (int i = 0; i < rows; i++)
    {
    for (int j = 0; j < cols; j++)
    {
    if (blockTable[i][j].y >= y)
    {
    break;
    }
    blockTable[i][j].moveDown();
    }
    }
    }

    /**
     * @param blockToClean
     */
    public void cleanBlock(Block blockToClean)
    {
    blockToClean.visible = false;
    visibleBlocks.remove(blockToClean);
    int[] indexOfTable = blockToClean.tableIndex;
    shapeDesc[indexOfTable[0]][indexOfTable[1]] = 0;
    }

    /**
     * @param x1
     * @return
     */
    public Vector<Block> getAllBlocksAtY(int y)
    {
    Vector<Block> blocks = new Vector<Block>();
    for (int i = 0; i < visibleBlocks.size(); i++)
    {
    Block theBlock = visibleBlocks.get(i);
    if (theBlock.y == y)
    {
    blocks.add(theBlock);
    }
    }
    return blocks;
    }

    /**
     * @param currentShape
     * @return
     */
    public boolean otherShapeAboveOnMe(Shape otherShape)
    {
    for (int i = otherShape.visibleBlocks.size() - 1; i >= 0; i--)
    {
    Block otherBlock = otherShape.visibleBlocks.get(i);
    for (int j = 0; j < visibleBlocks.size(); j++)
    {
    Block thisBlock = visibleBlocks.get(j);
    if (thisBlock.x == otherBlock.x && (otherBlock.y + Block.BLOCK_HEIGHT == thisBlock.y))
    {
    return true;
    }
    }
    }
    return false;
    }

    /**
     * @param currentShape
     * @return
     */
    public boolean otherShapeUnderMe(Shape otherShape)
    {
    for (int i = 0; i < otherShape.visibleBlocks.size(); i++)
    {
    Block otherBlock = otherShape.visibleBlocks.get(i);
    for (int j = 0; j < visibleBlocks.size(); j++)
    {
    Block thisBlock = visibleBlocks.get(j);
    if (thisBlock.x == otherBlock.x && (otherBlock.y - Block.BLOCK_HEIGHT == thisBlock.y))
    {
    return true;
    }
    }
    }
    return false;
    }

    /**
     * @param currentShape
     * @return
     */
    public boolean otherShapeLeftSideByMe(Shape otherShape)
    {
    for (int i = otherShape.visibleBlocks.size() - 1; i >= 0; i--)
    {
    Block otherBlock = otherShape.visibleBlocks.get(i);
    for (int j = 0; j < visibleBlocks.size(); j++)
    {
    Block thisBlock = visibleBlocks.get(j);
    if (thisBlock.y == otherBlock.y && (otherBlock.x + Block.BLOCK_WIDTH == thisBlock.x))
    {
    return true;
    }
    }
    }
    return false;
    }

    /**
     * @param currentShape
     * @return
     */
    public boolean otherShapeRightSideByMe(Shape otherShape)
    {
    for (int i = otherShape.visibleBlocks.size() - 1; i >= 0; i--)
    {
    Block otherBlock = otherShape.visibleBlocks.get(i);
    for (int j = 0; j < visibleBlocks.size(); j++)
    {
    Block thisBlock = visibleBlocks.get(j);
    if (thisBlock.y == otherBlock.y && (otherBlock.x - Block.BLOCK_WIDTH == thisBlock.x))
    {
    return true;
    }
    }
    }
    return false;
    } /**
     * 
     */
    public int getYDistanceWithOtherShape(Shape otherShape)
    {
    int minValue = abs(buttomBlock.y - otherShape.buttomBlock.y);
    boolean hasSameX = false;
    for (int i = otherShape.visibleBlocks.size() - 1; i >= 0; i--)
    {
    Block otherBlock = otherShape.visibleBlocks.get(i);
    for (int j = 0; j < visibleBlocks.size(); j++)
    {
    Block thisBlock = visibleBlocks.get(j);
    if (thisBlock.x == otherBlock.x)
    {
    hasSameX = true;
    int tmp = abs(thisBlock.y - otherBlock.y);
    if (tmp < minValue)
    {
    minValue = tmp;
    }
    }
    }
    }
    if (hasSameX)
    {
    return minValue - Block.BLOCK_HEIGHT;
    }
    return -1;
    } /**
     * @param i
     * @return
     */
    private static int abs(int i)
    {
    return i < 0 ? -i : i;
    }

    }
      

  11.   


    /**
     * 
     */
    package cross.pauliuyou.block.graph;import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseMotionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.util.Vector;import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JPanel;
    import javax.swing.JSlider;
    import javax.swing.KeyStroke;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;import cross.pauliuyou.block.common.ConfigUtil;
    import cross.pauliuyou.block.common.RandomProducer;/**
     * @author 刘优
     *
     */
    public class BlockFrame extends JFrame implements ActionListener,
      Runnable,
      KeyListener,
      MouseListener, 
      ChangeListener, 
      MouseMotionListener
    { public WorkArea workArea; private static final long serialVersionUID = 1L;

    public static final int TITLE_PANEL_HEIGHT = ConfigUtil.FRAME_TITLE_PANEL_HEIGHT;

    public static final int MENU_PANEL_HEIGHT = ConfigUtil.FRAME_MENU_PANEL_HEIGHT;

    private static byte[][] desc1 = {{1,1,1,1},
     {0,0,0,0},
     {0,0,0,0},
     {0,0,0,0}};
    private static byte[][] desc2 = {{1,1,0,0},
     {1,1,0,0},
     {0,0,0,0},
     {0,0,0,0}};
    private static byte[][] desc3 = {{1,0,0,0},
     {1,1,0,0},
     {0,1,0,0},
     {0,0,0,0}};
    private static byte[][] desc4 = {{0,1,0,0},
     {1,1,0,0},
     {1,0,0,0},
     {0,0,0,0}};
    private static byte[][] desc5 = {{0,1,0,0},
     {1,1,1,0},
     {0,0,0,0},
     {0,0,0,0}};
    private static byte[][] desc6 = {{1,1,0,0},
     {0,1,0,0},
     {0,1,0,0},
     {0,0,0,0}};
    private static byte[][] desc7 = {{1,1,0,0},
     {1,0,0,0},
     {1,0,0,0},
     {0,0,0,0}};

    private static byte[][][] allShapes = {desc1,desc2,desc3,desc4,desc5,desc6,desc7};

    private static Color[] allColors = {Color.red,Color.yellow,Color.blue,Color.green,Color.orange,Color.magenta,Color.pink};

    private RandomProducer shapeRandom = new RandomProducer(7);

    Graphics graph;

    private static final String STRING_FONT = ConfigUtil.STRING_FONT; private boolean gameThreadRunFlag; private Thread gameThread; private int frameWidth;

    private int frameHeight;

    private int blockInitX = 10;

    private int blockCountOfX = ConfigUtil.blockCountOfX; private int blockCountOfY = ConfigUtil.blockCountOfY;

    private int speed = ConfigUtil.initSpeed;

    private JSlider speedSlider;

    private JLabel speedLabel;

    private Shape currentShape;

    private Vector<Shape> stoppedShapes = new Vector<Shape>(); private boolean gameOver; private boolean gamePause; private WorkArea workArea1; private WorkArea workArea2; private int currentShapeIndex;

    private int nextShapeIndex1; private int nextShapeIndex2; private Shape nextShape1; private Shape nextShape2; private boolean currentShapeTouched; private int moveDownCount;

    private int score; private boolean producing; private int previousScore = 1; private boolean gameThreadOver; private static int gapSize = 4; /**
     */
    public BlockFrame()
    {
    super("方块");

    getMenu();

    speedSlider = new JSlider();
    speedSlider.setMinimum(0);
    speedSlider.setMaximum(1000);
    speedSlider.setValue(speed);
    speedSlider.addChangeListener(this);

    speedLabel = new JLabel("" + speed);
    JPanel southPanel = new JPanel(new BorderLayout());
    southPanel.add(new JLabel("速度: "),"West");
    southPanel.add(speedLabel,"East");
    southPanel.add(speedSlider);

    //add(southPanel,"South");

    addKeyListener(this);

    thisFrameInit();
    } /**
     * 
     */
    private void thisFrameInit()
    {
    workArea = new WorkArea(blockInitX - gapSize / 2,
    TITLE_PANEL_HEIGHT,
    Block.BLOCK_WIDTH * blockCountOfX + gapSize ,
    Block.BLOCK_HEIGHT * blockCountOfY + gapSize);

    frameWidth = workArea.width + Block.BLOCK_WIDTH * ConfigUtil.RECTANGLE_STANDARD_ROWS + gapSize * 15;
    frameHeight = workArea.height + TITLE_PANEL_HEIGHT + gapSize * 15;

    workArea1 = new WorkArea(workArea.x + workArea.width + gapSize,
     TITLE_PANEL_HEIGHT,
     Block.BLOCK_WIDTH * ConfigUtil.RECTANGLE_STANDARD_ROWS + gapSize,
     Block.BLOCK_WIDTH * ConfigUtil.RECTANGLE_STANDARD_COLS + gapSize);

    workArea2 = new WorkArea(workArea.x + workArea.width + gapSize,
     workArea1.y + workArea1.height + gapSize,
     Block.BLOCK_WIDTH * ConfigUtil.RECTANGLE_STANDARD_ROWS + gapSize,
     Block.BLOCK_WIDTH * ConfigUtil.RECTANGLE_STANDARD_COLS + gapSize);

    setSize(frameWidth,frameHeight);
    WindowUtil.centerFrameOnScreen(this);
    setVisible(true);

    graph = getGraphics();

    setResizable(false);
    addWindowListener(new WindowAdapter(){
    public void windowClosing(WindowEvent we)
    {
    shutdown();
    }
    });

    newGame();

    } /**
     * 
     */
    protected void shutdown()
    {
    gameThreadRunFlag = false;
    gameThread.interrupt();
    this.dispose();
    }

    /**
     * 
     */
    private void newGame()
    {
    stoppedShapes.clear();

    if (gameThread != null)
    {
    gameThreadRunFlag = false;
    gameThread.interrupt();
    while (!gameThreadOver)
    {
    }
    }

    previousScore = 1;
    score = 0;

    int randShapeIndex = shapeRandom.getInt();
    currentShape = new Shape(graph,workArea,allColors[randShapeIndex],allShapes[randShapeIndex]);
    currentShape.drawMe();
    nextShapeIndex1 = shapeRandom.getInt();
    nextShapeIndex2 = shapeRandom.getInt();
    printNextTwoShapes(true);

    if (gamePause)
    {
    resume();
    }

    gameOver = false;
    gamePause = false;
    currentShapeTouched = false;

    gameThread = new Thread(this);
    gameThread.setName("GameThread");
    gameThreadOver = false;
    gameThreadRunFlag = true;
    gameThread.start();

    } /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    public void run()
    {
    while (gameThreadRunFlag)
    {
    if (speed > 0)
    {
    if (!currentShape.stopped)
    {
    repaintWorkArea();
    judgeCurrentShapeAbovedOther();
    }

    if (currentShape.isAtButtom() || currentShapeTouched || currentShape.stopped)
    {
    if (stoppedShapes.size() >= 2)
    {
    judgeCleanedBlock();
    }
    produceNextShape();
    }

    currentShape.moveDown();
    ++moveDownCount;

    try
    {
    Thread.sleep(speedToSleepTime());
    }
    catch (InterruptedException e)
    {
    }

    if (moveDownCount == 1)
    {
    judgeCurrentShapeAbovedOther();
    if (currentShapeTouched || currentShape.stopped)
    {
    gameOver();
    break;
    }
    }
    }
    else
    {
    try
    {
    Thread.sleep(100);
    }
    catch (InterruptedException e)
    {
    }
    }
    }
    gameThreadOver = true;
    }

    /**
     * 
     */
    private void judgeCleanedBlock()
    {
    if (producing)
    {
    return;
    }
    Block topBlock = currentShape.getTopBlock();
    Block buttomBlock = currentShape.getButtomBlock();

    int cleanedLayers = 0;
    for (int y = topBlock.y; y <= buttomBlock.y; y += Block.BLOCK_HEIGHT)
    {
    Vector<Block> totalLineBlocks = currentShape.getAllBlocksAtY(y);
    for (int i = stoppedShapes.size() - 1; i >= 0; i--)
    {
    Shape shape = stoppedShapes.get(i);
    Vector<Block> blocks = shape.getAllBlocksAtY(y);
    if (blocks.size() > 0)
    {
    totalLineBlocks.addAll(blocks);
    }
    }

    if (totalLineBlocks.size() == this.blockCountOfX)
    {
    for (int i = 0; i < totalLineBlocks.size(); i++)
    {
    Block blockToClean = totalLineBlocks.get(i);
    ((Shape)blockToClean.getOwner()).cleanBlock(blockToClean);
    }
    currentShape.moveDownBlocksUponAtY(y);
    for (int j = 0; j < stoppedShapes.size(); j++)
    {
    Shape shape = stoppedShapes.get(j);
    shape.moveDownBlocksUponAtY(y);
    }
    ++cleanedLayers;
    }
    }

    calculateScore(cleanedLayers);

    if (cleanedLayers > 0)
    {
    outer:
    while(true)
    {
    for (int i = 0; i < stoppedShapes.size(); i++)
    {
    Shape shape = stoppedShapes.get(i);
    if (shape.isAllInvisible())
    {
    stoppedShapes.remove(i);
    continue outer;
    }
    }
    break;
    }
    }
    }
      

  12.   


    /**
     * @param cleanLayer
     */
    private void calculateScore(int cleanLayer)
    {
    score += cleanLayer;
    } /**
     * 
     */
    private void produceNextShape()
    {
    if (producing)
    {
    //return;
    }

    //System.out.println("next1["+ nextShapeIndex1 + "],next2[" + nextShapeIndex2 + "]\n");

    stoppedShapes.add(currentShape);

    this.repaintWorkArea();

    producing = true;

    currentShapeIndex = nextShapeIndex1;

    currentShape = new Shape(graph,workArea,allColors[currentShapeIndex],allShapes[currentShapeIndex]);
    currentShapeTouched = false;

    nextShapeIndex1 = nextShapeIndex2;
    nextShapeIndex2 = shapeRandom.getInt();

    printNextTwoShapes(true);
    moveDownCount = 0;
    producing = false;

    this.repaintWorkArea();

    //System.out.println("current[" + currentShapeIndex + "],next1["+ nextShapeIndex1 + "],next2[" + nextShapeIndex2 + "]\n");
    }

    /**
     * 
     */
    private void judgeCurrentShapeAbovedOther()
    {
    for (int i = stoppedShapes.size() - 1; i >= 0; i--)
    {
    Shape shape = stoppedShapes.get(i);
    if (shape.otherShapeAboveOnMe(currentShape))
    {
    currentShapeTouched = true;
    currentShape.stopped = true;
    break;
    }
    }
    }

    /**
     * 
     */
    public boolean judgeCurrentShapeUnderedOther()
    {
    for (int i = stoppedShapes.size() - 1; i >= 0; i--)
    {
    Shape shape = stoppedShapes.get(i);
    if (shape.otherShapeUnderMe(currentShape))
    {
    return true;
    }
    }
    return false;
    }

    /**
     * 
     */
    private boolean judgeCurrentShapeLeftSideOther()
    {
    for (int i = stoppedShapes.size() - 1; i >= 0; i--)
    {
    Shape shape = stoppedShapes.get(i);
    if (shape.otherShapeLeftSideByMe(currentShape))
    {
    return true;
    }
    }
    return false;
    }

    /**
     * 
     */
    private boolean judgeCurrentShapeRightSideOther()
    {
    for (int i = stoppedShapes.size() - 1; i >= 0; i--)
    {
    Shape shape = stoppedShapes.get(i);
    if (shape.otherShapeRightSideByMe(currentShape))
    {
    return true;
    }
    }
    return false;
    }

    /**
     * @param refresh
     */
    private void printNextTwoShapes(boolean refresh)
    {
    if (refresh)
    {
    //System.out.println("printNextShapes["+nextShapeIndex1+"]["+nextShapeIndex2+"]");
    workArea1.clearArea(graph);
    workArea2.clearArea(graph);
    nextShape1 = new Shape(graph,workArea1,allColors[nextShapeIndex1],allShapes[nextShapeIndex1]);
    nextShape2 = new Shape(graph,workArea2,allColors[nextShapeIndex2],allShapes[nextShapeIndex2]);
    }

    //workArea1.clearArea(graph);
    //workArea2.clearArea(graph);

    //workArea1.drawArea(graph);
    //workArea2.drawArea(graph);

    if (nextShape1 != null && nextShape2 != null)
    {
    nextShape1.drawMe();
    nextShape2.drawMe();
    }
    }

    private void printInfors()
    {
    if (previousScore == score)
    {
    //return;
    }
    int x = workArea2.x + Block.BLOCK_WIDTH / 10;
    int y = workArea2.y + workArea2.height + Block.BLOCK_HEIGHT;

    // not work. strange!!
    //graph.clearRect(x,y, getWidth(), getHeight());

    graph.setColor(Color.black);
    graph.setFont(new Font(STRING_FONT,Block.BLOCK_WIDTH,Block.BLOCK_WIDTH));
    graph.drawString("Score:" + score, x, y);
    graph.drawString("Speed:" + speed, x, y + Block.BLOCK_WIDTH * 2);
    previousScore = score;
    }

    /**
     * 重要方法, 用来重绘窗口
     */
    @Override
    public void paint(Graphics graph)
    {
    super.paint(graph);
    repaintWorkArea();
    }

    /**
     * 
     */
    private void repaintWorkArea()
    {
    graph.clearRect(0,TITLE_PANEL_HEIGHT, getWidth(), getHeight());
    workArea.drawArea(graph);

    for (int i = 0; i < stoppedShapes.size(); i++)
    {
    stoppedShapes.get(i).drawMe();
    }

    if (gameOver)
    {
    gameOver();
    }
    if (gamePause)
    {
    pause();
    }
    printInfors();
    printNextTwoShapes(false);
    }

    private void pause()
    {
    if (gameOver || gamePause)
    {
    return;
    }
    graph.setColor(Color.green);
    graph.setFont(new Font(STRING_FONT,22,22));
    graph.drawString("Pause", workArea.x + workArea.width / 2 - 20, workArea.height / 2);
    speed = 0;
    gamePause = true;
    currentShape.drawMe();
    }

    private void resume()
    {
    speed = speedSlider.getValue();
    gamePause = false;
    gameThread.interrupt();
    }

    /**
     * 
     */
    private void gameOver()
    {
    graph.setColor(Color.red);
    graph.setFont(new Font(STRING_FONT,20,20));
    graph.drawString("GameOver", workArea.x + workArea.width / 2 - 20, workArea.height / 2);
    gameOver = true;
    moveDownCount = 0;
    currentShapeTouched = false;
    }

    /**
     * @return
     */
    private long speedToSleepTime()
    {
    return (long)((5.0 / speed) * 1000);
    }

    /**
     * @return
     */
    public WorkArea getWorkArea()
    {
    return workArea;
    } /* (non-Javadoc)
     * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
     */
    public void keyPressed(KeyEvent event)
    {
    if (currentShape == null || 
    gameOver || 
    gamePause ||
    currentShape.stopped)
    {
    return;
    }

    //System.out.println("keyPressed:" + event.getKeyCode());
    int keyCode = event.getKeyCode();
    if (keyCode >= 37 && keyCode <= 40 || keyCode == 32 || keyCode == 10)
    {
    repaintWorkArea();
    }
    // space
    if (keyCode == 32)
    {
    currentShape.clockRotate();
    }
    // enter
    else if (keyCode == 10)
    {
    currentShape.deClockRotate();
    }
    // up
    else if (keyCode == 38)
    {
    currentShape.moveUp();
    }
    // down
    else if (keyCode == 40)
    {
    moveToButtom();
    //currentShape.moveDown();
    }
    // left
    else if (keyCode == 37)
    {
    if (!judgeCurrentShapeRightSideOther())
    {
    currentShape.moveLeft();
    }
    }
    // right
    else if (keyCode == 39)
    {
    if (!judgeCurrentShapeLeftSideOther())
    {
    currentShape.moveRight();
    }
    }
    judgeCurrentShapeAbovedOther();
    }

    /**
     * 
     */
    private void moveToButtom()
    {
    currentShapeTouched = true;
    int distanceOfY = (workArea.y + workArea.height) - (currentShape.getButtomBlock().y + Block.BLOCK_HEIGHT) - gapSize / 2;
    System.out.println("begin y distance : " + distanceOfY);
    for (int i = 0; i < stoppedShapes.size(); i++)
    {
    Shape shape = stoppedShapes.get(i);
    if (shape.getRightBlock().x  < currentShape.getLeftBlock().x || 
    shape.getLeftBlock().x > currentShape.getRightBlock().x)
    {
    continue;
    }
    int tmp = shape.getYDistanceWithOtherShape(currentShape);
    if (tmp != -1 && tmp < distanceOfY)
    {
    distanceOfY = tmp;
    }
    }
    System.out.println("final y distance : " + distanceOfY);
    currentShape.moveDown(distanceOfY);
    currentShape.stopped = true;
    this.judgeCleanedBlock();
    this.produceNextShape();
    }
      

  13.   


    /* (non-Javadoc)
     * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
     */
    public void keyReleased(KeyEvent event)
    {
    //System.out.println("keyReleased:" + event.getKeyCode());

    } /* (non-Javadoc)
     * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
     */
    public void keyTyped(KeyEvent event)
    {
    //System.out.println("keyTyped:" + event.getKeyCode());

    } /* (non-Javadoc)
     * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
     */
    public void mouseClicked(MouseEvent arg0)
    {
    //System.out.println("mouseClicked");
    //pause();
    //repaintWorkArea();

    } /* (non-Javadoc)
     * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
     */
    public void mouseEntered(MouseEvent arg0)
    {

    } /* (non-Javadoc)
     * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
     */
    public void mouseExited(MouseEvent arg0)
    {

    } /* (non-Javadoc)
     * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
     */
    public void mousePressed(MouseEvent arg0)
    {
    //System.out.println("mousePressed");
    //pause();
    //repaintWorkArea();
    } /* (non-Javadoc)
     * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
     */
    public void mouseReleased(MouseEvent arg0)
    {
    // TODO Auto-generated method stub

    }

    /* (non-Javadoc)
     * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
     */
    public void stateChanged(ChangeEvent arg0)
    {
    speed = speedSlider.getValue();
    gameThread.interrupt();
    speedLabel.setText(speedSlider.getValue() + "");
    }

    /**
     * 初始化菜单
     * 
     */
    private void getMenu()
    {
    JMenuBar menuBar = new JMenuBar();

    menuBar.addMouseMotionListener(this);

    JMenu fileMenu = new JMenu("文 件 (F)  ");
    fileMenu.setMnemonic(KeyEvent.VK_F);
    fileMenu.setActionCommand("filemenu");
    fileMenu.addMouseListener(this);

    JMenu gameMenu = new JMenu("游 戏 (G)  ");
    gameMenu.setMnemonic(KeyEvent.VK_G);

    JMenuItem openMenuItem = new JMenuItem("打 开... (O)", KeyEvent.VK_O);
    KeyStroke ctrlOKeyStroke = KeyStroke.getKeyStroke("control O");
    openMenuItem.setAccelerator(ctrlOKeyStroke);

    JMenuItem saveMenuItem = new JMenuItem("保 存 (S)", KeyEvent.VK_S);
    KeyStroke ctrlSKeyStroke = KeyStroke.getKeyStroke("control S");
    saveMenuItem.setAccelerator(ctrlSKeyStroke);

    JMenuItem aboutMenuItem = new JMenuItem("关于本程序", KeyEvent.VK_A);
    aboutMenuItem.addActionListener(this);
    aboutMenuItem.setActionCommand("about");

    JMenuItem exitMenuItem = new JMenuItem("退出游戏 (X)", KeyEvent.VK_X);

    openMenuItem.addActionListener(this);
    openMenuItem.setActionCommand("opengame");

    saveMenuItem.addActionListener(this);
    saveMenuItem.setActionCommand("savegame");

    exitMenuItem.addActionListener(this);
    exitMenuItem.setActionCommand("exitgame");

    fileMenu.add(openMenuItem);
    fileMenu.add(saveMenuItem);
    fileMenu.addSeparator();
    fileMenu.add(aboutMenuItem);
    fileMenu.addSeparator();
    fileMenu.add(exitMenuItem);


    // /////////////

    JMenuItem newGameItem = new JMenuItem("新游戏 (N)", KeyEvent.VK_N);
    newGameItem.addActionListener(this);
    newGameItem.setActionCommand("newgame");
    KeyStroke ctrlZKeyStroke = KeyStroke.getKeyStroke("control N");
    newGameItem.setAccelerator(ctrlZKeyStroke);

    gameMenu.add(newGameItem);

    JMenuItem pauseGameItem = new JMenuItem("暂 停 (P)", KeyEvent.VK_P);
    pauseGameItem.addActionListener(this);
    pauseGameItem.setActionCommand("pausegame");
    KeyStroke ctrlYKeyStroke = KeyStroke.getKeyStroke("control P");
    pauseGameItem.setAccelerator(ctrlYKeyStroke);
    gameMenu.add(pauseGameItem);

    JMenuItem resumeGameItem = new JMenuItem("继 续 (C)", KeyEvent.VK_C);
    resumeGameItem.addActionListener(this);
    resumeGameItem.setActionCommand("resumegame");
    KeyStroke ctrlCKeyStroke = KeyStroke.getKeyStroke("control C");
    resumeGameItem.setAccelerator(ctrlCKeyStroke);
    gameMenu.add(resumeGameItem);

    JMenuItem optionGameItem = new JMenuItem("选 项 (O)", KeyEvent.VK_O);
    optionGameItem.addActionListener(this);
    optionGameItem.setActionCommand("option");
    KeyStroke ctrlPKeyStroke = KeyStroke.getKeyStroke("control O");
    optionGameItem.setAccelerator(ctrlPKeyStroke);

    gameMenu.addSeparator();
    gameMenu.add(optionGameItem);
    // ///////////////

    menuBar.add(fileMenu);
    menuBar.add(gameMenu);

    this.setJMenuBar(menuBar);
    }

    /* (non-Javadoc)
     * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
     */
    public void mouseDragged(MouseEvent arg0)
    {
    // TODO Auto-generated method stub

    }
    /* (non-Javadoc)
     * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
     */
    public void mouseMoved(MouseEvent arg0)
    {
    if (gameOver || gamePause)
    {
    return;
    }
    pause();
    }

    /* (non-Javadoc)
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent event)
    {
    String cmd = event.getActionCommand();
    if (cmd.equals("exitgame"))
    {
    shutdown();
    }
    else if (cmd.equals("newgame"))
    {
    newGame();
    }
    else if (cmd.equals("pausegame"))
    {
    pause();
    }
    else if (cmd.equals("resumegame"))
    {
    resume();
    }
    //  未处理的命令部分.提示开发人员
    else
    {
    MsgBox.alert("您还未在actionPerformed()方法中完成处理命令[" + cmd + "]的响应代码");
    }

    repaintWorkArea();
    }

    public static void main(String[] args)
    {
    ConfigUtil.config();

    new BlockFrame();
    }
    }
      

  14.   

    唉 ClockFrame中的moveToButtom() 方法还有BUG. 不是方法有BUG,是Shape中的实现好象不太对....
      

  15.   

    想自己也做一个,可Java的图形界面好晕哦!
      

  16.   

    Matrix.java 文件1;/*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package lesson54;import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.border.LineBorder;/**
     *
     * @author scj
     */
    /**
     * 运行该文件
     */
    public class Matrix extends JPanel {    private JLabel matrix[][];
        public static final int ROW = 20;
        public static final int COLUMN = 15;
        private MatrixModel model;    public Matrix() {
            this.setLayout(new GridLayout(ROW, COLUMN));
            init();
            Dimension size = new Dimension(COLUMN * 20, ROW * 20);
            this.setPreferredSize(size);
            this.setMinimumSize(size);
            this.setMaximumSize(size);
            this.addKeyListener(new MyKeyListener());
            this.setFocusable(true);
            model = new MatrixModel(this);
        }    public void start() {
            model.start();
        }    private void init() {
            matrix = new JLabel[ROW][COLUMN];
            JLabel label = null;
            for (int i = 0; i < ROW; i++) {
                for (int j = 0; j < COLUMN; j++) {
                    label = new JLabel(" ");
                    label.setBorder(new LineBorder(Color.GRAY));
                    label.setOpaque(true);
                    matrix[i][j] = label;
                    add(matrix[i][j]);
                }
            }
        }    public void displayState(int[][] state) {
            for (int i = 0; i < state.length; i++) {
                for (int j = 0; j < state[i].length; j++) {
                    if (state[i][j] == 1) {
                        matrix[i][j].setBackground(Color.red);
                    } else {
                        matrix[i][j].setBackground(Color.black);
                    }
                }
            }
        }    class MyKeyListener extends KeyAdapter {        public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                    model.moveLeft();
                } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                    model.moveRight();
                } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                    model.down();
                } else if (e.getKeyCode() == KeyEvent.VK_UP) {
                    model.rotateSharp();
                }
            }
        }    public static void main(String arg[]) {
            JFrame frame = new JFrame();
            Matrix matrix = new Matrix();
            matrix.start();
            frame.add(new JScrollPane(matrix));
            frame.pack();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
            /*
             * int i[][] = {{10,20}, {11, 21}, {21, 31}}; int j[][] = new int[3][2];
             * System.arraycopy(i, 0, j, 0, i.length); for(int x=0; x<j.length;
             * x++){ for(int y=0; y<j[x].length; y++){ System.out.print(j[x][y]+"
             * "); } System.out.println(); }
             */
        }
    }
      

  17.   

    MatrixModel文件2/*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package lesson54;import java.util.*;/**
     *
     * @author scj
     */
    public class MatrixModel {    private int model[][];
        private int sharp[][];
        private int state[][];
        private int currentX, currentY;
        private Matrix myParent;
        private RunThread runThread;
        private int currentIndex;    public MatrixModel(Matrix parent) {
            myParent = parent;
            model = new int[Matrix.ROW][Matrix.COLUMN];
            state = new int[Matrix.ROW][Matrix.COLUMN];
            newSharp();
        }    public void start() {
            runThread = new RunThread();
            runThread.start();
        }    private int[][] randomSharp() {
            currentIndex = (int) (MatrixSharp.NUMBER * Math.random());
            return MatrixSharp.sharp[currentIndex];
        }    private synchronized boolean isMoveAvaliable(int currentX, int currentY) {
            if (currentX > Matrix.COLUMN - 1) {
                return false;
            }
            if (currentX < 0) {
                for (int i = 0; i < 4; i++) {
                    for (int j = 0; j < Math.abs(currentX); j++) {
                        if (sharp[i][j] != 0) {
                            return false;
                        }
                    }
                }
            }
            if (currentY < 0 || currentY > Matrix.ROW - 1) {
                return false;
            }
            for (int x = 0; x < 4; x++) {
                for (int y = 0; y < 4; y++) {
                    if (currentX + x > -1 && currentX + x < Matrix.COLUMN && currentY + y < Matrix.ROW) {
                        if ((sharp[y][x] & model[currentY + y][currentX + x]) != 0) {
                            return false;
                        }
                    } else {
                        if (currentX + x >= Matrix.COLUMN) {
                            if (sharp[y][x] != 0) {
                                return false;
                            }
                        } else if (currentY + y >= Matrix.ROW) {
                            if (sharp[y][x] != 0) {
                                return false;
                            }
                        }
                    }
                }
            }
            return true;
        }    private synchronized void moveTo(int x, int y) {
            for (int i = 0; i < Matrix.ROW; i++) {
                for (int j = 0; j < Matrix.COLUMN; j++) {
                    state[i][j] = model[i][j];
                }
            }
            for (int c = 0; c < 4; c++) {
                for (int r = 0; r < 4; r++) {
                    if (currentX + c > -1 && currentX + c < Matrix.COLUMN && currentY + r < Matrix.ROW) {
                        state[currentY + r][currentX + c] |= sharp[r][c];
                    }
                }
            }
            myParent.displayState(state);
        }    public void over() {
            System.out.println("game over");
            runThread.end();
        }    public synchronized void moveLeft() {
            if (isMoveAvaliable(currentX - 1, currentY)) {
                currentX -= 1;
                moveTo(currentX, currentY);
            }
        }    public synchronized void moveRight() {
            if (isMoveAvaliable(currentX + 1, currentY)) {
                currentX += 1;
                moveTo(currentX, currentY);
            }
        }    private boolean isOver() {
            if (currentY == 0) {
                return false;
            }
            return false;
        }    private synchronized void resetState() {
            state = new int[Matrix.ROW][Matrix.COLUMN];
            moveTo(currentX, currentY);
        }    public synchronized void down() {
            if (isMoveAvaliable(currentX, currentY + 1)) {
                currentY += 1;
                moveTo(currentX, currentY);
            } else {
                if (isOver()) {
                    over();
                    return;
                }
                model = state;
                check();
                resetState();
                newSharp();
            }
        }    public synchronized void check() {
            Vector clearVector = new Vector();
            for (int i = Matrix.ROW - 1; i > 0; i--) {
                int j = 0;
                for (; j < Matrix.COLUMN; j++) {
                    if (model[i][j] == 0) {
                        break;
                    }
                }
                if (j == Matrix.COLUMN) {
                    clearVector.add(new Integer(i));
                }
            }
            clearRows(clearVector);
        }    private synchronized void clearRows(Vector clearVector) {        for (int i = clearVector.size(); i > 0; i--) {
                int row = ((Integer) clearVector.get(i - 1)).intValue();
                for (int j = 0; j < Matrix.COLUMN; j++) {
                    for (int k = row; k >= 0; k--) {
                        if (k == 0) {
                            model[k][j] = 0;
                        } else {
                            model[k][j] = model[k - 1][j];
                        }
                    }
                }
            }
        }    public synchronized void rotateSharp() {
            int tmpIndex = currentIndex++;
            if (currentIndex % 4 == 0) {
                currentIndex -= 4;
            }
            int[][] tmpSharp = MatrixSharp.sharp[currentIndex];
            if (isRotateAble(tmpSharp)) {
                sharp = MatrixSharp.sharp[currentIndex];
                moveTo(currentX, currentY);
            } else {
                currentIndex = tmpIndex;
            }
        }    private synchronized boolean isRotateAble(int sharp[][]) {
            for (int x = 0; x < 4; x++) {
                for (int y = 0; y < 4; y++) {
                    if ((currentX + x < 0 || currentX + x >= Matrix.COLUMN) || (currentY + y < 0 || currentY + y >= Matrix.ROW)) {
                        if (sharp[y][x] != 0) {
                            return false;
                        }
                    }
                }
            }
            return isMoveAvaliable(currentX, currentY);
        }    private synchronized void newSharp() {
            currentX = Matrix.COLUMN / 2;
            currentY = 0;
            sharp = randomSharp();
        }    class RunThread extends Thread {        boolean isRun = true;        public void end() {
                isRun = false;
            }        public void run() {
                while (isRun) {
                    down();
                    try {
                        sleep(500);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }interface MatrixSharp {    static int sharp[][][] = new int[][][]{
            {{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}},
            {{0, 0, 0, 0}, {0, 1, 0, 0}, {0, 1, 1, 1}, {0, 0, 0, 0}},
            {{0, 1, 1, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}},
            {{0, 0, 0, 0}, {1, 1, 1, 0}, {0, 0, 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, 1, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}},
            {{1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
            {{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}},
            {{1, 1, 1, 1}, {0, 0, 0, 0}, {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}, {0, 1, 1, 0}, {0, 0, 1, 1}, {0, 0, 0, 0}},
            {{0, 0, 1, 0}, {0, 1, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}},
            {{0, 0, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 1}, {0, 0, 0, 0}},
            {{0, 0, 1, 0}, {0, 1, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}},
            {{0, 0, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
            {{0, 0, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
            {{0, 0, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
            {{0, 0, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
            {{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}},
            {{0, 0, 0, 0}, {0, 0, 1, 0}, {1, 1, 1, 0}, {0, 0, 0, 0}},
            {{0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}},
            {{0, 0, 0, 0}, {0, 1, 1, 1}, {0, 1, 0, 0}, {0, 0, 0, 0}}};
        static int NUMBER = sharp.length;
    }
      

  18.   

    好复杂啊,谢谢lz分享,O(∩_∩)O~
      

  19.   

    哈哈,我是直接诶ctrl+d倒着看的~
      

  20.   

    好长 看90行的实现
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    public class Terris extends JFrame implements Runnable, KeyListener {
        private short isPlaying=0/*是否游戏,声明*/,xOffSet = 3/*当前方块的横坐标*/, yOffSet = 0/*当前方块的纵坐标*/, blockType = (short) Math.round(Math.random() * 6)/*随即初始方块类型*/, blockRotation = 0/*初始方块旋转角度*/, blockColor = (short) Math.round(Math.random() * 5)/*随即初始方块颜色*/;
        private short matrix[][] = new short[21][10];/*整个画布21*10的矩阵*/
        private short block[][][][] = {{{{ 0, 1, 0, 0 },{ 0, 1, 0, 0 },{ 0, 1, 0, 0 },{ 0, 1, 0, 0 }},/* l */{{ 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 },{ 0, 0, 0, 0 } } },/*-*/{{ { 0, 0, 0, 0 }, { 1, 1, 0, 0 }, { 0, 1, 1, 0 },{ 0, 0, 0, 0 } },/* z */{ { 0, 0, 0, 0 }, { 0, 0, 1, 0 }, { 0, 1, 1, 0 },{ 0, 1, 0, 0 } } },/* z| */{{ { 0, 0, 0, 0 }, { 0, 1, 1, 0 }, { 1, 1, 0, 0 },{ 0, 0, 0, 0 } },/* xz */{ { 0, 1, 0, 0 }, { 0, 1, 1, 0 }, { 0, 0, 1, 0 },{ 0, 0, 0, 0 } } },/* xz| */{ { { 0, 0, 0, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 0, 0, 0 } } },/** []*/{{ { 0, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 },{ 0, 0, 0, 0 } },{ { 0, 0, 0, 0 }, { 1, 1, 1, 0 }, { 0, 0, 1, 0 },{ 0, 0, 0, 0 } },{ { 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 } } },/* f */{{ { 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 } },{ { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 1, 0 },{ 0, 0, 0, 0 } },{ { 0, 0, 0, 0 }, { 1, 1, 1, 0 }, { 1, 0, 0, 0 },{ 0, 0, 0, 0 } } },/* xf */ {{ { 0, 1, 0, 0 }, { 1, 1, 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, 0, 0, 0 }, { 1, 1, 1, 0 }, { 0, 1, 0, 0 },{ 0, 0, 0, 0 } },{ { 0, 1, 0, 0 }, { 1, 1, 0, 0 }, { 0, 1, 0, 0 },{ 0, 0, 0, 0 } } } };/* t *//*保存所有方块的4维矩阵,分别是:方块类型、方块旋转、方块x坐标、方块y坐标*/
        private Image[] images = {new ImageIcon("D:/Java/eclipse/workspace/Terris/src/img/Red.gif").getImage(),new ImageIcon("D:/Java/eclipse/workspace/Terris/src/img/Blue.gif").getImage(),new ImageIcon(("D:/Java/eclipse/workspace/Terris/src/img/Pink.gif")).getImage(),new ImageIcon(("D:/Java/eclipse/workspace/Terris/src/img/BBlue.gif")).getImage(),new ImageIcon(("D:/Java/eclipse/workspace/Terris/src/img/Orange.gif")).getImage(),new ImageIcon(("D:/Java/eclipse/workspace/Terris/src/img/Green.gif")).getImage(),new ImageIcon("D:/Java/eclipse/workspace/Terris/src/img/Red.gif").getImage()};/*各种颜色方块图片*/
        public Terris() {
            setSize(160, 335);/*窗口大小*/
            setVisible(true);/*可视*/
            createBufferStrategy(2);/*对当前窗口创建双缓冲*/
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);/*设置关闭按钮事件*/
            addKeyListener(this);/*添加按键响应*/
        }
        public void paint(Graphics g) {
            Graphics tg = this.getBufferStrategy().getDrawGraphics();/*获取后台缓冲画布*/
            tg.fillRect(5, 30, 150, 340);/*涂黑背景*/
            for (int i = 0; i < 21; i++)
                for (int j = 0; j < 10; j++) {
                    if (matrix[i][j] != 0)
                        tg.drawImage(images[matrix[i][j]], j * 15 + 5, i * 15 + 15,null);/*根据后台背景的矩阵绘制已经固定的各方块*/
                    if (i < 4 && j < 4&& block[blockType][blockRotation][i][j] != 0)
                        tg.drawImage(images[blockColor + 1],((j + xOffSet) * 15) + 5,((i + yOffSet) * 15) + 15, null);/*绘制当前能控制的方块*/
                }
            this.getBufferStrategy().show();/*切换后台画布到前台显示*/
        }
        public static void main(String[] args) {
            new Thread(new Terris()).start();//初始化界面并创建启动游戏线程
        }
        public void run() {
            while (isPlaying==0)/*当游戏正在进行 不断下落*/
                try {
                    if (check(0, 0, 0, 1))/*最后一个参数1 是下落 表示下落一格 其他参数见下面的注释*/
                        yOffSet += 1;/*如果能下落 y坐标+1*/
                    else {/*如不能下落 说明到底了*/
                        if (yOffSet == 0) {/*如果当前是第一个方块 游戏结束*/
                            isPlaying = 1;
                            continue;/*不再循环*/
                        }
                        freezeAndNew();/*将当前控制的方块合并到背景矩阵中 并初始化新的方块*/
                    }
                    repaint();/*重绘画布*/
                    Thread.sleep(600);/*线程sleep 可以修改作为难度*/
                } catch (InterruptedException e) {/*无用*/
                }
        }
        private boolean check(int left, int right, int up, int down) {/*判断方块是否可以左右移动、下落、旋转 都合并到一个方法中了 四个参数分别代表要判断左移、右移、旋转、下落 如果对应方向有动作 则传入1 没有动作传入0 在判断时直接计算参数值即可 而不考虑传入的具体值是1还是0*/
            for (int i = 0; i < 4; i++)
                for (int j = 0; j < 4; j++)
                    if (((xOffSet + j - left + right < 0 || xOffSet + j - left+ right >= 10) && block[blockType][((blockRotation + up) >= block[blockType].length ? 0: (blockRotation + up))][i][j] != 0)|| ((yOffSet + i + down >= 21) && block[blockType][((blockRotation + up) >= block[blockType].length ? 0: (blockRotation + up))][i][j] != 0)|| (block[blockType][((blockRotation + up) >= block[blockType].length ? 0: (blockRotation + up))][i][j] != 0 && matrix[yOffSet+ i + down][xOffSet + j - left + right] != 0))
                        return false;
            return true;
        }
        private synchronized void  freezeAndNew() {/*方块到底 固定到背景矩阵 并初始化新方块*/
            boolean[] clear = new boolean[]{false,false,false,false};/*是否可以消行的数组 每个方块4*4 只需判断方块所在的4行即可*/
            for (int i = 0; i < 4; i++){
                for (int j = 0; j < 4; j++)
                    if (block[blockType][blockRotation][i][j] != 0)/*循环将方块的1赋值到背景的矩阵中 方块4*4中的0 没有方块的地方不复制*/
                        matrix[i + yOffSet][j + xOffSet] = (short) (blockColor + 1);/*根据当前方块颜色复制到背景 可修改为灰色*/
                clear[i]=i + yOffSet>=matrix.length?false:(matrix[i + yOffSet][0]!=0&&matrix[i + yOffSet][1]!=0&&matrix[i + yOffSet][2]!=0&&matrix[i + yOffSet][3]!=0&&matrix[i + yOffSet][4]!=0&&matrix[i + yOffSet][5]!=0&&matrix[i + yOffSet][6]!=0&&matrix[i + yOffSet][7]!=0&&matrix[i + yOffSet][8]!=0&&matrix[i + yOffSet][9]!=0);/*一次判断一行0~9个方块是否有值 有值 复制到消行数组为true*/
            }
            for(int i=0;i<clear.length;i++)
                if(clear[i])/*如果消行*/
                    for(int j=yOffSet+i;j>0;j--)
                        System.arraycopy(matrix[j-1],0,matrix[j],0,10);/*循环从当前行依次把上面一行复制下来 下落效果*/
            yOffSet = blockRotation = 0;/*消行结束 下面几行是初始化新方块 xy方块类型 旋转 颜色*/
            xOffSet = 3;
            blockType = (short) Math.round(Math.random() * 6);
            blockRotation = (short) Math.round((Math.random() * (block[blockType].length - 1)));
            blockColor = (short) Math.round(Math.random() * 5);
        }
        public void keyPressed(KeyEvent e) {// 38-上 40-下 37-左 39-右
            if ((e.getKeyCode() == 65 || e.getKeyCode() == 37) && check(1, 0, 0, 0)&&isPlaying==0) {// left/*左移 传入判断方块是否能移动的方法 第一个参数传1 其他传0*/
                xOffSet--;/*能左移 x减1*/
            } else if ((e.getKeyCode() == 68 || e.getKeyCode() == 39)&& check(0, 1, 0, 0)&&isPlaying==0) {// right/*类似上面 右移第二个参数传1 其他0*/
                xOffSet++;/*能右移 x加1*/
            } else if ((e.getKeyCode() == 87 || e.getKeyCode() == 38)&& check(0, 0, 1, 0)&&isPlaying==0) {// up
                blockRotation = (short) ((blockRotation + 1) >= block[blockType].length ? 0: (blockRotation + 1));/*能旋转 根据当前方块类型进行旋转 如果到最后一个角度 回到0 继续旋转*/
            } else if ((e.getKeyCode() == 83 || e.getKeyCode() == 40)&& check(0, 0, 0, 1)&&isPlaying==0) {// down
                    yOffSet += 1;/*能下落 y加1*/
            } else if((e.getKeyCode() == 83 || e.getKeyCode() == 40)&& isPlaying==0)
                    freezeAndNew();/*不能下落 固定 并消行 新方块*/
            repaint();/*移动事件触发重绘*/
        }
        public void keyReleased(KeyEvent arg0) {/*无用*/
        }
        public void keyTyped(KeyEvent arg0) {/*无用*/
        }
    }
    //作者:http://wireless.javaeye.com/blog/595321