📄 ersblocksgame.java
字号:
if (box.isColorBox()) return true;
}
return false;
}
}
//程序入口函数, @param args String[], 附带的命令行参数
public static void main(String[] args) {
new ErsBlocksGame("俄罗斯方块");
}
}
/**
* 画布类,内有<行数> * <列数>个方格类实例。
* 继承自JPanel类。
* ErsBlock线程类动态改变画布类的方格颜色,画布类通过
* 检查方格颜色来体现ErsBlock块的移动情况。
*/
class GameCanvas extends JPanel {
private Color backColor = Color.black, frontColor = Color.orange;
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 与public GameCanvas(int rows, int cols)同
* @param cols 与public GameCanvas(int rows, int cols)同
* @param backColor Color, 背景色
* @param frontColor Color, 前景色
*/
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 int, 方格的行数
*/
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;
}
/**
* 升级后,将上一次升级以来的积分清0
*/
public void resetScoreForLevelUpdate() {
scoreForLevelUpdate -= ErsBlocksGame.PER_LEVEL_SCORE;
}
/**
* 得到某一行某一列的方格引用。
* @param 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 图形设备环境
*/
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 fanning() {
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 += ErsBlocksGame.PER_LINE_SCORE;
scoreForLevelUpdate += ErsBlocksGame.PER_LINE_SCORE;
repaint();
}
/**
* 重置画布,置积分为0
*/
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();
}
}
/**
* 方格类,是组成块的基本元素,用自己的颜色来表示块的外观
*/
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,克隆的结果
*/
public Object clone() {
Object cloned = null;
try {
cloned = super.clone();
} catch (Exception ex) {
ex.printStackTrace();
}
return cloned;
}
}
/**
* 块类,继承自线程类(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
*/
private final static int BLOCK_KIND_NUMBER = 7;
/**
* 每一个样式的方块的反转状态种类为4
*/
private 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()函数覆盖,下落块,直到块不能再下落
*/
public void run() {
while (moving) {
try {
sleep(BETWEEN_LEVELS_DEGRESS_TIME
* (ErsBlocksGame.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 pauseMove() {
pausing = true;
}
/**
* 继续块的下落,对应游戏继续
*/
public void resumeMove() {
pausing = false;
}
/**
* 停止块的下落,对应游戏停止
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -