俄罗斯方块

package com.zhao.demo.block;

import java.awt.image.BufferedImage;

import java.util.Objects;

/**

* @author xiaoZhao

* @date 2022/5/7

* @describe

* 小方块类

* 方法: 左移、右移、下落

*/

public class Cell {

// 行

private int row;

// 列

private int col;

private BufferedImage image;

public Cell() {

}

public Cell(int row, int col, BufferedImage image) {

this.row = row;

this.col = col;

this.image = image;

}

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;

}

@Override

public String toString() {

return "Cell{" +

"row=" + row +

", col=" + col +

", image=" + image +

'}';

}

@Override

public boolean equals(Object o) {

if (this == o) {

return true;

}

if (!(o instanceof Cell)) {

return false;

}

Cell cell = (Cell) o;

return getRow() == cell.getRow() &&

getCol() == cell.getCol() &&

Objects.equals(getImage(), cell.getImage());

}

@Override

public int hashCode() {

return Objects.hash(getRow(), getCol(), getImage());

}

//左移动一格

public void left(){

col--;

}

//右移动一格

public void right(){

col++;

}

//下移动一格

public void down(){

row++;

}

}

四方格图形的父类

package com.zhao.demo.block;

import com.zhao.demo.shape.*;

/**

* @author xiaoZhao

* @date 2022/5/11

* @describe 编写四方格父类

*/

public class Tetromino {

public Cell[] cells = new Cell[4];

//旋转的状态

protected State[] states;

//声明旋转次数

protected int count = 10000;

//左移方法

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.down();

}

}

//编写随机生成四方格

public static Tetromino randomOne() {

int num = (int) (Math.random() * 7);

Tetromino tetromino = null;

switch (num) {

case 0:

tetromino = new I();

break;

case 1:

tetromino = new J();

break;

case 2:

tetromino = new L();

break;

case 3:

tetromino = new O();

break;

case 4:

tetromino = new S();

break;

case 5:

tetromino = new T();

break;

case 6:

tetromino = new Z();

break;

}

return tetromino;

}

//顺时针旋转的方法

public void rotateRight() {

if (states.length == 0) {

return;

}

//旋转次数+1

count++;

State s = states[count % states.length];

Cell cell = cells[0];

int row = cell.getRow();

int col = cell.getCol();

cells[1].setRow(row + s.row1);

cells[1].setCol(col + s.col1);

cells[2].setRow(row + s.row2);

cells[2].setCol(col + s.col2);

cells[3].setRow(row + s.row3);

cells[3].setCol(col + s.col3);

}

//逆时针旋转的方法

public void rotateLeft() {

if (states.length == 0) {

return;

}

//旋转次数+1

count--;

State s = states[count % states.length];

Cell cell = cells[0];

int row = cell.getRow();

int col = cell.getCol();

cells[1].setRow(row + s.row1);

cells[1].setCol(col + s.col1);

cells[2].setRow(row + s.row2);

cells[2].setCol(col + s.col2);

cells[3].setRow(row + s.row3);

cells[3].setCol(col + s.col3);

}

//四方格旋转状态的内部类

protected class State {

//存储四方格各元素的位置

int row0, col0, row1, col1, row2, col2, row3, col3;

public State() {

}

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 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 +

'}';

}

}

}

七种图形类

package com.zhao.demo.shape;

import com.zhao.demo.App.Tetris;

import com.zhao.demo.block.Cell;

import com.zhao.demo.block.Tetromino;

/**

* @author xiaoZhao

* @date 2022/5/11

* @describe

*/

public class I extends Tetromino {

public I() {

cells[0] = new Cell(0,4, Tetris.I);

cells[1] = new Cell(0,3, Tetris.I);

cells[2] = new Cell(0,5, Tetris.I);

cells[3] = new Cell(0,6, Tetris.I);

//共有两种旋转状态

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);

}

}

J

package com.zhao.demo.shape;

import com.zhao.demo.App.Tetris;

import com.zhao.demo.block.Cell;

import com.zhao.demo.block.Tetromino;

/**

* @author xiaoZhao

* @date 2022/5/11

* @describe

*/

public class J extends Tetromino {

public J() {

cells[0] = new Cell(0,4, Tetris.J);

cells[1] = new Cell(0,3, Tetris.J);

cells[2] = new Cell(0,5, Tetris.J);

cells[3] = new Cell(1,5, Tetris.J);

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);

}

}

L

package com.zhao.demo.shape;

import com.zhao.demo.App.Tetris;

import com.zhao.demo.block.Cell;

import com.zhao.demo.block.Tetromino;

/**

* @author xiaoZhao

* @date 2022/5/11

* @describe

*/

public class L extends Tetromino {

public L() {

cells[0] = new Cell(0,4, Tetris.L);

cells[1] = new Cell(0,3, Tetris.L);

cells[2] = new Cell(0,5, Tetris.L);

cells[3] = new Cell(1,3, Tetris.L);

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);

}

}

O

package com.zhao.demo.shape;

import com.zhao.demo.App.Tetris;

import com.zhao.demo.block.Cell;

import com.zhao.demo.block.Tetromino;

/**

* @author xiaoZhao

* @date 2022/5/11

* @describe

*/

public class O extends Tetromino {

public O() {

cells[0] = new Cell(0, 4, Tetris.O);

cells[1] = new Cell(0, 5, Tetris.O);

cells[2] = new Cell(1, 4, Tetris.O);

cells[3] = new Cell(1, 5, Tetris.O);

//无旋转状态

states = new State[0];

}

}

S

package com.zhao.demo.shape;

import com.zhao.demo.App.Tetris;

import com.zhao.demo.block.Cell;

import com.zhao.demo.block.Tetromino;

/**

* @author xiaoZhao

* @date 2022/5/11

* @describe

*/

public class S extends Tetromino {

public S() {

cells[0] = new Cell(0,4, Tetris.S);

cells[1] = new Cell(0,5, Tetris.S);

cells[2] = new Cell(1,3, Tetris.S);

cells[3] = new Cell(1,4, Tetris.S);

//共有两种旋转状态

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);

}

}

T

package com.zhao.demo.shape;

import com.zhao.demo.App.Tetris;

import com.zhao.demo.block.Cell;

import com.zhao.demo.block.Tetromino;

/**

* @author xiaoZhao

* @date 2022/5/11

* @describe

*/

public class T extends Tetromino {

public T() {

cells[0] = new Cell(0,4, Tetris.T);

cells[1] = new Cell(0,3, Tetris.T);

cells[2] = new Cell(0,5, Tetris.T);

cells[3] = new Cell(1,4, Tetris.T);

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);

}

}

Z

package com.zhao.demo.shape;

import com.zhao.demo.App.Tetris;

import com.zhao.demo.block.Cell;

import com.zhao.demo.block.Tetromino;

/**

* @author xiaoZhao

* @date 2022/5/11

* @describe

*/

public class Z extends Tetromino {

public Z() {

cells[0] = new Cell(1,4, Tetris.Z);

cells[1] = new Cell(0,3, Tetris.Z);

cells[2] = new Cell(0,4, Tetris.Z);

cells[3] = new Cell(1,5, Tetris.Z);

//共有两种旋转状态

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);

}

}

俄罗斯方块游戏主类

package com.zhao.demo.App;

import com.zhao.demo.block.Cell;

import com.zhao.demo.block.Tetromino;

import javax.imageio.ImageIO;

import javax.swing.*;

import java.awt.*;

import java.awt.event.KeyAdapter;

import java.awt.event.KeyEvent;

import java.awt.event.KeyListener;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.IOException;

import java.security.cert.Certificate;

/**

* @author xiaoZhao

* @date 2022/5/11

* @describe 俄罗斯方块游戏主类

*/

