import java.awt.*;
import java.awt.event.*;
import java.applet.*;

/*
TRTRIS GAME
WRITE BY DELFAN
EMAIL : webmaster@delfan.com
URL : http://www.delfan.com

經典"俄羅斯方塊"游戲
作者 : DELFAN
EMail : webmaster@delfan.com
主頁 : http://www.delfan.com

版本信息:
2002.01.13 基本完成

請任何時候都保留以上信息.謝謝!
*/


public class tetris extends Applet implements Runnable
{
Thread thread;
private Image offImg; // 緩沖圖象
private Graphics offG; // 緩沖


final int BaseX = 20;
final int BaseY = 20;
final int BlockSize = 20; // 每個塊的大小

//
// 定義游戲中出現的信息
//
final String INFO_READY = "S鍵 開始游戲";
final String INFO_PAUSE = "P鍵 繼續游戲";
final String INFO_GAMEOVER = "游戲結束 任意鍵繼續";

byte SHAPE[][][][] = // [造型索引][旋轉索引][4][坐標]
{
{ // 造型一
{{ 0, 0},{ 1, 0},{ 0, 1},{ 1, 1}}, // 旋轉一 [][]....
{{ 0, 0},{ 1, 0},{ 0, 1},{ 1, 1}}, // 旋轉二 [][]....
{{ 0, 0},{ 1, 0},{ 0, 1},{ 1, 1}}, // 旋轉三 .........
{{ 0, 0},{ 1, 0},{ 0, 1},{ 1, 1}} // 旋轉四 .........
},
{ // 造型二
{{-1, 0},{ 0, 0},{ 0, 1},{ 1, 1}}, // 旋轉一 []
{{ 0,-1},{ 0, 0},{-1, 0},{-1, 1}}, // 旋轉二 []() []()
{{-1, 0},{ 0, 0},{ 0, 1},{ 1, 1}}, // 旋轉三 [][] []
{{ 0,-1},{ 0, 0},{-1, 0},{-1, 1}} // 旋轉四
},
{ // 造型三
{{ 1, 0},{ 0, 0},{ 0, 1},{-1, 1}}, // 旋轉一 []
{{ 0,-1},{ 0, 0},{ 1, 0},{ 1, 1}}, // 旋轉二 ()[] ()[]
{{ 1, 0},{ 0, 0},{ 0, 1},{-1, 1}}, // 旋轉三 [][] []
{{ 0,-1},{ 0, 0},{ 1, 0},{ 1, 1}} // 旋轉四
},
{ // 造型四
{{ 0, 0},{ 1, 0},{ 2, 0},{ 0, 1}}, // 旋轉一 [] []
{{ 0,-2},{ 0,-1},{ 0, 0},{ 1, 0}}, // 旋轉二 ()[][] []() [][]() []
{{-2, 0},{-1, 0},{ 0, 0},{ 0,-1}}, // 旋轉三 [] [] ()[]
{{-1, 0},{ 0, 0},{ 0, 1},{ 0, 2}} // 旋轉四 []
},
{ // 造型五
{{-2, 0},{-1, 0},{ 0, 0},{ 0, 1}}, // 旋轉一 []
{{ 0, 0},{ 1, 0},{ 0, 1},{ 0, 2}}, // 旋轉二 [][]() [] [] ()[]
{{ 0,-1},{ 0, 0},{ 1, 0},{ 2, 0}}, // 旋轉三 [] []() ()[][] []
{{ 0,-2},{ 0,-1},{ 0, 0},{-1, 0}} // 旋轉四 []
},
{ // 造型六
{{-1, 0},{ 0, 0},{ 1, 0},{ 0, 1}}, // 旋轉一
{{ 0,-1},{ 0, 0},{ 0, 1},{ 1, 0}}, // 旋轉二 [] [] []
{{-1, 0},{ 0, 0},{ 1, 0},{ 0,-1}}, // 旋轉三 []()[] ()[] []()[] []()
{{-1, 0},{ 0, 0},{ 0,-1},{ 0, 1}} // 旋轉四 [] [] []
},
{ // 造型六
{{ 0,-1},{ 0, 0},{ 0, 1},{ 0, 2}}, // 旋轉一 []
{{-1, 0},{ 0, 0},{ 1, 0},{ 2, 0}}, // 旋轉二 () []()[][]
{{ 0,-1},{ 0, 0},{ 0, 1},{ 0, 2}}, // 旋轉三 []
{{-1, 0},{ 0, 0},{ 1, 0},{ 2, 0}} // 旋轉四 []
}
};

//
// 定義游戲中使用的變量
//
final int[] Speeds = {60,50,40,30,20,15,10,5,3,1}; // 速度值定義

byte[][] Ground = new byte[10][20]; // 在 10 X 20 的場地游戲,預留頂部放置方塊的空間一格
byte[][] NextShape = new byte[4][2]; // 存放下塊造型
int CurrentX; // 當前X左邊
int CurrentY; // 當前Y坐標
int CurrentShapeIndex; // 當前造型索引
int CurrentTurnIndex; // 當前旋轉索引
int CurrentColorIndex; // 當前造型色彩索引
int NextShapeIndex; // 下塊出現的造型的索引
int GameSpeed = 0; // 游戲速度
int SpeedVar = 0; // 延時計數
int FlashSpeed = 60; // 信息提示閃爍速度
int FlashVar = 0; // 閃爍延時計數
int ClearTotalLine = 0; // 消掉的總行數


Color[] Colors = {Color.black,Color.red,Color.green,Color.blue,Color.magenta,Color.yellow,Color.orange,Color.pink};

//
// 定義游戲中出現的狀態
//
final int READY = 0;
final int GAMING = 1;
final int PAUSE = 2;
final int GAMEOVER = 3;
private int CurrentMode = READY ; // 游戲狀態變量

String InfoStr = new String(INFO_READY);

public void init()
{
offImg = createImage(getSize().width, getSize().height); // 創建緩沖圖象大小
offG = offImg.getGraphics();
setBackground(Color.black);
}

public void MakeNextShape()
{
NextShapeIndex = (int)(Math.random()*70) /10;
NextShape = SHAPE[NextShapeIndex][0];
}

public void ClearGround() // 清除場地
{
for(int i=0; i<10; i++)
for(int j=0; j<20; j++) Ground[i][j]=0;
CurrentMode = READY;
ClearTotalLine = 0;
}

public void StartGame() // 開始游戲
{
ClearGround();
CurrentShapeIndex = (int)(Math.random()*70) /10;
CurrentX = 4;
CurrentY = 0;
CurrentMode = GAMING;
CurrentColorIndex = (int)(Math.random()*70) /10 +1;
MakeNextShape();
}

public void drawABlock(Graphics g,int x,int y,int colorIndex) // 用指定的顏色畫一個方塊
{
g.setColor(Colors[colorIndex]);
g.fill3DRect(BaseX + x * BlockSize, BaseY + y * BlockSize , BlockSize, BlockSize, true);
g.fill3DRect(BaseX + x * BlockSize + 1, BaseY + y * BlockSize +1, BlockSize -2, BlockSize-2, true);
}

public void drawShape(Graphics g,int x,int y, int shapeindex,int trunindex) // 在指定位置畫指定的造型
{
for(int i=0; i<4; i++)
{
if(y+SHAPE[shapeindex][trunindex][i][1]>=0) // 不畫最頂上不在區域的塊
drawABlock(g,x+SHAPE[shapeindex][trunindex][i][0]
,y+SHAPE[shapeindex][trunindex][i][1],CurrentColorIndex);
}
}

public void drawGround(Graphics g) // 畫整個畫面
{
// 畫提示信息及行數及其他
g.setColor(new Color(255,255,255));
if(CurrentMode == READY) g.drawString(" + / - : 調整速度",BaseX,BaseY-3);
if(CurrentMode == GAMING) g.drawString("Up:翻轉 Left/Right:移動 Down:快落 R:重玩",BaseX,BaseY-3);
g.drawRect(BaseX-1,BaseY-1,BlockSize*10, BlockSize*20);
for(int i=0; i<10; i++)
for(int j=1; j<20; j++)
if(Ground[i][j]!=0) drawABlock(g,i,j,Ground[i][j]);
// 顯示相關信息
g.setColor(Color.lightGray);
g.drawRect(BaseX + BlockSize * 10 , BaseY-1,BlockSize * 2 + BlockSize /2 + BlockSize/2,20); // 與下一塊提示對齊
g.drawString("TETRIS",BaseX + BlockSize * 10+8,BaseY + 14); // 畫游戲相關信息
g.drawString("已消行數",BaseX + BlockSize * 10+5,BaseY * 3 );
g.drawString(String.valueOf(ClearTotalLine),BaseX + BlockSize * 10+5,BaseY * 4);
g.drawString("當前速度",BaseX + BlockSize * 10+5,BaseY * 6 );
g.drawString(String.valueOf(GameSpeed),BaseX + BlockSize * 10+5,BaseY * 7);
g.drawString("http://www.delfan.com" ,BaseX,BaseY + BlockSize * 21-10 );
}

public void drawNextBlock(Graphics g) // 畫下一塊
{
g.setColor(Color.lightGray);
g.drawString("下一塊",BaseX+11*BlockSize - BlockSize / 2,BaseY+17*BlockSize);
g.drawRect(BaseX + BlockSize * 10, BaseY + BlockSize *18 - BlockSize / 2
,BlockSize * 2 + BlockSize / 2,BlockSize * 2);
g.setColor(Color.blue);
for(int i=0; i<4; i++)
g.fill3DRect(BaseX + 11 * BlockSize + NextShape[i][0]*BlockSize / 2
, BaseY + 18 * BlockSize + NextShape[i][1]*BlockSize / 2 , BlockSize / 2 , BlockSize /2, true);
}

public void drawInfo(Graphics g) // 繪制提示的信息
{
g.setColor(Color.white);
Font old = g.getFont();
g.setFont(new Font("宋體",0,24));
g.drawString(InfoStr,BaseX+5*BlockSize - InfoStr.length()* 7 ,BaseY+10*BlockSize);
g.setFont(old);
}

public void paint(Graphics g)
{
offG.clearRect(0,0,getSize().width,getSize().height);
drawGround(offG);
switch(CurrentMode)
{
case READY :
case PAUSE :
case GAMEOVER :
drawInfo(offG);
break;
case GAMING :
drawShape(offG,CurrentX,CurrentY,CurrentShapeIndex,CurrentTurnIndex);
drawNextBlock(offG);
break;
}
if(offG!=null) g.drawImage(offImg,0,0,this);
}

public void update(Graphics g)
{
paint(g);
}

public void start()
{
thread = new Thread(this);
thread.start();
}

public void stop()
{
thread = null;
}

public void run()
{
Thread current = Thread.currentThread();

while(thread == current)
{
try
{
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {}

if(CurrentMode == GAMING)
{
if(SpeedVar ++ > Speeds[GameSpeed])
{
SpeedVar = 0;
DownIt();
repaint();
}
}
else
if(FlashVar ++ > FlashSpeed)
{
FlashVar = 0;
switch(CurrentMode)
{
case READY :
if(InfoStr.equals("")) InfoStr = INFO_READY;
else InfoStr = "";
break;
case PAUSE :
if(InfoStr.equals("")) InfoStr = INFO_PAUSE;
else InfoStr = "";
break;
case GAMEOVER :
if(InfoStr.equals("")) InfoStr = INFO_GAMEOVER;
else InfoStr = "";
}
repaint();
} // End of if(FlashVar++...
}// End of While
}

public boolean CanMoveTo(int shape,int turn,int x,int y) //判斷是否能移動到指定位置
{
boolean result = true;

turn %=4;

for(int i=0; i<4; i++)
{
if( (x + SHAPE[shape][turn][i][0] < 0) || (x + SHAPE[shape][turn][i][0] > 9) )
{
result = false;
break;
}
if( y + SHAPE[shape][turn][i][1] > 19)
{
result = false;
break;
}
if(Ground[x+SHAPE[shape][turn][i][0]][y + SHAPE[shape][turn][i][1]] != 0)
{
result = false;
break;
}
}
return result;
}

public synchronized void DownIt() // 處理下落過程
{
if(CanMoveTo(CurrentShapeIndex,CurrentTurnIndex,CurrentX,CurrentY+1))
{
CurrentY++;
}
else // 已經下落到底部了
{
if(CurrentY == 0) CurrentMode = GAMEOVER;
else
{
// 將當前塊放到Ground中去
for(int i=0; i<4; i++)
Ground[CurrentX + SHAPE[CurrentShapeIndex][CurrentTurnIndex][i][0]]
[CurrentY + SHAPE[CurrentShapeIndex][CurrentTurnIndex][i][1]] = (byte)CurrentColorIndex;
CurrentX=4;
CurrentY=0;
CurrentShapeIndex = NextShapeIndex;
CurrentColorIndex = (int)(Math.random()*70) /10 + 1;
MakeNextShape();
CurrentTurnIndex =0;
// 判斷有沒有一行的數據
int total;
for(int y=19; y>=0; y--)
{
total = 0;
for(int x=0; x<10; x++)
if(Ground[x][y] != 0) total ++;

if(total == 10) // 說明行滿了
{
// 將此行上面所有數據復制下來
for(int i=0; i<10; i++)
for(int j=y; j>0; j--) Ground[i][j] = Ground[i][j-1];
y++;
ClearTotalLine++;
if(ClearTotalLine % 50 == 0)
{
GameSpeed ++; // 每消50行增加一次速度
if(GameSpeed>9) GameSpeed = 9;
}
}
}//end of For
} // of else
} // of else
}

public boolean keyDown(Event e, int key) // 處理鍵盤事件
{
switch(CurrentMode)
{
case READY :
if(key == ´s´ || key ==´S´) StartGame();
if(key == ´+´)
{
GameSpeed ++;
if(GameSpeed>9) GameSpeed = 9;
}
if(key == ´-´)
{
GameSpeed --;
if(GameSpeed<0) GameSpeed = 0;
}
break;
case PAUSE :
if(key == ´p´ || key ==´P´) CurrentMode = GAMING;
break;
case GAMEOVER :
CurrentMode = READY; // 按任意鍵準備游戲
break;
case GAMING :
if(key == ´p´ || key == ´P´) CurrentMode = PAUSE;
if(key == ´r´ || key == ´R´) CurrentMode = READY;
if(key == Event.LEFT && CanMoveTo(CurrentShapeIndex,CurrentTurnIndex,CurrentX-1,CurrentY)) CurrentX --;
if(key == Event.RIGHT && CanMoveTo(CurrentShapeIndex,CurrentTurnIndex,CurrentX+1,CurrentY)) CurrentX ++;
if(key == Event.UP && CurrentY>1 && CanMoveTo(CurrentShapeIndex,CurrentTurnIndex+1,CurrentX,CurrentY))
{
CurrentTurnIndex ++;
CurrentTurnIndex %= 4;
}
if(key == Event.DOWN) DownIt();
repaint();
break;
}
return true;
}



 import java.awt.*;
import java.awt.event.*;
//俄羅斯方塊類
public class ERS_Block extends Frame{
public static boolean isPlay=false;
public static int level=1,score=0;
public static TextField scoreField,levelField;

public static MyTimer timer;
GameCanvas gameScr;

public static void main(String[] args){
ERS_Block ers = new ERS_Block("俄羅斯方塊游戲 V1.0 Author:Vincent");
WindowListener win_listener = new WinListener();
ers.addWindowListener(win_listener);
}

//俄羅斯方塊類的構造方法
ERS_Block(String title){
super(title);

setSize(600,480);
setLayout(new GridLayout(1,2));

gameScr = new GameCanvas();
gameScr.addKeyListener(gameScr);

timer = new MyTimer(gameScr);
timer.setDaemon(true);
timer.start();
timer.suspend();

add(gameScr);

Panel rightScr = new Panel();
rightScr.setLayout(new GridLayout(2,1,0,30));
rightScr.setSize(120,500);
add(rightScr);

//右邊信息窗體的布局
MyPanel infoScr = new MyPanel();
infoScr.setLayout(new GridLayout(4,1,0,5));
infoScr.setSize(120,300);
rightScr.add(infoScr);

//定義標簽和初始值
Label scorep = new Label("分數:",Label.LEFT);
Label levelp = new Label("級數:",Label.LEFT);
scoreField = new TextField(8);
levelField = new TextField(8);
scoreField.setEditable(false);
levelField.setEditable(false);
infoScr.add(scorep);
infoScr.add(scoreField);
infoScr.add(levelp);
infoScr.add(levelField);
scorep.setSize(new Dimension(20,60));
scoreField.setSize(new Dimension(20,60));
levelp.setSize(new Dimension(20,60));
levelField.setSize(new Dimension(20,60));
scoreField.setText("0");
levelField.setText("1");

//右邊控制按鈕窗體的布局
MyPanel controlScr = new MyPanel();
controlScr.setLayout(new GridLayout(5,1,0,5));
rightScr.add(controlScr);

//定義按鈕play
Button play_b = new Button("開始游戲");
play_b.setSize(new Dimension(50,200));
play_b.addActionListener(new Command(Command.button_play,gameScr));

//定義按鈕Level UP
Button level_up_b = new Button("提高級數");
level_up_b.setSize(new Dimension(50,200));
level_up_b.addActionListener(new Command(Command.button_levelup,gameScr));

//定義按鈕Level Down
Button level_down_b =new Button("降低級數");
level_down_b.setSize(new Dimension(50,200));
level_down_b.addActionListener(new Command(Command.button_leveldown,gameScr));

//定義按鈕Level Pause
Button pause_b =new Button("游戲暫停");
pause_b.setSize(new Dimension(50,200));
pause_b.addActionListener(new Command(Command.button_pause,gameScr));

//定義按鈕Quit
Button quit_b = new Button("退出游戲");
quit_b.setSize(new Dimension(50,200));
quit_b.addActionListener(new Command(Command.button_quit,gameScr));

controlScr.add(play_b);
controlScr.add(level_up_b);
controlScr.add(level_down_b);
controlScr.add(pause_b);
controlScr.add(quit_b);
setVisible(true);
gameScr.requestFocus();
}
}

//重寫MyPanel類,使Panel的四周留空間
class MyPanel extends Panel{
public Insets getInsets(){
return new Insets(30,50,30,50);
}
}

//游戲畫布類
class GameCanvas extends Canvas implements KeyListener{
final int unitSize = 30; //小方塊邊長
int rowNum; //正方格的行數
int columnNum; //正方格的列數
int maxAllowRowNum; //允許有多少行未削
int blockInitRow; //新出現塊的起始行坐標
int blockInitCol; //新出現塊的起始列坐標
int [][] scrArr; //屏幕數組
Block b; //對方快的引用

//畫布類的構造方法
GameCanvas(){
rowNum = 15;
columnNum = 10;
maxAllowRowNum = rowNum - 2;
b = new Block(this);
blockInitRow = rowNum - 1;
blockInitCol = columnNum/2 - 2;
scrArr = new int [32][32];
}

//初始化屏幕,并將屏幕數組清零的方法
void initScr(){
for(int i=0;i<rowNum;i++)
for (int j=0; j<columnNum;j++)
scrArr[i][j]=0;
b.reset();
repaint();
}

//重新刷新畫布方法
public void paint(Graphics g){
for(int i = 0; i < rowNum; i++)
for(int j = 0; j < columnNum; j++)
drawUnit(i,j,scrArr[i][j]);
}

//畫方塊的方法
public void drawUnit(int row,int col,int type){
scrArr[row][col] = type;
Graphics g = getGraphics();
switch(type){ //表示畫方快的方法
case 0: g.setColor(Color.black);break; //以背景為顏色畫
case 1: g.setColor(Color.blue);break; //畫正在下落的方塊
case 2: g.setColor(Color.magenta);break; //畫已經落下的方法
}
g.fill3DRect(col*unitSize,getSize().height-(row+1)*unitSize,unitSize,unitSize,true);
g.dispose();
}

public Block getBlock(){
return b; //返回block實例的引用
}

//返回屏幕數組中(row,col)位置的屬性值
public int getScrArrXY(int row,int col){
if (row < 0 || row >= rowNum || col < 0 || col >= columnNum)
return(-1);
else
return(scrArr[row][col]);
}

//返回新塊的初始行坐標方法
public int getInitRow(){
return(blockInitRow); //返回新塊的初始行坐標
}

//返回新塊的初始列坐標方法
public int getInitCol(){
return(blockInitCol); //返回新塊的初始列坐標
}

//滿行刪除方法
void deleteFullLine(){
int full_line_num = 0;
int k = 0;
for (int i=0;i<rowNum;i++){
boolean isfull = true;

L1:for(int j=0;j<columnNum;j++)
if(scrArr[i][j] == 0){
k++;
isfull = false;
break L1;
}
if(isfull) full_line_num++;
if(k!=0 && k-1!=i && !isfull)
for(int j = 0; j < columnNum; j++){
if (scrArr[i][j] == 0)
drawUnit(k-1,j,0);
else
drawUnit(k-1,j,2);
scrArr[k-1][j] = scrArr[k][j];
}
}
for(int i = k-1 ;i < rowNum; i++){
for(int j = 0; j < columnNum; j++){
drawUnit(i,j,0);
scrArr[i][j]=0;
}
}
ERS_Block.score += full_line_num;
ERS_Block.scoreField.setText(""+ERS_Block.score);
}

//判斷游戲是否結束方法
boolean isGameEnd(){
for (int col = 0 ; col <columnNum; col ++){
if(scrArr[maxAllowRowNum][col] !=0)
return true;
}
return false;
}

public void keyTyped(KeyEvent e){
}

public void keyReleased(KeyEvent e){
}

//處理鍵盤輸入的方法
public void keyPressed(KeyEvent e){
if(!ERS_Block.isPlay)
return;
switch(e.getKeyCode()){
case KeyEvent.VK_DOWN:b.fallDown();break;
case KeyEvent.VK_LEFT:b.leftMove();break;
case KeyEvent.VK_RIGHT:b.rightMove();break;
case KeyEvent.VK_SPACE:b.leftTurn();break;
}
}
}

//處理控制類
class Command implements ActionListener{
static final int button_play = 1; //給按鈕分配編號
static final int button_levelup = 2;
static final int button_leveldown = 3;
static final int button_quit = 4;
static final int button_pause = 5;
static boolean pause_resume = true;

int curButton; //當前按鈕
GameCanvas scr;

//控制按鈕類的構造方法
Command(int button,GameCanvas scr){
curButton = button;
this.scr=scr;
}

//按鈕執行方法
public void actionPerformed (ActionEvent e){
switch(curButton){
case button_play:if(!ERS_Block.isPlay){
scr.initScr();
ERS_Block.isPlay = true;
ERS_Block.score = 0;
ERS_Block.scoreField.setText("0");
ERS_Block.timer.resume();
}
scr.requestFocus();
break;
case button_levelup:if(ERS_Block.level < 10){
ERS_Block.level++;
ERS_Block.levelField.setText(""+ERS_Block.level);
ERS_Block.score = 0;
ERS_Block.scoreField.setText(""+ERS_Block.score);
}
scr.requestFocus();
break;
case button_leveldown:if(ERS_Block.level > 1){
ERS_Block.level--;
ERS_Block.levelField.setText(""+ERS_Block.level);
ERS_Block.score = 0;
ERS_Block.scoreField.setText(""+ERS_Block.score);
}
scr.requestFocus();
break;
case button_pause:if(pause_resume){
ERS_Block.timer.suspend();
pause_resume = false;
}else{
ERS_Block.timer.resume();
pause_resume = true;
}
scr.requestFocus();
break;
case button_quit:System.exit(0);
}
}
}

//方塊類
class Block {
static int[][] pattern = {
{0x0f00,0x4444,0x0f00,0x4444},//用十六進至表示,本行表示長條四種狀態
{0x04e0,0x0464,0x00e4,0x04c4},
{0x4620,0x6c00,0x4620,0x6c00},
{0x2640,0xc600,0x2640,0xc600},
{0x6220,0x1700,0x2230,0x0740},
{0x6440,0x0e20,0x44c0,0x8e00},
{0x0660,0x0660,0x0660,0x0660}
};
int blockType; //塊的模式號(0-6)
int turnState; //塊的翻轉狀態(0-3)
int blockState; //快的下落狀態
int row,col; //塊在畫布上的坐標
GameCanvas scr;

//塊類的構造方法
Block(GameCanvas scr){
this.scr = scr;
blockType = (int)(Math.random() * 1000)%7;
turnState = (int)(Math.random() * 1000)%4;
blockState = 1;
row = scr.getInitRow();
col = scr.getInitCol();
}

//重新初始化塊,并顯示新塊
public void reset(){
blockType = (int)(Math.random() * 1000)%7;
turnState = (int)(Math.random() * 1000)%4;
blockState = 1;
row = scr.getInitRow();
col = scr.getInitCol();
dispBlock(1);
}

//實現“塊”翻轉的方法
public void leftTurn(){
if(assertValid(blockType,(turnState + 1)%4,row,col)){
dispBlock(0);
turnState = (turnState + 1)%4;
dispBlock(1);
}
}

//實現“塊”的左移的方法
public void leftMove(){
if(assertValid(blockType,turnState,row,col-1)){
dispBlock(0);
col--;
dispBlock(1);
}
}

//實現塊的右移
public void rightMove(){
if(assertValid(blockType,turnState,row,col+1)){
dispBlock(0);
col++;
dispBlock(1);
}
}

//實現塊落下的操作的方法
public boolean fallDown(){
if(blockState == 2)
return(false);
if(assertValid(blockType,turnState,row-1,col)){
dispBlock(0);
row--;
dispBlock(1);
return(true);
}else{
blockState = 2;
dispBlock(2);
return(false);
}
}

//判斷是否正確的方法
boolean assertValid(int t,int s,int row,int col){
int k = 0x8000;
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
if((int)(pattern[t][s]&k) != 0){
int temp = scr.getScrArrXY(row-i,col+j);
if (temp<0||temp==2)
return false;
}
k = k >> 1;
}
}
return true;
}

//同步顯示的方法
public synchronized void dispBlock(int s){
int k = 0x8000;
for (int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
if(((int)pattern[blockType][turnState]&k) != 0){
scr.drawUnit(row-i,col+j,s);
}
k=k>>1;
}
}
}
}

//定時線程
class MyTimer extends Thread{
GameCanvas scr;

public MyTimer(GameCanvas scr){
this.scr = scr;
}

public void run(){
while(true){
try{
sleep((10-ERS_Block.level + 1)*100);
}
catch(InterruptedException e){}
if(!scr.getBlock().fallDown()){
scr.deleteFullLine();
if(scr.isGameEnd()){
ERS_Block.isPlay = false;
suspend();
}else
scr.getBlock().reset();
}
}
}
}

class WinListener extends WindowAdapter{
public void windowClosing (WindowEvent l){
System.exit(0);
}
}