Java20: 俄罗斯方块

业务分析:百度

数据模型:

类的设计:

1) Cell 格子

int row 行;

int col 列;

Image image 贴图;

2) Tetromino 四格方块

Cell[] cells 4个格子;

3) Tetris 俄罗斯方块  继承 JPanel

int score 分数;

int lines 行数;

Cell[][] wall = new Cell[20][10] 墙;

Tetromino tetromino 四格方块;

Tetromino nextOne 下一个四格方块;

数据的初始化:

构造器

设计功能:

下落

左移动

右移动

旋转

计分

入墙

界面绘制

java Swing API

背景图片

结束游戏图片

七种方块

ps技术有限,有个样子就行了

package xyz.rhel.els;

import java.awt.Image;

public class Cell {
	private int row;
	private int col;
	private Image image;

	public Cell(int row, int col, Image image) {
		this.row = row;
		this.col = col;
		this.image = image;
	}

	public int getRow() {
		return row;
	}

	public int getCol() {
		return col;
	}

	public Image getImage() {
		return image;
	}

	public void setRow(int row) {
		this.row = row;
	}

	public void setCol(int col) {
		this.col = col;
	}

	public void setImage(Image image) {
		this.image = image;
	}

	public void up() {
		row--;
	}

	public void drop() {
		row++;
	}

	public void moveLeft() {
		col--;
	}

	public void moveRight() {
		col++;
	}

	public String toString() {
		return "[" + row + "," + col + "]";
	}
}
package xyz.rhel.els;

import java.util.Random;

public abstract class Tetromino {
	protected Cell[] cells = new Cell[4];
	protected State[] states;
	private int index = 100;

	private Tetromino() {
	}

	protected class State {
		int row0, col0;
		int row1, col1;
		int row2, col2;
		int 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 static Tetromino randomOne() {
		Random r = new Random();
		int type = r.nextInt(7);
		switch (type) {
		case 0:
			return new T();
		case 1:
			return new I();
		case 2:
			return new S();
		case 3:
			return new Z();
		case 4:
			return new J();
		case 5:
			return new L();
		case 6:
			return new O();
		}
		return null;
	}

	public void up() {
		for (Cell cell : cells) {
			cell.up();
		}
	}

	public void softDrop() {
		for (Cell cell : cells) {
			cell.drop();
		}
	}

	public void moveRight() {
		for (Cell cell : cells) {
			cell.moveRight();
		}
	}

	public void moveLeft() {
		for (Cell cell : cells) {
			cell.moveLeft();
		}
	}

	public void rotateRight() {
		index++;
		State s = states[index % states.length];
		Cell rotatingCenter = cells[0];
		int row = rotatingCenter.getRow();
		int col = rotatingCenter.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() {
		index--;
		State s = states[index % states.length];
		Cell rotatingCenter = cells[0];
		int row = rotatingCenter.getRow();
		int col = rotatingCenter.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);
	}

	private static 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);// 右90
			states[2] = new State(0, 0, 0, 1, 0, -1, -1, 0);// 右90
			states[3] = new State(0, 0, 1, 0, -1, 0, 0, 1);// 右90

		}
	}

	private static 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);
		}
	}

	private static 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);
		}
	}

	private static class Z extends Tetromino {
		public Z() {
			cells[0] = new Cell(0, 4, Tetris.Z);
			cells[1] = new Cell(0, 3, Tetris.Z);
			cells[2] = new Cell(1, 4, Tetris.Z);
			cells[3] = new Cell(1, 5, Tetris.Z);
			states = new State[2];
			states[0] = new State(0, 0, 0, -1, 1, 0, 1, 1);
			states[1] = new State(0, 0, -1, 0, 0, -1, 1, -1);
		}
	}

	private static 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);
		}
	}

	private static 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);
		}
	}

	private static 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[1];
			states[0] = new State(0, 0, 0, 1, 1, 0, 1, 1);
		}
	}
}
package xyz.rhel.els;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.JFrame;

