java实现俄罗斯方块小程序

这是java课最后做的课程设计,由于java是初学的,所以做的时候有参考一些技术大牛的博客,在此表示感谢。

发在这里跟大家交流学习一下。

如需要完整工程文件、说明文档以及可运行jar文件,下载地址:点击打开链接

RussianBlocksGame.java

package RussiaBlocksGame; 

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder; 

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

private static final long serialVersionUID = -7332245439279674749L;
/**
  * 每填满一行计多少分
  */
 public final static int PER_LINE_SCORE = 100;
 /**
  * 积多少分以后能升级
  */
 public final static int PER_LEVEL_SCORE = PER_LINE_SCORE * 20;
 /**
  * 最大级数是10级
  */
 public final static int MAX_LEVEL = 10;
 /**
  * 默认级数是2
  */
 public final static int DEFAULT_LEVEL = 2;
 private GameCanvas canvas;
 private ErsBlock block;
 private boolean playing = false;
 private ControlPanel ctrlPanel;
 //初始化菜单栏
 private JMenuBar bar = new JMenuBar();
 private JMenu mGame = new JMenu(" 游戏"),
   mControl = new JMenu(" 控制"),
   mInfo = new JMenu("帮助");
 private JMenuItem miNewGame = new JMenuItem("新游戏"),
   miSetBlockColor = new JMenuItem("设置方块颜色..."),
   miSetBackColor = new JMenuItem("设置背景颜色..."),
   miTurnHarder = new JMenuItem("升高游戏难度"),
   miTurnEasier = new JMenuItem("降低游戏难度"),
   miExit = new JMenuItem("退出"),
   miPlay = new JMenuItem("开始"),
   miPause = new JMenuItem("暂停"),
   miResume = new JMenuItem("恢复"),
   miStop = new JMenuItem("终止游戏"),
   miRule = new JMenuItem("游戏规则"),
   miAuthor = new JMenuItem("关于本游戏"); 

 /**
  * 建立并设置窗口菜单
  */
 private void creatMenu() {
  bar.add(mGame);
  bar.add(mControl);
  bar.add(mInfo);
  mGame.add(miNewGame);
  mGame.addSeparator();//在菜单中加水平分割线
  mGame.add(miSetBlockColor);
  mGame.add(miSetBackColor);
  mGame.addSeparator();//在菜单中加水平分割线
  mGame.add(miTurnHarder);
  mGame.add(miTurnEasier);
  mGame.addSeparator();//在菜单中加水平分割线
  mGame.add(miExit);
  mControl.add(miPlay);
  miPlay.setEnabled(true);
  mControl.add(miPause);
  miPause.setEnabled(false);
  mControl.add(miResume);
  miResume.setEnabled(false);
  mControl.add(miStop);
  miStop.setEnabled(false);
  mInfo.add(miRule);
  mInfo.add(miAuthor);
  setJMenuBar(bar); 

  miNewGame.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    stopGame();
    reset();
    setLevel(DEFAULT_LEVEL);
   }
  }); 

  //设置方块颜色
  miSetBlockColor.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    Color newFrontColor =
      JColorChooser.showDialog(RussiaBlocksGame.this, "设置方块颜色", canvas.getBlockColor());
    if (newFrontColor != null) {
     canvas.setBlockColor(newFrontColor);
    }
   }
  }); 

  //设置背景颜色
  miSetBackColor.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    Color newBackColor =
      JColorChooser.showDialog(RussiaBlocksGame.this, "设置背景颜色", canvas.getBackgroundColor());
    if (newBackColor != null) {
     canvas.setBackgroundColor(newBackColor);
    }
   }
  }); 

  //定义菜单栏"关于"的功能,弹出确认框。
  miAuthor.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    JOptionPane.showMessageDialog(null, "软件工程(4)班\n3115005372\n杨宇杰\n©一切解释权归杨宇杰所有", "关于俄罗斯方块 - 2016", 1);
   }
  }); 

  //游戏规则说明
  miRule.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    JOptionPane.showMessageDialog(null, "由小方块组成的不同形状的板块陆续从屏幕上方落下来,\n玩家通过调整板块的位置和方向,使它们在屏幕底部拼\n出完整的一条或几条。这些完整的横条会随即消失,给新\n落下来的板块腾出空间,与此同时,玩家得到分数奖励。\n没有被消除掉的方块不断堆积起来,一旦堆到屏幕顶端,\n玩家便告输,游戏结束。", "游戏规则", 1);
   }
  }); 

  //增加难度
  miTurnHarder.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    int curLevel = getLevel();
    if (!playing && curLevel < MAX_LEVEL) {
     setLevel(curLevel + 1);
    }
   }
  }); 

  //减少难度
  miTurnEasier.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    int curLevel = getLevel();
    if (!playing && curLevel > 1) {
     setLevel(curLevel - 1);
    }
   }
  }); 

  //退出按钮动作响应
  miExit.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    System.exit(0);
   }
  }); 

 } 

 /**
  * 主游戏类的构造方法
  *
  * @param title String ,窗口标题
  */
 public RussiaBlocksGame(String title) {
  super(title);           //设置标题
  setSize(500, 600);          //设置窗口大小
  setLocationRelativeTo(null);        //设置窗口居中 

  creatMenu();
  Container container = getContentPane(); //创建菜单栏
  container.setLayout(new BorderLayout(6, 0));    //设置窗口的布局管理器
  canvas = new GameCanvas(20, 15);       //新建游戏画布
  ctrlPanel = new ControlPanel(this);      //新建控制面板
  container.add(canvas, BorderLayout.CENTER);    //左边加上画布
  container.add(ctrlPanel, BorderLayout.EAST);    //右边加上控制面板 

  //注册窗口事件。当点击关闭按钮时,结束游戏,系统退出。
  addWindowListener(new WindowAdapter() {
   @Override
   public void windowClosing(WindowEvent we) {
    stopGame();
    System.exit(0);
   }
  }); 

  //根据窗口大小,自动调节方格的尺寸
  addComponentListener(new ComponentAdapter() {
   @Override
   public void componentResized(ComponentEvent ce) {
    canvas.adjust();
   }
  }); 

  setVisible(true);
  canvas.adjust();
 } 

 /**
  * 让游戏复位
  */
 public void reset() {       //画布复位,控制面板复位
  ctrlPanel.setPlayButtonEnable(true);
  ctrlPanel.setPauseButtonEnable(false);
  ctrlPanel.setPauseButtonLabel(true);
  ctrlPanel.setStopButtonEnable(false);
  ctrlPanel.setTurnLevelDownButtonEnable(true);
  ctrlPanel.setTurnLevelUpButtonEnable(true);
  miPlay.setEnabled(true);
  miPause.setEnabled(false);
  miResume.setEnabled(false);
  miStop.setEnabled(false);
  ctrlPanel.reset();
  canvas.reset();
 } 

 /**
  * 判断游戏是否还在进行
  *
  * @return boolean,true -还在运行,false-已经停止
  */
 public boolean isPlaying() {
  return playing;
 } 

 /**
  * 得到当前活动的块
  *
  * @return ErsBlock,当前活动块的引用
  */
 public ErsBlock getCurBlock() {
  return block;
 } 

 /**
  * 得到当前画布
  *
  * @return GameCanvas,当前画布的引用
  */
 public GameCanvas getCanvas() {
  return canvas;
 } 

 /**
  * 开始游戏
  */
 public void playGame() {
  play();
  ctrlPanel.setPlayButtonEnable(false);
  ctrlPanel.setPauseButtonEnable(true);
  ctrlPanel.setPauseButtonLabel(true);
  ctrlPanel.setStopButtonEnable(true);
  ctrlPanel.setTurnLevelDownButtonEnable(false);
  ctrlPanel.setTurnLevelUpButtonEnable(false);
  miStop.setEnabled(true);
  miTurnHarder.setEnabled(false);
  miTurnEasier.setEnabled(false);
  ctrlPanel.requestFocus();    //设置焦点在控制面板上
 } 

 /**
  * 游戏暂停
  */
 public void pauseGame() {
  if (block != null) {
   block.pauseMove();
  }
  ctrlPanel.setPlayButtonEnable(false);
  ctrlPanel.setPauseButtonLabel(false);
  ctrlPanel.setStopButtonEnable(true);
  miPlay.setEnabled(false);
  miPause.setEnabled(false);
  miResume.setEnabled(true);
  miStop.setEnabled(true);
 } 

 /**
  * 让暂停中的游戏继续
  */
 public void resumeGame() {
  if (block != null) {
   block.resumeMove();
  }
  ctrlPanel.setPlayButtonEnable(false);
  ctrlPanel.setPauseButtonEnable(true);
  ctrlPanel.setPauseButtonLabel(true);
  miPause.setEnabled(true);
  miResume.setEnabled(false);
  ctrlPanel.requestFocus();
 } 

 /**
  * 用户停止游戏
  */
 public void stopGame() {
  playing = false;
  if (block != null) {
   block.stopMove();
  }
  ctrlPanel.setPlayButtonEnable(true);
  ctrlPanel.setPauseButtonEnable(false);
  ctrlPanel.setPauseButtonLabel(true);
  ctrlPanel.setStopButtonEnable(false);
  ctrlPanel.setTurnLevelDownButtonEnable(true);
  ctrlPanel.setTurnLevelUpButtonEnable(true);
  miPlay.setEnabled(true);
  miPause.setEnabled(false);
  miResume.setEnabled(false);
  miStop.setEnabled(false);
  miTurnHarder.setEnabled(true);
  miTurnEasier.setEnabled(true);
  reset();//重置画布和控制面板
 } 

 /**
  * 得到游戏者设置的难度
  *
  * @return int ,游戏难度1-MAX_LEVEL
  */
 public int getLevel() {
  return ctrlPanel.getLevel();
 } 

 /**
  * 用户设置游戏难度
  *
  * @param level int ,游戏难度1-MAX_LEVEL
  */
 public void setLevel(int level) {
  if (level < 11 && level > 0) {
   ctrlPanel.setLevel(level);
  }
 } 

 /**
  * 得到游戏积分
  *
  * @return int,积分
  */
 public int getScore() {
  if (canvas != null) {
   return canvas.getScore();
  }
  return 0;
 } 

 /**
  * 得到自上次升级以来的游戏积分,升级以后,此积分清零
  *
  * @return int,积分
  */
 public int getScoreForLevelUpdate() {
  if (canvas != null) {
   return canvas.getScoreForLevelUpdate();
  }
  return 0;
 } 

 /**
  * 当积分累积到一定数值时,升一次级
  *
  * @return Boolean,true-update succeed,false-update fail
  */
 public boolean levelUpdate() {
  int curLevel = getLevel();
  if (curLevel < MAX_LEVEL) {
   setLevel(curLevel + 1);
   canvas.resetScoreForLevelUpdate();
   return true;
  }
  return false;
 } 

 /**
  * 游戏开始
  */
 private void play() {
  reset();
  playing = true;
  Thread thread = new Thread(new Game());//启动游戏线程
  thread.start();
 } 

 /**
  * 报告游戏结束了
  */
 private void reportGameOver() {
  new gameOverDialog(this, "俄罗斯方块", "游戏结束,您的得分为" + canvas.getScore());
 } 

 /**
  * 一轮游戏过程,实现了Runnable接口 一轮游戏是一个大循环,在这个循环中,每隔100毫秒, 检查游戏中的当前块是否已经到底了,如果没有,
  * 就继续等待。如果到底了,就看有没有全填满的行, 如果有就删除它,并为游戏者加分,同时随机产生一个新的当前块并让它自动落下。
  * 当新产生一个块时,先检查画布最顶上的一行是否已经被占了,如果是,可以判断Game Over 了。
  */
