一、用Java实现俄罗斯方块游戏:
1、效果图,如下图所示:
7种形态的第一种形态, 如下所示:分布是 :|、S、Z、J、O、L、T;
0 1 0 0 0 1 1 0 1 1 0 0 0 1 0 0 1 1 0 0 1 0 0 0 1 1 1 0
0 1 0 0 1 1 0 0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
我在绘制图形的时候,让1的坐标绘制出来,0 不绘制;横数4位数,竖数4位数,16位数为一组形态;
1.1.需要新建窗口;
1.2.绘制游戏内容;
1.3.实现形状旋转功能;
1.4.实现形状的移动;(监听键盘事件)
1.5.实现图形自动降落;
2、首先创建java项目,web Project
3、创建项目成功后,添加一个class文件(文件名自定义命名),代码如下:
package com.gx.games;
import java.awt.Color;
import java.awt.Font;
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 java.util.Random;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
/**
* 俄罗斯方块游戏主体类
* @author LXT
*
*/
public class TetrisPanel extends JPanel implements KeyListener{
TetrisPanel () {
newBlock();
newMap();
drawWall();//调用画围墙方法
Timer timer = new Timer(1000, new TimeListener());
timer.start();//启动定时器
}
Random random = new Random();
private int score = 0;
private int delLineNum = 0;
//定义方块的初始坐标;
private int x;
private int y;
//shapes[0][1]
private int blockType;//方块的类型 = random.nextInt(7)
private int turnState;//方块的旋转状态 = random.nextInt(4)
private int preBlockType = random.nextInt(7);
private int preTurnState = random.nextInt(4);
//定义方块的大小
private int blockSize = 10;
//定义地图大小
private int mapSizeX = 17;
private int mapSizeY = 28;
//定义地图
int[][] map = new int[mapSizeX][mapSizeY];
int i;
int j;
//地图中的值 0:没有 1:绘制形状 2:绘制围墙
//定义形状
private final static int shapes[][][] = new int[][][]{
// |型
{
{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},
},
// S型
{
{0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
},
// Z型
{
{1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
},
// J型
{
{0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
// O型
{
{1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
// L型
{
{1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
// T型
{
{1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
}
};
/**
* 产生新的形状
*/
public void newBlock(){
//当前形状用预览形状代替
blockType = preBlockType;
turnState = preTurnState;
//第三个
preBlockType = random.nextInt(7);
preTurnState = random.nextInt(4);
//初始化xy坐标(方块的出现位置)
x = 6;
y = 0;
if (gameOver (x, y) == 0) {
newMap();
drawWall();
JOptionPane.showMessageDialog(null, "GAME OVER!");
}
}
/**
* 填充围墙
*/
public void drawWall(){
for(i = 0; i < mapSizeX - 1; i++){
map[i][mapSizeY - 2] = 2;//绘制右边的围墙
}
for(j = 0; j < mapSizeY - 1; j++){
map[0][j] = 2;//绘制左边的围墙
map[mapSizeX - 2][j] = 2;//绘制底下的围墙
}
}
/**
* 初始化地图
*/
public void newMap () {
for (i = 0; i < mapSizeX - 1; i++){
for (j = 0; j < mapSizeY - 1; j++){
map[i][j] = 0;
}
}
}
/**
* 改变方向
*/
public void turn () {
int tempTurnState = turnState;
//产生新的方向代码
turnState = (turnState + 1) % 4;
if (check (x,y,blockType, turnState) == 0) {
turnState = tempTurnState;
}
repaint();
}
//左移
public void left () {
if (check (x - 1, y, blockType, turnState) == 1) {
x = x - 1;
}
repaint();
}
//右移
public void right () {
if (check (x + 1, y, blockType, turnState) == 1) {
x = x + 1;
}
repaint();
}
//下降
public void down () {
delLineNum = 0;
if (check (x, y + 1, blockType, turnState) == 1) {
y = y + 1;
delLine();
}
if (check (x, y + 1, blockType, turnState) == 0) {
add(x, y, blockType, turnState);
newBlock();
delLine();
}
//制订分数
switch (delLineNum) {
case 1:score += 10; break;
case 2:score += 50; break;
case 3:score += 100; break;
case 4:score += 200; break;
}
repaint();
}
/**
* 添加一个形状
* @param x
* @param y
* @param blockType
* @param turnState
*/
public void add (int x, int y, int blockType, int turnState) {
int j = 0;
for (int outer = 0; outer < 4; outer++) {
for (int inner = 0; inner < 4; inner++) {
if (map[x + inner + 1][y + outer] == 0) {
map[x + inner + 1][y + outer] = shapes[blockType][turnState][j];
}
j++;
}
}
}
//消行
public void delLine () {
int flag = 0;
for(int y = 0; y < mapSizeY - 1; y++) {
for(int x = 0; x < mapSizeX - 1; x++) {
if(map[x][y] == 1) {
flag = flag + 1;
//判断是否填充满一行
if(flag == mapSizeX - 3) {
delLineNum++;
for (int d = y; d > 0; d--) {
for (int e = 0; e < mapSizeX - 2; e++) {
map[e][d] = map[e][d - 1];
}
}
}
}
}
flag = 0;
}
}
/**
* 判断是不是游戏结束
* @param x
* @param y
* @return
*/
public int gameOver (int x , int y) {
if (check (x, y, blockType, turnState) == 0) {
return 0;
}
return 1;
}
/**
* 检查操作是否有效
* @param x
* @param y
* @param blockType
* @param turnState
* @return
*/
public int check (int x, int y, int blockType, int turnState) {
for (int outer = 0; outer < 4; outer++) {
for (int inner = 0; inner < 4; inner++) {
boolean flag1 = shapes[blockType][turnState][outer * 4 + inner] == 1;
boolean flag2 = map[x + inner + 1][y + outer] == 1;
boolean flag3 = map[x + inner + 1][y + outer] == 2;
if ((flag1 && flag2) || (flag1 && flag3)) {
return 0;//碰到一起 无效
}
}
}
return 1;//有效
}
/**
* 真正绘制
*/
@Override
public void paintComponent (Graphics g){
super.paintComponent(g);//调用paintComponent方法,绘制一些父类的东西
g.setColor(Color.BLACK);
//画形状
for (j = 0; j < 16; j++){
if (shapes[blockType][turnState][j] == 1){
int x1 = (j % 4 + x + 1) * blockSize;
int y1 = (j / 4 + y) * blockSize;
g.fillRect(x1, y1, blockSize, blockSize);
}
}
//固定方块
for (j = 0; j < mapSizeY - 1; j++){
for (i = 0; i < mapSizeX - 1; i++){
//已固定的方块
if (map[i][j] == 1){
g.setColor(Color.BLACK);//设置一个颜色(黑色)
g.fillRect(i * blockSize, j * blockSize, blockSize, blockSize);//填充
}
if(map[i][j] == 2){
g.drawRect(i * blockSize, j * blockSize, blockSize, blockSize);//画线
}
}
}
//画预览图
for (j = 0; j < 16; j++){
if (shapes[preBlockType][preTurnState][j] == 1){
int x1 = (j % 4 + 20) * blockSize;
int y1 = (j / 4 + 1) * blockSize;
g.fillRect(x1, y1, blockSize, blockSize);
}
}
g.setColor(Color.BLUE);
g.setFont(new Font ("宋体", Font.BOLD, 16));
g.drawString("得分:" + score, 170, 80);
g.drawString("软件IT学院", 170, 110);
g.drawString("2016级1班", 170, 140);
g.drawString("默默雨[著]", 170, 170);
g.drawString("[版权所有]", 170, 200);
g.drawString("代号:12580", 170, 230);
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
int KeyCode = e.getKeyCode();
switch (KeyCode) {
case KeyEvent.VK_DOWN:
//执行下降
down();
break;
case KeyEvent.VK_UP:
//执行变形
turn();
break;
case KeyEvent.VK_RIGHT:
//右移
right();
break;
case KeyEvent.VK_LEFT:
//左移
left();
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
/**
* 定时器 自动下降
* @author LXT
*
*/
class TimeListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//repaint();
down();
}
}
}
4、然后在创建一个class文件(文件名自定义命名),代码如下:
package com.gx.games;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
public class LiuTetnis extends JFrame {
public LiuTetnis () {
TetrisPanel panel = new TetrisPanel ();
addKeyListener(panel);
add(panel);
}
public static void main(String[] args) {
LiuTetnis frame = new LiuTetnis ();
frame.setLocationRelativeTo(null); // 居中
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//点击关闭按钮,退出程序
frame.setSize(270, 330);//设置窗体大小(高度和宽度)
frame.setTitle("俄罗斯方块");//设置窗体标题
//菜单栏
JMenuBar menuBar = new JMenuBar();
JMenu help = new JMenu("帮助");
JMenuItem about = help.add("关于");
menuBar.add(help);
about.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "【俄罗斯方块练习版】作者:软件学院-liu");
}
});
frame.setJMenuBar(menuBar);
//菜单栏
frame.setVisible(true);//让窗体显示出来
frame.setResizable(false);//不能调整窗口大小
}
}
5、然后在main方法里面的任意地方点击鼠标右键选择“Run AS”,选择“Java Application”,进行启动即可。