public class Tetris extends JPanel {

//正在下落的方块

private Tetromino currentOne = Tetromino.randomOne();

//将要下落的方块

private Tetromino nextOne = Tetromino.randomOne();

//游戏主区域

private Cell[][] wall = new Cell[18][9];

//声明单元格的值

private static final int CELL_SIZE = 48;

//游戏分数池

int[] scores_pool = {0, 1, 2, 5, 10};

//当前游戏的分数

private int totalScore = 0;

//当前消除的行数

private int totalLine = 0;

//游戏三种状态 游戏中、暂停、结束

public static final int PLING = 0;

public static final int STOP = 1;

public static final int OVER = 2;

//当前游戏状态值

private int game_state;

//显示游戏状态

String[] show_state = {"P[pause]", "C[continue]", "S[replay]"};

//载入方块图片

public static BufferedImage I;

public static BufferedImage J;

public static BufferedImage L;

public static BufferedImage O;

public static BufferedImage S;

public static BufferedImage T;

public static BufferedImage Z;

public static BufferedImage background;

static {

try {

I = ImageIO.read(new File("images/I.png"));

J = ImageIO.read(new File("images/J.png"));

L = ImageIO.read(new File("images/L.png"));

O = ImageIO.read(new File("images/O.png"));

S = ImageIO.read(new File("images/S.png"));

T = ImageIO.read(new File("images/T.png"));

Z = ImageIO.read(new File("images/Z.png"));

background = ImageIO.read(new File("images/background.png"));

} catch (IOException e) {

e.printStackTrace();

}

}

@Override

public void paint(Graphics g) {

g.drawImage(background, 0, 0, null);

//平移坐标轴

g.translate(22, 15);

//绘制游戏主区域

paintWall(g);

//绘制正在下落的四方格

paintCurrentOne(g);

//绘制下一个将要下落的四方格

paintNextOne(g);

//绘制游戏得分

paintSource(g);

//绘制当前游戏状态

paintState(g);

}

public void start() {

game_state = PLING;

KeyListener l = new KeyAdapter() {

@Override

public void keyPressed(KeyEvent e) {

int code = e.getKeyCode();

switch (code) {

case KeyEvent.VK_DOWN:

sortDropActive();

break;

case KeyEvent.VK_LEFT:

moveleftActive();

break;

case KeyEvent.VK_RIGHT:

moveRightActive();

break;

case KeyEvent.VK_UP:

rotateRightActive();

break;

case KeyEvent.VK_SPACE:

hadnDropActive();

break;

case KeyEvent.VK_P:

//判断当前游戏状态

if (game_state == PLING) {

game_state = STOP;

}

break;

case KeyEvent.VK_C:

if (game_state == STOP) {

game_state = PLING;

}

break;

case KeyEvent.VK_S:

//重新开始

game_state = PLING;

wall = new Cell[18][9];

currentOne = Tetromino.randomOne();

nextOne = Tetromino.randomOne();

totalScore = 0;

totalLine = 0;

break;

}

}

};

//将窗口设置为焦点

this.addKeyListener(l);

this.requestFocus();

while (true) {

if (game_state == PLING) {

try {

Thread.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

if (camDrop()) {

currentOne.moveDrop();

} else {

landToWall();

destroyLine();

if (isGameOver()) {

game_state = OVER;

} else {

//游戏没有结束

currentOne = nextOne;

nextOne = Tetromino.randomOne();

}

}

}

repaint();

}

}

//创建顺时针旋转

public void rotateRightActive() {

currentOne.rotateRight();

if (outOFBounds() || coincide()) {

currentOne.rotateLeft();

}

}

//瞬间下落

public void hadnDropActive() {

while (true) {

//判断能否下落

if (camDrop()) {

currentOne.moveDrop();

} else {

break;

}

}

//嵌入到墙中

landToWall();

destroyLine();

if (isGameOver()) {

game_state = OVER;

} else {

//游戏没有结束

currentOne = nextOne;

nextOne = Tetromino.randomOne();

}

}

//按键一次,下落一格

public void sortDropActive() {

if (camDrop()) {

//当前四方格下落一格

currentOne.moveDrop();

} else {

landToWall();

destroyLine();

if (isGameOver()) {

game_state = OVER;

} else {

//游戏没有结束

currentOne = nextOne;

nextOne = Tetromino.randomOne();

}

}

}

//单元格嵌入墙中

private void landToWall() {

Cell[] cells = currentOne.cells;

for (Cell cell : cells) {

int row = cell.getRow();

int col = cell.getCol();

wall[row][col] = cell;

}

}

//判断四方格能否下落

public boolean camDrop() {

Cell[] cells = currentOne.cells;

for (Cell cell : cells) {

int row = cell.getRow();

int col = cell.getCol();

//判断是否到达底部

if (row == wall.length - 1) {

return false;

} else if (wall[row + 1][col] != null) {

return false;

}

}

return true;

}

//消除行

public void destroyLine() {

int line = 0;

Cell[] cells = currentOne.cells;

for (Cell cell : cells) {

int row = cell.getRow();

if (isFullLine(row)) {

line++;

for (int i = row; i > 0; i--) {

System.arraycopy(wall[i - 1], 0, wall[i], 0, wall[0].length);

}

wall[0] = new Cell[9];

}

}

//分数池获取分数,累加到总分

totalScore += scores_pool[line];

//总行数

totalLine += line;

}

//判断当前行是否已经满了

public boolean isFullLine(int row) {

Cell[] cells = wall[row];

for (Cell cell : cells) {

if (cell == null) {

return false;

}

}

return true;

}

//判断游戏是否结束

public boolean isGameOver() {

Cell[] cells = nextOne.cells;

for (Cell cell : cells) {

int row = cell.getRow();

int col = cell.getCol();

if (wall[row][col] != null) {

return true;

}

}

return false;

}

private void paintState(Graphics g) {

if (game_state == PLING) {

g.drawString(show_state[PLING], 500, 660);

} else if (game_state == STOP) {

g.drawString(show_state[STOP], 500, 660);

} else {

g.drawString(show_state[OVER], 500, 660);

g.setColor(Color.RED);

g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 60));

g.drawString("GAME OVER!", 30, 400);

}

}