private class Game implements Runnable {
  @Override
  public void run() {
   int col = (int) (Math.random() * (canvas.getCols() - 3));//随机生成方块出现的位置
   int style = ErsBlock.STYLES[ (int) (Math.random() * 7)][(int) (Math.random() * 4)];//随机生成一种形状的方块 

   while (playing) {
    if (block != null) { //第一次循环时,block为空
     if (block.isAlive()) {
      try {
       Thread.currentThread();
 Thread.sleep(500);
      } catch (InterruptedException ie) {
       ie.printStackTrace();
      }
      continue;
     }
    } 

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

    if (isGameOver()) {
     reportGameOver();
     miPlay.setEnabled(true);
     miPause.setEnabled(false);
     miResume.setEnabled(false);
     miStop.setEnabled(false);
     ctrlPanel.setPlayButtonEnable(true);
     ctrlPanel.setPauseButtonLabel(false);
     ctrlPanel.setStopButtonEnable(false);
     return;
    } 

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

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

    ctrlPanel.setTipStyle(style);
   }
  } 

  //检查画布中是否有全填满的行,如果有就删之
  public void checkFullLine() {
   for (int i = 0; i < canvas.getRows(); i++) {
    int row = -1;
    boolean fullLineColorBox = true;
    for (int j = 0; j < canvas.getCols(); j++) {
     if (!canvas.getBox(i, j).isColorBox()) {
      fullLineColorBox = false;
      break;
     }
    }
    if (fullLineColorBox) {
     row = i--;
     canvas.removeLine(row);
    }
   }
  } 

