Java学习之路———俄罗斯方块

一、游戏简介

俄罗斯方块,相信大家都很熟悉这个游戏了。记得以前还在qq游戏里火过一阵子。这次的练习就是用java来实现这个小游戏,这次是带图形界面的游戏了,不再是简略版。

先看一下游戏的运行图片。
在这里插入图片描述

我们首先要完成对这个游戏界面的绘制,下面的游戏信息类是完成右边信息面板的绘制,地图类则是左边游戏区的绘制。绘制的具体方法在注释里都有详细提到。主要就是重写了paintComponent 的方法

二、游戏信息类

这是右边的游戏信息类,最上方的是一张图片和中间的4*4 的方格与下面的文字,都是通过paintComponent()这个方法来画上去的。需要注意的是画线的位置和其他文字的位置。在第一次操作计算的的时候最好 拿一张纸,画一画可以更好的理解

具体的逻辑都注释里都写的很详细

package com.yc.Tetris;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.LayoutManager;
import java.awt.Toolkit;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class GameInfo extends JPanel {
	private JLabel score ;
	private JLabel bestScore;
	private JLabel bestOwner;
	//数组存储形状
	private int[] shape = null;
	
	//构造函数
	public GameInfo() {
		init();
	}
	//初始化界面
	private void init() {
		//绝对定位
		this.setLayout(null);
		JLabel label_1 = new JLabel("得分");
		JLabel label_5 = new JLabel("最高分");
		//JLabel label_6 = new JLabel("保持者");
		//设置字体颜色
		label_1.setForeground(Color.red);
		label_5.setForeground(Color.red);
		//设置字体
		Font font = new Font("微软雅黑",Font.BOLD,24);
		label_1.setFont(font);
		label_5.setFont(font);
		//设置位置
		label_1.setBounds(0,340,80,30);
		label_5.setBounds(0,390,80,30);
		
		score = new JLabel("0");
		score.setForeground(Color.RED);
		score.setFont(font);
		score.setBounds(85,340,165,30);
		
		bestScore = new JLabel("0");
		bestScore.setForeground(Color.RED);
		bestScore.setFont(font);
		bestScore.setBounds(85,390,165,30);
		
		//游戏温馨提示
		JLabel label_3 = new JLabel("适当游戏益脑, 沉迷游戏伤身。");
		JLabel label_4 = new JLabel("合理安排时间, 享受健康生活。");
		
		
		
		Font f = new Font("微软雅黑",Font.BOLD,18);
		label_3.setForeground(Color.ORANGE);
		label_4.setForeground(Color.ORANGE);
		
		label_3.setFont(f);
		label_4.setFont(f);
		
		label_3.setBounds(0,440,260,45);
		label_4.setBounds(0,485,260,45);
		
		this.add(label_1);
		this.add(score);
		this.add(bestScore);
		this.add(label_3);
		this.add(label_4);
		this.add(label_5);
		
	}
	@Override
	protected void paintComponent(Graphics g) {//g就是画笔
		// TODO Auto-generated method stub
		super.paintComponent(g);
		ImageIcon img = new ImageIcon(Toolkit.getDefaultToolkit().getImage(Test.class.getResource("/com/yc/Tetris/images/pic2.jpg")));
		//开始画图     画的那张图   x   y   大小                绘制对象的容器
		g.drawImage(img.getImage(), 0, 10, 260, 85, null);
		
		//画方块
		if(shape != null) {
			for(int i = 0; i < shape.length; i++) {
				if(shape[i] == 1) {
					//先设置颜色
					g.setColor(Color.orange);
					
					// 40-130 80-130 120-130 160-130; 40-170 80-170 120-170  160-170
					g.fillRect(40 + (i % 4) * 40, 130 + (i / 4) * 40, 40, 40); //从那个点开始画,画多宽  多高
				}
			}
		}
		
		//图片画完 开始画线
		//循环画线
		for(int i = 1; i < 6; i++) {
			//一个小格子长40
			g.setColor(Color.white);
			g.drawLine(40, 90 + i*40, 200, 90 + i * 40);
			g.drawLine( i * 40, 130,  i * 40, 290);
		}
		
	}
	
	public void showNext(int[] shape) {
		this.shape = shape;
		//每次调用这个方法,意味着要重新显示方块,那么每次都要重新绘制一下
		repaint();
	}
	
	
	public  void setScore(int score) {
		this.score.setText(score + "");
	}
	
	public void setBestScore(int bestScore) {
		this.bestScore.setText(bestScore + "");
	}
	

	
	
}

三、游戏地图类