private void paintSource(Graphics g) {

g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 30));

g.drawString("分数: " + totalScore, 500, 250);

g.drawString("行数: " + totalLine, 500, 430);

}

private void paintNextOne(Graphics g) {

Cell[] cells = nextOne.cells;

for (Cell cell : cells) {

int x = cell.getCol() * CELL_SIZE + 370;

int y = cell.getRow() * CELL_SIZE + 25;

g.drawImage(cell.getImage(), x, y, null);

}

}

private void paintCurrentOne(Graphics g) {

Cell[] cells = currentOne.cells;

for (Cell cell : cells) {

int x = cell.getCol() * CELL_SIZE;

int y = cell.getRow() * CELL_SIZE;

g.drawImage(cell.getImage(), x, y, null);

}

}

private void paintWall(Graphics g) {

for (int i = 0; i < wall.length; i++) {

for (int j = 0; j < wall[i].length; j++) {

int x = j * CELL_SIZE;

int y = i * CELL_SIZE;

Cell cell = wall[i][j];

//判断是否有小方块

if (cell == null) {

g.drawRect(x, y, CELL_SIZE, CELL_SIZE);

} else {

g.drawImage(cell.getImage(), x, y, null);

}

}

}

}

//判断是否出界

public boolean outOFBounds() {

Cell[] cells = currentOne.cells;

for (Cell cell : cells) {

int col = cell.getCol();

int row = cell.getRow();

if (row < 0 || row > wall.length - 1 || col < 0 || col > wall[0].length-1) {

return true;

}

}

return false;

}

//按键一次,左移一次

public void moveleftActive() {

currentOne.moveLeft();

//判断是否越界或重合

if (outOFBounds() || coincide()) {

currentOne.moveRight();

}

}

//按键一次,右移一次

public void moveRightActive() {

currentOne.moveRight();

//判断是否越界或重合

if (outOFBounds() || coincide()) {

currentOne.moveLeft();

}

}

//判断是否重合

public boolean coincide() {

Cell[] cells = currentOne.cells;

for (Cell cell : cells) {

int row = cell.getRow();

int col = cell.getCol();

if (wall[row][col] != null) {

return true;

}

}

return false;

}

public static void main(String[] args) {

JFrame jFrame = new JFrame("俄罗斯方块");

//创建游戏界面

Tetris panel = new Tetris();

jFrame.add(panel);

//设置可见

jFrame.setVisible(true);

//设置窗口大小

jFrame.setSize(810, 940);

//设置剧中

jFrame.setLocationRelativeTo(null);

//设置窗口关闭时停止

jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//游戏主要开始逻辑

panel.start();

}

}

相关推荐
湫ccc9 分钟前
《Python基础》之字符串格式化输出
开发语言·python
弗拉唐9 分钟前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi7741 分钟前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
mqiqe1 小时前
Python MySQL通过Binlog 获取变更记录 恢复数据
开发语言·python·mysql
AttackingLin1 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python
少说多做3431 小时前
Android 不同情况下使用 runOnUiThread
android·java
知兀1 小时前
Java的方法、基本和引用数据类型
java·笔记·黑马程序员
蓝黑20201 小时前
IntelliJ IDEA常用快捷键
java·ide·intellij-idea