日历
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
29 | 30 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|
统计
- 随笔 - 2
- 文章 - 6
- 评论 - 5
- 引用 - 0
导航
常用链接
留言簿(1)
随笔档案
文章档案
搜索
最新评论
阅读排行榜
评论排行榜
|
最近在学习JAVA,就学参考学着写了一个俄罗斯方块,代码有详细注释,这里就不多做说明了。
可以用键盘,空格控制,或者用界面上的按钮。
1import java.awt.*;
2import java.awt.event.*;
3import javax.swing.*;
4import javax.swing.event.*;
5
6class Block implements Runnable// 方块类
7{
8 static final int type = 7, state = 4;
9
10 static final int[][] patten = { // 16进制代表每种方块
11 { 0x0f00, 0x4444, 0x0f00, 0x4444 },// 长条
12 { 0x6600, 0x6600, 0x6600, 0x6600 },// 正方块
13 { 0x04e0, 0x0464, 0x00e4, 0x04c4 },// 三角
14 { 0x08e0, 0x0644, 0x00e2, 0x044c },// 弯折一下,1、3,1左
15 { 0x02e0, 0x0446, 0x00e8, 0x0c44 },// 弯折一下,1、3,1右
16 { 0x0462, 0x006c, 0x0462, 0x006c },// 弯折两下,1、2、1,1左上;1右下
17 { 0x0264, 0x00c6, 0x0264, 0x00c6 } // 弯折两下,1、2、1,1右上;1左下
18 };
19
20 private int blockType = -1; // 方块类型,7种,大小范围0-6
21
22 private int blockState;// 方块状态,4种,大小范围0-3
23
24 private int row, col; // 方块所在的行数,列数
25
26 private int oldRow, oldCol; // 记录方块变化前所在的行数,列数
27
28 private int oldType = -1, oldState; // 记录方块变化前的类型和状态
29
30 private int isfall = 1; // 标记若画,画成什么颜色的,
31
32 // 1表示可以下落,画为红色;0表示不可下落,画为蓝色
33
34 private boolean end = false;// 结束标记,为true时表示结束
35
36 LeftShowCanvas lsc;
37
38 public Block(LeftShowCanvas lsc)
39 {
40 this.lsc = lsc;
41 row = 0;
42 col = 3;
43 oldRow = row;
44 oldCol = col;
45 }
46
47 public void reInit() // 一个方块无法下落后,重新初始化
48 {
49 blockType = -1;
50 isfall = 1;
51 }
52
53 public void reInitRowCol() // 初始化方块起始点
54 {
55 row = 0;
56 col = 3;
57 }
58
59 public void run() // 下落线程
60 {
61 lsc.requestFocusInWindow(); // 获得焦点
62 while (!end)
63 {
64 int blocktype = (int) (Math.random() * 100) % 7;
65 drawBlock(blocktype);
66 do
67 {
68 try
69 {
70 Thread.sleep(500); // 控制下落速度
71 } catch (InterruptedException e)
72 {
73
74 }
75 } while (fallMove()); // 下落
76 for (int j = 0; j < lsc.maxcols; j++)
77 // 判断是否结束
78 if (lsc.unitState[3][j] == 2)
79 end = true;
80 }
81 }
82
83 public synchronized void drawBlock(int blockType) // 画方块
84 {
85 if (this.blockType != blockType)
86 blockState = (int) (Math.random() * 100) % 4; // 状态
87 this.blockType = blockType; // 样式
88 if (!isMove(3)) // 判断是否能画
89 {
90 this.blockType = oldType;
91 this.blockState = oldState;
92 return;
93 }
94 int comIndex = 0x8000;
95 if (this.oldType != -1)
96 {
97 for (int i = oldRow; i < oldRow + 4; i++)
98 for (int j = oldCol; j < oldCol + 4; j++)
99 {
100 if ((patten[oldType][oldState] & comIndex) != 0
101 && lsc.unitState[i][j] == 1)
102 //lsc.drawUnit(i, j, 0); // 先还原
103 lsc.unitState[i][j]=0;//将状态记录改变,用于画下张图
104 comIndex = comIndex >> 1;
105 }
106 }
107 comIndex = 0x8000;
108 for (int i = row; i < row + 4; i++)
109 for (int j = col; j < col + 4; j++)
110 {
111 if ((patten[blockType][blockState] & comIndex) != 0)
112 {
113 if (isfall == 1)
114 //lsc.drawUnit(i, j, 1); // 再画,画为RED
115 lsc.unitState[i][j]=1; //将状态记录改变
116 else if (isfall == 0)
117 {
118 //lsc.drawUnit(i, j, 2); // 无法下落,画为BLUE
119 lsc.unitState[i][j]=2;//将状态记录改变,用于画下张图
120 lsc.deleteFullLine(i); // 判断此行是否可以消
121 }
122 }
123 comIndex = comIndex >> 1;
124 }
125
126 Image image; //创建缓冲图片,利用双缓冲消除闪烁,画的下个状态图
127 image=lsc.createImage(lsc.getWidth(),lsc.getHeight());
128 Graphics g=image.getGraphics();
129 lsc.paint(g);
130 g.drawImage(image, 0, 0, lsc);
131
132 if (isfall == 0) // 无法下落,先判断是否能消行,再重新初始化
133 {
134 // lsc.deleteFullLine(row,col);
135 reInit();
136 reInitRowCol();
137 }
138 oldRow = row;
139 oldCol = col;
140 oldType = blockType;
141 oldState = blockState;
142 }
143
144 public void leftTurn() // 旋转,左转
145 {
146 if (this.blockType != -1)
147 {
148 blockState = (blockState + 1) % 4;
149 if (isMove(3))
150 drawBlock(blockType);
151 else
152 blockState = (blockState + 3) % 4;
153 }
154 }
155
156 public void leftMove() // 左移
157 {
158 if (this.blockType != -1 && isMove(0))
159 {
160 col -= 1;
161 drawBlock(blockType);
162 }
163 }
164
165 public void rightMove() // 右移
166 {
167 if (this.blockType != -1 && isMove(1))
168 {
169 col += 1;
170 drawBlock(blockType);
171 }
172 }
173
174 public boolean fallMove() // 下移
175 {
176 if (this.blockType != -1)
177 {
178 if (isMove(2))
179 {
180 row += 1;
181 drawBlock(blockType);
182 return true;
183 } else
184 {
185 isfall = 0;
186 drawBlock(blockType);
187 return false;
188 }
189 }
190 return false;
191 }
192
193 public synchronized boolean isMove(int tag) // 左 0 ,右 1 ,下 2 ,旋转 3
194 {
195 int comIndex = 0x8000;
196 for (int i = row; i < row + 4; i++)
197 for (int j = col; j < col + 4; j++)
198 {
199 if ((patten[blockType][blockState] & comIndex) != 0)
200 {
201 if (tag == 0 && (j == 0 || lsc.unitState[i][j - 1] == 2))// 是否能左移
202 return false;
203 else if (tag == 1 && // 是否能右移
204 (j == lsc.maxcols - 1 || lsc.unitState[i][j + 1] == 2))
205 return false;
206 else if (tag == 2 && // 是否能下移
207 (i == lsc.maxrows - 1 || lsc.unitState[i + 1][j] == 2))
208 return false;
209 else if (tag == 3 && // 是否能旋转
210 (i > lsc.maxrows - 1 || j < 0
211 || j > lsc.maxcols - 1 || lsc.unitState[i][j] == 2))
212 return false;
213 }
214 comIndex = comIndex >> 1;
215 }
216 return true;
217 }
218}
219
220class LeftShowCanvas extends Canvas
221{
222 int maxrows, maxcols; // 画布最大行数,列数
223
224 int unitSize; // 单元格的大小,小正方格
225
226 int[][] unitState; // 每个小方格的状态 0、1、2表示
227
228 RightPanel rp;
229
230 int score;
231
232 public LeftShowCanvas(RightPanel rp)
233 {
234 this.rp = rp;
235 score = Integer.valueOf(rp.jtf.getText());
236 maxrows = 20;
237 maxcols = 10;
238 unitSize = 20;
239 unitState = new int[maxrows][maxcols];
240 initCanvas();
241 }
242
243 public void initCanvas() // 初始化,画布方格
244 {
245 for (int i = 0; i < maxrows; i++)
246 for (int j = 0; j < maxcols; j++)
247 unitState[i][j] = 0;
248 }
249
250 public void paint(Graphics g)
251 {
252 for (int i = 0; i < maxrows; i++)
253 {
254 for (int j = 0; j < maxcols; j++)
255 drawUnit(i, j, unitState[i][j]); // 画方格
256 if (i == 3)
257 {
258 g.setColor(Color.RED);
259 g.drawLine(0, (i + 1) * (unitSize + 1) - 1, maxcols
260 * (unitSize + 1) - 1, (i + 1) * (unitSize + 1) - 1);
261 }
262 }
263 }
264
265 public void drawUnit(int row, int col, int tag) // 画方格
266 {
267 unitState[row][col] = tag; // 记录状态
268 Graphics g = getGraphics();
269 switch (tag)
270 {
271 case 0: // 初始黑色
272 g.setColor(Color.BLACK);
273 break;
274 case 1: // 方格黑色
275 g.setColor(Color.RED);
276 break;
277 case 2:
278 g.setColor(Color.BLUE);
279 break;
280 }
281 g.fillRect(col * (unitSize + 1), row * (unitSize + 1), unitSize,
282 unitSize);
283 }
284
285 public void deleteFullLine(int row) // 判断此行是否可以消,同时可消就消行
286 {
287 for (int j = 0; j < maxcols; j++)
288 if (unitState[row][j] != 2)
289 return;
290
291 for (int i = row; i > 3; i--)
292 // 到此即为可消,将上面的移下消此行
293 for (int j = 0; j < maxcols; j++)
294 //drawUnit(i, j, unitState[i - 1][j]);
295 unitState[i][j]=unitState[i-1][j];//将状态记录改变,用于画下张图
296 score++;
297 rp.jtf.setText(String.valueOf(score));
298 }
299}
300
301class RightPanel extends JPanel
302{
303 JButton[] jbt = new JButton[7];
304
305 JButton[] jbt2 = new JButton[4];
306
307 JButton jbt3;
308
309 JTextField jtf;
310
311 JLabel jlb;
312
313 MyJPanel jp1, jp2;
314
315 public RightPanel()
316 {
317 jbt[0] = new JButton("长条");
318 jbt[1] = new JButton("方块");
319 jbt[2] = new JButton("三角");
320 jbt[3] = new JButton("左三");
321 jbt[4] = new JButton("右三");
322 jbt[5] = new JButton("左二");
323 jbt[6] = new JButton("右二");
324 jbt2[0] = new JButton("左移");
325 jbt2[1] = new JButton("右移");
326 jbt2[2] = new JButton("下移");
327 jbt2[3] = new JButton("翻转");
328
329 jbt3 = new JButton("开始");
330 jtf = new JTextField("0", 5);
331 jlb = new JLabel("得分", JLabel.CENTER);
332
333 jp1 = new MyJPanel(); // 左边的上面板
334 jp2 = new MyJPanel(); // 左边的下面板
335 jp1.setLayout(new GridLayout(4, 2, 20, 10)); // 网格布局
336 jp2.setLayout(new GridLayout(4, 2, 20, 10)); // 网格布局
337 this.setLayout(new BorderLayout()); // 边界布局
338 for (int i = 0; i < 7; i++)
339 jp1.add(jbt[i]);
340
341 jp1.add(jbt3);
342
343 for (int i = 0; i < 4; i++)
344 jp2.add(jbt2[i]);
345
346 jp2.add(jlb);
347 jp2.add(jtf);
348
349 this.add(jp1, "North");
350 this.add(jp2, "Center");
351 }
352}
353
354// 重写MyPanel类,使Panel的四周留空间
355class MyJPanel extends JPanel
356{
357 public Insets getInsets()
358 {
359 return new Insets(10, 30, 30, 30);
360 }
361}
362
363class MyActionListener implements ActionListener
364{
365 RightPanel rp;
366
367 Block bl;
368
369 LeftShowCanvas lsc;
370
371 public MyActionListener(RightPanel rp, Block bl, LeftShowCanvas lsc)
372 {
373 this.rp = rp;
374 this.bl = bl;
375 this.lsc = lsc;
376 }
377
378 public void actionPerformed(ActionEvent e)
379 {
380 if (e.getSource().equals(rp.jbt3))
381 {
382 // 这样子则按几次开始按钮就创建几个相同的线程,控制着相同的数据
383 Thread th = new Thread(bl);
384 th.start();
385 }
386 for (int i = 0; i < Block.type; i++)
387 if (e.getSource().equals(rp.jbt[i])) // 看是画哪个
388 {
389 bl.reInitRowCol();
390 bl.drawBlock(i);
391 lsc.requestFocusInWindow(); // 获得焦点
392 return;
393 }
394 if (e.getSource().equals(rp.jbt2[0]))
395 bl.leftMove();
396 else if (e.getSource().equals(rp.jbt2[1]))
397 bl.rightMove();
398 else if (e.getSource().equals(rp.jbt2[2]))
399 bl.fallMove();
400 else if (e.getSource().equals(rp.jbt2[3]))
401 bl.leftTurn();
402 lsc.requestFocusInWindow(); // 获得焦点
403 }
404}
405
406class MyKeyAdapter extends KeyAdapter
407{
408 Block bl;
409
410 public MyKeyAdapter(Block bl)
411 {
412 this.bl = bl;
413 }
414
415 public void keyPressed(KeyEvent e)
416 {
417 if (e.getKeyCode() == KeyEvent.VK_LEFT)
418 bl.leftMove();
419 else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
420 bl.rightMove();
421 else if (e.getKeyCode() == KeyEvent.VK_DOWN)
422 bl.fallMove();
423 else if (e.getKeyCode() == KeyEvent.VK_SPACE)
424 bl.leftTurn();
425 }
426}
427
428public class FinalElsBlock extends JFrame
429{
430 Block bl;
431
432 LeftShowCanvas lsc;
433
434 RightPanel rp;
435
436 public FinalElsBlock()
437 {
438 super("ELSBlock Study");
439 setBounds(130, 130, 500, 450);
440 setLayout(new GridLayout(1, 2, 50, 30));
441 rp = new RightPanel();
442 lsc = new LeftShowCanvas(rp);
443 bl = new Block(lsc);
444 rp.setSize(80, 400);
445 for (int i = 0; i < 7; i++)
446 // 为每个按钮添加消息监听
447 rp.jbt[i].addActionListener(new MyActionListener(rp, bl, lsc));
448 rp.jbt3.addActionListener(new MyActionListener(rp, bl, lsc));
449 for (int i = 0; i < 4; i++)
450 rp.jbt2[i].addActionListener(new MyActionListener(rp, bl, lsc));
451 lsc.addKeyListener(new MyKeyAdapter(bl));
452 this.add(lsc);
453 this.add(rp);
454 this.addWindowListener(new WindowAdapter()
455 {
456 public void windowClosing(WindowEvent e)
457 {
458 dispose();
459 System.exit(0);
460 }
461 });
462 setVisible(true);
463 }
464
465 public static void main(String[] args)
466 {
467 new FinalElsBlock();
468 }
469}
|