www.pudn.com > JavaTet.zip > Tetris.java
/**
*俄罗斯方块v1.0
*
*我的第一个Java程序,类写得很烂,望不吝赐教。
*
*本人近来对Java颇感兴趣,希望能和众Java爱好者多多交流。
*
* By csdn [nothing]
* Email: yychaoban@china.com
* 2001.8.16
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Tetris extends Applet {
public Game game;
public int
Offset_x = 40,
Offset_y = 30;
public void init() {
this.setLayout(null);
this.setBackground(Color.white);
game = new Game(this, Offset_x, Offset_y);
game.init();
}
public void start() {
}
public void paint(Graphics g) {
if(game.getHasInit()) game.repaint();
}
public static void main(String[] args) {
Tetris applet = new Tetris();
Frame aFrame = new Frame("俄罗斯方块v1.0 By[csdn_nothing]");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(250, 400);
applet.init();
applet.start();
aFrame.setVisible(true);
}
}
//游戏控制入口
class Game extends ActionThread {
private boolean hasInit = false;
private boolean hasPause = false;
private boolean hasStart = false;
private Label labScore, labLevel;
private Label labConstTextScore, labConstTextLevel, labConstTextNextObject;
private Button btnStart, btnReset;
private int nextFigure;
private String msg;
private Color msgColor = Color.red; //显示的消息的颜色
private Color constTextColor = Color.blue; //标题颜色
private Color infoBgColor = Color.lightGray;
private Color infoColor = Color.red;
public Game(Tetris mainForm, int x, int y) {
super(mainForm, x, y);
}
public int getCtrlPanelX() { return getOffset_x()+getWorkPiexWidth()+10;}
public int getCtrlPanelY() { return getOffset_y();}
public boolean getHasInit() { return hasInit;}
public void init() {
if(hasInit) return;
hasInit = true;
hasPause = false;
nextFigure = (int)(Math.random()*tBlock.getMaxFigureNumber()*10) % tBlock.getMaxFigureNumber();
labConstTextScore = new Label("得分:");
labConstTextScore.setBounds(getCtrlPanelX(), getCtrlPanelY()+15, 55, 20);
labConstTextScore.setForeground(constTextColor);
labScore = new Label("0");
labScore.setBackground(infoBgColor);
labScore.setBounds(getCtrlPanelX(), getCtrlPanelY()+35, 55, 20);
labScore.setForeground(infoColor);
labConstTextLevel = new Label("级别:");
labConstTextLevel.setBounds(getCtrlPanelX(), getCtrlPanelY()+65, 55, 20);
labConstTextLevel.setForeground(constTextColor);
labLevel = new Label("1");
labLevel.setBackground(infoBgColor);
labLevel.setBounds(getCtrlPanelX(), getCtrlPanelY()+85, 55, 20);
labLevel.setForeground(infoColor);
labConstTextNextObject = new Label("下一个:");
labConstTextNextObject.setBounds(getCtrlPanelX(), getCtrlPanelY()+140, 55, 20);
labConstTextNextObject.setForeground(constTextColor);
btnStart = new Button("开始");
btnStart.setBounds(getCtrlPanelX(), getCtrlPanelY()+getWorkPiexHeight()-30, 55, 25);
btnReset = new Button("重来");
btnReset.setBounds(getCtrlPanelX(), getCtrlPanelY()+getWorkPiexHeight()-60, 55, 25);
btnReset.setEnabled(false);
btnReset.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
handleKeyEvent(e);
}
});
btnReset.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
gamereset();
}
});
btnStart.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
handleKeyEvent(e);
}
});
btnStart.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(!hasStart) {
play();
btnStart.setLabel("暂停");
} else
if(hasPause) {
play();
btnStart.setLabel("暂停");
} else {
pause();
btnStart.setLabel("开始");
}
btnReset.setEnabled(hasStart);
}
});
mainForm.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
handleKeyEvent(e);
}
});
mainForm.add(labScore);
mainForm.add(labLevel);
mainForm.add(btnReset);
mainForm.add(btnStart);
mainForm.add(labConstTextScore);
mainForm.add(labConstTextLevel);
mainForm.add(labConstTextNextObject);
}
public void play() {
if(!hasStart) start();
hasPause = false;
hasStart = true;
}
public void pause() {
hasPause = true;
}
public void gamereset() {
super.reset();
hasPause = true;
nextFigure = (int)(Math.random()*tBlock.getMaxFigureNumber()*10) % tBlock.getMaxFigureNumber();
newObject(objectColor, nextFigure);
nextFigure = (int)(Math.random()*tBlock.getMaxFigureNumber()*10) % tBlock.getMaxFigureNumber();
repaint();
score = 0;
level = 1;
showlevel(level);
showscore(score);
play();
}
public void run() {
showmsg("开始新游戏...");
System.out.print("Game started!\n");
mySleep(1000);
clearAndrepaint();
score = 0;
level = 1;
//hasStart = true;
//hasPause = false;
if(!newObject(objectColor, nextFigure)) return;
nextFigure = (int)(Math.random()*tBlock.getMaxFigureNumber()*10) % tBlock.getMaxFigureNumber();
showNextObject(nextFigure);
while(true) {
if(hasPause) continue;
mySleep(downSpeed);
if(!moveObject(mdDown)) { //can't down
writeGlassWorkSheet(Sheet_x, Sheet_y, tBlock.getFigureWorkSheet());
int[] Lines = getLines();
int maxLine = 0;
int onetimeDelLines = 0; //一次所消行数
for(int i = 0; i < Lines.length; i++) {
if(Lines[i] != 0) {
delLine(Lines[i]);
if(maxLine < Lines[i]) maxLine = Lines[i];
onetimeDelLines++;
}
}
if(onetimeDelLines > tBlock.getMaxCornerNumber())
onetimeDelLines = tBlock.getMaxCornerNumber();
score += onetimeToScore[onetimeDelLines];
showscore(score);
if(score >= levelSpeed[0][level]) {
level++;
showlevel(level);
showmsg("第 " + Integer.toString(level) + " 关!");
mySleep(1000);
clearAndrepaint();
downSpeed = levelSpeed[1][level];
}
if(level > maxLevel) {
showmsg("恭喜,您玩通关了!");
return;
}
if(maxLine > 0) repaint(maxLine);
if(!newObject(objectColor, nextFigure)) break;
nextFigure = (int)(Math.random()*tBlock.getMaxFigureNumber()*10) % tBlock.getMaxFigureNumber();
showNextObject(nextFigure);
}
}
}
public void showscore(int theScore) {
labScore.setText(Integer.toString(theScore));
}
public void showlevel(int theLevel) {
labLevel.setText(Integer.toString(theLevel));
}
public void showNextObject(int Figure) {
Graphics g = mainForm.getGraphics();
g.setColor(Color.blue);
tBlock.drawMyObject(getCtrlPanelX(), getCtrlPanelY()+165, g, Figure);
}
public void showmsg(String s) {
msg = s;
Graphics g = mainForm.getGraphics();
g.setColor(msgColor);
g.drawString(msg, getOffset_x(), getOffset_y()+10);
}
public void clearAndrepaint() {
mainForm.getGraphics().clearRect(getOffset_x(), getOffset_y(),
getWorkPiexWidth(), getWorkPiexHeight());
repaint();
}
public void mySleep(int t) {
try {
sleep(t);
} catch(InterruptedException e) {}
}
public void repaint() {
super.repaint();
if(hasStart) showNextObject(nextFigure);
}
public void handleKeyEvent(KeyEvent e) {
if(!hasInit || hasPause)
return;
if(e.getKeyCode() == e.VK_LEFT)
moveObject(mdLeft);
else if(e.getKeyCode() == e.VK_DOWN)
moveObject(mdDown);
else if(e.getKeyCode() == e.VK_RIGHT)
moveObject(mdRight);
else if(e.getKeyCode() == e.VK_UP)
turn();
}
}
//动作线程
class ActionThread extends Thread {
protected int
mdLeft = 0,
mdDown = 1,
mdRight = 2;
private int
GlassHeight = 28, //背景高(n方块)
GlassWidth = 10; //背景宽(n方块)
private int
Offset_x = 0, //背景位置(x像素)
Offset_y = 0; //背景位置(y像素)
protected int downSpeed = 500; //下落速度(越大越慢)
private boolean lockObject = false;
protected Color backgroundColor = Color.lightGray;
protected Color objectColor = Color.blue;
private byte[][] GlassWorkSheet = new byte[GlassHeight][GlassWidth];
protected int Sheet_x, Sheet_y;
private int currFigure;
protected int score;
protected int level;
protected int[][] levelSpeed = new int[][] {
{ 0, 1000, 2000, 3000, 4000, 5000, 6000, 0 }, //score
{ 0, 500, 400, 300, 200, 100, 50, 0 } //speed
};
protected int maxLevel = levelSpeed[0].length - 2;
protected int[] onetimeToScore = new int[] {
0, 100, 300, 500, 1000 //同时消0-4行所得分数
};
protected TetrisBlock tBlock;
protected Tetris mainForm;
public ActionThread(Tetris mainForm, int x, int y) {
this.mainForm = mainForm;
Offset_x = x;
Offset_y = y;
tBlock = new TetrisBlock(mainForm);
tBlock.setBackgroundColor(backgroundColor);
reset();
System.out.print("Thread creating...\n");
}
public int getScore() { return score;}
public int getLevel() { return level;}
public int getWorkPiexWidth() { return GlassWidth*tBlock.getBlockWidth();}
public int getWorkPiexHeight() { return GlassHeight*tBlock.getBlockHeight();}
public int getOffset_x() { return Offset_x;}
public int getOffset_y() { return Offset_y;}
public void reset() {
for(int y = 0; y < GlassHeight; y++)
for(int x = 0; x < GlassWidth; x++)
GlassWorkSheet[y][x] = 0;
}
public void repaint(int pos) {
if((pos < 0) || (pos >= GlassHeight)) return;
Color oldColor;
Graphics g = mainForm.getGraphics();
int w = tBlock.getBlockWidth();
int h = tBlock.getBlockHeight();
//g.clearRect(Offset_x, Offset_y, GlassWidth*w, GlassHeight*h);
for(int y = 0; (y <= pos) || (y < GlassHeight); y++)
for(int x = 0; x < GlassWidth; x++) {
oldColor = g.getColor();
if(GlassWorkSheet[y][x] == 1) {
g.setColor(objectColor);
g.fill3DRect(Offset_x+x*w, Offset_y+y*h, w-1, h-1, true);
}
else {
g.setColor(backgroundColor);
g.fillRect(Offset_x+x*w, Offset_y+y*h, w-1, h-1);
}
g.setColor(oldColor);
}
}
public void repaint() {
repaint(GlassHeight-1);
tBlock.repaint();
}
public boolean delLine(int pos) {
if((pos >= GlassHeight) || (pos < 0)) return false;
lockObject = true;
try {
if(pos == 0) {
for(int x = 0; x < GlassWidth; x++)
GlassWorkSheet[0][x] = 0;
} else {
for(int y = pos; y > 0; y--)
for(int x = 0; x < GlassWidth; x++)
GlassWorkSheet[y][x] = GlassWorkSheet[y-1][x];
}
} finally {
lockObject = false;
}
return true;
}
public int[] getLines() { //扫描背景,返回所有整行都为1的行的位置
int MaxCornerNumber = tBlock.getMaxCornerNumber();
int[] results = new int[MaxCornerNumber];
int x, y;
for(y = Sheet_y; y < Sheet_y + results.length; y++) {
if(y >= GlassHeight) break;
for(x = 0; x < GlassWidth; x++)
if(GlassWorkSheet[y][x] == 0) break;
if(x == GlassWidth)
results[y - Sheet_y] = y;
else
results[y - Sheet_y] = 0;
}
return results;
}
public boolean newObject(Color color, int Figure) {
Sheet_x = (int)(GlassWidth/2);
Sheet_y = 0;
currFigure = Figure;
if(!canPlace(Sheet_x, Sheet_y, tBlock.getSheet(currFigure))) //can't place the new object
return false;
tBlock.setColor(color);
tBlock.newObject(Offset_x+Sheet_x*tBlock.getBlockWidth(),
Offset_y+Sheet_y*tBlock.getBlockHeight(), currFigure);
return true;
}
protected boolean moveObject(int MoveDirect) {
if(lockObject) return true;
lockObject = true;
try {
switch(MoveDirect) {
//move to left
case 0:
if(!canPlace(Sheet_x-1, Sheet_y, tBlock.getFigureWorkSheet()))
return false;
else
Sheet_x -= 1;
break;
//move down
case 1:
if(!canPlace(Sheet_x, Sheet_y+1, tBlock.getFigureWorkSheet()))
return false;
else
Sheet_y += 1;
break;
//move to right
case 2:
if(!canPlace(Sheet_x+1, Sheet_y, tBlock.getFigureWorkSheet()))
return false;
else
Sheet_x += 1;
break;
}
tBlock.moveObject(MoveDirect);
} finally {
lockObject = false;
}
return true;
}
public void turn() {
if(lockObject) return;
lockObject = true;
try {
byte[][] Sheet = tBlock.getTurnSheet();
for(int moveToXX = 0; moveToXX < tBlock.getBlockWidth()-1; moveToXX++)
if(canPlace(Sheet_x-moveToXX, Sheet_y, Sheet)) {
Sheet_x -= moveToXX;
tBlock.setObjectXY(Offset_x+Sheet_x*tBlock.getBlockWidth(),
Offset_y+Sheet_y*tBlock.getBlockHeight());
tBlock.turn();
break;
}
} finally {
lockObject = false;
}
}
private boolean canPlace(int xx, int yy, byte[][] Sheet) {
int Glass_x, Glass_y;
int MaxCornerNumber = tBlock.getMaxCornerNumber();
//xx, yy是否越界?
if((xx >= 0) && (xx < GlassWidth) && (yy >=0) && (yy < GlassHeight)) { //没越界
for(int y = 0; y < MaxCornerNumber; y++)
for(int x = 0; x < MaxCornerNumber; x++) {
Glass_x = xx + x;
Glass_y = yy + y;
if(Sheet[y][x] == 1) {
if((Glass_x >= GlassWidth) || (Glass_y >= GlassHeight))
return false;
else if(Sheet[y][x] == GlassWorkSheet[Glass_y][Glass_x])
return false;
}
}
return true;
} else //越界
return false;
}
protected void writeGlassWorkSheet(int xx, int yy, byte[][] Sheet) {
for(int y = 0; y < tBlock.getMaxCornerNumber(); y++)
for(int x = 0; x < tBlock.getMaxCornerNumber(); x++) {
if(Sheet[y][x] == 1)
GlassWorkSheet[yy+y][xx+x] = Sheet[y][x];
}
}
}
//方块
class TetrisBlock {
private int BlockWidth = 12; //单元块宽度
private int BlockHeight = 12; //单元块高度
private int MaxFigureNumber = 7; //方块种类
private int MaxCornerNumber = 4; //最多单元块数(每方块每列/行)
private byte[][]
Triada = new byte[][]{
{0, 1, 0, 0},
{1, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
LCorner = new byte[][]{
{1, 1, 1, 0},
{1, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
RCorner = new byte[][]{
{1, 1, 1, 0},
{0, 0, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
LZigzag = new byte[][]{
{1, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
RZigzag = new byte[][]{
{0, 1, 1, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
Stick = new byte[][]{
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
Box = new byte[][]{
{1, 1, 0, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
};
private byte[][]
FigureWorkSheet = new byte[][]{
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
};
private byte[][][]
blockObjects = new byte[][][]{
Triada, LCorner, RCorner, LZigzag, RZigzag, Stick, Box
};
private int Figure = 0;
//private int FirstColor, SecondColor;
private Color color = Color.blue;
private boolean lockObject = false;
private Color backgroundColor;
private int object_loc_x, object_loc_y;
//private Graphics g;
private Tetris tetris;
public TetrisBlock(Tetris tetris) {
this.tetris = tetris;
//this.g = tetris.getGraphics();
}
public int getBlockWidth() { return BlockWidth;}
public int getBlockHeight() { return BlockHeight;}
public int getMaxFigureNumber() { return MaxFigureNumber;}
public int getMaxCornerNumber() { return MaxCornerNumber;}
public int getobject_loc_x() { return object_loc_x;}
public int getobject_loc_y() { return object_loc_y;}
public byte[][] getSheet(int Figure) {
if((Figure >= 0) && (Figure < MaxFigureNumber))
return blockObjects[Figure];
else
return null;
}
public byte[][] getFigureWorkSheet() { return FigureWorkSheet;}
//public void setGraphics(Graphics g) { this.g = g;}
public void setColor(Color color) {
this.color = color;
}
public void setBackgroundColor(Color color) {
this.backgroundColor = color;
}
public void newObject(int loc_x, int loc_y, int Figure) {
object_loc_x = loc_x;
object_loc_y = loc_y;
this.Figure = Figure;
FigureWorkSheet = blockObjects[this.Figure];
drawObject(object_loc_x, object_loc_y);
}
public void moveObject(int MoveDirect) {
if(lockObject) return;
lockObject = true;
try {
clearObject(object_loc_x, object_loc_y);
switch(MoveDirect) {
//move to left
case 0:
object_loc_x -= getBlockWidth();
break;
//move down
case 1:
object_loc_y += getBlockHeight();
break;
//move to right
case 2:
object_loc_x += getBlockWidth();
break;
}
drawObject(object_loc_x, object_loc_y);
} finally {
lockObject = false;
}
}
public void turn() {
lockObject = true;
try {
clearObject(object_loc_x, object_loc_y);
FigureWorkSheet = getTurnSheet();
drawObject(object_loc_x, object_loc_y);
} finally {
lockObject = false;
}
}
public byte[][] getTurnSheet() {
//返回逆时钟转90度,值为1的元素向左上角平行靠拢后的方块数组
byte[][] Sheet = new byte[MaxCornerNumber][MaxCornerNumber];
boolean toBreak = false;
int x, y;
for(y = 0; y < MaxCornerNumber; y++) {
for(x=0; x < MaxCornerNumber; x++)
Sheet[MaxCornerNumber-1-x][y] = FigureWorkSheet[y][x];
}
for(y = 0; y < MaxCornerNumber; y++) {
for(x=0; x < MaxCornerNumber; x++)
if(Sheet[y][x] == 1) {
toBreak = true;
break;
}
if(toBreak) break;
}
int yy = y;
for(; y < MaxCornerNumber; y++) { //行上移
for(x=0; x < MaxCornerNumber; x++)
Sheet[y-yy][x] = Sheet[y][x];
}
for(y = MaxCornerNumber-yy; y < MaxCornerNumber; y++) { //上移后原位置清零
for(x=0; x < MaxCornerNumber; x++)
Sheet[y][x] = 0;
}
return Sheet;
}
public void setObjectXY(int loc_x, int loc_y) {
clearObject(object_loc_x, object_loc_y);
object_loc_x = loc_x;
object_loc_y = loc_y;
drawObject(object_loc_x, object_loc_y);
}
public void repaint() {
drawObject(object_loc_x, object_loc_y);
}
public void drawMyObject(int loc_x, int loc_y, Graphics g, int Figure) {
byte[][] Sheet;
if((Sheet = getSheet(Figure)) == null) return;
g.clearRect(loc_x, loc_y,
getMaxCornerNumber()*getBlockWidth(), getMaxCornerNumber()*getBlockHeight());
for(int y=0; y < MaxCornerNumber; y++)
for(int x=0; x < MaxCornerNumber; x++) {
if(Sheet[y][x] == 1)
drawBlock(loc_x+x*getBlockWidth(), loc_y+y*getBlockHeight(),
getBlockWidth(), getBlockHeight(),
g);
}
}
private void drawObject(int loc_x, int loc_y) {
Graphics g = tetris.getGraphics();
g.setColor(color);
for(int y=0; y < MaxCornerNumber; y++)
for(int x=0; x < MaxCornerNumber; x++) {
if(FigureWorkSheet[y][x] == 1)
drawBlock(loc_x+x*getBlockWidth(), loc_y+y*getBlockHeight(),
getBlockWidth(), getBlockHeight(),
g);
}
}
private void clearObject(int loc_x, int loc_y) {
Color oldColor;
Graphics g = tetris.getGraphics();
oldColor = color;
g.setColor(backgroundColor);
for(int y=0; y < MaxCornerNumber; y++)
for(int x=0; x < MaxCornerNumber; x++) {
if(FigureWorkSheet[y][x] == 1)
g.fillRect(loc_x+x*getBlockWidth(), loc_y+y*getBlockHeight(),
getBlockWidth()-1, getBlockHeight()-1);
}
g.setColor(oldColor);
}
private void drawBlock(int x, int y, int w, int h, Graphics g) {
g.fill3DRect(x, y, w-1, h-1, true);
}
}