Java game development - Tetris

introduction:

        The code implementation of Tetris is very simple and very interesting!

Idea:

        1. Create the main window, load menu and game panel.

        2. Initialize various parameters in the game panel and establish various functional components.

        3. Use the paint() function to start drawing squares.

        4. The game is over, wrap up, and prepare for the next game.


This game uses JDK1.8 and encodes UTF-8;

        There are 5 classes in total, Gobang.java is the game entry class. GameFrame.java is the main window class. GamePanel.java is the game panel class. GameLogic.java is the game logic class. Let’s post all the code in one go first.

1. Tetris.java game entry class

package com.game.tetris;

/**
 * 功能:俄罗斯方块<br>
 * 作者:我是小木鱼(Lag)<br>
 */
public class Tetris 
{

	public static void main(String[] args)
	{
		new GameFrame();
	}

}

2. GameFrame.java main window class.

package com.game.tetris;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * 功能:游戏窗口<br>
 * 作者:我是小木鱼(Lag)<br>
 */
public class GameFrame extends JFrame implements ActionListener
{
	private static final long serialVersionUID = 1L;

	/** 游戏面板 */
	private GamePanel gamePanel;

	/**
	 * 功能:构造函数<br>
	 */
	public GameFrame()
	{
		try
		{
			//菜单
			JMenuBar jmb_tetris = new JMenuBar();
			JMenu jm_game = new JMenu("游戏");
			JMenuItem jmi_game_new = jm_game.add("新游戏");
			jmi_game_new.addActionListener(this);
			jmi_game_new.setActionCommand("new");
			JMenuItem jmi_game_pause = jm_game.add("暂停");
			jmi_game_pause.addActionListener(this);
			jmi_game_pause.setActionCommand("pause");
			JMenuItem jmi_game_continue = jm_game.add("继续");
			jmi_game_continue.addActionListener(this);
			jmi_game_continue.setActionCommand("continue");
			jm_game.addSeparator();
			JMenuItem jmi_game_exit = jm_game.add("退出");
			jmi_game_exit.addActionListener(this);
			jmi_game_exit.setActionCommand("exit");
			jmb_tetris.add(jm_game);
			JMenu jm_help = new JMenu("帮助");
			JMenuItem jmi_help_about = jm_help.add("关于");
			jmi_help_about.addActionListener(this);
			jmi_help_about.setActionCommand("about");
			jmb_tetris.add(jm_help);
			this.setJMenuBar(jmb_tetris);
			//面板
			this.gamePanel = new GamePanel();
			this.add(this.gamePanel);
			//显示
			this.setTitle("俄罗斯方块");
			this.setSize(400,500);
			this.setResizable(false);
			this.setLocationRelativeTo(null);
			this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			this.setVisible(true);
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog(this,"程序出现异常错误,即将退出!\r\n\r\n"+e.toString(),"提示",JOptionPane.ERROR_MESSAGE);
			System.exit(0);
		}
		
	}
	
	/**
	 * 功能:事件监听<br>
	 */
	@Override
	public void actionPerformed(ActionEvent e)
	{
		String command = e.getActionCommand();
		if("new".equals(command))
		{
			this.gamePanel.newGame();
		}
		else if("pause".equals(command))
		{
			this.gamePanel.pauseGame();
		}
		else if("continue".equals(command))
		{
			this.gamePanel.continueGame();
		}
		else if("exit".equals(command))
		{
			System.exit(0);
		}
		else if("about".equals(command))
		{
			JOptionPane.showMessageDialog(this,"左右键移动,向上键旋转!\r\n\r\n我是小木鱼(Lag)\r\n\r\n","提示",JOptionPane.INFORMATION_MESSAGE);
		}
	}

}

3. GamePanel.java game panel class.

package com.game.tetris;

import java.awt.Font;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;

/**
 * 功能:游戏面板<br>
 * 作者:我是小木鱼(Lag)<br>
 */
public class GamePanel extends JPanel implements KeyListener,ActionListener
{
	private static final long serialVersionUID = 1L;

	/** 游戏逻辑 */
	private GameLogic gameLogic;

	/** 游戏地图(共21行12列,该地图包含墙和固定死的方块信息) */
	private byte[][] map;
	
	/** 是否接收键盘信息(true-接收,false-不接收) */
	private boolean isAcceptKey = true;

