import java.awt.*;
3.import java.awt.event.*;
4.
5.//俄罗斯方块类
6.public class ERS_Block extends Frame {
7.
/**
8.
*
9.
*/
10.
private static final long serialVersionUID = -1443760309099067025L;
11.
12.
public static boolean isPlay = false;
13.
14.
public static int level = 1, score = 0;
15.
16.
public static TextField scoreField, levelField;
17.
18.
public static MyTimer timer;
19.
20.
GameCanvas gameScr;
21.
22.
public static void main(String[] argus) {
23.
ERS_Block ers = new ERS_Block("俄罗斯方块游戏 V1.0 Author:Vincent");
24.
WindowListener win_listener = new WinListener();
25.
ers.addWindowListener(win_listener);
26.
}
27.
28.
// 俄罗斯方块类的构造方法
29.
ERS_Block(String title) {
30.
super(title);
31.
32.
setSize(600, 480);
33.
setLayout(new GridLayout(1, 2));
34.
35.
gameScr = new GameCanvas();
36.
gameScr.addKeyListener(gameScr);
37.
38.
timer = new MyTimer(gameScr);
39.
timer.setDaemon(true);
40.
timer.start();
41.
timer.suspend();
42.
43.
add(gameScr);
44.
45.
Panel rightScr = new Panel();
46.
rightScr.setLayout(new GridLayout(2, 1, 0, 30));
47.
rightScr.setSize(120, 500);
48.
add(rightScr);
49.
50.
// 右边信息窗体的布局
51.
MyPanel infoScr = new MyPanel();
52.
infoScr.setLayout(new GridLayout(4, 1, 0, 5));
53.
infoScr.setSize(120, 300);
54.
rightScr.add(infoScr);
55.
56.
// 定义标签和初始值
57.
Label scorep = new Label("分数:", Label.LEFT);
58.
Label levelp = new Label("级数:", Label.LEFT);
59.
scoreField = new TextField(8);
60.
levelField = new TextField(8);
61.
scoreField.setEditable(false);
62.
levelField.setEditable(false);
63.
infoScr.add(scorep);
64.
infoScr.add(scoreField);
65.
infoScr.add(levelp);
66.
infoScr.add(levelField);
67.
scorep.setSize(new Dimension(20, 60));
68.
scoreField.setSize(new Dimension(20, 60));
69.
levelp.setSize(new Dimension(20, 60));
70.
levelField.setSize(new Dimension(20, 60));
71.
scoreField.setText("0");
72.
levelField.setText("1");
73.
74.
// 右边控制按钮窗体的布局
75.
MyPanel controlScr = new MyPanel();
76.
controlScr.setLayout(new GridLayout(5, 1, 0, 5));
77.
rightScr.add(controlScr);
78.
79.
// 定义按钮play
80.
Button play_b = new Button("开始游戏");
81.
play_b.setSize(new Dimension(50, 200));
82.
play_b.addActionListener(new Command(Command.button_play, gameScr));
83.
84.
// 定义按钮Level UP
85.
Button level_up_b = new Button("提高级数");
86.
level_up_b.setSize(new Dimension(50, 200));
87.
level_up_b.addActionListener(new Command(Command.button_levelup,
88.
gameScr));
89.
90.
// 定义按钮Level Down
91.
Button level_down_b = new Button("降低级数");
92.
level_down_b.setSize(new Dimension(50, 200));
93.
level_down_b.addActionListener(new Command(Command.button_leveldown,
94.
gameScr));
95.
96.
// 定义按钮Level Pause
97.
Button pause_b = new Button("游戏暂停");
98.
pause_b.setSize(new Dimension(50, 200));
99.
pause_b.addActionListener(new Command(Command.button_pause, gameScr));
100.
101.
// 定义按钮Quit
102.
Button quit_b = new Button("退出游戏");
103.
quit_b.setSize(new Dimension(50, 200));
104.
quit_b.addActionListener(new Command(Command.button_quit, gameScr));
105.
106.
controlScr.add(play_b);
107.
controlScr.add(level_up_b);
108.
controlScr.add(level_down_b);
109.
controlScr.add(pause_b);
110.
controlScr.add(quit_b);
111.
setVisible(true);
112.
gameScr.requestFocus();
113.
}
114.}
115.
116.// 重写MyPanel类,使Panel的四周留空间
117.class MyPanel extends Panel {
118.
public Insets getInsets() {
119.
return new Insets(30, 50, 30, 50);
120.
}
121.}
122.
123.// 游戏画布类
124.class GameCanvas extends Canvas implements KeyListener {
125.
final int unitSize = 30; // 小方块边长
126.
127.
int rowNum; // 正方格的行数
128.
129.
int columnNum; // 正方格的列数
130.
131.
int maxAllowRowNum; // 允许有多少行未削
132.
133.
int blockInitRow; // 新出现块的起始行坐标
134.
135.
int blockInitCol; // 新出现块的起始列坐标
136.
137.
int[][] scrArr; // 屏幕数组
138.
139.
Block b; // 对方快的引用
140.
141.
// 画布类的构造方法
142.
GameCanvas() {
143.
rowNum = 15;
144.
columnNum = 10;
145.
maxAllowRowNum = rowNum - 2;
146.
b = new Block(this);
147.
blockInitRow = rowNum - 1;
148.
blockInitCol = columnNum / 2 - 2;
149.
scrArr = new int[32][32];
150.
}
151.
152.
// 初始化屏幕,并将屏幕数组清零的方法
153.
void initScr() {
154.
for (int i = 0; i < rowNum; i++)
155.
for (int j = 0; j < columnNum; j++)
156.
scrArr[i][j] = 0;
157.
b.reset();
158.
repaint();
159.
}
160.
161.
// 重新刷新画布方法
162.
public void paint(Graphics g) {
163.
for (int i = 0; i < rowNum; i++)
164.
for (int j = 0; j < columnNum; j++)
165.
drawUnit(i, j, scrArr[i][j]);
166.
}
167.
168.
// 画方块的方法
169.
public void drawUnit(int row, int col, int type) {
170.
scrArr[row][col] = type;
171.
Graphics g = getGraphics();
172.
switch (type) { // 表示画方快的方法
173.
case 0:
174.
g.setColor(Color.black);
175.
break; // 以背景为颜色画
176.
case 1:
177.
g.setColor(Color.blue);
178.
break; // 画正在下落的方块
179.
case 2:
180.
g.setColor(Color.magenta);
181.
break; // 画已经落下的方法
182.
}
183.
g.fill3DRect(col * unitSize, getSize().height - (row + 1) * unitSize,
184.
unitSize, unitSize, true);
185.
g.dispose();
186.
}
187.
188.
public Block getBlock() {
189.
return b; // 返回block实例的引用
190.
}
191.
192.
// 返回屏幕数组中(row,col)位置的属性值
193.
public int getScrArrXY(int row, int col) {
194.
if (row < 0 || row >= rowNum || col < 0 || col >= columnNum)
195.
return (-1);
196.
else
197.
return (scrArr[row][col]);
198.
}
199.
200.
// 返回新块的初始行坐标方法
201.
public int getInitRow() {
202.
return (blockInitRow); // 返回新块的初始行坐标
203.
}
204.
205.
// 返回新块的初始列坐标方法
206.
public int getInitCol() {
207.
return (blockInitCol); // 返回新块的初始列坐标
208.
}
209.
210.
// 满行删除方法
211.
void deleteFullLine() {
212.
int full_line_num = 0;
213.
int k = 0;
214.
for (int i = 0; i < rowNum; i++) {
215.
boolean isfull = true;
216.
217.
L1: for (int j = 0; j < columnNum; j++)
218.
if (scrArr[i][j] == 0) {
219.
k++;
220.
isfull = false;
221.
break L1;
222.
}
223.
if (isfull)
224.
full_line_num++;
225.
if (k != 0 && k - 1 != i && !isfull)
226.
for (int j = 0; j < columnNum; j++) {
227.
if (scrArr[i][j] == 0)
228.
drawUnit(k - 1, j, 0);
229.
else
230.
drawUnit(k - 1, j, 2);
231.
scrArr[k - 1][j] = scrArr[i][j];
232.
}
233.
}
234.
for (int i = k - 1; i < rowNum; i++) {
235.
for (int j = 0; j < columnNum; j++) {
236.
drawUnit(i, j, 0);
237.
scrArr[i][j] = 0;
238.
}
239.
}
240.
ERS_Block.score += full_line_num;
241.
ERS_Block.scoreField.setText("" + ERS_Block.score);
242.
}
243.
244.
// 判断游戏是否结束方法
245.
boolean isGameEnd() {
246.
for (int col = 0; col < columnNum; col++) {
247.
if (scrArr[maxAllowRowNum][col] != 0)
248.
return true;
249.
}
250.
return false;
251.
}
252.
253.
public void keyTyped(KeyEvent e) {
254.
}
255.
256.
public void keyReleased(KeyEvent e) {
257.
}
258.
259.
// 处理键盘输入的方法
260.
public void keyPressed(KeyEvent e) {
261.
if (!ERS_Block.isPlay)
262.
return;
263.
switch (e.getKeyCode()) {
264.
case KeyEvent.VK_DOWN:
265.
b.fallDown();
266.
break;
267.
case KeyEvent.VK_LEFT:
268.
b.leftMove();
269.
break;
270.
case KeyEvent.VK_RIGHT:
271.
b.rightMove();
272.
break;
273.
case KeyEvent.VK_SPACE:
274.
b.leftTurn();
275.
break;
276.
}
277.
}
278.}
279.
280.// 处理控制类
281.class Command implements ActionListener {
282.
static final int button_play = 1; // 给按钮分配编号
283.
284.
static final int button_levelup = 2;
285.
286.
static final int button_leveldown = 3;
287.
288.
static final int button_quit = 4;
289.
290.
static final int button_pause = 5;
291.
292.
static boolean pause_resume = true;
293.
294.
int curButton; // 当前按钮
295.
296.
GameCanvas scr;
297.
298.
// 控制按钮类的构造方法
299.
Command(int button, GameCanvas scr) {
300.
curButton = button;
301.
this.scr = scr;
302.
}
303.
304.
// 按钮执行方法
305.
public void actionPerformed(ActionEvent e) {
306.
switch (curButton) {
307.
case button_play:
308.
if (!ERS_Block.isPlay) {
309.
scr.initScr();
310.
ERS_Block.isPlay = true;
311.
ERS_Block.score = 0;
312.
ERS_Block.scoreField.setText("0");
313.
ERS_Block.timer.resume();
314.
}
315.
scr.requestFocus();
316.
break;
317.
case button_levelup:
318.
if (ERS_Block.level < 10) {
319.
ERS_Block.level++;
320.
ERS_Block.levelField.setText("" + ERS_Block.level);
321.
ERS_Block.score = 0;
322.
ERS_Block.scoreField.setText("" + ERS_Block.score);
323.
}
324.
scr.requestFocus();
325.
break;
326.
case button_leveldown:
327.
if (ERS_Block.level > 1) {
328.
ERS_Block.level--;
329.
ERS_Block.levelField.setText("" + ERS_Block.level);
330.
ERS_Block.score = 0;
331.
ERS_Block.scoreField.setText("" + ERS_Block.score);
332.
}
333.
scr.requestFocus();
334.
break;
335.
case button_pause:
336.
if (pause_resume) {
337.
ERS_Block.timer.suspend();
338.
pause_resume = false;
339.
} else {
340.
ERS_Block.timer.resume();
341.
pause_resume = true;
342.
}
343.
scr.requestFocus();
344.
break;
345.
case button_quit:
346.
System.exit(0);
347.
}
348.
}
349.}
350.
351.// 方块类
352.class Block {
353.
static int[][] pattern = {
354.
{ 0x0f00, 0x4444, 0x0f00, 0x4444 },// 用十六进至表示,本行表示长条四种状态
355.
{ 0x04e0, 0x0464, 0x00e4, 0x04c4 },
356.
{ 0x4620, 0x6c00, 0x4620, 0x6c00 },
357.
{ 0x2640, 0xc600, 0x2640, 0xc600 },
358.
{ 0x6220, 0x1700, 0x2230, 0x0740 },
359.
{ 0x6440, 0x0e20, 0x44c0, 0x8e00 },
360.
{ 0x0660, 0x0660, 0x0660, 0x0660 } };
361.
362.
int blockType; // 块的模式号(0-6)
363.
364.
int turnState; // 块的翻转状态(0-3)
365.
366.
int blockState; // 快的下落状态
367.
368.
int row, col; // 块在画布上的坐标
369.
370.
GameCanvas scr;
371.
372.
// 块类的构造方法
373.
Block(GameCanvas scr) {
374.
this.scr = scr;
375.
blockType = (int) (Math.random() * 1000) % 7;
376.
turnState = (int) (Math.random() * 1000) % 4;
377.
blockState = 1;
378.
row = scr.getInitRow();
379.
col = scr.getInitCol();
380.
}
381.
382.
// 重新初始化块,并显示新块
383.
public void reset() {
384.
blockType = (int) (Math.random() * 1000) % 7;
385.
turnState = (int) (Math.random() * 1000) % 4;
386.
blockState = 1;
387.
row = scr.getInitRow();
388.
col = scr.getInitCol();
389.
dispBlock(1);
390.
}
391.
392.
// 实现“块”翻转的方法
393.
public void leftTurn() {
394.
if (assertValid(blockType, (turnState + 1) % 4, row, col)) {
395.
dispBlock(0);
396.
turnState = (turnState + 1) % 4;
397.
dispBlock(1);
398.
}
399.
}
400.
401.
// 实现“块”的左移的方法
402.
public void leftMove() {
403.
if (assertValid(blockType, turnState, row, col - 1)) {
404.
dispBlock(0);
405.
col--;
406.
dispBlock(1);
407.
}
408.
}
409.
410.
// 实现块的右移
411.
public void rightMove() {
412.
if (assertValid(blockType, turnState, row, col + 1)) {
413.
dispBlock(0);
414.
col++;
415.
dispBlock(1);
416.
}
417.
}
418.
419.
// 实现块落下的操作的方法
420.
public boolean fallDown() {
421.
if (blockState == 2)
422.
return (false);
423.
if (assertValid(blockType, turnState, row - 1, col)) {
424.
dispBlock(0);
425.
row--;
426.
dispBlock(1);
427.
return (true);
428.
} else {
429.
blockState = 2;
430.
dispBlock(2);
431.
return (false);
432.
}
433.
}
434.
435.
// 判断是否正确的方法
436.
boolean assertValid(int t, int s, int row, int col) {
437.
int k = 0x8000;
438.
for (int i = 0; i < 4; i++) {
439.
for (int j = 0; j < 4; j++) {
440.
if ((int) (pattern[t][s] & k) != 0) {
441.
int temp = scr.getScrArrXY(row - i, col + j);
442.
if (temp < 0 || temp == 2)
443.
return false;
444.
}
445.
k = k >> 1;
446.
}
447.
}
448.
return true;
449.
}
450.
451.
// 同步显示的方法
452.
public synchronized void dispBlock(int s) {
453.
int k = 0x8000;
454.
for (int i = 0; i < 4; i++) {
455.
for (int j = 0; j < 4; j++) {
456.
if (((int) pattern[blockType][turnState] & k) != 0) {
457.
scr.drawUnit(row - i, col + j, s);
458.
}
459.
k = k >> 1;
460.
}
461.
}
462.
}
463.}
464.
465.// 定时线程
466.class MyTimer extends Thread {
467.
GameCanvas scr;
468.
469.
public MyTimer(GameCanvas scr) {
470.
this.scr = scr;
471.
}
472.
473.
public void run() {
474.
while (true) {
475.
try {
476.
sleep((10 - ERS_Block.level + 1) * 100);
477.
} catch (InterruptedException e) {
478.
}
479.
if (!scr.getBlock().fallDown()) {
480.
scr.deleteFullLine();
481.
if (scr.isGameEnd()) {
482.
ERS_Block.isPlay = false;
483.
suspend();
484.
} else
485.
scr.getBlock().reset();
486.
}
487.
}
488.
}
489.}
490.
491.class WinListener extends WindowAdapter {
492.
public void windowClosing(WindowEvent l) {
493.
System.exit(0);
494.
}
495.}