public class Tetris extends JPanel {
	public static final int ROWS = 20;// 墙的行
	public static final int COLS = 10;// 墙的列
	public static final int CELL_SIZE = 18;// 格子大小
	public static final int FONT_COLOR = 0x741852;
	public static final int FONT_SIZE = 25;

	public static Image background;// 背景图片
	public static Image I;
	public static Image T;
	public static Image S;
	public static Image Z;
	public static Image L;
	public static Image J;
	public static Image O;
	public static Image gameOverImg;

	private boolean pause;// 暂停标志
	private boolean gameOver;// 游戏结束标志
	private Timer timer;//
	private int inteval = 800;// 时间间隔
	private int lines;// 消除的行数
	private int[] scoreTable = { 0, 1, 20, 40, 60 };// 得分表
	private int score;// 得分
	private Cell[][] wall = new Cell[20][10];// 墙
	private Tetromino tetromino;// 正在下落
	private Tetromino nextOne;// 下一个将下落的

	static {// 静态加载图片
		try {
			Class cls = Tetris.class;
			background = ImageIO.read(cls.getResource("background.png"));
			I = ImageIO.read(cls.getResource("I.png"));
			T = ImageIO.read(cls.getResource("T.png"));
			S = ImageIO.read(cls.getResource("S.png"));
			Z = ImageIO.read(cls.getResource("Z.png"));
			L = ImageIO.read(cls.getResource("L.png"));
			J = ImageIO.read(cls.getResource("J.png"));
			O = ImageIO.read(cls.getResource("O.png"));
			gameOverImg = ImageIO.read(cls.getResource("gameOverImg.png"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void paintGmaeOver(Graphics g) {// 画结束图片
		g.drawImage(gameOverImg, 200, 200, null);
	}

	private void paintScore(Graphics g) {// 画得分
		String str = "分数:" + score;
		g.setColor(new Color(FONT_COLOR));
		Font font = getFont();
		font = new Font(font.getName(), Font.BOLD, FONT_SIZE);// 为了跨平台
		g.setFont(font);
		g.drawString(str, 250, 200);
	}

	private void paintLines(Graphics g) {// 画行
		String str = "行数:" + lines;
		g.drawString(str, 250, 250);
	}

	private void paintNextOne(Graphics g) {// 画下一个方块的方法
		if (nextOne == null) {
			return;
		}
		Cell[] cells = nextOne.cells;
		for (int i = 0; i < cells.length; i++) {
			Cell cell = cells[i];
			int x = cell.getCol() * CELL_SIZE;
			int y = cell.getRow() * CELL_SIZE;
			g.drawImage(cell.getImage(), x + 200, y + 100, null);
		}
	}

	private void paintNextOneBox(Graphics g) {// 画将要下落方块的容器的方法
		g.drawRect(250, 80, 80, 80);
	}

	private void paintTetromino(Graphics g) {// 画下落的方块
		if (tetromino == null) {
			return;
		}
		Cell[] cells = tetromino.cells;
		for (int i = 0; i < cells.length; i++) {
			Cell cell = cells[i];
			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 row = 0; row < wall.length; row++) {
			Cell[] line = wall[row];
			for (int col = 0; col < line.length; col++) {
				Cell cell = line[col];
				int x = col * CELL_SIZE;
				int y = row * CELL_SIZE;
				if (cell == null) {
					g.setColor(new Color(0xff0000));
					g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
				} else {
					g.drawImage(cell.getImage(), x, y, null);
				}
			}
		}
	}

	public void paint(Graphics g) {// 重写JPanel 中的paint方法 repaint来调用
		g.drawImage(background, 0, 0, null);// 在窗口中画背景图片
		g.translate(10, 10);// 坐标系平移
		paintWall(g);// 画墙
		paintTetromino(g);// 画下落的方块
		paintNextOneBox(g);// 画将要下落方块的容器
		paintNextOne(g);// 画下一个将下落的
		paintScore(g);// 画得分
		paintLines(g);// 画行
		if (pause) {
			g.drawString("暂停中请按C继续", 400, 100);
		}
		if (gameOver) {
			paintGmaeOver(g);
			g.drawString("重新开始请按S", 400, 100);
		}
	}

	private boolean canUp() {// 作弊使用,向上
		Cell[] cells = tetromino.cells;
		for (Cell cell : cells) {
			int row = cell.getRow();
			if (row == 0) {
				return false;
			}
		}
		return true;
	}

	private boolean canDrop() {// 判断当前方块是否可以下落
		Cell[] cells = tetromino.cells;
		for (Cell cell : cells) {// 检查当前方块是否到达底部
			int row = cell.getRow();
			if (row == ROWS - 1) {
				return false;
			}
		}
		for (Cell cell : cells) {// 检查当前方块的下一行是否有方块
			int row = cell.getRow();
			int col = cell.getCol();
			if (wall[row + 1][col] != null) {
				return false;
			}
		}
		return true;
	}

	private void landToWall() {// 进入墙
		Cell[] cells = tetromino.cells;
		for (Cell cell : cells) {
			int row = cell.getRow();
			int col = cell.getCol();
			wall[row][col] = cell;
		}

	}

	private boolean fullCells(int row) {// 查格子是否是满的
		Cell[] line = wall[row];
		for (Cell cell : line) {
			if (cell == null) {
				return false;
			}
		}
		return true;
	}

	private void deleteLine(int row) {// 删除满行
		for (int i = row; i >= 1; i--) {
			System.arraycopy(wall[i - 1], 0, wall[i], 0, COLS);
		}
		Arrays.fill(wall[0], null);
	}

	private void destroyLines() {// 消除行方法
		int lines = 0;
		for (int row = 0; row < ROWS; row++) {
			if (fullCells(row)) {
				deleteLine(row);
				lines++;
			}
		}
		this.lines += lines;
		this.score += scoreTable[lines];
	}

	private void checkGameOver() {// 检查游戏是否结束
		if (wall[0][4] != null) {
			gameOver = true;
			timer.cancel();
			repaint();
		}
	}

	private boolean outOfBounds() {// 左右边界检查
		Cell[] cells = tetromino.cells;
		for (Cell cell : cells) {
			int col = cell.getCol();
			if (col < 0 || col >= COLS) {
				return true;
			}
		}
		return false;
	}

	private boolean coincide() {// 格子重合检查
		Cell[] cells = tetromino.cells;
		for (Cell cell : cells) {
			int row = cell.getRow();
			int col = cell.getCol();
			if (row >= 0 && row < ROWS && col >= 0 && col < COLS
					&& wall[row][col] != null) {
				return true;
			}
		}
		return false;
	}

	private void upAction() {// 作弊使用,向上
		if (canUp()) {
			tetromino.up();
		}
	}

	private void softDropAction() {// 下落动作
		if (canDrop()) {
			tetromino.softDrop();
		} else {
			landToWall();
			destroyLines();
			checkGameOver();
			tetromino = nextOne;
			nextOne = Tetromino.randomOne();
		}
	}

	private void hardDropAction() {// 硬下落
		while (canDrop()) {
			tetromino.softDrop();
		}
		landToWall();
		destroyLines();
		checkGameOver();
		tetromino = nextOne;
		nextOne = Tetromino.randomOne();
	}

	private void moveLeftAction() {// 左移动方法
		tetromino.moveLeft();
		if (outOfBounds() || coincide()) {
			tetromino.moveRight();
		}
	}

	private void moveRightAction() {// 右移动方法
		tetromino.moveRight();
		if (outOfBounds() || coincide()) {
			tetromino.moveLeft();
		}
	}

	private void rotateRightAction() {// 右转动
		tetromino.rotateRight();
		if (outOfBounds() || coincide()) {
			tetromino.rotateLeft();
		}

	}

	private void rotateLeftAction() {// 左转动
		tetromino.rotateLeft();
		if (outOfBounds() || coincide()) {
			tetromino.rotateRight();
		}
	}

	private void action() {// 开始方法
		startAction();
		repaint();
		KeyListener l = new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				int key = e.getKeyCode();
				if (key == KeyEvent.VK_Q) {
					System.exit(0);
				}
				if (gameOver) {
					if (key == KeyEvent.VK_S) {
						startAction();
					}
					return;
				}
				if (pause) {
					if (key == KeyEvent.VK_C) {
						continueAction();
					}
					return;
				}
				switch (key) {
				case KeyEvent.VK_UP:
					upAction();
					break;
				case KeyEvent.VK_DOWN:
					softDropAction();
					break;
				case KeyEvent.VK_RIGHT:
					moveRightAction();
					break;
				case KeyEvent.VK_LEFT:
					moveLeftAction();
					break;
				case KeyEvent.VK_Z:
					rotateLeftAction();
					break;
				case KeyEvent.VK_X:
					rotateRightAction();
					break;
				case KeyEvent.VK_SPACE:
					hardDropAction();
					break;
				case KeyEvent.VK_S:
					pauseAction();
					break;
				}
				repaint();
			}
		};
		this.addKeyListener(l);
		this.requestFocus();
	}

	private void startAction() {// 开始
		pause = false;
		gameOver = false;
		score = 0;
		lines = 0;
		for (Cell[] line : wall) {
			Arrays.fill(line, null);
		}
		tetromino = Tetromino.randomOne();
		nextOne = Tetromino.randomOne();
		TimerTask task = new TimerTask() {
			public void run() {
				softDropAction();
				repaint();
			}
		};
		timer = new Timer();
		timer.schedule(task, inteval, inteval);
	}

	private void pauseAction() {// 暂停
		timer.cancel();
		pause = true;
	}

	private void continueAction() {// 继续
		pause = false;
		timer = new Timer();
		timer.schedule(new TimerTask() {
			public void run() {
				softDropAction();
				repaint();
			}
		}, inteval, inteval);
	}

	public static void main(String[] args) {
		JFrame frame = new JFrame("<俄罗斯方块>");
		Tetris tetris = new Tetris();
		// tetris.setBackground(new Color(0xff5511));
		frame.add(tetris);
		frame.setSize(800, 450);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
		tetris.action();
	}
}
时间: 2024-11-02 17:27:14

Java20: 俄罗斯方块的相关文章

很棒的计算机入门课程:公开课从与非门到俄罗斯方块(第二部分)

博客中的文章均为meelo原创,请务必以链接形式注明本文地址 Build a Modern Computer from First Principles: Nand to Tetris Part II (project-centered course) by: Noam Nisan & Shimon Schocken from: Hebrew University of Jerusalem 课程链接:https://www.coursera.org/learn/nand2tetris2/home

俄罗斯方块

俄罗斯方块游戏自动机 <用electron制作俄罗斯方块游戏> 后续文章,智能程序玩俄罗斯方块游戏. 背景 前不久用ES6完成了基本的俄罗斯方块游戏,今天已经完成了一个初步的智能算法,可以自动玩俄罗斯方块了,让自己的想法朝实现更近了一步. 效果图 第一次运行,消除了1398行,窃喜! 程序结构 主要关注智能算法,结构简单化,全部放在了index.js中. 用定时器驱动游戏 function autoPlayClick(){ isAutoPlay = document.getElementByI

C语言:俄罗斯方块

大一下学期,第一节c语言课程设计,老师分享了一个基于C语言的俄罗斯方块的游戏,让我们感受. 如果你想用Mac系统跑的话,也不是不行,但是得解决一些问题.在语言程序中#include<windows.h>这个是基于windows下的头文件,用在Mac的Xcode软件会出现Symbol not found的问题.自己百度了一下,一个是装虚拟机,另一个是把报错的地方修改成Xcode的代码,不用windows特有代码.还有一个就是定义了一个全局的变量,让工程不走windows.h.用Mac的同学们可以

关于俄罗斯方块游戏软件C语言初步感受

C语言课程设,老师先给我们发了一个使用C语言做的飞机游戏,第一次看到用C语言做的游戏,虽然画面简陋,但却是真正的游戏.后老师又给我们发了用C语言做的俄罗斯方块的游戏 int x;     //中心方块的x轴坐标 int y;     //中心方块的y轴坐标 int flag;    //标记方块类型的序号 int next;    //下一个俄罗斯方块类型的序号 int speed;    //俄罗斯方块移动的速度 int count;    //产生俄罗斯方块的个数 int score;  

俄罗斯方块软件:C语言应用初步感受

C语言课程设以一节课,老师提供了一个C语言的飞机游戏让我们感受,上学期C语言课程,主要是各种语句的练习,这次是用以前的知识来感受一个实际的系统. 首先安装c-free,然后运行程序. 游戏程序看似简单,但是用C语言来实现还是第一次见,感到很惊奇. 分析一下程序,感觉没有太复杂的,就是上学期学习的简单语句的组合,但是运用的非常好.首先看看用到了几种语句: 1.首先是在屏幕上显示的语句printf printf("俄罗斯方块"); gotoxy(hOut,FrameX+2*Frame_wi

俄罗斯方块和贪吃蛇游戏软件:C语言应用初始感受

C语言课程设以一节课,老师提供了一个C语言的飞俄罗斯方块让我们感受,我们所学的C语言课程,主要是各种语句的练习,这次是用我们所学过的知识来感受一个实际的系统. 首先安装c-free,然后是将代码贴进去运行 界面虽然有点简单,但这确实使用C语言做出来的游戏. 分析一下程序,感觉没有太复杂的,就是上学期学习的简单语句的组合,但是用的非常好.首先看看用到了几种语句: 1.首先是在屏幕上显示的语句printf, 2.另外一个就是多条件判断switch--case 应用方法 switch(tetris->

俄罗斯方块游戏:C语言程序设计初步感受

C语言课程设以一节课,老师提供了一个C语言的俄罗斯方块游戏让我们感受,本学期C语言课程,主要是各种语句的练习,这次是用以前的知识来感受一个实际的系统. 首先安装c-free,然后打开老师所发给我们的小程序. 界面很简单,没想到C语言还能做这么有意思的东西,真是没有想到. 分析一下程序,感觉比较太复杂的,但就是本学期学习的简单语句的组合,运用起来如此神奇. 1.首先是在屏幕上显示的语句printf 2.运用for语句建立窗口 for(i=2;i<2*Frame_width-2;i+=2) { go

前端作品五之——完美俄罗斯方块

---恢复内容开始--- 1.功能概述 实现传统的俄罗斯方块的功能.有几种固定形状和颜色的方块随机下落,满一行则此行消除.并让积分增加100,使用本地存储功能将方块的状态和得分存起来.在下次进行游戏的时候载入数据,并在游戏中进行存储操作. 2.选材布局 用canvas组件画方格图.用JavaScript语言实现逻辑功能. 3.功能实现与体会 源码中本人发现了几处bug, 1.测试发现在旋转操作频繁的时候,会出现方块严重错位,或丢失,出现一些匪夷所思的现象. 经分析,是旋转操作的处理出现的问题.

用JAVA写的俄罗斯方块

业务需求->业务对象模型(对象关系)->数据建模->类的设计->概要编码->详细功能设计 基本规则: 1)首先呢,俄罗斯方块都是由一个个小格子构成的,我们叫它Cell: 行宽:10,列高:20,以每个小正方形为单位 2)其次,所有的俄罗斯方块都是一组由4个小型正方形组成的规则图形,我们叫它Tetromino    分别为:S.Z.L.J.I.O.T这几种 哈哈,有了这样的分析,就可以构建数据结构设计了 数据结构设计: Cell     格子|--     int row 行|