  //根据最顶行是否被占,判断游戏是否已经结束了
  //@return boolean ,true-游戏结束了,false-游戏未结束
  private boolean isGameOver() {
   for (int i = 0; i < canvas.getCols(); i++) {
    ErsBox box = canvas.getBox(0, i);
    if (box.isColorBox()) {
     return true;
    }
   }
   return false;
  }
 } 

 /**
  * 定义GameOver对话框。
  */
 @SuppressWarnings("serial")
 private class gameOverDialog extends JDialog implements ActionListener { 

  private JButton againButton, exitButton;
  private Border border = new EtchedBorder(EtchedBorder.RAISED, Color.white, new Color(148, 145, 140)); 

  public gameOverDialog(JFrame parent, String title, String message) {
   super(parent, title, true);
   if (parent != null) {
    setSize(240, 120);
    this.setLocationRelativeTo(parent);
    JPanel messagePanel = new JPanel();
    messagePanel.add(new JLabel(message));
    messagePanel.setBorder(border);
    Container container = this.getContentPane();
    container.setLayout(new GridLayout(2, 0, 0, 10));
    container.add(messagePanel);
    JPanel choosePanel = new JPanel();
    choosePanel.setLayout(new GridLayout(0, 2, 4, 0));
    container.add(choosePanel);
    againButton = new JButton("再玩一局");
    exitButton = new JButton("退出游戏");
    choosePanel.add(new JPanel().add(againButton));
    choosePanel.add(new JPanel().add(exitButton));
    choosePanel.setBorder(border);
   }
   againButton.addActionListener(this);
   exitButton.addActionListener(this);
   this.setVisible(true);
  } 

  @Override
  public void actionPerformed(ActionEvent e) {
   if (e.getSource() == againButton) {
    this.setVisible(false);
    reset();
   } else if (e.getSource() == exitButton) {
    stopGame();
    System.exit(0); 

   }
  }
 }
} 

GameCanvas.java

package RussiaBlocksGame; 

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder; 

/**
 * 画布类,内有<行数>*<列数> 个方格类实例。 继承自JPanel类。 ErsBlock线程类动态改变画布类的方格颜色,画布类通过
 * 检查方格颜色来体现ErsBlock块的移动情况。
 */
public class GameCanvas extends JPanel { 

private static final long serialVersionUID = 6732901391026089276L;
private Color backColor = Color.darkGray, frontColor = Color.WHITE;
 private int rows, cols, score = 0, scoreForLevelUpdate = 0;
 private ErsBox[][] boxes;
 private int boxWidth, boxHeight; 