	/** 定时器 */
	private Timer timer;

	/**
	 * 功能:构造函数<br>
	 */
	public GamePanel()
	{
		//与主窗口大小保持一致(去掉菜单高度)
		this.setSize(400,440);
		//获得焦点(没焦点就不能截获键盘监听)
		this.setFocusable(true);
		//键盘监听
		this.addKeyListener(this);
		//游戏逻辑
		this.gameLogic = new GameLogic();
		//初始化游戏
		this.initGame();
		//定时器
		timer = new Timer(500,this);
		timer.start();
	}
	
	/**
	 * 功能:初始化游戏<br>
	 */
	private void initGame()
	{
		//初始化游戏逻辑
		this.gameLogic.init();
		//得到地图
		this.map = this.gameLogic.getMap();
		//重画地图
		this.repaint();
	}
	
	/**
	 * 功能:绘图<br>
	 * 备注:给我地图剩下的你就不用管了。<br>
	 */
	@Override
	public void paint(Graphics g)
	{
		int blockSize = 20;		//默认方块大小
		int row = 0;
		int column = 0;
		
		//调用父类,让其做一些事前的工作,如刷新屏幕等
		super.paint(g);
		
		//画大地图中已经固定的方块和围墙
		//==================地图==================
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, -1},	
		//{-1, 0, 0, 7, 7, 0, 0, 1, 1, 1, 1, -1},	
		//{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1}	
		//==================结束==================
		row = this.map.length;
		column = this.map[0].length;
		for(int i=0;i<row;i++)
		{
			for(int j=0;j<column;j++)
			{
				if(this.map[i][j] == -1)	//墙
				{
					g.setColor(Color.GRAY);
					g.fillRect(j * blockSize,i * blockSize,blockSize,blockSize);
					g.setColor(Color.WHITE);
					g.drawRect(j * blockSize,i * blockSize,blockSize,blockSize);
				}
				else if(this.map[i][j] > 0)	//方块
				{
					switch(this.map[i][j])
					{
						case 1:
							g.setColor(Color.RED);
							break;
						case 2:
							g.setColor(Color.ORANGE);
							break;
						case 3:
							g.setColor(Color.YELLOW);
							break;
						case 4:
							g.setColor(Color.GREEN);
							break;
						case 5:
							g.setColor(Color.BLUE);
							break;
						case 6:
							g.setColor(Color.PINK);
							break;
						case 7:
							g.setColor(Color.MAGENTA);
							break;
					}
					g.fillRect(j * blockSize,i * blockSize,blockSize,blockSize);
					g.setColor(Color.WHITE);
					g.drawRect(j * blockSize,i * blockSize,blockSize,blockSize);
				}
			}
		}
		
		//画当前方块
		byte[][] curShape = this.gameLogic.getShape();
		row = curShape.length;
		column = curShape[0].length;
		for(int i=0;i<row;i++)
		{
			for(int j=0;j<column;j++)
			{
				if(curShape[i][j] > 0)	//方块
				{
					switch(curShape[i][j])
					{
						case 1:
							g.setColor(Color.RED);
							break;
						case 2:
							g.setColor(Color.ORANGE);
							break;
						case 3:
							g.setColor(Color.YELLOW);
							break;
						case 4:
							g.setColor(Color.GREEN);
							break;
						case 5:
							g.setColor(Color.BLUE);
							break;
						case 6:
							g.setColor(Color.PINK);
							break;
						case 7:
							g.setColor(Color.MAGENTA);
							break;
					}
					g.fillRect((j + this.gameLogic.getShapeColumn()) * blockSize,(i + this.gameLogic.getShapeRow()) * blockSize,blockSize,blockSize);
					g.setColor(Color.WHITE);
					g.drawRect((j + this.gameLogic.getShapeColumn()) * blockSize,(i + this.gameLogic.getShapeRow()) * blockSize,blockSize,blockSize);
				}
			}
		}
		
		//画记分牌
		g.setColor(Color.BLACK);
		g.setFont(new Font("宋体",Font.PLAIN,12));
		g.drawString("当前分数: " + this.gameLogic.getScore(),this.map[0].length * blockSize + 20,30);
		
