俄罗斯方块代码

package Game1;

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.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

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

public class Tetris extends JFrame {

	public Tetris(){
		TetrisPanel tetris=new TetrisPanel();
		this.addKeyListener(tetris.listener);
		add(tetris);
		setSize(220, 275);
		setLocation(400, 100);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setTitle("俄罗斯方块");
		setResizable(false);
	}
	
	public static void main(String[] args) {
		Tetris te=new Tetris();
		te.setVisible(true);
	}
	class TetrisPanel extends JPanel{
		private int x,y;   //用来表示方块位置
		private int blockType;  //用来表示方块形态,如:L型,J型,Z型。。。0-6
		private int turnState;  //用来表示每个形态的变化方法,以下每个形态4种变化0-3
		private TimeListerner listener=new TimeListerner();
		private Timer timer;
		private int delay;
		private int score;
		int map[][]=new int[13][23];   //表示地图,游戏背景
		//以下用三维数组存储,第一维用取随机数来生成方块表示blockType,第二维用来表示方块旋转次数,三维代表方块矩阵
		int shape[][][]=new int[][][]{
				{	
					//I型长条方块
					{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}
				},
				
					//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}
				},
					//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 }
				},
					//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 }
				},
					//T型方块
				{
					{ 0, 1, 0, 0, 1, 1, 1, 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 },
					{ 1, 1, 1, 0, 0, 1, 0, 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 }
				},
					//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 }
				}
		};
		public TetrisPanel(){
			nextBlock();
			newGame();
		}
		public void down(){   			//向下控制
			if(crash(x,y+1,blockType,turnState)==0){
				add( x, y, blockType, turnState);
				nextBlock();
			}
			y++;
			repaint();
		}
		public void upturn() {     //按键上的控制(即变换形态)
			turnState=(turnState+crash(x, y, blockType, (turnState+1)%4))%4;
			repaint();
		}
		public void left(){			//左控制
			if(x>=0){
				x-=+crash(x-1, y, blockType, turnState);
				repaint();
			}
		}
		public void right(){   		//右控制
			if(x<8){
				x+=crash(x+1, y, blockType, turnState);
				repaint();
			}
		}
		//判断是否碰撞
		public int crash(int x,int y,int blockType,int turnState){
			for(int a=0;a<4;a++){
				for(int b=0;b<4;b++){
					if((shape[blockType][turnState][a*4+b] & map[x+b+1][y+a])==1){
						return 0;
					}
				}
			}
			return 1;
		}
		//把增加的方块搞到地图上面去,用表示方块形状的三维数组和地图的二维数组控制,如果碰到,则把方块此时的坐标和地图的坐标相加,得出新的值(即新的地图)
		public void add(int x,int y,int blockType,int turnState){
			for(int a=0;a<4;a++){
				for(int b=0;b<4;b++){
					if(shape[blockType][turnState][a*4+b]==1){
						map[x + b + 1][y + a] = shape[blockType][turnState][a * 4 + b];
					}
				}
			}
			TryDeline();
		}
		
		private void newGame() {
			for(int i=0;i<12;i++){       //初始化地图,地图看成是由12*22的方块构成
				for(int j=0;j<22;j++){
					map[i][j]=0;
					map[11][j]=map[0][j]=3;   //边界赋值3,用于下面画出边界,下面代码思想是如果map[i][j]=3,那么就画一个红色格子当分界线
				}
				map[i][21]=3;    //此处赋值最下面一层的值
			}
			delay=1000;   //速度初始值
			timer=new Timer(delay, listener);  
			timer.start();   
			nextBlock();    //下一个方块
			repaint();     //刷新地图
		}
		//消行的代码
		private void TryDeline(){
			//先遍历整个map看map中有没有一行整个都是满的,如果都是满的,那么map【a】【b】=1,与1(以下代码用的一个整形c)相&就是1;否则为0
			for(int b=0;b<21;b++){    //表示多少行
				int c=1;
				for(int a=0;a<12;a++){  //表示每列,用来看该行是否满的格子
					c&=map[a][b];
				}
				//以下是消除,如果满了(即c=1),就把上一行的赋给下一行,
				if(c==1){
					for(int d=b;d>0;d--){
						for(int e=1;e<11;e++){
							map[e][d]=map[e][d-1];
						}
					}
					//以下是分数的加法和速度的变化
					score+=10;
					if(delay>500){
						delay-=50;
					}else if(delay>200){
						delay-=40;
					}else {
						delay=200;
					}
				}
			}
		}

		private void nextBlock() {
			blockType=(int) (Math.random()*1000)%7;   //用随机数生成新的类型
			turnState=(int) (Math.random()*1000)%4;   //用随机数生成新类型中的形态
			x=4;  //表示生成位置的X坐标
			y=0;  //表示生成位置的Y坐标
			if (crash(x, y, blockType, turnState) == 0) {
				timer.stop();
				int option = JOptionPane.showConfirmDialog(this,
						"Game Over!!您的最后得分是:"+score);
				if (option == JOptionPane.OK_OPTION) {
					newGame();
					score=0;
				} else if (option == JOptionPane.NO_OPTION) {
					System.exit(0);
				}
			}
			
		}
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.setColor(Color.blue);
			//画出当前形态
			for(int j=0;j<16;j++){
				if(shape[blockType][turnState][j]==1){
					g.fillRect((j%4+x+1)*10,(j/4+y)*10, 10, 10);
				}
			}
			//画地图
			g.setColor(Color.red);
			for(int j=0;j<22;j++){
				for(int i=0;i<12;i++){
					if(map[i][j]==1){
						g.fillRect(i*10, j*10, 10, 10);
						// 让堆积块有分界线
						g.setColor(Color.green);
						g.drawRect(i * 10, j * 10, 10, 10);
						g.setColor(Color.red);
						
					}else if(map[i][j]==3){
						g.drawRect(i*10, j*10, 10, 10);				
					}
				}
			}
			//设置界面左右边的显示界面
			g.setColor(Color.blue);
			g.setFont(new Font("aa", Font.BOLD, 15));
			g.drawString("score="+score, 130, 20);
			g.setFont(new Font("aa", Font.ITALIC,13));
			g.drawString("关爱残疾人", 130, 70);
			g.drawString("远离鲁阿鲁", 130, 90);
			g.drawString("俄罗斯方块", 130, 110);
			g.drawString("益身心健康", 130, 130);
			g.drawString("防受骗上当", 130, 150);
			g.drawString("这游戏益脑", 130, 170);
		}
		//以下是添加的键盘监听
		class TimeListerner extends KeyAdapter implements ActionListener{

			@Override
			public void actionPerformed(ActionEvent e) {
				down();
			}
			@Override
			public void keyPressed(KeyEvent e) {
				int keycode=e.getKeyCode();
				switch (keycode) {
				case KeyEvent.VK_DOWN:   //方向键下的监听
					down();    //方法在上面
					break;
				case KeyEvent.VK_UP:    //方向键上的监听
					upturn();    //方法在上面
					break;
				case KeyEvent.VK_LEFT:    //方向键左的监听
					left();
					break;
				case KeyEvent.VK_RIGHT:    //方向键右的监听
					right();
					break;
				}
			}
		}	
	}
}

猜你喜欢

转载自blog.csdn.net/asd529735325/article/details/50925064