 /**
  * 画布类的构造函数
  *
  * @param rows int,画布的行数
  * @param cols int,画布的列数 行数和列数决定着画布拥有方格的数目
  */
 public GameCanvas(int rows, int cols) {
  this.rows = rows;
  this.cols = cols; 

  boxes = new ErsBox[rows][cols];
  for (int i = 0; i < boxes.length; i++) {
   for (int j = 0; j < boxes[i].length; j++) {
    boxes[i][j] = new ErsBox(false);
   }
  } 

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

 /**
  * 画布类的构造函数
  *
  * @param rows
  * @param cols
  * @param backColor
  * @param frontColor
  */
 public GameCanvas(int rows, int cols,
   Color backColor, Color frontColor) {
  this(rows, cols);
  this.backColor = backColor;
  this.frontColor = frontColor;
 } 

 /**
  * 设置游戏背景色彩
  *
  * @param backColor Color,背景色彩
  */
 public void setBackgroundColor(Color backColor) {
  this.backColor = backColor;
 } 

 /**
  * 取得游戏背景色彩
  *
  * @return Color ,背景色彩
  */
 public Color getBackgroundColor() {
  return backColor;
 } 

 /**
  * 设置游戏方块颜色
  *
  * @param frontColor Color,方块颜色
  */
 public void setBlockColor(Color frontColor) {
  this.frontColor = frontColor;
 } 

 /**
  * 取得游戏方块色彩
  *
  * @return Color,方块颜色
  */
 public Color getBlockColor() {
  return frontColor;
 } 

 /**
  * 取得画布中方格的行数
  *
  * @return
  */
 public int getRows() {
  return rows;
 } 

 /**
  * 取得画布中方格的列数
  *
  * @return int,方格的列数
  */
 public int getCols() {
  return cols;
 } 

 /**
  * 取得游戏成绩
  *
  * @return int, 分数
  */
 public int getScore() {
  return score;
 } 

 /**
  * 取得自上一次升级后的积分
  *
  * @return int ,上一次升级后的积分
  */
 public int getScoreForLevelUpdate() {
  return scoreForLevelUpdate;
 } 

 /**
  * 升级后,将上一次升级以来的积分清零
  */
 public void resetScoreForLevelUpdate() {
  scoreForLevelUpdate -= RussiaBlocksGame.PER_LEVEL_SCORE;
 } 

 /**
  * 得到某一行某一列的方格引用
  *
  * @return row int ,要引用的方格所在的行
  * @param col int, 要引用的方格所在的行
  * @return ErsBox,在row行col列的方格的引用
  */
 public ErsBox getBox(int row, int col) {
  if (row < 0 || row > boxes.length - 1 || col < 0 || col > boxes[0].length - 1) {
   return null;
  }
  return (boxes[row][col]);
 } 

 /**
  * 覆盖JComponent类的函数,画组件。
  *
  * @param g 图形设备环境
  */
 @Override
 public void paintComponent(Graphics g) {
  super.paintComponent(g); 

  g.setColor(frontColor);
  for (int i = 0; i < boxes.length; i++) {
   for (int j = 0; j < boxes[i].length; j++) {
    g.setColor(boxes[i][j].isColorBox() ? frontColor : backColor);
    g.fill3DRect(j * boxWidth, i * boxHeight,
      boxWidth, boxHeight, true);
   }
  }
 } 

 /**
  * 根据窗口大小,自动调节方格的尺寸
  */
 public void adjust() {
  boxWidth = getSize().width / cols;
  boxHeight = getSize().height / rows;
 } 

 /**
  * 当一行被游戏者叠满后,将此行清除,并为游戏者加分
  *
  * @param row int,要清除的行,是由ErsBoxesGame类计算的
  */
 public synchronized void removeLine(int row) {
  for (int i = row; i > 0; i--) {
   for (int j = 0; j < cols; j++) {
    boxes[i][j] = (ErsBox) boxes[i - 1][j].clone();     //将上一行的方块颜色克隆下来,
   }                 //即消去一行方块
  } 

  score += RussiaBlocksGame.PER_LEVEL_SCORE;
  scoreForLevelUpdate += RussiaBlocksGame.PER_LEVEL_SCORE;
  repaint();
 } 

 /**
  * 重置画布,置积分为零
  */
 public void reset() {
  score = 0;
  scoreForLevelUpdate = 0;
  for (int i = 0; i < boxes.length; i++) {
   for (int j = 0; j < boxes[i].length; j++) {
    boxes[i][j].setColor(false);
   }
  } 

  repaint();
 }
} 

ControlPanel.java

package RussiaBlocksGame; 

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date; 

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder; 

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

private static final long serialVersionUID = 3900659640646175724L;
private JTextField tfLevel = new JTextField("" + RussiaBlocksGame.DEFAULT_LEVEL),
   tfScore = new JTextField(" 0"),
   tfTime = new JTextField(" ");
 private JButton btPlay = new JButton(" 开始"),
   btPause = new JButton(" 暂停"),
   btStop = new JButton("终止游戏"),
   btTurnLevelUp = new JButton(" 增加难度"),
   btTurnLevelDown = new JButton(" 降低难度");
 private JPanel plTip = new JPanel(new BorderLayout());
 private TipPanel plTipBlock = new TipPanel();
 private JPanel plInfo = new JPanel(new GridLayout(4, 1));
 private JPanel plButton = new JPanel(new GridLayout(6, 1));
 private Timer timer;
 private Border border = new EtchedBorder(EtchedBorder.RAISED, Color.white, new Color(148, 145, 140)); 