		//画下一个方块
		g.drawString("下一个方块是:",this.map.length * blockSize + 20,60);
		byte[][] nextShape = this.gameLogic.getNextShape();
		row = nextShape.length;
		column = nextShape[0].length;
		for(int i=0;i<row;i++)
		{
			for(int j=0;j<column;j++)
			{
				if(nextShape[i][j] > 0)
				{
					switch(nextShape[i][j])
					{
						case 1:
							g.setColor(Color.RED);
							break;
						case 2:
							g.setColor(Color.ORANGE);
							break;
						case 3:
							g.setColor(Color.YELLOW);
							break;
						case 4:
							g.setColor(Color.GREEN);
							break;
						case 5:
							g.setColor(Color.BLUE);
							break;
						case 6:
							g.setColor(Color.PINK);
							break;
						case 7:
							g.setColor(Color.MAGENTA);
							break;
					}
					g.fillRect(this.map[0].length * blockSize + 36 + j * blockSize,100 + i * blockSize,blockSize,blockSize);
					g.setColor(Color.WHITE);
					g.drawRect(this.map[0].length * blockSize + 36 + j * blockSize,100 + i * blockSize,blockSize,blockSize);
				}
			}
		}
		
	}
	
	/**
	 * 功能:方块移动<br>
	 */
	private void move(int keyCode)
	{
		if(!this.isAcceptKey){return;}
		
		//开始移动
		if(!this.gameLogic.move(keyCode)){return;}

		//得到移动后的新地图
		this.map = this.gameLogic.getMap();

		//重绘界面
		this.repaint();

		//判断是否Gave Over
		if(this.gameLogic.gameOver())
		{
			//屏蔽键盘信息
			this.isAcceptKey = false;
			return;
		}
	}
	
	/**
	 * 功能:开始新游戏<br>
	 */
	public void newGame()
	{
		this.isAcceptKey = true;
		this.initGame();
		timer.start();
	}
	
	/**
	 * 功能:暂停游戏<br>
	 */
	public void pauseGame()
	{
		this.isAcceptKey = false;
		timer.stop();
	}

	/**
	 * 功能:继续游戏<br>
	 */
	public void continueGame()
	{
		this.isAcceptKey = true;
		timer.start();
	}

	/**
	 * 功能:键盘监听<br>
	 */
	@Override
	public void keyPressed(KeyEvent e)
	{
		int keyCode = e.getKeyCode();
		if(keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT)
		{
			this.move(keyCode);
		}

	}

	@Override
	public void keyTyped(KeyEvent e){}

	@Override
	public void keyReleased(KeyEvent e){}

	/**
	 * 功能:事件监听<br>
	 */
	@Override
	public void actionPerformed(ActionEvent e) 
	{
		if(e.getSource() == this.timer)		//定时器
		{
			this.move(KeyEvent.VK_DOWN);
		}
	}

}

4. GameLogic.java game logic class.

package com.game.tetris;

import java.awt.event.KeyEvent;
import javax.swing.JOptionPane;

/**
 * 功能:游戏逻辑<br>
 * 作者:我是小木鱼(Lag)<br>
 */
public class GameLogic
{
	/** 大地图(共21行12列,该地图包含墙和后加入固定死的方块信息) */
	private byte[][] map;

	/** 方块类型(共7种) */
	private int blockType = 0;
	
	/** 方块状态(共4种) */
	private int turnState = 0;

	/** 当前方块图形(1-长条形方块,2-Z形方块,3-倒Z字形方块,4-J形方块,5-L字形,6-T字形方块,7-田字形方块) */
	private byte[][] shape;
	
	/** 当前方块图形(4×4矩阵)左上角所在行 */
	private int shapeRow;

	/** 当前方块图形(4×4矩阵)左上角所在列 */
	private int shapeColumn;

	/** 下一个方块类型 */
	private int nextBlockType = -1;
	
	/** 下一个方块状态 */
	private int nextTurnState = -1;

	/** 下一个方块图形 */
	private byte[][] nextShape;
	
	/** 得分 */
	private int score = 0;
	
	/**
	 * 功能:构造函数<br>
	 */
	public GameLogic()
	{}
	
	/**
	 * 功能:初始化<br>
	 */
	public void init()
	{
		//得到大地图
		this.map = GameMap.getMap();
		
		//随机生成新方块
		this.newBlock();
		
	}
	
