俄罗斯方块java版_俄罗斯方块 Java 版

俄罗斯方块java版_俄罗斯方块 Java 版1packageersblockgamedemo;23/**4*5*@authorjiangnan3146*/7importjava.applet.Applet;8importjava.applet.AudioClip;9importjava.awt.*;10importjava.awt.event.*;11importjava.text.DateFormat;12im…

1 packageersblockgamedemo;2

3 /**

4 *5 *@authorjiangnan3146 */

7 importjava.applet.Applet;8 importjava.applet.AudioClip;9 import java.awt.*;10 import java.awt.event.*;11 importjava.text.DateFormat;12 importjava.text.SimpleDateFormat;13 importjava.util.Date;14 import javax.swing.*;15 importjavax.swing.border.Border;16 importjavax.swing.border.EtchedBorder;17

18 /**

19 * 游戏主类,继承自JFrame类,负责游戏的全局控制。 内含: 1.一个GameCanvas画布类的实例对象,20 * 2.一个保存当前活动块(ErsBlock)实例的对象; 3.一个保存当前控制面板(ControlPanel)实例的对象;21 */

22 public class ErsBlocksGame extendsJFrame {23

24 /**

25 * 每填满一行计多少分26 */

27 public final static int PER_LINE_SCORE = 100;28 /**

29 * 积多少分以后能升级30 */

31 public final static int PER_LEVEL_SCORE = PER_LINE_SCORE * 20;32 /**

33 * 最大级数是10级34 */

35 public final static int MAX_LEVEL = 10;36 /**

37 * 默认级数是238 */

39 public final static int DEFAULT_LEVEL = 2;40 privateGameCanvas canvas;41 privateErsBlock block;42 private FileDialog dialog = new FileDialog(this);43 private boolean playing = false;44 privateAudioClip audioclip;45 privateControlPanel ctrlPanel;46 private JMenuBar bar = newJMenuBar();47 private JMenu mGame = new JMenu(” 游戏”),48 mControl = new JMenu(” 控制”),49 mWindowStyle = new JMenu(“游戏风格”),50 mMusic = new JMenu(“设置游戏音乐”),51 mInfo = new JMenu(“帮助”);52 private JMenuItem miNewGame = new JMenuItem(“新游戏”),53 miSetBlockColor = new JMenuItem(“设置方块颜色…”),54 miSetBackColor = new JMenuItem(“设置背景颜色…”),55 miTurnHarder = new JMenuItem(“升高游戏难度”),56 miTurnEasier = new JMenuItem(“降低游戏难度”),57 miExit = new JMenuItem(“退出”),58 miPlay = new JMenuItem(“开始”),59 miPause = new JMenuItem(“暂停”),60 miResume = new JMenuItem(“恢复”),61 miOpen = new JMenuItem(“打开”),62 playMusic = new JMenuItem(“播放”),63 stopMusic = new JMenuItem(“停止”),64 miStop = new JMenuItem(“终止游戏”),65 loopMusic = new JMenuItem(“循环”),66 miAuthor = new JMenuItem(“关于本游戏”);67 private JCheckBoxMenuItem miAsWindows = new JCheckBoxMenuItem(“Windows”),68 miAsMotif = new JCheckBoxMenuItem(“Motif”),69 miAsMetal = new JCheckBoxMenuItem(“Metal”, true);70

71 /**

72 * 主游戏类的构造方法73 *74 *@paramtitle String ,窗口标题75 */

76 publicErsBlocksGame(String title) {77 super(title); //设置标题

78 setSize(328, 405); //设置窗口大小

79 setLocationRelativeTo(null); //设置窗口居中

80

81 creatMenu();82 Container container =getContentPane();83 container.setLayout(new BorderLayout(6, 0)); //设置窗口的布局管理器

84 canvas = new GameCanvas(20, 15); //新建游戏画布

85 ctrlPanel = new ControlPanel(this); //新建控制面板

86 container.add(canvas, BorderLayout.CENTER); //左边加上画布

87 container.add(ctrlPanel, BorderLayout.EAST); //右边加上控制面板

88

89 addWindowListener(new WindowAdapter() { //注册窗口事件。当点击关闭按钮时,结束游戏,系统退出。

90 @Override91 public voidwindowClosing(WindowEvent we) {92 stopGame();93 System.exit(0);94 }95 });96 addComponentListener(newComponentAdapter() {97 @Override98 public voidcomponentResized(ComponentEvent ce) {99 canvas.fanning();100 }101 });102

103 setVisible(true);104 canvas.fanning();105

106

107 }108

109 /**

110 * 让游戏复位111 */

112 public void reset() { //画布复位,控制面板复位

113 ctrlPanel.setPlayButtonEnable(true);114 ctrlPanel.setPauseButtonEnable(false);115 ctrlPanel.setPauseButtonLabel(true);116 ctrlPanel.setStopButtonEnable(false);117 ctrlPanel.setTurnLevelDownButtonEnable(true);118 ctrlPanel.setTurnLevelUpButtonEnable(true);119 miPlay.setEnabled(true);120 miPause.setEnabled(false);121 miResume.setEnabled(false);122 miStop.setEnabled(false);123 ctrlPanel.reset();124 canvas.reset();125 }126

127 /**

128 * 判断游戏是否还在进行129 *130 *@returnboolean,true -还在运行,false-已经停止131 */

132 public booleanisPlaying() {133 returnplaying;134 }135

136 /**

137 * 得到当前活动的块138 *139 *@returnErsBlock,当前活动块的引用140 */

141 publicErsBlock getCurBlock() {142 returnblock;143 }144

145 /**

146 * 得到当前画布147 *148 *@returnGameCanvas,当前画布的引用149 */

150 publicGameCanvas getCanvas() {151 returncanvas;152 }153

154 /**

155 * 开始游戏156 */

157 public voidplayGame() {158 play();159 ctrlPanel.setPlayButtonEnable(false);160 ctrlPanel.setPauseButtonEnable(true);161 ctrlPanel.setPauseButtonLabel(true);162 ctrlPanel.setStopButtonEnable(true);163 ctrlPanel.setTurnLevelDownButtonEnable(false);164 ctrlPanel.setTurnLevelUpButtonEnable(false);165 miPlay.setEnabled(false);166 miPause.setEnabled(true);167 miResume.setEnabled(false);168 miStop.setEnabled(true);169 miTurnHarder.setEnabled(false);170 miTurnEasier.setEnabled(false);171 ctrlPanel.requestFocus(); //设置焦点

172 }173

174 /**

175 * 游戏暂停176 */

177 public voidpauseGame() {178 if (block != null) {179 block.pauseMove();180 }181 ctrlPanel.setPlayButtonEnable(false);182 ctrlPanel.setPauseButtonLabel(false);183 ctrlPanel.setStopButtonEnable(true);184 miPlay.setEnabled(false);185 miPause.setEnabled(false);186 miResume.setEnabled(true);187 miStop.setEnabled(true);188 }189

190 /**

191 * 让暂停中的游戏继续192 */

193 public voidresumeGame() {194 if (block != null) {195 block.resumeMove();196 }197 ctrlPanel.setPlayButtonEnable(false);198 ctrlPanel.setPauseButtonEnable(true);199 ctrlPanel.setPauseButtonLabel(true);200 miPause.setEnabled(true);201 miResume.setEnabled(false);202 ctrlPanel.requestFocus();203 }204

205 /**

206 * 用户停止游戏207 */

208 public voidstopGame() {209 playing = false;210 if (block != null) {211 block.stopMove();212 }213 ctrlPanel.setPlayButtonEnable(true);214 ctrlPanel.setPauseButtonEnable(false);215 ctrlPanel.setPauseButtonLabel(true);216 ctrlPanel.setStopButtonEnable(false);217 ctrlPanel.setTurnLevelDownButtonEnable(true);218 ctrlPanel.setTurnLevelUpButtonEnable(true);219 miPlay.setEnabled(true);220 miPause.setEnabled(false);221 miResume.setEnabled(false);222 miStop.setEnabled(false);223 miTurnHarder.setEnabled(true);224 miTurnEasier.setEnabled(true);225 }226

227 publicAudioClip getAudioClip() {228 returnaudioclip;229 }230

231 public voidsetAudioClip(AudioClip clip) {232 this.audioclip =clip;233 }234

235 public voidplayAudio() {236 if (audioclip != null) {237 audioclip.play();238 }239 }240

241 public voidloop() {242 if (audioclip != null) {243 loop();244 }245 }246

247 public voidstop() {248 if (audioclip != null) {249 stop();250 }251 }252

253 /**

254 * 得到游戏者设置的难度255 *256 *@returnint ,游戏难度1-MAX_LEVEL257 */

258 public intgetLevel() {259 returnctrlPanel.getLevel();260 }261

262 /**

263 * 用户设置游戏难度264 *265 *@paramlevel int ,游戏难度1-MAX_LEVEL266 */

267 public void setLevel(intlevel) {268 if (level < 11 && level > 0) {269 ctrlPanel.setLevel(level);270 }271 }272

273 /**

274 * 得到游戏积分275 *276 *@returnint,积分277 */

278 public intgetScore() {279 if (canvas != null) {280 returncanvas.getScore();281 }282 return 0;283 }284

285 /**

286 * 得到自上次升级以来的游戏积分,升级以后,此积分清零287 *288 *@returnint,积分289 */

290 public intgetScoreForLevelUpdate() {291 if (canvas != null) {292 returncanvas.getScoreForLevelUpdate();293 }294 return 0;295 }296

297 /**

298 * 当积分累积到一定数值时,升一次级299 *300 *@returnBoolean,true-update succeed,false-update fail301 */

302 public booleanlevelUpdate() {303 int curLevel =getLevel();304 if (curLevel

312 /**

313 * 游戏开始314 */

315 private voidplay() {316 reset();317 playing = true;318 Thread thread = new Thread(newGame());319 thread.start();320 }321

322 /**

323 * 报告游戏结束了324 */

325 private voidreportGameOver() {326 new gameOverDialog(this, “俄罗斯方块”, “游戏结束,您的得分为” +canvas.getScore());327 }328

329 /**

330 * 建立并设置窗口菜单331 */

332 private voidcreatMenu() {333 bar.add(mGame);334 bar.add(mControl);335 bar.add(mWindowStyle);336 bar.add(mMusic);337 bar.add(mInfo);338 mGame.add(miNewGame);339 mGame.addSeparator();340 mGame.add(miSetBlockColor);341 mGame.add(miSetBackColor);342 mGame.addSeparator();343 mGame.add(miTurnHarder);344 mGame.add(miTurnEasier);345 mGame.addSeparator();346 mGame.add(miExit);347 mControl.add(miPlay);348 miPlay.setEnabled(true);349 mControl.add(miPause);350 miPause.setEnabled(false);351 mControl.add(miResume);352 miResume.setEnabled(false);353 mControl.add(miStop);354 miStop.setEnabled(false);355 mWindowStyle.add(miAsWindows);356 mWindowStyle.add(miAsMotif);357 mWindowStyle.add(miAsMetal);358 mMusic.add(miOpen);359 mMusic.add(playMusic);360 mMusic.add(stopMusic);361 mMusic.add(loopMusic);362 mInfo.add(miAuthor);363 setJMenuBar(bar);364

365 miPause.setAccelerator(KeyStroke.getKeyStroke(366 KeyEvent.VK_P, KeyEvent.CTRL_MASK));367 miResume.setAccelerator(KeyStroke.getKeyStroke(368 KeyEvent.VK_R, KeyEvent.CTRL_MASK));369

370 miNewGame.addActionListener(newActionListener() {371 @Override372 public voidactionPerformed(ActionEvent e) {373 stopGame();374 reset();375 setLevel(DEFAULT_LEVEL);376 }377 });378 miSetBlockColor.addActionListener(newActionListener() {379 @Override380 public voidactionPerformed(ActionEvent e) {381 Color newFrontColor =

382 JColorChooser.showDialog(ErsBlocksGame.this, “设置方块颜色”, canvas.getBlockColor());383 if (newFrontColor != null) {384 canvas.setBlockColor(newFrontColor);385 }386 }387 });388 miSetBackColor.addActionListener(newActionListener() {389 @Override390 public voidactionPerformed(ActionEvent e) {391 Color newBackColor =

392 JColorChooser.showDialog(ErsBlocksGame.this, “设置背景颜色”, canvas.getBackgroundColor());393 if (newBackColor != null) {394 canvas.setBackgroundColor(newBackColor);395 }396 }397 });398 miAuthor.addActionListener(new ActionListener() { //定义菜单栏”关于”的功能,弹出确认框。

399 @Override400 public voidactionPerformed(ActionEvent e) {401 JOptionPane.showMessageDialog(null, “© Copyright 姜楠-张卓\n” + ” All Rights Reserved.”, “关于俄罗斯方块 – 2013”, 1);402 }403 });404 miTurnHarder.addActionListener(newActionListener() {405 @Override406 public voidactionPerformed(ActionEvent e) {407 int curLevel =getLevel();408 if (!playing && curLevel 1) {418 setLevel(curLevel – 1);419 }420 }421 });422 miExit.addActionListener(newActionListener() {423 @Override424 public voidactionPerformed(ActionEvent e) {425 System.exit(0);426 }427 });428 miPlay.addActionListener(newActionListener() {429 @Override430 public voidactionPerformed(ActionEvent e) {431 playGame();432 }433 });434 miPause.addActionListener(newActionListener() {435 @Override436 public voidactionPerformed(ActionEvent e) {437 pauseGame();438 }439 });440 miResume.addActionListener(newActionListener() {441 @Override442 public voidactionPerformed(ActionEvent e) {443 resumeGame();444 }445 });446 miStop.addActionListener(newActionListener() {447 @Override448 public voidactionPerformed(ActionEvent e) {449 stopGame();450 }451 });452 miOpen.addActionListener(newActionListener() {453 @Override454 public voidactionPerformed(ActionEvent e) {455 dialog.setVisible(true);456 if (dialog.getFile() != null) {457 String filename = dialog.getDirectory() +dialog.getFile();458 try{459 setAudioClip(Applet.newAudioClip((newjava.io.File(filename)).toURI().toURL()));460 playAudio();461 } catch(Exception ex) {462 ex.printStackTrace();463 }464 }465 }466 });467 playMusic.addActionListener(newActionListener() {468 @Override469 public voidactionPerformed(ActionEvent e) {470 playAudio();471 playMusic.setEnabled(false);472 stopMusic.setEnabled(true);473 }474 });475 stopMusic.addActionListener(newActionListener() {476 @Override477 public voidactionPerformed(ActionEvent e) {478 stop();479 }480 });481 loopMusic.addActionListener(newActionListener() {482 @Override483 public voidactionPerformed(ActionEvent e) {484 loop();485 }486 });487 miAsWindows.addActionListener(new ActionListener() { //改变游戏风格,Windows风格,motif风格,metal风格

488 @Override489 public voidactionPerformed(ActionEvent ae) {490 String plaf = “com.sun.java.swing.plaf.windows.WindowsLookAndFeel”;491 setWindowStyle(plaf);492 canvas.fanning(); //以新的界面风格的重新绘制画布和控制面板

493 ctrlPanel.fanning();494 miAsWindows.setState(true); //495 miAsMetal.setState(false);496 miAsMotif.setState(false);497 }498 });499 miAsMotif.addActionListener(newActionListener() {500 @Override501 public voidactionPerformed(ActionEvent e) {502 String plaf = “com.sun.java.swing.plaf.motif.MotifLookAndFeel”;503 setWindowStyle(plaf);504 canvas.fanning();505 ctrlPanel.fanning();506 miAsWindows.setState(false);507 miAsMetal.setState(false);508 miAsMotif.setState(true);509 }510 });511 miAsMetal.addActionListener(newActionListener() {512 @Override513 public voidactionPerformed(ActionEvent e) {514 String plaf = “javax.swing.plaf.metal.MetalLookAndFeel”;515 setWindowStyle(plaf);516 canvas.fanning();517 ctrlPanel.fanning();518 miAsWindows.setState(false);519 miAsMetal.setState(true);520 miAsMotif.setState(false);521 }522 });523

524

525 }526

527 /**

528 * 根据字串设置窗口外观529 *530 *@paramplaf String,窗口外观的描述531 */

532 private voidsetWindowStyle(String plaf) {533 try{534 UIManager.setLookAndFeel(plaf);535 SwingUtilities.updateComponentTreeUI(this);536 } catch(Exception e) {537 }538 }539

540 /**

541 * 一轮游戏过程,实现了Runnable接口 一轮游戏是一个大循环,在这个循环中,每隔100毫秒, 检查游戏中的当前块是否已经到底了,如果没有,542 * 就继续等待。如果到底了,就看有没有全填满的行, 如果有就删除它,并为游戏者加分,同时随机产生一个 新的当前块人 让它自动落下。543 * 当新产生一个块时,先检查画布最顶上的一行是否已经 被占了,如果是,可以判断Game Over 了。544 */

545 private class Game implementsRunnable {546

547 @Override548 public voidrun() {549 int col = (int) (Math.random() * (canvas.getCols() – 3));550 int style = ErsBlock.STYLES[ (int) (Math.random() * 7)][(int) (Math.random() * 4)];551

552 while(playing) {553 if (block != null) { //第一次循环时,block为空

554 if(block.isAlive()) {555 try{556 Thread.currentThread().sleep(500);557 } catch(InterruptedException ie) {558 ie.printStackTrace();559 }560 continue;561 }562 }563

564 checkFullLine(); //检查是否有全填满的行

565

566 if(isGameOver()) {567 reportGameOver();568 miPlay.setEnabled(true);569 miPause.setEnabled(false);570 miResume.setEnabled(false);571 miStop.setEnabled(false);572 ctrlPanel.setPlayButtonEnable(true);573 ctrlPanel.setPauseButtonLabel(false);574 ctrlPanel.setStopButtonEnable(false);575 return;576 }577

578 block = new ErsBlock(style, -1, col, getLevel(), canvas);579 block.start();580

581 col = (int) (Math.random() * (canvas.getCols() – 3));582 style = ErsBlock.STYLES[ (int) (Math.random() * 7)][(int) (Math.random() * 4)];583

584 ctrlPanel.setTipStyle(style);585 }586 }587

588 //检查画布中是否有全填满的行,如果有就删之

589 public voidcheckFullLine() {590 for (int i = 0; i < canvas.getRows(); i++) {591 int row = -1;592 boolean fullLineColorBox = true;593 for (int j = 0; j < canvas.getCols(); j++) {594 if (!canvas.getBox(i, j).isColorBox()) {595 fullLineColorBox = false;596 break;597 }598 }599 if(fullLineColorBox) {600 row = i–;601 canvas.removeLine(row);602 }603 }604 }605

606 //根据最顶行是否被占,判断游戏是否已经结束了607 //@return boolean ,true-游戏结束了,false-游戏未结束

608 private booleanisGameOver() {609 for (int i = 0; i < canvas.getCols(); i++) {610 ErsBox box = canvas.getBox(0, i);611 if(box.isColorBox()) {612 return true;613 }614 }615 return false;616 }617 }618

619 /**

620 * 定义GameOver对话框。621 */

622 private class gameOverDialog extends JDialog implementsActionListener {623

624 privateJButton againButton, exitButton;625 private Border border = new EtchedBorder(EtchedBorder.RAISED, Color.white, new Color(148, 145, 140));626

627 publicgameOverDialog(JFrame parent, String title, String message) {628 super(parent, title, true);629 if (parent != null) {630 setSize(240, 120);631 this.setLocationRelativeTo(parent);632 JPanel messagePanel = newJPanel();633 messagePanel.add(newJLabel(message));634 messagePanel.setBorder(border);635 Container container = this.getContentPane();636 container.setLayout(new GridLayout(2, 0, 0, 10));637 container.add(messagePanel);638 JPanel choosePanel = newJPanel();639 choosePanel.setLayout(new GridLayout(0, 2, 4, 0));640 container.add(choosePanel);641 againButton = new JButton(“再玩一局”);642 exitButton = new JButton(“退出游戏”);643 choosePanel.add(newJPanel().add(againButton));644 choosePanel.add(newJPanel().add(exitButton));645 choosePanel.setBorder(border);646 }647 againButton.addActionListener(this);648 exitButton.addActionListener(this);649 this.setVisible(true);650 }651

652 @Override653 public voidactionPerformed(ActionEvent e) {654 if (e.getSource() ==againButton) {655 this.setVisible(false);656 reset();657 } else if (e.getSource() ==exitButton) {658 stopGame();659 System.exit(0);660

661 }662 }663 }664

665 /**

666 * 程序入口函数667 *668 *@paramargs String[],附带的命令行参数669 */

670 public static voidmain(String[] args) {671 new ErsBlocksGame(“俄罗斯方块:ZJUT-CS&T”);672 }673 }674

675 /**

676 * 画布类,内有* 个方格类实例。 继承自JPanel类。 ErsBlock线程类动态改变画布类的方格颜色,画布类通过677 * 检查方格颜色来体现ErsBlock块的移动情况。678 */

679 class GameCanvas extendsJPanel {680

681 private Color backColor = Color.LIGHT_GRAY, frontColor =Color.orange;682 private int rows, cols, score = 0, scoreForLevelUpdate = 0;683 privateErsBox[][] boxes;684 private intboxWidth, boxHeight;685

686 /**

687 * 画布类的构造函数688 *689 *@paramrows int,画布的行数690 *@paramcols int,画布的列数 行数和列数决定着画布拥有方格的数目691 */

692 public GameCanvas(int rows, intcols) {693 this.rows =rows;694 this.cols =cols;695

696 boxes = newErsBox[rows][cols];697 for (int i = 0; i < boxes.length; i++) {698 for (int j = 0; j < boxes[i].length; j++) {699 boxes[i][j] = new ErsBox(false);700 }701 }702

703 setBorder(new EtchedBorder(EtchedBorder.RAISED, Color.white, new Color(148, 145, 140)));704 }705

706 /**

707 * 画布类的构造函数708 *709 *@paramrows710 *@paramcols711 *@parambackColor712 *@paramfrontColor713 */

714 public GameCanvas(int rows, intcols,715 Color backColor, Color frontColor) {716 this(rows, cols);717 this.backColor =backColor;718 this.frontColor =frontColor;719 }720

721 /**

722 * 设置游戏背景色彩723 *724 *@parambackColor Color,背景色彩725 */

726 public voidsetBackgroundColor(Color backColor) {727 this.backColor =backColor;728 }729

730 /**

731 * 取得游戏背景色彩732 *733 *@returnColor ,背景色彩734 */

735 publicColor getBackgroundColor() {736 returnbackColor;737 }738

739 /**

740 * 设置游戏方块颜色741 *742 *@paramfrontColor Color,方块颜色743 */

744 public voidsetBlockColor(Color frontColor) {745 this.frontColor =frontColor;746 }747

748 /**

749 * 取得游戏方块色彩750 *751 *@returnColor,方块颜色752 */

753 publicColor getBlockColor() {754 returnfrontColor;755 }756

757 /**

758 * 取得画布中方格的列数759 *760 *@return

761 */

762 public intgetRows() {763 returnrows;764 }765

766 /**

767 * 取得画布中方格的行数768 *769 *@returnint,方格的行数770 */

771 public intgetCols() {772 returncols;773 }774

775 /**

776 * 取得游戏成绩777 *778 *@returnint, 分数779 */

780 public intgetScore() {781 returnscore;782 }783

784 /**

785 * 取得自上一次升级后的积分786 *787 *@returnint ,上一次升级后的积分788 */

789 public intgetScoreForLevelUpdate() {790 returnscoreForLevelUpdate;791 }792

793 /**

794 * 升级后,将上一次升级以来的积分清零795 */

796 public voidresetScoreForLevelUpdate() {797 scoreForLevelUpdate -=ErsBlocksGame.PER_LEVEL_SCORE;798 }799

800 /**

801 * 得到某一行某一列的方格引用802 *803 *@returnrow int ,要引用的方格所在的行804 *@paramcol int, 要引用的方格所在的行805 *@returnErsBox,在row行col列的方格的引用806 */

807 public ErsBox getBox(int row, intcol) {808 if (row < 0 || row > boxes.length – 1 || col < 0 || col > boxes[0].length – 1) {809 return null;810 }811 return(boxes[row][col]);812 }813

814 /**

815 * 覆盖JComponent类的函数,画组件。816 *817 *@paramg 图形设备环境818 */

819 @Override820 public voidpaintComponent(Graphics g) {821 super.paintComponent(g);822

823 g.setColor(frontColor);824 for (int i = 0; i < boxes.length; i++) {825 for (int j = 0; j < boxes[i].length; j++) {826 g.setColor(boxes[i][j].isColorBox() ?frontColor : backColor);827 g.fill3DRect(j * boxWidth, i *boxHeight,828 boxWidth, boxHeight, true);829 }830 }831 }832

833 /**

834 * 根据窗口大小,自动调节方格的尺寸835 */

836 public voidfanning() {837 boxWidth = getSize().width /cols;838 boxHeight = getSize().height /rows;839 }840

841 /**

842 * 当一行被游戏者叠满后,将此行清除,并为游戏者加分843 *844 *@paramrow int,要清除的行,是由ErsBoxesGame类计算的845 */

846 public synchronized void removeLine(introw) {847 for (int i = row; i > 0; i–) {848 for (int j = 0; j < cols; j++) {849 boxes[i][j] = (ErsBox) boxes[i – 1][j].clone(); //将上一行的方块颜色克隆下来,

850 } //即消去一行方块

851 }852

853 score +=ErsBlocksGame.PER_LEVEL_SCORE;854 scoreForLevelUpdate +=ErsBlocksGame.PER_LEVEL_SCORE;855 repaint();856 }857

858 /**

859 * 重置画布,置积分为零860 */

861 public voidreset() {862 score = 0;863 scoreForLevelUpdate = 0;864 for (int i = 0; i < boxes.length; i++) {865 for (int j = 0; j < boxes[i].length; j++) {866 boxes[i][j].setColor(false);867 }868 }869

870 repaint();871 }872 }873

874 /**

875 * 方格类,是组成块的基本元素,用自己的颜色来表示块的外观876 */

877 class ErsBox implementsCloneable {878

879 private booleanisColor;880 private Dimension size = newDimension();881

882 /**

883 * 方格类的构造函数,884 *885 *@paramisColor 是不是用前景色来为此方格着色 true前景色,false 用背景色886 */

887 public ErsBox(booleanisColor) {888 this.isColor =isColor;889 }890

891 /**

892 * 此方格是不是用前景色表现893 *894 *@returnboolean ,true用前景色表现,false 用背景色表现895 */

896 public booleanisColorBox() {897 returnisColor;898 }899

900 /**

901 * 设置方格的颜色,902 *903 *@paramisColor boolean ,true用前景色表现,false 用背景色表现904 */

905 public void setColor(booleanisColor) {906 this.isColor =isColor;907 }908

909 /**

910 * 得到此方格的尺寸911 *912 *@returnDimension ,方格的尺寸913 */

914 publicDimension getSize() {915 returnsize;916 }917

918 /**

919 * 设置方格的尺寸,920 *921 *@paramsize Dimension ,方格的尺寸922 */

923 public voidsetSize(Dimension size) {924 this.size =size;925 }926

927 /**

928 * 覆盖Object的Object clone(),实现克隆929 *930 *@returnObject,克隆的结果931 */

932 @Override933 publicObject clone() {934 Object cloned = null;935 try{936 cloned = super.clone();937 } catch(Exception ex) {938 ex.printStackTrace();939 }940

941 returncloned;942 }943 }944

945 /**

946 * 块类,继承自线程类(Thread) 由4 × 4个方块(ErsBox)构成一个方块, 控制块的移动·下落·变形等947 */

948 class ErsBlock extendsThread {949

950 /**

951 * 一个块占的行数是4行952 */

953 public final static int BOXES_ROWS = 4;954 /**

955 * 一个块占的列数是4列956 */

957 public final static int BOXES_COLS = 4;958 /**

959 * 让升级变化平滑的因子,避免最后几级之间的速度相差近一倍960 */

961 public final static int LEVEL_FLATNESS_GENE = 3;962 /**

963 * 相近的两级之间,块每下落一行的时间差别为多少(毫秒)964 */

965 public final static int BETWEEN_LEVELS_DEGRESS_TIME = 50;966 /**

967 * 方块的样式数目为7968 */

969 public final static int BLOCK_KIND_NUMBER = 7;970 /**

971 * 每一个样式的方块的反转状态种类为4972 */

973 public final static int BLOCK_STATUS_NUMBER = 4;974 /**

975 * 分别对应7种模型的28种状态976 */

977 public final static int[][] STYLES = { //共28种状态

978 {0x0f00, 0x4444, 0x0f00, 0x4444}, //长条型的四种状态

979 {0x04e0, 0x0464, 0x00e4, 0x04c4}, //T型的四种状态

980 {0x4620, 0x6c00, 0x4620, 0x6c00}, //反Z型的四种状态

981 {0x2640, 0xc600, 0x2640, 0xc600}, //Z型的四种状态

982 {0x6220, 0x1700, 0x2230, 0x0740}, //7型的四种状态

983 {0x6440, 0x0e20, 0x44c0, 0x8e00}, //反7型的四种状态

984 {0x0660, 0x0660, 0x0660, 0x0660}, //方块的四种状态

985 };986 privateGameCanvas canvas;987 private ErsBox[][] boxes = newErsBox[BOXES_ROWS][BOXES_COLS];988 private intstyle, y, x, level;989 private boolean pausing = false, moving = true;990

991 /**

992 * 构造函数,产生一个特定的块993 *994 *@paramstyle 块的样式,对应STYLES的28个值中的一个995 *@paramy 起始位置,左上角在canvas中的坐标行996 *@paramx 起始位置,左上角在canvas中的坐标lie997 *@paramlevel 游戏等级,控制块的下落速度998 *@paramcanvas 画板999 */

1000 public ErsBlock(int style, int y, int x, intlevel, GameCanvas canvas) {1001 this.style =style;1002 this.y =y;1003 this.x =x;1004 this.level =level;1005 this.canvas =canvas;1006

1007 int key = 0x8000;1008 for (int i = 0; i < boxes.length; i++) {1009 for (int j = 0; j < boxes[i].length; j++) {1010 boolean isColor = ((style & key) != 0);1011 boxes[i][j] = newErsBox(isColor);1012 key >>= 1;1013 }1014 }1015

1016 display();1017 }1018

1019 /**

1020 * 线程类的run()函数覆盖,下落块,直到块不能再下落1021 */

1022 @Override1023 public voidrun() {1024 while(moving) {1025 try{1026 sleep(BETWEEN_LEVELS_DEGRESS_TIME1027 * (ErsBlocksGame.MAX_LEVEL – level +LEVEL_FLATNESS_GENE));1028 } catch(InterruptedException ie) {1029 ie.printStackTrace();1030 }1031 //后边的moving是表示在等待的100毫秒间,moving没有被改变

1032 if (!pausing) {1033 moving = (moveTo(y + 1, x) &&moving);1034 }1035 }1036 }1037

1038 /**

1039 * 块向左移动一格1040 */

1041 public voidmoveLeft() {1042 moveTo(y, x – 1);1043 }1044

1045 /**

1046 * 块向右移动一格1047 */

1048 public voidmoveRight() {1049 moveTo(y, x + 1);1050 }1051

1052 /**

1053 * 块向下移动一格1054 */

1055 public voidmoveDown() {1056 moveTo(y + 1, x);1057 }1058

1059 /**

1060 * 块变型1061 */

1062 public voidturnNext() {1063 for (int i = 0; i < BLOCK_KIND_NUMBER; i++) {1064 for (int j = 0; j < BLOCK_STATUS_NUMBER; j++) {1065 if (STYLES[i][j] ==style) {1066 int newStyle = STYLES[i][(j + 1) %BLOCK_STATUS_NUMBER];1067 turnTo(newStyle);1068 return;1069 }1070 }1071 }1072 }1073

1074 public voidstartMove() {1075 pausing = false;1076 moving = true;1077 }1078

1079 /**

1080 * 暂停块的下落,对应游戏暂停1081 */

1082 public voidpauseMove() {1083 pausing = true;1084 //moving = false;

1085 }1086

1087 /**

1088 * 继续块的下落,对应游戏继续1089 */

1090 public voidresumeMove() {1091 pausing = false;1092 moving = true;1093 }1094

1095 /**

1096 * 停止块的下落,对应游戏停止1097 */

1098 public voidstopMove() {1099 pausing = false;1100 moving = false;1101 }1102

1103 /**

1104 * 将当前块从画布的对应位置移除,要等到下次重画画布时才能反映出来1105 */

1106 private voiderase() {1107 for (int i = 0; i < boxes.length; i++) {1108 for (int j = 0; j < boxes[i].length; j++) {1109 if(boxes[i][j].isColorBox()) {1110 ErsBox box = canvas.getBox(i + y, j +x);1111 if (box == null) {1112 continue;1113 }1114 box.setColor(false);1115 }1116 }1117 }1118 }1119

1120 /**

1121 * 让当前块放置在画布的对因位置上,要等到下次重画画布时才能看见1122 */

1123 private voiddisplay() {1124 for (int i = 0; i < boxes.length; i++) {1125 for (int j = 0; j < boxes[i].length; j++) {1126 if(boxes[i][j].isColorBox()) {1127 ErsBox box = canvas.getBox(i + y, j +x);1128 if (box == null) {1129 continue;1130 }1131 box.setColor(true);1132 }1133 }1134 }1135 }1136

1137 /**

1138 * 当前块能否移动到newRow/newCol 所指定的位置1139 *1140 *@paramnewRow int,目的地所在行1141 *@paramnewCol int,目的地所在列1142 *@returnboolean,true-能移动,false-不能移动1143 */

1144 public boolean isMoveAble(int newRow, intnewCol) {1145 erase();1146 for (int i = 0; i < boxes.length; i++) {1147 for (int j = 0; j < boxes[i].length; j++) {1148 if(boxes[i][j].isColorBox()) {1149 ErsBox box = canvas.getBox(i + newRow, j +newCol);1150 if (box == null ||(box.isColorBox())) {1151 display();1152 return false;1153 }1154 }1155 }1156 }1157 display();1158 return true;1159 }1160

1161 /**

1162 * 将当前块移动到newRow/newCol 所指定的位置1163 *1164 *@paramnewRow int,目的地所在行1165 *@paramnewCol int,目的地所在列1166 *@returnboolean,true-移动成功,false-移动失败1167 */

1168 private synchronized boolean moveTo(int newRow, intnewCol) {1169 if (!isMoveAble(newRow, newCol) || !moving) {1170 return false;1171 }1172

1173 erase();1174 y =newRow;1175 x =newCol;1176

1177 display();1178 canvas.repaint();1179

1180 return true;1181 }1182

1183 /**

1184 * 当前块能否变成newStyle所指定的块样式,主要是考虑 边界以及被其他块挡住,不能移动的情况1185 *1186 *@paramnewSytle int,希望改变的块样式,对应STYLES的28个值中的一个1187 *@returnboolean,true-能改变,false-不能改变1188 */

1189 private boolean isTurnAble(intnewStyle) {1190 int key = 0x8000;1191 erase();1192 for (int i = 0; i < boxes.length; i++) {1193 for (int j = 0; j < boxes[i].length; j++) {1194 if ((newStyle & key) != 0) {1195 ErsBox box = canvas.getBox(i + y, j +x);1196 if (box == null ||(box.isColorBox())) {1197 display();1198 return false;1199 }1200 }1201 key >>= 1;1202 }1203 }1204 display();1205 return true;1206 }1207

1208 /**

1209 * 将当前块变成newStyle所指定的块样式1210 *1211 *@paramnewStyle int,希望改变的块样式,对应STYLES的28个值中的一个1212 *@returntrue-改变成功,false-改变失败1213 */

1214 private boolean turnTo(intnewStyle) {1215 if (!isTurnAble(newStyle) || !moving) {1216 return false;1217 }1218

1219 erase();1220 int key = 0x8000;1221 for (int i = 0; i < boxes.length; i++) {1222 for (int j = 0; j < boxes[i].length; j++) {1223 boolean isColor = ((newStyle & key) != 0);1224 boxes[i][j].setColor(isColor);1225 key >>= 1;1226 }1227 }1228 style =newStyle;1229

1230 display();1231 canvas.repaint();1232

1233 return true;1234 }1235 }1236

1237 /**

1238 * 控制面板类,继承自JPanel。 上边安放预显窗口,等级,得分,控制按钮 主要用来控制游戏进程。1239 */

1240 class ControlPanel extendsJPanel {1241

1242 private JTextField tfLevel = new JTextField(“” +ErsBlocksGame.DEFAULT_LEVEL),1243 tfScore = new JTextField(” 0″),1244 tfTime = new JTextField(” “);1245 private JButton btPlay = new JButton(” 开始”),1246 btPause = new JButton(” 暂停”),1247 btStop = new JButton(“终止游戏”),1248 btTurnLevelUp = new JButton(” 增加难度”),1249 btTurnLevelDown = new JButton(” 降低难度”);1250 private JPanel plTip = new JPanel(newBorderLayout());1251 private TipPanel plTipBlock = newTipPanel();1252 private JPanel plInfo = new JPanel(new GridLayout(4, 1));1253 private JPanel plButton = new JPanel(new GridLayout(6, 1));1254 privateTimer timer;1255 privateErsBlocksGame game;1256 private Border border = new EtchedBorder(EtchedBorder.RAISED, Color.white, new Color(148, 145, 140));1257

1258 /**

1259 * 控制面板类的构造函数1260 *1261 *@paramgame ErsBlocksGame,ErsBlocksGame 类的一个实例引用 方便直接控制ErsBlocksGame类的行为。1262 */

1263 public ControlPanel(finalErsBlocksGame game) {1264 setLayout(new GridLayout(3, 1, 0, 2));1265 this.game =game;1266

1267 plTip.add(new JLabel(” 下一个方块”), BorderLayout.NORTH); //添加组件

1268 plTip.add(plTipBlock);1269 plTip.setBorder(border);1270

1271 plInfo.add(new JLabel(” 难度系数”));1272 plInfo.add(tfLevel);1273 plInfo.add(new JLabel(” 得分”));1274 plInfo.add(tfScore);1275 plInfo.setBorder(border);1276

1277 plButton.add(btPlay);1278 btPlay.setEnabled(true);1279 plButton.add(btPause);1280 btPause.setEnabled(false);1281 plButton.add(btStop);1282 btStop.setEnabled(false);1283 plButton.add(btTurnLevelUp);1284 plButton.add(btTurnLevelDown);1285 plButton.add(tfTime);1286 plButton.setBorder(border);1287

1288 tfLevel.setEditable(false);1289 tfScore.setEditable(false);1290 tfTime.setEditable(false);1291

1292 add(plTip);1293 add(plInfo);1294 add(plButton);1295

1296 addKeyListener(newKeyAdapter() {1297 @Override1298 public voidkeyPressed(KeyEvent ke) {1299 if (!game.isPlaying()) {1300 return;1301 }1302

1303 ErsBlock block =game.getCurBlock();1304 switch(ke.getKeyCode()) {1305 caseKeyEvent.VK_DOWN:1306 block.moveDown();1307 break;1308 caseKeyEvent.VK_LEFT:1309 block.moveLeft();1310 break;1311 caseKeyEvent.VK_RIGHT:1312 block.moveRight();1313 break;1314 caseKeyEvent.VK_UP:1315 block.turnNext();1316 break;1317 default:1318 break;1319 }1320 }1321 });1322

1323 btPlay.addActionListener(new ActionListener() { //开始游戏

1324 @Override1325 public voidactionPerformed(ActionEvent ae) {1326 game.playGame();1327 }1328 });1329 btPause.addActionListener(new ActionListener() { //暂停游戏

1330 @Override1331 public voidactionPerformed(ActionEvent ae) {1332 if (btPause.getText().equals(” 暂停”)) {1333 game.pauseGame();1334 } else{1335 game.resumeGame();1336 }1337 }1338 });1339 btStop.addActionListener(new ActionListener() { //停止游戏

1340 @Override1341 public voidactionPerformed(ActionEvent ae) {1342 game.stopGame();1343 }1344 });1345 btTurnLevelUp.addActionListener(new ActionListener() { //升高难度

1346 @Override1347 public voidactionPerformed(ActionEvent ae) {1348 try{1349 int level =Integer.parseInt(tfLevel.getText());1350 if (level

1359 @Override1360 public voidactionPerformed(ActionEvent ae) {1361 try{1362 int level =Integer.parseInt(tfLevel.getText());1363 if (level > 1) {1364 tfLevel.setText(“” + (level – 1));1365 }1366 } catch(NumberFormatException e) {1367 }1368 requestFocus();1369 }1370 });1371

1372 addComponentListener(newComponentAdapter() {1373 @Override1374 public voidcomponentResized(ComponentEvent ce) {1375 plTipBlock.fanning();1376 }1377 });1378

1379 timer = new Timer(1000, newActionListener() {1380 @Override1381 public voidactionPerformed(ActionEvent ae) {1382 DateFormat format = new SimpleDateFormat(“时间:HH:mm:ss”); //系统获得时间

1383 Date date = newDate();1384 tfTime.setText(format.format(date));1385

1386 tfScore.setText(“” +game.getScore());1387 int ScoreForLevelUpdate = //判断当前分数是否能升级

1388 game.getScoreForLevelUpdate();1389 if (ScoreForLevelUpdate >=ErsBlocksGame.PER_LEVEL_SCORE1390 && ScoreForLevelUpdate > 0) {1391 game.levelUpdate();1392 }1393 }1394 });1395 timer.start();1396 }1397

1398 /**

1399 * 设置预显窗口的样式1400 *1401 *@paramstyle int,对应ErsBlock类的STYLES中的28个值1402 */

1403 public void setTipStyle(intstyle) {1404 plTipBlock.setStyle(style);1405 }1406

1407 /**

1408 * 取得用户设置的游戏等级。1409 *1410 *@returnint ,难度等级,1-ErsBlocksGame.MAX_LEVEL1411 */

1412 public intgetLevel() {1413 int level = 0;1414 try{1415 level =Integer.parseInt(tfLevel.getText());1416 } catch(NumberFormatException e) {1417 }1418 returnlevel;1419 }1420

1421 /**

1422 * 让用户修改游戏难度等级。1423 *1424 *@paramlevel 修改后的游戏难度等级1425 */

1426 public void setLevel(intlevel) {1427 if (level > 0 && level < 11) {1428 tfLevel.setText(“” +level);1429 }1430 }1431

1432 /**

1433 * 设置“开始”按钮的状态。1434 */

1435 public void setPlayButtonEnable(booleanenable) {1436 btPlay.setEnabled(enable);1437 }1438

1439 public void setPauseButtonEnable(booleanenable) {1440 btPause.setEnabled(enable);1441 }1442

1443 public void setPauseButtonLabel(booleanpause) {1444 btPause.setText(pause ? ” 暂停” : ” 继续”);1445 }1446

1447 public void setStopButtonEnable(booleanenable) {1448 btStop.setEnabled(enable);1449 }1450

1451 public void setTurnLevelUpButtonEnable(booleanenable) {1452 btTurnLevelUp.setEnabled(enable);1453 }1454

1455 public void setTurnLevelDownButtonEnable(booleanenable) {1456 btTurnLevelDown.setEnabled(enable);1457 }1458

1459 /**

1460 * 重置控制面板1461 */

1462 public voidreset() {1463 tfScore.setText(” 0″);1464 plTipBlock.setStyle(0);1465 }1466

1467 /**

1468 * 重新计算TipPanel里的boxes[][]里的小框的大小1469 */

1470 public voidfanning() {1471 plTipBlock.fanning();1472 }1473

1474 /**

1475 * 预显窗口的实现细节类1476 */

1477 private class TipPanel extends JPanel { //TipPanel用来显示下一个将要出现方块的形状

1478

1479 private Color backColor = Color.LIGHT_GRAY, frontColor =Color.ORANGE;1480 private ErsBox[][] boxes = newErsBox[ErsBlock.BOXES_ROWS][ErsBlock.BOXES_COLS];1481 private intstyle, boxWidth, boxHeight;1482 private boolean isTiled = false;1483

1484 /**

1485 * 预显示窗口类构造函数1486 */

1487 publicTipPanel() {1488 for (int i = 0; i < boxes.length; i++) {1489 for (int j = 0; j < boxes[i].length; j++) {1490 boxes[i][j] = new ErsBox(false);1491 }1492 }1493 }1494

1495 /**

1496 * 预显示窗口类构造函数1497 *1498 *@parambackColor Color,窗口的背景色1499 *@paramfrontColor Color,窗口的前景色1500 */

1501 publicTipPanel(Color backColor, Color frontColor) {1502 this();1503 this.backColor =backColor;1504 this.frontColor =frontColor;1505 }1506

1507 /**

1508 * 设置预显示窗口的方块样式1509 *1510 *@paramstyle int,对应ErsBlock类的STYLES中的28个值1511 */

1512 public void setStyle(intstyle) {1513 this.style =style;1514 repaint();1515 }1516

1517 /**

1518 * 覆盖JComponent类的函数,画组件。1519 *1520 *@paramg 图形设备环境1521 */

1522 @Override1523 public voidpaintComponent(Graphics g) {1524 super.paintComponent(g);1525

1526 if (!isTiled) {1527 fanning();1528 }1529

1530 int key = 0x8000;1531 for (int i = 0; i < boxes.length; i++) {1532 for (int j = 0; j < boxes[i].length; j++) {1533 Color color = ((key & style) != 0 ?frontColor : backColor);1534 g.setColor(color);1535 g.fill3DRect(j * boxWidth, i *boxHeight,1536 boxWidth, boxHeight, true);1537 key >>= 1;1538 }1539 }1540 }1541

1542 /**

1543 * g根据窗口的大小,自动调整方格的尺寸1544 */

1545 public voidfanning() {1546 boxWidth = getSize().width /ErsBlock.BOXES_COLS;1547 boxHeight = getSize().height /ErsBlock.BOXES_ROWS;1548 isTiled = true;1549 }1550 }1551 }

今天的文章俄罗斯方块java版_俄罗斯方块 Java 版分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/26282.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注