 /**
  * 控制面板类的构造函数
  *
  * @param game ErsBlocksGame,ErsBlocksGame 类的一个实例引用 方便直接控制ErsBlocksGame类的行为。
  */
 public ControlPanel(final RussiaBlocksGame game) {
  setLayout(new GridLayout(3, 1, 0, 2));
  plTip.add(new JLabel(" 下一个方块"), BorderLayout.NORTH);    //添加组件
  plTip.add(plTipBlock);
  plTip.setBorder(border); 

  plInfo.add(new JLabel(" 难度系数"));
  plInfo.add(tfLevel);
  plInfo.add(new JLabel(" 得分"));
  plInfo.add(tfScore);
  plInfo.setBorder(border); 

  plButton.add(btPlay);
  btPlay.setEnabled(true);
  plButton.add(btPause);
  btPause.setEnabled(false);
  plButton.add(btStop);
  btStop.setEnabled(false);
  plButton.add(btTurnLevelUp);
  plButton.add(btTurnLevelDown);
  plButton.add(tfTime);
  plButton.setBorder(border); 

  tfLevel.setEditable(false);
  tfScore.setEditable(false);
  tfTime.setEditable(false); 

  add(plTip);
  add(plInfo);
  add(plButton); 

  addKeyListener(new KeyAdapter() {
   @Override
   public void keyPressed(KeyEvent ke) {
    if (!game.isPlaying()) {
     return;
    } 

    ErsBlock block = game.getCurBlock();
    switch (ke.getKeyCode()) {
     case KeyEvent.VK_DOWN:
      block.moveDown();
      break;
     case KeyEvent.VK_LEFT:
      block.moveLeft();
      break;
     case KeyEvent.VK_RIGHT:
      block.moveRight();
      break;
     case KeyEvent.VK_UP:
      block.turnNext();
      break;
     default:
      break;
    }
   }
  }); 

  btPlay.addActionListener(new ActionListener() {       //开始游戏
   @Override
   public void actionPerformed(ActionEvent ae) {
    game.playGame();
   }
  });
  btPause.addActionListener(new ActionListener() {      //暂停游戏
   @Override
   public void actionPerformed(ActionEvent ae) {
    if (btPause.getText().equals(" 暂停")) {
     game.pauseGame();
    } else {
     game.resumeGame();
    }
   }
  });
  btStop.addActionListener(new ActionListener() {       //停止游戏
   @Override
   public void actionPerformed(ActionEvent ae) {
    game.stopGame();
   }
  });
  btTurnLevelUp.addActionListener(new ActionListener() {     //升高难度
   @Override
   public void actionPerformed(ActionEvent ae) {
    try {
     int level = Integer.parseInt(tfLevel.getText());
     if (level < RussiaBlocksGame.MAX_LEVEL) {
      tfLevel.setText("" + (level + 1));
     }
    } catch (NumberFormatException e) {
    }
    requestFocus();
   }
  });
  btTurnLevelDown.addActionListener(new ActionListener() {    //降低游戏难度
   @Override
   public void actionPerformed(ActionEvent ae) {
    try {
     int level = Integer.parseInt(tfLevel.getText());
     if (level > 1) {
      tfLevel.setText("" + (level - 1));
     }
    } catch (NumberFormatException e) {
    }
    requestFocus();
   }
  }); 

  addComponentListener(new ComponentAdapter() {
   @Override
   public void componentResized(ComponentEvent ce) {
    plTipBlock.adjust();
   }
  }); 

  timer = new Timer(1000, new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent ae) {
    DateFormat format = new SimpleDateFormat("时间:HH:mm:ss");  //系统获得时间
    Date date = new Date();
    tfTime.setText(format.format(date)); 

    tfScore.setText("" + game.getScore());
    int ScoreForLevelUpdate = //判断当前分数是否能升级
      game.getScoreForLevelUpdate();
    if (ScoreForLevelUpdate >= RussiaBlocksGame.PER_LEVEL_SCORE
      && ScoreForLevelUpdate > 0) {
     game.levelUpdate();
    }
   }
  });
  timer.start();
 } 

 /**
  * 设置预显窗口的样式
  *
  * @param style int,对应ErsBlock类的STYLES中的28个值
  */
 public void setTipStyle(int style) {
  plTipBlock.setStyle(style);
 } 

 /**
  * 取得用户设置的游戏等级。
  *
  * @return int ,难度等级,1-ErsBlocksGame.MAX_LEVEL
  */
 public int getLevel() {
  int level = 0;
  try {
   level = Integer.parseInt(tfLevel.getText());
  } catch (NumberFormatException e) {
  }
  return level;
 } 

 /**
  * 让用户修改游戏难度等级。
  *
  * @param level 修改后的游戏难度等级
  */
 public void setLevel(int level) {
  if (level > 0 && level < 11) {
   tfLevel.setText("" + level);
  }
 } 

 /**
  * 设置“开始”按钮的状态。
  */
 public void setPlayButtonEnable(boolean enable) {
  btPlay.setEnabled(enable);
 } 

 public void setPauseButtonEnable(boolean enable) {
  btPause.setEnabled(enable);
 } 

 public void setPauseButtonLabel(boolean pause) {
  btPause.setText(pause ? " 暂停" : " 继续");
 } 

 public void setStopButtonEnable(boolean enable) {
  btStop.setEnabled(enable);
 } 

 public void setTurnLevelUpButtonEnable(boolean enable) {
  btTurnLevelUp.setEnabled(enable);
 } 

 public void setTurnLevelDownButtonEnable(boolean enable) {
  btTurnLevelDown.setEnabled(enable);
 } 

 /**
  * 重置控制面板
  */
 public void reset() {
  tfScore.setText(" 0");
  plTipBlock.setStyle(0);
 } 

 /**
  * 重新计算TipPanel里的boxes[][]里的小框的大小
  */
 public void adjust() {
  plTipBlock.adjust();
 } 

 /**
  * 预显窗口的实现细节类
  */
public class TipPanel extends JPanel {         //TipPanel用来显示下一个将要出现方块的形状 

private static final long serialVersionUID = 5160553671436997616L;
private Color backColor = Color.darkGray, frontColor = Color.WHITE;
  private ErsBox[][] boxes = new ErsBox[ErsBlock.BOXES_ROWS][ErsBlock.BOXES_COLS];
  private int style, boxWidth, boxHeight;
  private boolean isTiled = false; 

  /**
   * 预显示窗口类构造函数
   */
  public TipPanel() {
   for (int i = 0; i < boxes.length; i++) {
    for (int j = 0; j < boxes[i].length; j++) {
     boxes[i][j] = new ErsBox(false);
    }
   }
  } 

  /**
   * 设置预显示窗口的方块样式
   *
   * @param style int,对应ErsBlock类的STYLES中的28个值
   */
  public void setStyle(int style) {
   this.style = style;
   repaint();
  } 

  /**
   * 覆盖JComponent类的函数,画组件。
   *
   * @param g 图形设备环境
   */
  @Override
  public void paintComponent(Graphics g) {
   super.paintComponent(g); 

   if (!isTiled) {
   adjust();
   } 

   int key = 0x8000;
   for (int i = 0; i < boxes.length; i++) {
    for (int j = 0; j < boxes[i].length; j++) {
     Color color = ((key & style) != 0 ? frontColor : backColor);
     g.setColor(color);
     g.fill3DRect(j * boxWidth, i * boxHeight,
       boxWidth, boxHeight, true);
     key >>= 1;
    }
   }
  } 

  /**
   * g根据窗口的大小,自动调整方格的尺寸
   */
  public void adjust() {
   boxWidth = getSize().width / ErsBlock.BOXES_COLS;
   boxHeight = getSize().height / ErsBlock.BOXES_ROWS;
   isTiled = true;
  }
 }
}