	/**
	 * 功能:随机生成新方块<br>
	 */
	private void newBlock()
	{
		//如果当前没有下一方块(即游戏刚开局,还未生成当前方块和下一方块)
		if(this.nextBlockType == -1 && this.nextTurnState == -1)
		{
			this.blockType = (int)(Math.random() * 7);		//随机生成7种形状中的一种
			this.turnState = (int)(Math.random() * 4);		//随机生成4种旋转中的一种
			this.nextBlockType = (int)(Math.random() * 7);
			this.nextTurnState = (int)(Math.random() * 4);
		}
		else
		{
			this.blockType = this.nextBlockType;
			this.turnState = this.nextTurnState;
			this.nextBlockType = (int)(Math.random() * 7);
			this.nextTurnState = (int)(Math.random() * 4);
		}
		
		//获得当前方块,并设置初始位置(方块(4×4矩阵)最左上角方格初始行列位置即最顶端水平居中)
		this.shape = GameMap.getShape(this.blockType,this.turnState);
		this.shapeRow = 0;
		this.shapeColumn = 5;
		
		//获得下一个方块
		this.nextShape = GameMap.getShape(this.nextBlockType,this.nextTurnState);
		
	}

	
	/**
	 * 功能:将方块信息添加到地图数组信息中<br>
	 * 备注:方块信息是已经固定死了的<br>
	 */
	private void add()
	{
		//添加当前方块位置状态
		int rowCount = this.shape.length;
		int columnCount = this.shape[0].length;
		for(int i=this.shapeRow;i<this.shapeRow+rowCount;i++)
		{
			for(int j=this.shapeColumn;j<this.shapeColumn+columnCount;j++)
			{
				if(this.shape[i - this.shapeRow][j - this.shapeColumn] > 0)
				{
					this.map[i][j] = this.shape[i - this.shapeRow][j - this.shapeColumn];
				}
			}
		}
		
	}

	/**
	 * 功能:销毁满行的部分<br>
	 * 原理:一行一行对地图信息进行扫描,如果一行的每个元素值均大于0,说明满行,销毁该行,该行上面的方块依次下落一行。<br>
	 */
	private void deleteLine()
	{
		int count = 0;
		int mapRowCount = this.map.length;
		int mapColumnCount = this.map[0].length;
		
		for(int i=0;i<mapRowCount - 1;i++)		//20行
		{
			for(int j=1;j<mapColumnCount - 1;j++)	//10列
			{
				if(this.map[i][j] > 0)
				{
					count++;
					if(count == (mapColumnCount - 2))	//满行了,可以销毁该行
					{
						for(int m=i;m>0;m--)			//从当前行往回计算
						{
							for(int n=1;n<mapColumnCount - 1;n++)
							{
								this.map[m][n] = this.map[m-1][n];
							}
						}
						this.score += 10;
					}
				}
			}
			count = 0;	//开始下一行计数
		}
	}

	/**
	 * 功能:判断当前方块的位置是否合法<br>
	 * 参数:_row -> 图形左上角所在行 <br>
	 * 参数:_column -> 图形左上角所在列 <br>
	 * 参数:_shape -> 移动变化的图形 <br>
	 * 返回:0-不合法(可能与围墙或其他固定的方块位置重叠),1-合法<br>
	 */
	private int blow(int _row,int _column,byte[][] _shape)
	{
		int rowCount = _shape.length;
		int columnCount = _shape[0].length;
		
		//方块所在的行列与墙或其他方块的行列都大于0或-1
		for(int i=0;i<rowCount;i++)
		{
			for(int j=0;j<columnCount;j++)
			{
				if(_shape[i][j] > 0)	//对该图形进行循环,找出大于零的数,即是方块
				{
					//判断墙
					if(this.map[_row + i][_column + j] == -1){return 0;}
					//判断固定方块
					if(this.map[_row + i][_column + j] > 0){return 0;}
				}
			}
		}
		
		return 1;
	}

