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