ErsBox.java

package RussiaBlocksGame; 

import java.awt.Dimension; 

/**
 * 方格类,是组成块的基本元素,用自己的颜色来表示块的外观
 */
public class ErsBox implements Cloneable { 

 private boolean isColor;
 private Dimension size = new Dimension(); 

 /**
  * 方格类的构造函数,
  *
  * @param isColor 是不是用前景色来为此方格着色 true前景色,false 用背景色
  */
 public ErsBox(boolean isColor) {
  this.isColor = isColor;
 } 

 /**
  * 此方格是不是用前景色表现
  *
  * @return boolean ,true用前景色表现,false 用背景色表现
  */
 public boolean isColorBox() {
  return isColor;
 } 

 /**
  * 设置方格的颜色,
  *
  * @param isColor boolean ,true用前景色表现,false 用背景色表现
  */
 public void setColor(boolean isColor) {
  this.isColor = isColor;
 } 

 /**
  * 得到此方格的尺寸
  *
  * @return Dimension ,方格的尺寸
  */
 public Dimension getSize() {
  return size;
 } 

 /**
  * 设置方格的尺寸,
  *
  * @param size Dimension ,方格的尺寸
  */
 public void setSize(Dimension size) {
  this.size = size;
 } 

 /**
  * 覆盖Object的Object clone(),实现克隆
  *
  * @return Object,克隆的结果
  */
 @Override
 public Object clone() {
  Object cloned = null;
  try {
   cloned = super.clone();
  } catch (Exception ex) {
   ex.printStackTrace();
  } 

  return cloned;
 }
}

ErsBlock.java

package RussiaBlocksGame; 

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

class ErsBlock extends Thread { 

 /**
  * 一个块占的行数是4行
  */
 public final static int BOXES_ROWS = 4;
 /**
  * 一个块占的列数是4列
  */
 public final static int BOXES_COLS = 4;
 /**
  * 让升级变化平滑的因子,避免最后几级之间的速度相差近一倍
  */
 public final static int LEVEL_FLATNESS_GENE = 3;
 /**
  * 相近的两级之间,块每下落一行的时间差别为多少(毫秒)
  */
 public final static int BETWEEN_LEVELS_DEGRESS_TIME = 50;
 /**
  * 方块的样式数目为7
  */
 public final static int BLOCK_KIND_NUMBER = 7;
 /**
  * 每一个样式的方块的反转状态种类为4
  */
 public final static int BLOCK_STATUS_NUMBER = 4;
 /**
  * 分别对应7种模型的28种状态
  */
 public final static int[][] STYLES = { //共28种状态
  {0x0f00, 0x4444, 0x0f00, 0x4444}, //长条型的四种状态
  {0x04e0, 0x0464, 0x00e4, 0x04c4}, //T型的四种状态
  {0x4620, 0x6c00, 0x4620, 0x6c00}, //反Z型的四种状态
  {0x2640, 0xc600, 0x2640, 0xc600}, //Z型的四种状态
  {0x6220, 0x1700, 0x2230, 0x0740}, //7型的四种状态
  {0x6440, 0x0e20, 0x44c0, 0x8e00}, //反7型的四种状态
  {0x0660, 0x0660, 0x0660, 0x0660}, //方块的四种状态
 };
 private GameCanvas canvas;
 private ErsBox[][] boxes = new ErsBox[BOXES_ROWS][BOXES_COLS];
 private int style, y, x, level;
 private boolean pausing = false, moving = true; 

 /**
  * 构造函数,产生一个特定的块
  *
  * @param style 块的样式,对应STYLES的28个值中的一个
  * @param y 起始位置,左上角在canvas中的坐标行
  * @param x 起始位置,左上角在canvas中的坐标列
  * @param level 游戏等级,控制块的下落速度
  * @param canvas 画板
  */
 public ErsBlock(int style, int y, int x, int level, GameCanvas canvas) {
  this.style = style;
  this.y = y;
  this.x = x;
  this.level = level;
  this.canvas = canvas; 

  int key = 0x8000;
  for (int i = 0; i < boxes.length; i++) {
   for (int j = 0; j < boxes[i].length; j++) {
    boolean isColor = ((style & key) != 0);
    boxes[i][j] = new ErsBox(isColor);
    key >>= 1;
   }
  } 

  display();
 } 

 /**
  * 线程类的run()函数覆盖,下落块,直到块不能再下落
  */
 @Override
 public void run() {
  while (moving) {
   try {
    sleep(BETWEEN_LEVELS_DEGRESS_TIME
      * (RussiaBlocksGame.MAX_LEVEL - level + LEVEL_FLATNESS_GENE));
   } catch (InterruptedException ie) {
    ie.printStackTrace();
   }
   //后边的moving是表示在等待的100毫秒间,moving没有被改变
   if (!pausing) {
    moving = (moveTo(y + 1, x) && moving);
   }
  }
 } 

 /**
  * 块向左移动一格
  */
 public void moveLeft() {
  moveTo(y, x - 1);
 } 

 /**
  * 块向右移动一格
  */
 public void moveRight() {
  moveTo(y, x + 1);
 } 

 /**
  * 块向下移动一格
  */
 public void moveDown() {
  moveTo(y + 1, x);
 } 

 /**
  * 块变型
  */
 public void turnNext() {
  for (int i = 0; i < BLOCK_KIND_NUMBER; i++) {
   for (int j = 0; j < BLOCK_STATUS_NUMBER; j++) {
    if (STYLES[i][j] == style) {
     int newStyle = STYLES[i][(j + 1) % BLOCK_STATUS_NUMBER];
     turnTo(newStyle);
     return;
    }
   }
  }
 } 

 public void startMove() {
  pausing = false;
  moving = true;
 } 