	/**
	 * 功能:方块移动<br>
	 * 返回:true -> 可以移动旋转,需要刷新地图,false ->不可以,也不需要刷新地图<br>
	 */
	public boolean move(int keyCode)
	{
		if(keyCode == KeyEvent.VK_UP)			//向上旋转
		{
			//得到逆时针要变的旋转变形
			int tempTurnState = (this.turnState + 1) % this.shape.length;
			byte[][] turnShape = GameMap.getShape(this.blockType,tempTurnState);
			if(blow(this.shapeRow,this.shapeColumn,turnShape) == 1)
			{
				this.shape = turnShape;
				this.turnState = tempTurnState;
			}
			else
			{
				return false;
			}
		}
		else if(keyCode == KeyEvent.VK_DOWN)		//向下移动
		{
			if(blow(this.shapeRow + 1,this.shapeColumn,this.shape) == 1)
			{
				this.shapeRow++;
			}
			else
			{
				this.add();
				this.deleteLine();
				this.newBlock();
			}
		}
		else if(keyCode == KeyEvent.VK_LEFT)		//向左移动
		{
			if(blow(this.shapeRow,this.shapeColumn - 1,this.shape) == 1)	//可以向左移
			{
				this.shapeColumn--;
			}
			else
			{
				return false;
			}
		}
		else if(keyCode == KeyEvent.VK_RIGHT)		//向右移动
		{
			if(blow(this.shapeRow,this.shapeColumn + 1,this.shape) == 1)	//可以向右移
			{
				this.shapeColumn++;
			}
			else
			{
				return false;
			}
		}
		
		return true;
	}

	/**
	 * 功能:判断游戏是否结束<br>
	 * 参数:true -> 已结束<br>
	 * 参数:false -> 未结束<br>
	 */
	public boolean gameOver()
	{
		if(blow(this.shapeRow,this.shapeColumn,this.shape) == 0)	//如果碰到围墙或固定方块,游戏结束。
		{
			this.score = 0;
			JOptionPane.showMessageDialog(null,"大虾,请重新来过吧!","提示",JOptionPane.ERROR_MESSAGE);
			return true;
		}
		else
		{
			return false;
		}
	}

	/**
	 * 功能:返回大地图(共21行12列,该地图包含墙和固定死的方块信息)<br>
	 */
	public byte[][] getMap()
	{
		return map;
	}

	/**
	 * 功能:返回当前方块图形<br>
	 */
	public byte[][] getShape()
	{
		return shape;
	}

	/**
	 * 功能:返回当前方块图形(4×4矩阵)左上角所在行<br>
	 */
	public int getShapeRow()
	{
		return shapeRow;
	}

	/**
	 * 功能:返回当前方块图形(4×4矩阵)左上角所在列<br>
	 */
	public int getShapeColumn() 
	{
		return shapeColumn;
	}

	/**
	 * 功能:返回下一个随机方块<br>
	 */
	public byte[][] getNextShape()
	{
		return nextShape;
	}

	/**
	 * 功能:返回分数 <br>
	 */
	public int getScore() 
	{
		return score;
	}
	
	
}

5. GameMap.java game map class.

package com.game.tetris;

/**
 * 功能:游戏地图<br>
 * 作者:我是小木鱼(Lag)<br>
 */