地图也是一个二维数组,墙壁的值为2,方块的值为1,空的值为0

左边的游戏区,具体的游戏的逻辑方法都在这里
需要解决的主要问题是:
1.方块的随机生成
2.方块的下落
3.方块的形态转变,左移,右移,加速下降
4.碰撞检测
5.方块的消除以及积分的增加

1.方块的随机生成
一共又7类方块的形状,每个方块有不同的形态
我们用一个长度为16 的一维数组来存储一种形态。
一个形状的四种形态又是一个数组
7种类型又是一维数组
所以用一个三维数组来存储方块的形态
通过随机函数随机数组的下标来随机生成方块

2.方块的下落
用一个定时器来重绘地图,每次重绘方块有下落一个单位

3.方块的形态转变
通过键盘监听事件实现,形态转变通过改变数组的下标实现,左移右移通过方块在地图上的位置的改变来实现

4.碰撞检测
当方块碰到墙壁和地图上其他的方块时,都要进行碰撞检测,具体的逻辑看详细代码。

5.方块的消除以及积分的增加,定义一个计数器,通过循环,当当前位置是1 的时候自加,当count的值等于一层的值的时候,消除该层,该层上方的全部下移。每消除一次积分增加

package com.yc.Tetris;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Map extends JPanel{
	//先定义右边游戏区域的大小
	private int width = 420;
	private int height = 660;
	private int score;
	
	//方块的状态 种类
	private int blockType;
	private int turnState;
	
	private int newType = -1;
	private int newState;
	//随机数
	Random r = new Random();
	//gameinfo 对象
	private GameInfo gameInfo;
	//音乐对象
	private MusicUtil music;
	//定时器
	private Timer timer;
	private int x;
	private int y;
	//最高分的文件
	private File highestScore;
	private boolean isGameOver = false;
	//定义区域
	public static int[][] map = new int[22][14];
	//形状
	public static int[][][] shapes = {
			//  一
			{ {
				0,1,0,0,
				0,1,0,0,
				0,1,0,0,
				0,1,0,0
			},{
				1,1,1,1,
				0,0,0,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,1,0,0,
				0,1,0,0,
				0,1,0,0,
				0,1,0,0
			},{
				1,1,1,1,
				0,0,0,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,1,1,0,
				0,1,1,0,
				0,0,0,0,
				0,0,0,0
			} },
			// 7 
			{{
				0,1,1,0,
				0,0,1,0,
				0,0,1,0,
				0,0,0,0
			},{
				0,0,1,0,
				1,1,1,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,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
			}},
			//反7
			{{
				0,1,1,0,
				0,1,0,0,
				0,1,0,0,
				0,0,0,0
			},{
				1,1,1,0,
				0,0,1,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,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,0,0,
				1,1,1,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,1,0,0,
				0,1,1,0,
				0,1,0,0,
				0,0,0,0
			},{
				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
			}},
			//  z
			{{
				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,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
			}},
			//  反z
			{{
				1,1,0,0,
				0,1,1,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,0,1,0,
				0,1,1,0,
				0,1,0,0,
				0,0,0,0
			},{
				1,1,0,0,
				0,1,1,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,0,1,0,
				0,1,1,0,
				0,1,0,0,
				0,0,0,0
			}}
	};
	
	//构造函数
	public Map(GameInfo gameInfo) {
		this.gameInfo = gameInfo;
		//实例化定时器
		
		timer = new Timer(1000, new TimerListener());
		
		init();
	}

	private void init() {
		// TODO 游戏初始化
		initMap();
		drawWall();
		music = new MusicUtil();
		MusicUtil.ac.loop();
		newBlock();
		//开启定时器
		timer.start();
		
	}

	private void newBlock() {
		// TODO 随机下标值
		// 判断是刚开始还是 已经开始一轮了
		if (newType == -1) {
			//游戏刚开始
			
			blockType = r.nextInt(7);  //0-6
			turnState = r.nextInt(4);
			
			newType = r.nextInt(7);	  
			newState = r.nextInt(4); //0-3
		}else {
			//不是游戏刚开始,当前状态就是new出来的上一个状态
			blockType = newType;
			turnState = newState;
			//新状态随机
			newType = r.nextInt(7);	  
			newState = r.nextInt(4); //0-3
		}
		
		//在右下的区域,显示下一次的方法
		gameInfo.showNext(shapes[newType][newState]);
		
		//规定新的方块生成的位置
		x = 5;
		y = 0;
		
		//游戏结束
		if(isGameOver) {
			timer.stop();//停止计时器
			
			MusicUtil.ac.stop();
			music.gameOver();
			judgeScore();
			int index = JOptionPane.showConfirmDialog(this, "就这? 再来一局!","游戏结束",JOptionPane.YES_NO_CANCEL_OPTION);
			if(index == 0) {
				//再来一局
				repaint();
				init();
				
			}else {
				System.exit(1);
			}
		}
	}
	//判断 是否超过历史最高分
	private void judgeScore() {
		highestScore = new File("E:\\新建文件夹\\java\\javadata\\API\\src\\com\\yc\\Tetris\\images\\HigestScore.txt");
		String str = "";
		try {
			BufferedInputStream is = new BufferedInputStream(new FileInputStream(highestScore));
			byte[] bs = new byte[is.available()];
			 is.read(bs);
			 str = new String(bs);
			 System.out.println(str);
		
		
			 int temp = Integer.parseInt(str);
			 //读取的数据大于 最高分则替换
			 if(score > temp) {
				String s = score + "";
				BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(highestScore));
				os.write(s.getBytes());
				os.flush();
				os.close();
			}
			 is.close();
			 
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	//初始化地图
	private void initMap() {
		
		MusicUtil.ac.loop();
		showBestScore();
		score = 0;
		isGameOver =false;
		gameInfo.setScore(score);
		
		for(int i = 0;i < 22 ;i++) {
			for(int j = 0; j < 14; j++) {
				map[i][j] = 0;
			}
		}
	}
	//显示最高分
	private void showBestScore() {
		// TODO Auto-generated method stub
		highestScore = new File("E:\\新建文件夹\\java\\javadata\\API\\src\\com\\yc\\Tetris\\images\\HigestScore.txt");
		
		
			BufferedInputStream is;
			try {
				is = new BufferedInputStream(new FileInputStream(highestScore));
				byte[] bs = new byte[is.available()];
				 is.read(bs);
				 String str = new String(bs);
				 int bestScore = Integer.parseInt(str);
				 gameInfo.setBestScore(bestScore);
				 System.out.println(str);
				 
				 is.close();
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		
	}

	/**
	 * 碰撞检测
	 * @param x            当前位置
	 * @param y
	 * @param blockType    方块类型
	 * @param turnState
	 */
	public boolean checkCrash(int x, int y,int blockType , int turnState) {
		//首先循环方块
		for(int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				  //                                                         xy 和index反过来的                         
				if(shapes[blockType][turnState][i * 4 + j] == 1 && map[y + i + 1][x + j] == 2) {
					//当方块的值为1  才做碰撞检测 撞到墙
					
					return true;
					
				}
				if(shapes[blockType][turnState][i * 4 + j] == 1 && map[y + i + 1][x + j] == 1) {
					//当方块的值为1  才做碰撞检测 撞到墙
					if( y + i <= 1) {
						//游戏结束
						isGameOver = true;
					}
					//撞到其他方块
					return true;
					
				}
				
			}
		}
		
		
		//没有碰撞
		return false;
		
	}
	
	public boolean checkCrashL(int x3 ,int y3 , int blockType, int turnState) {
		//首先循环方块
		for(int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				  //                                                         xy 和index反过来的                         
				if(shapes[blockType][turnState][i * 4 + j] == 1 && map[y + i][x + j - 1 ] == 2) {
					//当方块的值为1  才做碰撞检测 撞到墙
					
					return true;
					
				}
				if(shapes[blockType][turnState][i * 4 + j] == 1 && map[y + i ][x + j - 1 ] == 1) {
					//当方块的值为1  才做碰撞检测 撞到墙
					if( y + i <= 1) {
						//游戏结束
						isGameOver = true;
					}
					//撞到其他方块
					return true;
					
				}
				
			}
		}
		
		
		//没有碰撞
		return false;
	}
	
	public boolean checkCrashR(int x3 ,int y3 , int blockType, int turnState) {
		//首先循环方块
		for(int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				  //                                                         xy 和index反过来的                         
				if(shapes[blockType][turnState][i * 4 + j] == 1 && map[y + i][x + j + 1 ] == 2) {
					//当方块的值为1  才做碰撞检测 撞到墙
					
					return true;
					
				}
				if(shapes[blockType][turnState][i * 4 + j] == 1 && map[y + i ][x + j + 1 ] == 1) {
					//当方块的值为1  才做碰撞检测 撞到墙
					if( y + i <= 1) {
						//游戏结束
						isGameOver = true;
					}
					//撞到其他方块
					return true;
					
				}
				
			}
		}
		
		
		//没有碰撞
		return false;
	}
	/**
	 * 将 方块添加到map数组中去
	 * @param x2
	 * @param y2
	 * @param blockType2
	 * @param turnState2
	 */
	private void add(int x2, int y2, int blockType2, int turnState2) {
		
		for (int i = 0; i < 4; i++) {
			
			for (int j = 0; j < 4; j++) {
				if( y + i > 20 || x + j < 1 || x + j > 12) {
					//边界不能替换
					continue;
				}else {
					if(map[y + i ][x + j ]== 0) {
						//地图为空
						map[y + i][x + j] = shapes[blockType][turnState][i * 4 + j];
					}
					
				}
				
			}
		}
		
	}
	private void drawWall() {
		// TODO 画墙
		for(int i = 0; i < 14; i++) {
			map[21][i] = 2;
		}
		for(int i = 0; i < 22; i++) {
			map[i][0] = 2;
			map[i][13] = 2;
		}
		
	}
	
	//键盘触发的操作
	public void up(){
		int temp = turnState;
		turnState = (turnState + 1) % 4;
		if(checkCrash(x, y, blockType, turnState)) {
			turnState = temp;
		}
		repaint();
		
	}
	
	public void left(){
		if(! checkCrashL(x,y,blockType,turnState)) {
			x--;
			
		}
		repaint();
	}
	
	public void right(){
		if(! checkCrashR(x,y,blockType,turnState)) {
			x++;
			
		}
		repaint();
	}
	
	public void down(){
		if(! checkCrash(x,y,blockType,turnState)) {
			y++;
			
		}else {
			add(x,y,blockType,turnState);
			newBlock();
			//判断能否消除
			removeLine();
		}
		repaint();
	}
	
	private void removeLine() {
		int count = 0;
		for (int i = 0; i < 21; i++) {
			for (int j = 1; j < 13; j++) {
				if(map[i][j] == 1) {
					count ++ ;
					//将地图上面的图像整体往下移
					if(count >= 12) {
						for (int a = i;a > 1; a--) {
							for(int b = 1; b < 13 ; b++) {
								map[a][b] = map[a-1][b];
							}
						}
						//每消除一行+ 10 分
						score += 10;
						gameInfo.setScore(score);
						music.removeMusic();
						if(score > 50 && score <100) {
							timer.setDelay(700);
						}else if (score > 100 && score <200 ) {
							timer.setDelay(500);
						}else if(score > 200 && score < 300){
							timer.setDelay(300);
						}else if(score > 300) {
							timer.setDelay(100);
						}
						count = 0;
						
					}
				}else {
					//中间有空的不能消除, 直接判断下一行,记得清零
					count = 0;
					break;
				}
			}
		}
		
	}

	//重写绘图方法
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		//开始画黄色方块
		for(int i = 0; i < 16; i++) {
			//值为1,才画黄色方块
			if( shapes[blockType][turnState][i] == 1) {
				g.setColor(Color.orange);
				//经典画矩形
				g.fillRect((i % 4 + x) * 30, (i / 4 + y) * 30, 30, 30);
			}
		}
		
		//开始画形状和边框
		for(int i = 0; i < 22; i++) {
			for(int j = 0; j < 14; j++) {
				if(map[i][j]==1) {
					//黄色区域
					g.setColor(Color.orange);
					g.fillRect(j * 30, i * 30, 30 , 30);
				}else if(map[i][j] == 2) {
					//黑色边框
					g.setColor(Color.black);
					g.fillRect(j * 30, i * 30, 30, 30);
				}
			}
		}
		
		//画线
		g.setColor(Color.WHITE);
		for(int i = 1; i < 22 ; i++) {
			//0 30 - 420 30
			//0 60 - 420 60
			//0 90 - 420 90
			g.drawLine(0, 30 * i, 420, 30 * i);
		}
		for(int i = 1; i < 14 ;i++) {
			g.drawLine(i * 30, 0 , i * 30, 660);
		}
		
		
		
	}
	
	//定时器的实现
	class TimerListener implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			//重绘
			repaint();
			
			if(! checkCrash(x,y,blockType,turnState)) {
				y++;
				
			}else {
				//将方块添加到地图中
				add(x,y,blockType,turnState);
				//判断能否消除
				removeLine();
				newBlock();
			}
			//repaint();
			
		}

		
		
	}
	
	
}