 /**
  * 暂停块的下落,对应游戏暂停
  */
 public void pauseMove() {
  pausing = true;
  // moving = false;
 } 

 /**
  * 继续块的下落,对应游戏继续
  */
 public void resumeMove() {
  pausing = false;
  moving = true;
 } 

 /**
  * 停止块的下落,对应游戏停止
  */
 public void stopMove() {
  pausing = false;
  moving = false;
 } 

 /**
  * 将当前块从画布的对应位置移除,要等到下次重画画布时才能反映出来
  */
 private void erase() {
  for (int i = 0; i < boxes.length; i++) {
   for (int j = 0; j < boxes[i].length; j++) {
    if (boxes[i][j].isColorBox()) {
     ErsBox box = canvas.getBox(i + y, j + x);
     if (box == null) {
      continue;
     }
     box.setColor(false);
    }
   }
  }
 } 

 /**
  * 让当前块放置在画布的对因位置上,要等到下次重画画布时才能看见
  */
 private void display() {
  for (int i = 0; i < boxes.length; i++) {
   for (int j = 0; j < boxes[i].length; j++) {
    if (boxes[i][j].isColorBox()) {
     ErsBox box = canvas.getBox(i + y, j + x);
     if (box == null) {
      continue;
     }
     box.setColor(true);
    }
   }
  }
 } 

 /**
  * 当前块能否移动到newRow/newCol 所指定的位置
  *
  * @param newRow int,目的地所在行
  * @param newCol int,目的地所在列
  * @return boolean,true-能移动,false-不能移动
  */
 public boolean isMoveAble(int newRow, int newCol) {
  erase();
  for (int i = 0; i < boxes.length; i++) {
   for (int j = 0; j < boxes[i].length; j++) {
    if (boxes[i][j].isColorBox()) {
     ErsBox box = canvas.getBox(i + newRow, j + newCol);
     if (box == null || (box.isColorBox())) {
      display();
      return false;
     }
    }
   }
  }
  display();
  return true;
 } 

 /**
  * 将当前块移动到newRow/newCol 所指定的位置
  *
  * @param newRow int,目的地所在行
  * @param newCol int,目的地所在列
  * @return boolean,true-移动成功,false-移动失败
  */
 private synchronized boolean moveTo(int newRow, int newCol) {
  if (!isMoveAble(newRow, newCol) || !moving) {
   return false;
  } 

  erase();
  y = newRow;
  x = newCol; 

  display();
  canvas.repaint(); 

  return true;
 } 

 /**
  * 当前块能否变成newStyle所指定的块样式,主要是考虑 边界以及被其他块挡住,不能移动的情况
  *
  * @param newSytle int,希望改变的块样式,对应STYLES的28个值中的一个
  * @return boolean,true-能改变,false-不能改变
  */
 private boolean isTurnAble(int newStyle) {
  int key = 0x8000;
  erase();
  for (int i = 0; i < boxes.length; i++) {
   for (int j = 0; j < boxes[i].length; j++) {
    if ((newStyle & key) != 0) {
     ErsBox box = canvas.getBox(i + y, j + x);
     if (box == null || (box.isColorBox())) {
      display();
      return false;
     }
    }
    key >>= 1;
   }
  }
  display();
  return true;
 } 

 /**
  * 将当前块变成newStyle所指定的块样式
  *
  * @param newStyle int,希望改变的块样式,对应STYLES的28个值中的一个
  * @return true-改变成功,false-改变失败
  */
 private boolean turnTo(int newStyle) {
  if (!isTurnAble(newStyle) || !moving) {
   return false;
  } 

  erase();
  int key = 0x8000;
  for (int i = 0; i < boxes.length; i++) {
   for (int j = 0; j < boxes[i].length; j++) {
    boolean isColor = ((newStyle & key) != 0);
    boxes[i][j].setColor(isColor);
    key >>= 1;
   }
  }
  style = newStyle; 

  display();
  canvas.repaint(); 

  return true;
 }
} 

Main.java

package RussiaBlocksGame; 

/**
 * 程序入口函数
 *
 * @param args String[],附带的命令行参数
 */ 

public class Main {
public static void main(String[] args) {
  new RussiaBlocksGame("俄罗斯方块:杨宇杰");
 }
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java实现微信小程序登录态维护的示例代码

    相信不少喜欢开发的朋友都已经知道微信小程序是个什么物种了,楼主也是从小程序内测期间就开始关注,并且也写过几个已经上线的微信小程序.但是基本上都是写的纯前端,最近楼主从后端到前端写一个完整的小程序项目,中间碰到了一些问题,楼主会找一些个人觉得有学习价值的点不定时的拿出来跟大家分享,希望对你有一些帮助. 本次就从最基本的微信小程序登录态维护开始吧.小程序官方api文档里面有对登录态的一个完整的解释,并且有相关的代码.想看详情,可以出门右转:https://mp.weixin.qq.com/debug

  • Java实现简单日历小程序 Java图形界面小日历开发

