📄 tetrics.java
字号:
package tetrics;
import java.awt.*;
import javax.swing.*;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
public class Tetrics
extends JPanel
implements Runnable, KeyListener {
Thread m_theThread = null;
BorderLayout borderLayout1 = new BorderLayout();
final int XOFFSET = 200; //信息区大小
static int m_nCols;
static int m_nRows;
int m_nSqLength; //每个方块的大小
boolean m_bGameInPlay; // 判断当前游戏是不是正在玩
boolean m_bNeedNewPiece; // 判断当前是不是需要一个新的方块组
int m_nPlayLevel; // 游戏当前的级别
int m_nPieceValue = 0; // 当前方块组的分值
int m_nTheScore = 0; // 当前游戏的分数
Color m_colors[]; //定义一组颜色,为每个不同的方块组赋不同的颜色
int m_nDelayMap[] = {
600, 600, 600, 600, 500, 400, 300, 250, 200, 150, 100}; //定义一个数组,来定义每个级别的方块组移动的速度(每次移动之间的时间)
public static int NOSQUARE = 0; // 表征当前位置没有方块存在
Square m_curPiece[] = new Square[4]; // 游戏正在玩的方块组。我们将4个小方块组成的各种不同的方块组合叫做方块组
Square m_prePiece[] = new Square[4]; // 正在预览的方块组
int m_nField[][]; //表述整个游戏的当前状态的数组
int m_nOldField[][]; //表述整个游戏的状态刚刚改变之前的状态数组
int m_nTotalPieces; // 当前游戏已经玩过的方块组的个数
boolean m_bPaused = false; // 当前游戏是否已经暂停
TetricsFrame m_tFrame;
//private String m_nTheScore;
private boolean m_bJustupdating = false;
public Tetrics() {
super();
try {
jbInit();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
public Tetrics(TetricsFrame tFrame) {
super();
m_tFrame = tFrame;
try {
jbInit();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
void jbInit() throws Exception {
this.addKeyListener(this);
//设置初始参数
m_nSqLength = 20;
m_nCols = 10;
m_nRows = 20;
m_nField = new int[m_nCols][m_nRows + 4];
m_nOldField = new int[m_nCols][m_nRows + 4];
m_nPlayLevel = 5;
//定义8种颜色
m_colors = new Color[8];
m_colors[0] = new Color(40, 40, 40);
m_colors[1] = new Color(255, 0, 0);
m_colors[2] = new Color(0, 200, 0);
m_colors[3] = new Color(0, 200, 255);
m_colors[4] = new Color(255, 255, 0);
m_colors[5] = new Color(255, 150, 0);
m_colors[6] = new Color(210, 0, 240);
m_colors[7] = new Color(40, 0, 240);
//to initialize the m_prePiece;
this.setFont(new java.awt.Font("Dialog", 0, 18));
this.setLayout(borderLayout1);
this.setVisible(true);
}
public synchronized void paint(Graphics g) {
g.setFont(new Font("宋体", 0, 18));
int gx = m_nSqLength;
int gy = m_nSqLength * m_nRows / 4;
//打印Score和Level的位置
//g.clearRect(gx, gy - 25, XOFFSET - gx, 25);
g.drawString("Score:" + m_nTheScore, gx, gy);
gy += 30;
//g.clearRect(gx, gy - 25, XOFFSET - gx, 25);
g.drawString("Level:5", gx, gy);
//画预览的方块
int middle = m_nCols / 2;
int top = m_nRows;
gy += 30;
g.setColor(Color.black);
g.fillRect(gx, gy, m_nSqLength * 4, m_nSqLength * 4);
//画游戏区
if (m_bGameInPlay) {
for (int i = 0; i < 4; i++) {
g.setColor(m_colors[m_prePiece[i].m_nColor]);
g.fill3DRect( (m_prePiece[i].m_nColumn - middle + 2) * m_nSqLength + gx,
gy - (m_prePiece[i].m_nRow - top) * m_nSqLength,
m_nSqLength, m_nSqLength, true);
}
}
for (int i = 0; i < m_nCols; i++) {
for (int j = 0; j < m_nRows; j++) {
//-1代表没有刚刚开始
if (!m_bJustupdating || m_nOldField[i][m_nRows - 1 - j] == -1 ||
m_nOldField[i][m_nRows - 1 - j] != m_nField[i][m_nRows - 1 - j]) {
g.setColor(m_colors[m_nField[i][m_nRows - 1 - j]]);
g.fill3DRect(XOFFSET + m_nSqLength * i, m_nSqLength + m_nSqLength * j,
m_nSqLength, m_nSqLength, true);
}
m_nOldField[i][m_nRows - 1 - j] = m_nField[i][m_nRows - 1 - j];
}
}
m_bJustupdating = false;
}
public void update(Graphics g)
{
m_bJustupdating=true;
paint(g);
}
private void newPrePiece() {
int middle = m_nCols / 2;
int top = m_nRows;
switch ( (int) (Math.random() * 7)) {
case 0:
//红色方块组
m_nPieceValue = 100;
m_prePiece[0] = new Square(middle - 1, top - 1, 1);
m_prePiece[1] = new Square(middle - 2, top - 1, 1);
m_prePiece[2] = new Square(middle, top - 1, 1);
m_prePiece[3] = new Square(middle + 1, top - 1, 1);
break;
case 1:
//桔红色方块组
m_nPieceValue = 200;
m_prePiece[0] = new Square(middle, top - 2, 5);
m_prePiece[1] = new Square(middle, top - 1, 5);
m_prePiece[2] = new Square(middle - 1, top - 2, 5);
m_prePiece[3] = new Square(middle + 1, top - 2, 5);
break;
case 2:
//绿色方块组
m_nPieceValue = 180;
m_prePiece[0] = new Square(middle, top - 2, 2);
m_prePiece[1] = new Square(middle - 1, top - 1, 2);
m_prePiece[2] = new Square(middle, top - 1, 2);
m_prePiece[3] = new Square(middle + 1, top - 2, 2);
break;
case 3:
//蓝色方块组
m_nPieceValue = 180;
m_prePiece[0] = new Square(middle, top - 2, 7);
m_prePiece[1] = new Square(middle + 1, top - 1, 7);
m_prePiece[2] = new Square(middle, top - 1, 7);
m_prePiece[3] = new Square(middle - 1, top - 2, 7);
break;
case 4:
//浅蓝色方块组
m_nPieceValue = 100;
m_prePiece[0] = new Square(middle - 1, top - 1, 3);
m_prePiece[1] = new Square(middle, top - 1, 3);
m_prePiece[2] = new Square(middle - 1, top - 2, 3);
m_prePiece[3] = new Square(middle, top - 2, 3);
break;
case 5:
//洋红色方块组
m_nPieceValue = 120;
m_prePiece[0] = new Square(middle, top - 1, 6);
m_prePiece[1] = new Square(middle - 1, top - 1, 6);
m_prePiece[2] = new Square(middle + 1, top - 1, 6);
m_prePiece[3] = new Square(middle + 1, top - 2, 6);
break;
case 6:
//黄色方块组
m_nPieceValue = 120;
m_prePiece[0] = new Square(middle, top - 1, 4);
m_prePiece[1] = new Square(middle + 1, top - 1, 4);
m_prePiece[2] = new Square(middle - 1, top - 1, 4);
m_prePiece[3] = new Square(middle - 1, top - 2, 4);
break;
}
}
/**
* 将预览的方块转变成正在动的方块
*/
private void transferPreToCur() {
Square old[] = new Square[4];
old[0] = old[1] = old[2] = old[3] = new Square( -1, -1, 0);
for (int i = 0; i < 4; i++) {
m_curPiece[i] = m_prePiece[i];
}
m_bGameInPlay = moveSquares(old, m_curPiece);
if (!m_bGameInPlay && m_tFrame != null) {
m_tFrame.insertScoreReport(m_nTheScore);
}
}
/**
* 移动方块,如果不能移动,则返回假
*/
boolean moveSquares(Square from[], Square to[]) {
//判断是否能移动
outerlable:
for (int i = 0; i < to.length; i++) {
if (to[i].InBounds() == false)return false;
//如果不在可玩区域,则返回假
if (m_nField[to[i].m_nColumn][to[i].m_nRow] != 0) {
for (int j = 0; j < from.length; j++)
if (to[i].IsEqual(from[j]))continue outerlable;
return false;
}
}
//移动
for (int i = 0; i < from.length; i++) {
if (from[i].InBounds()) {
m_nField[from[i].m_nColumn][from[i].m_nRow] = 0;
}
}
for (int i = 0; i < to.length; i++) {
m_nField[to[i].m_nColumn][to[i].m_nRow] = to[i].m_nColor;
}
return true;
}
/**
*移动方块
*@param nDx 左右移动,向左为-1
*@param nDy 上下移动,向下为-1
*@param bRotate 是否转动
*/
private synchronized boolean moveCurPiece(int nDx, int nDy, boolean bRotate) {
Square newpos[] = new Square[4];
for (int i = 0; i < 4; i++) {
//如果转动的话,则转动方块组
if (bRotate) {
int dx = m_curPiece[i].m_nColumn - m_curPiece[0].m_nColumn;
int dy = m_curPiece[i].m_nRow - m_curPiece[0].m_nRow;
newpos[i] = new
Square(m_curPiece[0].m_nColumn - dy, m_curPiece[0].m_nRow + dx,
m_curPiece[i].m_nColor);
}
else {
newpos[i] = new
Square(m_curPiece[i].m_nColumn + nDx, m_curPiece[i].m_nRow + nDy,
m_curPiece[i].m_nColor);
}
}
//调用上面提到的方法
if (moveSquares(m_curPiece, newpos) == false) {
return false;
}
m_curPiece = newpos;
return true;
}
//去掉可以消去的行
private void removelines() {
outerlabel:
for (int j = 0; j < m_nRows; j++) {
for (int i = 0; i < m_nCols; i++) {
if (m_nField[i][j] == 0) {
continue outerlabel;
}
}
for (int k = j; k < m_nRows - 1; k++) {
for (int i = 0; i < m_nCols; i++) {
m_nField[i][k] = m_nField[i][k + 1];
}
}
j -= 1;
}
}
public void run() {
while (m_bGameInPlay) {
try {
int t;
//取得要暂停的时间,这个决定着游戏的速度
if (m_nPlayLevel > 10) {
t = 75;
}else {
t = m_nDelayMap[m_nPlayLevel];
}
Thread.sleep(t);
}
catch (InterruptedException e) {
e.printStackTrace();
}
if (m_bNeedNewPiece){
if (m_nPieceValue > 0) {
//计算分数
m_nTheScore += m_nPieceValue;
m_nTotalPieces += 1;
if (m_nTotalPieces % 30 == 0) {
m_nPlayLevel++;
}
}
//消去一行
removelines();
transferPreToCur();
newPrePiece();
m_bNeedNewPiece = false;
}
else {
m_bNeedNewPiece = !moveCurPiece(0, -1, false);
if (!m_bNeedNewPiece) {
m_nPieceValue -= 5;
}
}
this.update(this.getGraphics());
}
m_theThread = null;
}
public synchronized void start() {
requestFocus();
if (m_theThread != null)//游戏是被暂停,而不是重新开始
{
m_bPaused = false;
// m_theThread.
m_theThread.resume();
this.repaint();
return;
}
//重新开始赋上游戏的状态
for (int i = 0; i < m_nCols; i++) {
for (int j = 0; j < m_nRows + 4; j++) {
m_nField[i][j] = 0;
m_nOldField[i][j] = -1;
}
}
m_nTheScore = 0;
m_nTotalPieces = 0;
m_bNeedNewPiece = true;
m_bGameInPlay = true;
m_theThread = new Thread(this);
newPrePiece();
m_theThread.start();
this.repaint();
//requestFocus();
}
public synchronized void pause() {
if (m_theThread != null) {
try {
m_theThread.suspend();
m_bPaused = true;
}
catch (Exception e) {
e.printStackTrace();
}
}
}
public synchronized void stop() {
if (m_theThread != null) {
//m_theThread.destroy();
m_theThread.stop();
}
m_theThread = null;
}
public void setPlayLevel(int nLevel) {
m_nPlayLevel = nLevel;
// System.out.println("m_nPlayLevel="+m_nPlayLevel);
Graphics g = getGraphics();
//g.setFont(new Font("宋体", 0, 18));
int gx = m_nSqLength;
int gy = m_nSqLength * m_nRows / 4 + 30;
g.clearRect(gx, gy - 25, XOFFSET - gx, 25);
g.drawString("Level:" + m_nPlayLevel, gx, gy);
// System.out.println("paint m_nPlayLevel="+m_nPlayLevel);
}
public int getPlayLevel() {
return m_nPlayLevel;
}
public void keyTyped(KeyEvent e) {
int nKeyCode = e.getKeyChar();
switch (nKeyCode) {
case 97:
moveCurPiece( -1, 0, false);
m_bNeedNewPiece = false;
this.update(this.getGraphics());
break;
case 115:
while (moveCurPiece(0, -1, false)) {
;
}
this.update(this.getGraphics());
break;
case 100:
moveCurPiece(1, 0, false);
m_bNeedNewPiece = false;
this.update(this.getGraphics());
break;
case 119:
moveCurPiece(0, 0, true);
this.update(this.getGraphics());
break;
}
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -