主页附完整资源(俄罗斯方块.zip)
下面是代码和素材
utils包
package com.zdq.utils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
/**
* 静态资源加载工具类
*/
public class SourceUtil {
/**
* 静态图片资源
*/
public static BufferedImage iImage;
public static BufferedImage jImage;
public static BufferedImage lImage;
public static BufferedImage oImage;
public static BufferedImage sImage;
public static BufferedImage tImage;
public static BufferedImage zImage;
public static BufferedImage backgroundImage;
public static BufferedImage tetrisLogoImage;
/**
* 静态代码块,加载一次静态资源
*/
static {
/**
* ImageIO.read()方法可以读取项目下的静态资源文件
*/
try {
// iImage = ImageIO.read(SourceUtil.class.getResource("../image/I.png"));
iImage = ImageIO.read(SourceUtil.class.getResourceAsStream("/com/zdq/image/I.png"));
jImage = ImageIO.read(SourceUtil.class.getResourceAsStream("/com/zdq/image/J.png"));
lImage = ImageIO.read(SourceUtil.class.getResourceAsStream("/com/zdq/image/L.png"));
oImage = ImageIO.read(SourceUtil.class.getResourceAsStream("/com/zdq/image/O.png"));
sImage = ImageIO.read(SourceUtil.class.getResourceAsStream("/com/zdq/image/S.png"));
tImage = ImageIO.read(SourceUtil.class.getResourceAsStream("/com/zdq/image/T.png"));
zImage = ImageIO.read(SourceUtil.class.getResourceAsStream("/com/zdq/image/Z.png"));
backgroundImage = ImageIO.read(SourceUtil.class.getResourceAsStream("/com/zdq/image/background.png"));
tetrisLogoImage = ImageIO.read(SourceUtil.class.getResourceAsStream("/com/zdq/image/tetrisLogo.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
main包
(1)KeyActionListener
package com.zdq.main;
import com.zdq.domain.Cell;
import com.zdq.domain.TetrisModel;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Date;
/**
* 自定义行为动作监听器,实现人机交互
*/
public class KeyActionListener extends KeyAdapter implements ActionListener {
//统计消去行的个数
private int linesCount = 0;
//在类中创建一个 TetrisPanel对象,以便获取和更新方块对象
private TetrisPanel tetrisPanel;
//关卡级别: 默认为 1级
protected static int level = 1;
//当前分数
protected int score = 0;
//游戏暂停与继续切换标志
private boolean flag = true;
//控制下落速度:默认为 1000毫秒
protected int delay = 800;
protected Timer timer = new Timer(delay, this);
//开始游戏的时间
protected Date startTime;
//前面累计的游戏时间
protected long preGameTime;
public KeyActionListener(TetrisPanel tetrisPanel) {
this.tetrisPanel = tetrisPanel;
}
public KeyActionListener() {
}
/**
* 监听俄罗斯方块对象的动作
* @param e
*/
@Override
public void actionPerformed(ActionEvent e) {
// 获取当前方块对象,调用下落方法
boolean ifCanDrop = ifCanDrop();
if(ifCanDrop) {
//表示可以下落
tetrisPanel.currentBlock.moveDrop();
} else {
//表示不可下落,但是需要根据实际情况判断 游戏是否终止
if(ifGameOver()) {
//游戏结束,终止游戏,并给出友情提示
timer.stop();
int confirmDialog = JOptionPane.showConfirmDialog(null, "Game Over! 是否再来一局?");
if(confirmDialog == JOptionPane.YES_OPTION) {
//继续玩
// 初始化单元格,重启游戏
tetrisPanel.wall = new Cell[20][10];
preGameTime = 0;
score = 0;
delay = 800;
level = 0;
startTime = new Date();
timer.restart();
} else if(confirmDialog == JOptionPane.NO_OPTION) {
//不玩了,关闭程序即可
System.exit(0);
}
} else {
//游戏还未结束
//将方块定格在最后落下的位置
landToWall();
//判断是否可以消去一行,并执行
vanishLine();
//将下一个要下落的方块赋给当前要下落的方块
//再生成新的 下一个要下落的方块
//即 将下落和即将下落构成闭环,不断地落下方块
tetrisPanel.currentBlock = tetrisPanel.nextBlock;
tetrisPanel.nextBlock = TetrisModel.randomBlock();
}
}
//重新绘制画布
tetrisPanel.repaint();
}
/**
* 重写键盘监听器中的键盘键点击事件
* @param e ==
*/
@Override
public void keyPressed(KeyEvent e) {
//获取监听到的点击的键盘键
//此方法返回键盘上实际键的整数代码。
int keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_LEFT:
//按 ←键方块左移
if(flag) {
moveLeftAction();
//右移后重新绘制,移动则不会出现卡顿感
tetrisPanel.repaint();
}
break;
case KeyEvent.VK_RIGHT:
//按 →键方块右移
if(flag) {
moveRightAction();
//右移后重新绘制,移动则不会出现卡顿感
tetrisPanel.repaint();
}
break;
case KeyEvent.VK_DOWN:
//按 ↓键方块下移
if(flag) {
movePerformed(null);
}
break;
case KeyEvent.VK_UP:
//按 ↑键方块旋转
if(flag) {
moveRoteAction();
//右移后重新绘制,旋转则不会出现卡顿感
tetrisPanel.repaint();
}
break;
case KeyEvent.VK_ENTER:
//按 ENTER键切换游戏暂停或开始
if(flag) {
//暂停游戏时间
timer.stop();
//算出累计游戏时间
Date stopTime = new Date();
preGameTime += stopTime.getTime() - startTime.getTime();
//游戏暂停
flag = false;
} else {
//继续游戏时间
timer.start();
//游戏继续后,重新设置游戏时间
startTime = new Date();
flag = true;
tetrisPanel.repaint();
}
break;
default:
break;
}
}
/**
* 方块旋转实现
*/
private void moveRoteAction() {
// if(canStartRote()) {
tetrisPanel.currentBlock.rotateRight();
// }
if(!canRote()) {
tetrisPanel.currentBlock.rotateLeft();
}
}
/**
* 判断方块是否出界
*/
private boolean canStartRote() {
Cell[] cells = tetrisPanel.currentBlock.cells;
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
if(row <= 0) {
return false;
}
if(row > tetrisPanel.wall.length - 1 || col <= 0 || col >= tetrisPanel.wall[0].length - 1) {
return false;
}
}
return true;
}
/**
* 判断方块是否重合
*/
private boolean canRote() {
Cell[] cells = tetrisPanel.currentBlock.cells;
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
if(row >= 20 || row < 0 || col < 0 || col > 9) {
return false;
}
if(tetrisPanel.wall[row][col] != null) {
return false;
}
}
return true;
}
/**
* 方块下移实现
* @param o
*/
private void movePerformed(Object o) {
if(ifCanDrop()) {
tetrisPanel.currentBlock.moveDrop();
tetrisPanel.repaint();
}
}
/**
* 方块右移实现
*/
private void moveRightAction() {
if(ifCanRight()) {
tetrisPanel.currentBlock.moveRight();
}
}
/**
* 单独判断当前方块是否能够右移
*/
private boolean ifCanRight() {
Cell[] cells = tetrisPanel.currentBlock.cells;
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
// 判断右侧是否碰到墙体,右侧是墙体则返回false
if (col == 9) {
return false;
}
//判断右侧是否有方块,有方块也不能右移,返回false
if (tetrisPanel.wall[row][col + 1] != null) {
return false;
}
}
//如果方块相邻右侧的位置 即没有方块也不是墙体,则返回true
return true;
}
/**
* 方块左移实现
*/
private void moveLeftAction() {
if(ifCanLeft()) {
tetrisPanel.currentBlock.moveLeft();
}
}
/**
* 判断当前方块是否能够左移
*/
private boolean ifCanLeft() {
Cell[] cells = tetrisPanel.currentBlock.cells;
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
// 判断左侧是否碰到墙体,左侧是墙体则返回false
if(col == 0) {
return false;
}
//判断左侧是否有方块,有方块也不能左移,返回false
if(tetrisPanel.wall[row][col - 1] != null) {
return false;
}
}
//如果方块相邻左侧的位置 即没有方块也不是墙体,则返回true
return true;
}
/**
* 将当前下落的方块最后落下的位置 定格到 wall中
*/
private void landToWall() {
Cell[] cells = tetrisPanel.currentBlock.cells;
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
tetrisPanel.wall[row][col] = cell;
}
}
/**
* 如果该行已经填满方块,则消去该行
*/
private void vanishLine() {
int singleLinesCount = 0;
//获取正在下落的方块对象的单元格数组
Cell[] cells = tetrisPanel.currentBlock.cells;
for (Cell cell : cells) {
//取出每个单元格的行号
int row = cell.getRow();
while(row < 20) {
if (isFullLine(row)) {//如果当前行已填满
//
singleLinesCount++;
//重置当前行的单元格
tetrisPanel.wall[row] = new Cell[10];
//上面的位置下移
for (int i = row; i > 0; i--) {
System.arraycopy(tetrisPanel.wall[i - 1], 0, tetrisPanel.wall[i], 0, 10);
}
//在墙体的最顶端新增一行空的单元格
tetrisPanel.wall[0] = new Cell[10];
}
row++;
}
}
//消行计分的规则 消4行——70分 消3行——50分 消2行——30分 消1行——10分
score += (20 * singleLinesCount);
if (score == 200 * level && level <= 10) {
level++;
delay -= 30;
}
}
/**
* 判断当前行是否已经填满单元格
*/
private boolean isFullLine(int row) {
//获取 wall当前行的数组,存入一维数组中
Cell[] cells = tetrisPanel.wall[row];
for (Cell cell : cells) {
//如果该行有单元格是null,则表示该行还没填满
if(cell == null) {
return false;
}
}
return true;
}
/**
* 判断当前方块是否可以继续下落
* @return
*/
private boolean ifCanDrop() {
//先获取当前即将下落的方块对象
TetrisModel currentBlock = tetrisPanel.currentBlock;
//获取方块对象包含的单元格数组
Cell[] cells = currentBlock.cells;
//对包含的每个单元格所在行进行判断
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
//如果当前位置是最后一行,则不能下落
if(row == 19) {
return false;
}
//如果当前位置下面的单元格被占用,则不能下落
if(tetrisPanel.wall[row + 1][col] != null) {
return false;
}
}
//
return true;
}
/**
* 判断游戏是否结束,即是否 game over
*/
private boolean ifGameOver() {
//先获取当前下落的方块对象
TetrisModel currentBlock = tetrisPanel.currentBlock;
//获取方块对象包含的单元格数组
Cell[] cells = currentBlock.cells;
for (Cell cell : cells) {
int row = cell.getRow();
//如果当前行已经是第一行,返回 true,即 game over
if(row <= 0) {
return true;
}
}
return false;
}
// setter
public void setTetrisPanel(TetrisPanel tetrisPanel) {
this.tetrisPanel = tetrisPanel;
}
}
(2)TetrisMain
package com.zdq.main;
import com.zdq.utils.SourceUtil;
import javax.swing.*;
/**
* 俄罗斯方块游戏入口
*/
public class TetrisMain {
public static void main(String[] args) {
// 创建游戏窗口
JFrame jFrame = new JFrame("俄罗斯方块");
//设置窗口logo
jFrame.setIconImage(SourceUtil.tetrisLogoImage);
//在游戏窗口容器添加画布
TetrisPanel tetrisPanel = new TetrisPanel();
jFrame.add(tetrisPanel);
// 相关属性设置
jFrame.setSize(535, 595); //窗口尺寸
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 窗口关闭退出
jFrame.setLocationRelativeTo(null); // 窗口居中
jFrame.setResizable(false); // 设置窗口尺寸不可变化
jFrame.setVisible(true); // 窗口可见
tetrisPanel.start();
}
}
(3)TetrisPanel
package com.zdq.main;
import com.zdq.domain.Cell;
import com.zdq.domain.TetrisModel;
import com.zdq.utils.SourceUtil;
import javax.swing.*;
import java.awt.*;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 创建一个游戏画布类
*/
public class TetrisPanel extends JPanel {
//设置20行,10列的 墙体表格数组
public Cell[][] wall = new Cell[20][10];
//设置单元格对象的固定宽高
private static final int CELL_SIZE = 26;
//当前下落的俄罗斯方块
public TetrisModel currentBlock = TetrisModel.randomBlock();
//下一个下落的俄罗斯方块
public TetrisModel nextBlock = TetrisModel.randomBlock();
//获取监听器对象,控制游戏暂停与启动
private KeyActionListener keyActionListener = new KeyActionListener(this);
/**
* 重画父类画图方法
* @param g 代表画笔
*/
@Override
public void paint(Graphics g) {
//绘制画布背景游戏图
g.drawImage(SourceUtil.backgroundImage, 0, 0, null);
//让墙体往右下稍稍偏移,做一个微调
g.translate(15, 15);
//绘制主游戏区域的背景墙格子
paintWall(g);
//在画布绘制当前下落的俄罗斯方块
paintCurrentBlock(g);
//在画布绘制下一个即将下落的俄罗斯方块
paintNextBlock(g);
}
/**
* 自定义的在画布绘制下一个下落的俄罗斯方块
* @param g 表示画笔
*/
private void paintNextBlock(Graphics g) {
//获取当前方块对象对应的单元格数组
Cell[] cells = nextBlock.cells;
for (Cell cell : cells) {
int x = cell.getCol() * CELL_SIZE + 265;
int y = cell.getRow() * CELL_SIZE + 25;
//绘制每个俄罗斯方块对应的单元格即可
g.drawImage(cell.getImage(), x, y, null);
}
}
/**
* 自定义地在画布绘制正在下落的俄罗斯方块
* @param g 表示画笔
*/
private void paintCurrentBlock(Graphics g) {
//设置字体相关信息
Font font = new Font("楷体", Font.CENTER_BASELINE, 22);
g.setFont(font);
g.setColor(Color.magenta);
//关卡信息
g.drawString("关 卡: " + keyActionListener.level, 285, 160);
//分数信息
g.drawString("分 数: " + keyActionListener.score, 285, 220);
//闯关时间信息
Date now = new Date();
//后一阶段的游戏时长 + 之前累计的游戏时长,时间差,毫秒
long l = now.getTime() - keyActionListener.startTime.getTime() + keyActionListener.preGameTime;
//对日期时间进行格式化
SimpleDateFormat format = new SimpleDateFormat("mm分钟ss秒");
String gameTime = format.format(l);
g.drawString("时 间: " + gameTime, 285, 275);
//获取当前方块对象对应的单元格数组
Cell[] cells = currentBlock.cells;
for (Cell cell : cells) {
int x = cell.getCol() * CELL_SIZE;
int y = cell.getRow() * CELL_SIZE;
//绘制每个俄罗斯方块对应的单元格即可
g.drawImage(cell.getImage(), x, y, null);
}
}
/**
* 自定义的绘制游戏区域
* @param g 代表画笔
*/
private void paintWall(Graphics g) {
//循环对应的行
for (int i = 0; i < wall.length; i++) {
//循环对应的列
for (int j = 0; j < wall[i].length; j++) {
//通过 对应的行列坐标获取 对应位置的单元格对象
Cell cell = wall[i][j];
//开始初始化单元格对象
int x = j * CELL_SIZE;
int y = i * CELL_SIZE;
//对当前单元格判断,是否存在被占用,即是否被使用
if(cell == null) {
//如果当前位置没有被占用,直接画空的单元格即可
g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
} else {
//表示当前单元格已经被其他形状的俄罗斯方块占用,直接绘制对应方块的单元格图片即可
g.drawImage(cell.getImage(), x, y, null);
}
}
}
}
/**
* 封装了游戏的主要逻辑
*/
public void start() {
//面板添加监听事件
this.addKeyListener(keyActionListener);
//面板对象设置成焦点
this.requestFocus();
//
Timer timer = keyActionListener.timer;
//
Date date = new Date();
keyActionListener.startTime = date;
timer.start();
}
}
domain包
(1) Cell
package com.zdq.domain;
import java.awt.image.BufferedImage;
/**
* 俄罗斯方块对应的单元格类
*/
public class Cell {
private int row;//单元格对应的行
private int col;//单元格对应的类
private BufferedImage image;//单元格对应的背景颜色
//构造器
public Cell(int row, int col, BufferedImage image) {
this.row = row;
this.col = col;
this.image = image;
}
public Cell() {
}
/**
* 单元格左移
*/
public void left() {
col--;
}
/**
* 单元格右移
*/
public void right() {
col++;
}
/**
* 单元格下移
*/
public void drop() {
row++;
}
//对应的 getter和 setter
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
public BufferedImage getImage() {
return image;
}
public void setImage(BufferedImage image) {
this.image = image;
}
}
(2)I
package com.zdq.domain;
import com.zdq.utils.SourceUtil;
/**
* 对应的 I形状俄罗斯方块
*/
public class I extends TetrisModel {
/**
* 对默认构造方法进行改造,进行属性变量的初始化:
* 初始化方块中每一个单元格的位置,还有背景图片
*/
public I() {
cells[0] = new Cell(0, 4, SourceUtil.iImage);
cells[1] = new Cell(0, 3, SourceUtil.iImage);
cells[2] = new Cell(0, 5, SourceUtil.iImage);
cells[3] = new Cell(0, 6, SourceUtil.iImage);
//两种旋转状态
states = new State[2];
//初始化两种状态的相对坐标
states[0] = new State(0, 0, 0, -1, 0, 1, 0, 2);
states[1] = new State(0, 0, -1, 0, 1, 0, 2, 0);
}
}
(3)J
package com.zdq.domain;
import com.zdq.utils.SourceUtil;
/**
* 对应的 J形状俄罗斯方块
*/
public class J extends TetrisModel {
/**
* 对默认构造方法进行改造,进行属性变量的初始化:
* 初始化方块中每一个单元格的位置,还有背景图片
*/
public J() {
cells[0] = new Cell(0, 4, SourceUtil.jImage);
cells[1] = new Cell(0, 3, SourceUtil.jImage);
cells[2] = new Cell(0, 5, SourceUtil.jImage);
cells[3] = new Cell(1, 3, SourceUtil.jImage);
//四种旋转状态
states = new State[4];
//初始化四种状态的相对坐标
states[0] = new State(0, 0, 0, -1, 0, 1, 1, 1);
states[1] = new State(0, 0, -1, 0, 1, 0, 1, -1);
states[2] = new State(0, 0, 0, 1, 0, -1, -1, -1);
states[3] = new State(0, 0, 1, 0, -1, 0, -1, 1);
}
}
(4)L
package com.zdq.domain;
import com.zdq.utils.SourceUtil;
/**
* 对应的 L形状俄罗斯方块
*/
public class L extends TetrisModel {
/**
* 对默认构造方法进行改造,进行属性变量的初始化:
* 初始化方块中每一个单元格的位置,还有背景图片
*/
public L() {
cells[0] = new Cell(0, 4, SourceUtil.lImage);
cells[1] = new Cell(0, 3, SourceUtil.lImage);
cells[2] = new Cell(0, 5, SourceUtil.lImage);
cells[3] = new Cell(1, 5, SourceUtil.lImage);
//四种旋转状态
states = new State[4];
//初始化四种状态的相对坐标
states[0] = new State(0, 0, 0, -1, 0, 1, 1, -1);
states[1] = new State(0, 0, -1, 0, 1, 0, -1, -1);
states[2] = new State(0, 0, 0, 1, 0, -1, -1, 1);
states[3] = new State(0, 0, 1, 0, -1, 0, 1, 1);
}
}
(5)O
package com.zdq.domain;
import com.zdq.utils.SourceUtil;
/**
* 对应的 O形状俄罗斯方块
*/
public class O extends TetrisModel {
/**
* 对默认构造方法进行改造,进行属性变量的初始化:
* 初始化方块中每一个单元格的位置,还有背景图片
*/
public O() {
cells[0] = new Cell(0, 4, SourceUtil.oImage);
cells[1] = new Cell(0, 5, SourceUtil.oImage);
cells[2] = new Cell(1, 4, SourceUtil.oImage);
cells[3] = new Cell(1, 5, SourceUtil.oImage);
states = new State[0];
}
}
(6)S
package com.zdq.domain;
import com.zdq.utils.SourceUtil;
/**
* 对应的 S形状俄罗斯方块
*/
public class S extends TetrisModel {
/**
* 对默认构造方法进行改造,进行属性变量的初始化:
* 初始化方块中每一个单元格的位置,还有背景图片
*/
public S() {
cells[0] = new Cell(0, 4, SourceUtil.sImage);
cells[1] = new Cell(0, 5, SourceUtil.sImage);
cells[2] = new Cell(1, 3, SourceUtil.sImage);
cells[3] = new Cell(1, 4, SourceUtil.sImage);
//四种旋转状态
states = new State[2];
//初始化四种状态的相对坐标
states[0] = new State(0, 0, 0, 1, 1, -1, 1, 0);
states[1] = new State(0, 0, 1, 0, -1, -1, 0, -1);
}
}
(7)T
package com.zdq.domain;
import com.zdq.utils.SourceUtil;
/**
* 对应的 T形状俄罗斯方块
*/
public class T extends TetrisModel {
/**
* 对默认构造方法进行改造,进行属性变量的初始化:
* 初始化方块中每一个单元格的位置,还有背景图片
*/
public T() {
cells[0] = new Cell(0, 4, SourceUtil.tImage);
cells[1] = new Cell(0, 3, SourceUtil.tImage);
cells[2] = new Cell(0, 5, SourceUtil.tImage);
cells[3] = new Cell(1, 4, SourceUtil.tImage);
//四种旋转状态
states = new State[4];
//初始化四种状态的相对坐标
states[0] = new State(0, 0, 0, -1, 0, 1, 1, 0);
states[1] = new State(0, 0, -1, 0, 1, 0, 0, -1);
states[2] = new State(0, 0, 0, 1, 0, -1, -1, 0);
states[3] = new State(0, 0, 1, 0, -1, 0, 0, 1);
}
}
(8)TetrisModel
package com.zdq.domain;
import java.util.Random;
/**
* 向上抽取的方块父类
*/
public class TetrisModel {
//以数组的形式封装四个单元格
public Cell[] cells = new Cell[4];
//编写旋转状态
public State[] states;
//编写旋转次数
protected int count = 10000;
//四方格旋转状态的内部类
class State {
int row0,col0,row1,col1,row2,col2,row3,col3;
public State(int row0, int col0, int row1, int col1, int row2, int col2, int row3, int col3) {
this.row0 = row0;
this.col0 = col0;
this.row1 = row1;
this.col1 = col1;
this.row2 = row2;
this.col2 = col2;
this.row3 = row3;
this.col3 = col3;
}
public State() {
}
public int getRow0() {
return row0;
}
public void setRow0(int row0) {
this.row0 = row0;
}
public int getCol0() {
return col0;
}
public void setCol0(int col0) {
this.col0 = col0;
}
public int getRow1() {
return row1;
}
public void setRow1(int row1) {
this.row1 = row1;
}
public int getCol1() {
return col1;
}
public void setCol1(int col1) {
this.col1 = col1;
}
public int getRow2() {
return row2;
}
public void setRow2(int row2) {
this.row2 = row2;
}
public int getCol2() {
return col2;
}
public void setCol2(int col2) {
this.col2 = col2;
}
public int getRow3() {
return row3;
}
public void setRow3(int row3) {
this.row3 = row3;
}
public int getCol3() {
return col3;
}
public void setCol3(int col3) {
this.col3 = col3;
}
@Override
public String toString() {
return "State{" +
"row0=" + row0 +
", col0=" + col0 +
", row1=" + row1 +
", col1=" + col1 +
", row2=" + row2 +
", col2=" + col2 +
", row3=" + row3 +
", col3=" + col3 +
'}';
}
}
/**
* 方块顺时针旋转
*/
public void rotateRight() {
// O形方块不旋转,直接返回
if(this instanceof O) {
return;
}
//旋转次数增加
count++;
State state = states[count % states.length];
Cell cell = cells[0];
int row = cell.getRow();
int col = cell.getCol();
cells[1].setRow(row + state.row1);
cells[1].setCol(col + state.col1);
cells[2].setRow(row + state.row2);
cells[2].setCol(col + state.col2);
cells[3].setRow(row + state.row3);
cells[3].setCol(col + state.col3);
}
/**
* 方块逆时针旋转
*/
public void rotateLeft() {
if(this instanceof O) {
return;
}
//旋转次数减少
count--;
State state = states[count % states.length];
Cell cell = cells[0];
int row = cell.getRow();
int col = cell.getCol();
cells[1].setRow(row + state.row1);
cells[1].setCol(col + state.col1);
cells[2].setRow(row + state.row2);
cells[2].setCol(col + state.col2);
cells[3].setRow(row + state.row3);
cells[3].setCol(col + state.col3);
}
/**
* 方块左移
*/
public void moveLeft() {
for (Cell cell : cells) {
cell.left();
}
}
/**
* 方块右移
*/
public void moveRight() {
for (Cell cell : cells) {
cell.right();
}
}
/**
* 方块下移
*/
public void moveDrop() {
for (Cell cell : cells) {
cell.drop();
}
}
/**
* 随机生成不同的俄罗斯方块
*/
public static TetrisModel randomBlock() {
//创建 TetrisModel对象
TetrisModel tetrisModel = new TetrisModel();
//生成范围 [0,6]的随机整数
int num = new Random().nextInt(7);
switch (num) {
case 0:
tetrisModel = new I();
break;
case 1:
tetrisModel = new J();
break;
case 2:
tetrisModel = new L();
break;
case 3:
tetrisModel = new O();
break;
case 4:
tetrisModel = new S();
break;
case 5:
tetrisModel = new T();
break;
case 6:
tetrisModel = new Z();
break;
}
//返回随机生成的俄罗斯方块对象
return tetrisModel;
}
}
(9)Z
package com.zdq.domain;
import com.zdq.utils.SourceUtil;
/**
* 对应的 Z形状俄罗斯方块
*/
public class Z extends TetrisModel {
/**
* 对默认构造方法进行改造,进行属性变量的初始化:
* 初始化方块中每一个单元格的位置,还有背景图片
*/
public Z() {
cells[0] = new Cell(1, 4, SourceUtil.zImage);
cells[1] = new Cell(0, 3, SourceUtil.zImage);
cells[2] = new Cell(0, 4, SourceUtil.zImage);
cells[3] = new Cell(1, 5, SourceUtil.zImage);
//四种旋转状态
states = new State[2];
//初始化四种状态的相对坐标
states[0] = new State(0, 0, -1, -1, -1, 0, 0, 1);
states[1] = new State(0, 0, -1, 1, 0, 1, 1, 0);
}
}
image包