四、音乐类

播放背景音乐,消除音乐 ,游戏结束的音乐

package com.yc.Tetris;

import java.applet.Applet;
import java.applet.AudioClip;
import java.net.URL;

public class MusicUtil {
		//开始播放背景音乐
	static URL url = MusicUtil.class.getClass().getResource("/com/yc/Tetris/Music/4296.wav");
	static AudioClip ac = Applet.newAudioClip(url);
	
	
	
	public void removeMusic(){
		URL url = MusicUtil.class.getClass().getResource("/com/yc/Tetris/Music/9297.wav");
		AudioClip ac = Applet.newAudioClip(url);
		//循环播放
		ac.play();
	}
	
	public void gameOver() {
		URL url = MusicUtil.class.getClass().getResource("/com/yc/Tetris/Music/gameover.wav");
		AudioClip ac = Applet.newAudioClip(url);
		//循环播放
		ac.play();
	}
}

五、测试类

游戏还做了最高分的记录,通过文件的操作实现的,在地图类里有写到
根据积分的增长,加快下降速度,也是一个简单的判断,通过计时器的setdelay()实现 有兴趣的可以 仔细看一看

package com.yc.Tetris;

import java.awt.BorderLayout;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JSplitPane;

public class Test {
	public static int[][][] shapes = {
			//  一
			{ {
				0,1,0,0,
				0,1,0,0,
				0,1,0,0,
				0,1,0,0
			},{
				1,1,1,1,
				0,0,0,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,1,0,0,
				0,1,0,0,
				0,1,0,0,
				0,1,0,0
			},{
				1,1,1,1,
				0,0,0,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,1,1,0,
				0,1,1,0,
				0,0,0,0,
				0,0,0,0
			} },
			// 7 
			{{
				0,1,1,0,
				0,0,1,0,
				0,0,1,0,
				0,0,0,0
			},{
				0,0,1,0,
				1,1,1,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,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
			}},
			//反7
			{{
				0,1,1,0,
				0,1,0,0,
				0,1,0,0,
				0,0,0,0
			},{
				1,1,1,0,
				0,0,1,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,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,0,0,
				1,1,1,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,1,0,0,
				0,1,1,0,
				0,1,0,0,
				0,0,0,0
			},{
				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
			}},
			//  z
			{{
				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,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
			}},
			//  反z
			{{
				1,1,0,0,
				0,1,1,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,0,1,0,
				0,1,1,0,
				0,1,0,0,
				0,0,0,0
			},{
				1,1,0,0,
				0,1,1,0,
				0,0,0,0,
				0,0,0,0
			},{
				0,0,1,0,
				0,1,1,0,
				0,1,0,0,
				0,0,0,0
			}}
	};
	public static void main(String[] args) {
		JFrame jf = new JFrame();
		jf.setSize(696,696);
		jf.setTitle("俄罗斯方块");
		jf.setLocationRelativeTo(null);//居中显示
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jf.setResizable(false);
		//设置图标
		jf.setIconImage(Toolkit.getDefaultToolkit().getImage(Test.class.getResource("/com/yc/Tetris/images/logo.png")) );
		//实例化面板
		
		//定义一个分割面板
		JSplitPane jSplitpane = new JSplitPane();
		//添加到JFrame里去
		jf.add(jSplitpane,BorderLayout.CENTER);
		//实例化两个面板
		GameInfo gameinfo = new GameInfo();
		Map cb = new Map(gameinfo);
		//将左边的游戏区域,和右边的信息区域,添加到分割面板中
		jSplitpane.setLeftComponent(cb);
		jSplitpane.setRightComponent(gameinfo);
		//最后设置距离
		jSplitpane.setDividerLocation(420); //右边距离左边420
		jSplitpane.setEnabled(false);//禁止拖动
		
		//jf.add(gameinfo);
		jf.setVisible(true);
		
		
		//键盘监听事件
		jf.addKeyListener(new KeyListener() {
			
			@Override
			public void keyTyped(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void keyReleased(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void keyPressed(KeyEvent e) {
				// TODO 键盘事件
				//获取按压的键盘对应 的数值
				//System.out.println(e.getKeyCode());
				int code = e.getKeyCode();
				switch(code) {
					case 37:		//左
						cb.left();
						break;
					case 38:
						cb.up();	//上
						break;
					case 39:		//→
						cb.right();
						break;
					case 40:		//下
						cb.down();
						break;
				}
					
			}
		});
		//调用一下方法
//		int[] shape = {0,0,0,1,
//				       0,1,1,1,
//				       0,0,0,1,
//		               0,0,0,0};
//		
//		gameinfo.showNext(shape);
	}
}

六、源码链接

最后附上源码链接供大家下载参考
完全免费~

https://download.csdn.net/download/weixin_44420328/12648212

猜你喜欢

转载自blog.csdn.net/weixin_44420328/article/details/107499357