public class GameMap 
{
	/** 游戏大地图(存储方块[1~7]和围墙[-1]及空块[0]的信息,共21行12列252个小方格) */
	private static byte[][] map = 
		{
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},	
			{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1}	
		};
	
	/** 方块图形(存储七种形状及其四种旋转变形<逆时针旋转90度>,每种旋转变形用包含4×4的数组表示具体图形<盯住大于零的数字猛看,就能看到图形了>) */
	private static byte shape[][][][] = new byte[][][][]
	{
		//长条形方块
		{
			//旋转变形一
			{
				{0, 0, 0, 0},
				{1, 1, 1, 1},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形二
			{
				{0, 1, 0, 0},
				{0, 1, 0, 0},
				{0, 1, 0, 0},
				{0, 1, 0, 0}
			},
			//旋转变形三
			{
				{0, 0, 0, 0},
				{1, 1, 1, 1},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形四
			{
				{0, 1, 0, 0},
				{0, 1, 0, 0},
				{0, 1, 0, 0},
				{0, 1, 0, 0}
			}
		},
		//Z形方块
		{
			//旋转变形一
			{
				{2, 2, 0, 0},
				{0, 2, 2, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形二
			{
				{0, 2, 0, 0},
				{2, 2, 0, 0},
				{2, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形三
			{
				{2, 2, 0, 0},
				{0, 2, 2, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形四
			{
				{0, 2, 0, 0},
				{2, 2, 0, 0},
				{2, 0, 0, 0},
				{0, 0, 0, 0}
			}
		},
		//倒Z字形方块
		{
			//旋转变形一
			{
				{0, 3, 3, 0},
				{3, 3, 0, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形二
			{
				{3, 0, 0, 0},
				{3, 3, 0, 0},
				{0, 3, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形三
			{
				{0, 3, 3, 0},
				{3, 3, 0, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形四
			{
				{3, 0, 0, 0},
				{3, 3, 0, 0},
				{0, 3, 0, 0},
				{0, 0, 0, 0}
			}
		},
		//J形方块
		{
			//旋转变形一
			{
				{0, 4, 0, 0},
				{0, 4, 0, 0},
				{4, 4, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形二
			{
				{4, 4, 4, 0},
				{0, 0, 4, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形三
			{
				{4, 4, 0, 0},
				{4, 0, 0, 0},
				{4, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形四
			{
				{4, 0, 0, 0},
				{4, 4, 4, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			}
		},
		//L字形
		{
			//旋转变形一
			{
				{5, 0, 0, 0},
				{5, 0, 0, 0},
				{5, 5, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形二
			{
				{0, 0, 5, 0},
				{5, 5, 5, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形三
			{
				{5, 5, 0, 0},
				{0, 5, 0, 0},
				{0, 5, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形四
			{
				{5, 5, 5, 0},
				{5, 0, 0, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			}
		},
		//T字形方块
		{
			//旋转变形一
			{
				{0, 6, 0, 0},
				{6, 6, 6, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形二
			{
				{0, 6, 0, 0},
				{6, 6, 0, 0},
				{0, 6, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形三
			{
				{6, 6, 6, 0},
				{0, 6, 0, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形四
			{
				{6, 0, 0, 0},
				{6, 6, 0, 0},
				{6, 0, 0, 0},
				{0, 0, 0, 0}
			}
		},
		//田字形方块
		{
			//旋转变形一
			{
				{7, 7, 0, 0},
				{7, 7, 0, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形二
			{
				{7, 7, 0, 0},
				{7, 7, 0, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形三
			{
				{7, 7, 0, 0},
				{7, 7, 0, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			},
			//旋转变形四
			{
				{7, 7, 0, 0},
				{7, 7, 0, 0},
				{0, 0, 0, 0},
				{0, 0, 0, 0}
			}
		}
	};
	
	/**
	 * 功能:返回大地图<br>
	 * 备注:由于原始地图数据不允许修改,因此只返回复制后的地图赝品<br>
	 */
	public static byte[][] getMap()
	{
		//由于数组是个对象,而原始地图是不允许被修改的,所以不能直接赋值(引用地址),得复制一个新的地图让游戏随便修改。
		int row = map.length;
		int column = map[0].length;
		byte[][] copyMap = new byte[row][column];
		for(int i=0;i<row;i++)
		{
			for(int j=0;j<column;j++)
			{
				copyMap[i][j] = map[i][j];
			}
		}
		return copyMap;
	}
	
	/**
	 * 功能:返回方块图形<br>
	 * 参数:int _blockType -> 方块类型<br>
	 * 参数:int _turnState -> 旋转状态<br>
	 * 备注:由于原始方块图形数据不允许修改,因此只返回复制后的方块图形赝品<br>
	 */
	public static byte[][] getShape(int _blockType,int _turnState)
	{
		byte[][] temp = shape[_blockType][_turnState];
		//开始复制
		int row = temp.length;
		int column = temp[0].length;
		byte[][] shapeMap = new byte[row][column];
		for(int i=0;i<row;i++)
		{
			for(int j=0;j<column;j++)
			{
				shapeMap[i][j] = temp[i][j];
			}
		}
		return shapeMap;
	}
	
}

Detailed explanation: 

to be continued...

Run: 

        Make a DOS batch file, tetris.bat, with the following content:

@echo off
start javaw com.game.tetris.Tetris

  download: 

        Baidu network disk link: https://pan.baidu.com/s/1g1h9Zn1KmIoMWCMGLV1nCA Extraction code: h5m2

Remarks: 

none

Guess you like

Origin blog.csdn.net/lag_csdn/article/details/124711977