    今天给大家介绍一下如何用Java swing开发一款简单的小日历,下面我们来看代码: 首先创建一个CalendarBean类,用于基本的日期计算: package other1; import java.util.Calendar; public class CalendarBean { String day[]; int year=2005,month=0; public void setYear(int year) { this.year=year; } public int getYear

  • 拳皇(Java简单的小程序)代码实例

    刚开始学习Java,看完老九君的视频根据他的内容敲的代码,感觉还挺有成就感的,毕竟刚学习Java. package helloasd;import java.util.*; public class hellojava { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("输入名称: "); //用户自己输入名字 String userna

  • Java中基于Shiro,JWT实现微信小程序登录完整例子及实现过程

    小程序官方流程图如下,官方地址 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html : 本文是对接微信小程序自定义登录的一个完整例子实现 ,技术栈为 : SpringBoot+Shiro+JWT+JPA+Redis. 如果对该例子比较感兴趣或者觉得言语表达比较啰嗦,可查看完整的项目地址 : https://github.com/EalenXie/shiro-jwt-applet

  • java实现验证码小程序

    手动制作java的验证码,具体内容如下 Web应用验证码的组成: (1)输入框 (2)显示验证码的图片 验证码的制作流程: 生成验证码的容器使用 j2ee的servlet 生成图片需要的类: (1) BufferedImage 图像数据缓冲区 (2)Graphic绘制图片 (3)Color获取颜色 (4)Random生成随机数 (5)ImageIO输入图片 具体实现流程: (1)定义一个Servlet,用于生成验证码 (2)定已BufferedImage对象,主要作用就是制作一个图片缓冲区,作为

  • 微信小程序调用微信登陆获取openid及java做为服务端示例

    一.微信小程序 第一步:调用 wx.login获取code 文档地址 第二步:判断用户是否授权读取用户信息 文档地址 第三步:调用wx.getUserInfo读取用户数据 文档地址 第四步:由于小程序后台授权域名无法授权微信的域名,所以我们只能通过我们自己的服务器去调用微信服务器去获取用户信息,故我们将wx.login获取code 和 wx.getUserInfo 获取的encryptedData与iv 通过wx.request 请求传入后台 服务器返回的数据: 小程序代码: //调用登录接口,

  • Java解密微信小程序手机号的方法

    本文实例为大家分享了Java解密微信小程序手机号的具体代码,供大家参考,具体内容如下 第一步:创建AES解密工具类:代码如下 import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySp

  • 用Java编写经典小程序

    如果是刚接触或者刚学习java,练习一些基础的算法还是必须的,可以提升思维和语法的使用 1.输出两个int数中的最大值 import java.util.Scanner; public class demo { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请依次输入两个整数:a,b(以空格隔开)"); /*比较两个数的大小*/

  • Java实现表白小程序

    今天闲来无事,教大家一个哄妹子的小case.我们需要创建一个心形图案,按照心形图案的位置和长度,对所创建的字符串进行截断并在所需的位置上输出,最终能呈现在屏幕上满满的爱心.废话不多说,直接上源码看效果 ~ package ddd; import java.awt.*; import javax.swing.JFrame; public class Cardioid extends JFrame { //获取屏幕大小 private static final int WIDTH = 500; pr

  • java实现俄罗斯方块小程序

    这是java课最后做的课程设计,由于java是初学的,所以做的时候有参考一些技术大牛的博客,在此表示感谢. 发在这里跟大家交流学习一下. 如需要完整工程文件.说明文档以及可运行jar文件,下载地址:点击打开链接 RussianBlocksGame.java package RussiaBlocksGame; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.Bor

  • Java实现俄罗斯方块小游戏源码

    本文实例为大家分享了Java实现俄罗斯方块小游戏的具体代码,供大家参考,具体内容如下 一.最终效果 二.功能需求 1. 在二维平面里面用各种随机产生的方块堆积木,每满一行消去一行,当达到顶部时,游戏结束.2. 通过方向键来控制方块转动,左移,右移和直落.3. 方块下落统一设置蓝色,接触底部变粉色.4. 计算分数,分数是由方块的类型决定的,每堆积一个方块就把分数累加到总分中.5. 游戏有开始.重新开始.降低提高级数(速度).暂停.退出 三.程序实现 这个是最基础的方块素材 package 俄罗斯方

  • java与微信小程序实现websocket长连接

    本文实例为大家分享了java与微信小程序实现websocket长连接的具体代码,供大家参考,具体内容如下 背景: 需要在小程序实现地图固定坐标下实时查看消息 java环境 :tomcat7 jdk1.7 1.java websocket 类 package com.qs.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.

  • java实现微信小程序加密数据解密算法

    一.概述 微信推出了小程序,很多公司的客户端应用不仅具有了APP.H5.还接入了小程序开发.但是,小程序中竟然没有提供Java版本的加密数据解密算法.这着实让广大的Java开发人员蛋疼. 微信小程序提供的加密数据解密算法链接 我们下载的算法示例如下: 木有Java!! 木有Java!! 木有Java!! 那么如何解决这个问题,我们一起来实现Java版本的微信小程序加密数据解密算法. 二.实现Java版本的微信小程序加密数据解密算法 1.创建项目 这里,我们创建一个Maven工程,具体创建步骤略.

  • java实现发牌小程序

    本文实例为大家分享了java实现发牌小程序的具体代码,供大家参考,具体内容如下 关键字:掌握Java数组.方法的基本定义 内容要求: 编写程序,项目名和类名均为PokerGame. 实现功能: (1) 共有m幅扑克牌,每幅扑克牌不包括大王和小王共52张牌. (2) 可能有n个人参与扑克游戏,2<=n<=52. (3) 程序运行时输入扑克牌幅数m和人数n,然后所有牌分别依次分发给n个人.不能整除时,每个人的牌数可以不同,如3个人1幅牌,则第1个人18张,第2个和第3个人17张牌. (4) 发牌完

  • Java点餐小程序之黑心商人

    很久以前,有一个女人,开了一家酒店,她的名字叫孙二娘.下面是她找人做的点餐小程序.代码如下: import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.ArrayList; import java.util.Scanner; import java.util.Set; public class MyDianCai { sta

  • java遇到微信小程序 "支付验证签名失败" 问题解决

    最近在做一个微信小程序项目做到微信支付的时候遇到的一些问题! 详细步骤: 开发前准备(必须) 小程序标识(appid):wx4d4838ebec29b8** 商户号(mch_id):15508070** 商户密钥(key) :wHtQckdfiRBVF7ceGTcSWEEORt6C0D** 我们用微信官方提供的SDK开发 :https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1 下载 SDK完成后 : 开始写我们的程 进入微信

随机推荐