2021-08-28

这个博客介绍了一个使用Java编写的俄罗斯方块游戏。游戏包括初始化窗口、游戏界面、游戏说明面板的创建,以及游戏运行、方块生成、键盘控制、游戏暂停等功能。代码详细展示了游戏的核心逻辑,如方块的下落、旋转、消除行等操作。
摘要由CSDN通过智能技术生成

简单的JAVA游戏俄罗斯方块

1.初始化游戏窗口


public class Tetris extends JFrame {
	public void initWindow() {
		// 设置窗口大小
		this.setSize(600, 850);
		// 设置窗口可见
		this.setVisible(true);
		// 设置窗口居中
		this.setLocationRelativeTo(null);
		// 设置释放窗体
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// 设置窗口大小不可变
		this.setResizable(true);
		// 设置标题
		this.setTitle("简单的Java俄罗斯方块");
	}

	
	public Tetris() {
		initWindow();
	}

	public static void main(String[] args) {
		Tetris t = new Tetris();
	}

2.初始化游戏界面1

 	 private static final int game_x=26;
	 private static final int game_y=12;
	 //文本域数组
	 JTextArea [][] text;
	 //每个格子的数组 二维数组
	 int[][]data;

	//初始化游戏界面
	public void initGamePanel() {
		//定义一个Jpanel对象
		JPanel game_main=new JPanel();
		game_main.setLayout(new GridLayout(game_x,game_y,1,1));
	}
	 //在构造方法初始化
	 public Tetris() {
		text=new JTextArea[game_x][game_y];
		data=new int[game_x][game_y];
		initWindow();
	}

3.初始化游戏界面2

//初始化游戏界面
	public void initGamePanel() {
		//定义一个Jpanel对象
		JPanel game_main=new JPanel();
		game_main.setLayout(new GridLayout(game_x,game_y,1,1));
		//初始化面板
		for(int i=0;i<text.length;i++) {
			for(int j=0;j<text[i].length;j++) {
				//设置文本域的行列数
				text[i][j]=new JTextArea(game_x,game_y);
				//设置文本域的背景颜色
				text[i][j].setBackground(Color.white);
				//添加键盘点击事件
				text[i][j].addKeyListener(this);
				//初始化游戏边界
				if(j==0||j==text[i].length-1||i==text.length-1) {
					text[i][j].setBackground(Color.blue);
					//data=1表示有方块
					data[i][j]=1;
				}
				//设置文本区域不可编辑
				text[i][j].setEditable(false);
				//文本区域添加到主面板上
				game_main.add(text[i][j]);
			}
		}
	}
		//把主面板添加到窗口中
		this.setLayout(new BorderLayout());
		this.add(game_main,BorderLayout.CENTER); 
			public Tetris() {
		text=new JTextArea[game_x][game_y];
		data=new int[game_x][game_y];
		initGamePanel();
		initWindow();
	}

4.初始化游戏的说明面板

 
	 //显示游戏状态标签
	 JLabel state;
	 //显示游戏分数标签
	 JLabel score;
//设置游戏说明面板
	public void initExplainPanel() {
		//创建游戏左侧说明面板
		JPanel explain_left=new JPanel();
		//创建游戏右侧说明面板
		JPanel explain_right=new JPanel();
		
		explain_left.setLayout(new GridLayout(4,1));
		explain_right.setLayout(new GridLayout(2,1));
		//初始化左侧和右侧说明面板
		explain_left.add(new JLabel("按空格键变形!"));
		explain_left.add(new JLabel("按A键左移动!"));
		explain_left.add(new JLabel("按D键右移动!!"));
		explain_left.add(new JLabel("按S键下落!"));
		//将标签内容设置为红色字体
		state.setForeground(Color.red);
		//把游戏状态标签游戏分数标签添加到右说明面板
		explain_right.add(score);
		explain_right.add(state);
		//将左说明面板添加到窗口左侧
		 this.add(explain_left,BorderLayout.WEST);
		//将右说明面板添加到窗口右侧
		 this.add(explain_right,BorderLayout.EAST);
	}
	public Tetris() {
		text=new JTextArea[game_x][game_y];
		data=new int[game_x][game_y];
		//初始化表示游戏状态的标签
		state=new JLabel("游戏当前状态:正在游戏中!");
		//初始化表示游戏状态的标签
		score=new JLabel("游戏当前分数:0");
		initGamePanel();
		initExplainPanel();
		initWindow();
	}

5.开始游戏的方法

boolean isrunning;

//开始游戏的方法
	public void game_begin() {
		//由于游戏直到死亡或者关闭才会结束,因此先写死循环并且创建一个boolean变量来判断
		while(true) {
			//判断游戏是否结束
			if(!isrunning) {
				break;
			}
			//进行游戏
			game_run();
		}
		//在游戏状态标签显示游戏结束!
		state.setText("游戏结束!");
	}
	
	//在无参构造方法初始化 开始游戏的标志
		public Tetris() {
		isrunning=true;
		}

6.随机生成下落方块

// 用于存储所有方块的数组
	int[] allRect;
	// 用于存储当前方块的变量
	int rect;
	//在无参构造方法初始化
	public Tetris() {
		allRect=new int[]{0x00cc,0x8888,0x000f,0x888f,0xf888,0xf111,0x0eee,0xffff,0x0008,0x0888,0x000e,0x0088,0x000c,0x08c8,0x00e4,0x04c4,0x004e,0x08c4,0x006c,0x04c8,0x00c6};
}
// 随机生成下落方块形状的方法
	public void ranRect() {
		Random random=new Random();
		rect=allRect[random.nextInt(22)];	
	}

7.游戏运行的方法1

	// 方块当前坐标
	int x, y;
	// 线程休眠时间
	int time = 1000;
// 游戏运行的方法
	public void game_run() {
		ranRect();
		// 方块下落位置
		x = 0;
		y = 5;
		for (int i = 0; i < game_x; i++) {
			try {
				Thread.sleep(time);
				// 判断方块是否可以下落
				if (!canFall(x, y)) {

				} else {
					// 层数+1
					x++;
					// 方块下落一行
					fall(x, y);
				}
			} catch (InterruptedException e) {

				e.printStackTrace();
			}
		}
	}

8.游戏运行的方法2

// 游戏运行的方法
	public void game_run() {
		ranRect();
		// 方块下落位置
		x = 0;
		y = 5;
		for (int i = 0; i < game_x; i++) {
			try {
				Thread.sleep(time);
				// 判断方块是否可以下落
				if (!canFall(x, y)) {
					//将data置为1,表示有方块占用
					changData(x,y);
					//循环遍历4层,看是否有行可消除
					for(int j=x;j<x+4;j++) {
						int sum=0;
						for(int k=1;k<game_y-2;k++) {
							if(data[j][k]==1) {
								sum++;
							}
						}
						//判断是否有一行能被消除
						if(sum==(game_y-2)) {
							//消除j该行
							removeRow(j);
						}
					}
					//判断游戏是否结束
					for(int j=1;j<=(game_y-2);j++) {
						if(data[3][j]==1) {
							isrunning=false;
							break;
						}
					}
					break;
				} else {
					// 层数+1
					x++;
					// 方块下落一行
					fall(x, y);
				}
			} catch (InterruptedException e) {

				e.printStackTrace();
			}
		}
	}

8.判断方块是否继续下落的方法

// 判断方块是否继续下落的方法
	public boolean canFall(int m, int n) {
		// 定义一个变量
		int temp = 0x8000;
		// 遍历4*4风格方块
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if ((temp & rect) != 0) {
					//判断该位置的下一行是否有方块
					if(data[m+1][n]==1) {
						return false;
					}
				}
				n++;
				temp>>=1;
			}
			m++;
			n=n-4;
		}
		//可以下落
		return true;
	}

9.改变不可方块对应的区域的值的方法

//改变不可方块对应的区域的值的方法
	public void changData(int m,int n) {
		//定义一个变量赋值为0x8000遍历右移
		int temp=0x8000;
		//遍历整个4*4方块
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if((temp&rect)!=0) {
					data[m][n]=1;
				}
				n++;
				temp>>=1;
			}
			//行数加1
			m++;
			//列数回归到首列
			n=n-4;
		}
	}

10.移除某一行的方块上面的方块下落的方法

//定义计数得分
	int gameScore;
	//移除某一行的方块,令上面的方块下落的方法
	public void removeRow(int row) {
		int temp=100;
		for(int i=row;i>=1;i++) {
			for(int j=1;j<=(game_y-2);j++) {
				//利用上一层的data值覆盖本层的data值
				data[i][j]=data[i-1][j];
				}
			}
		//刷新游戏区域
		reflesh(row);
		//方块加速
		if(time>temp) {
			time-=temp;
		}
		gameScore+=temp;
		//显示变化后的得分
		score.setText("游戏得分:"+gameScore);
	}

11.刷新移除某一行的游戏界面的方法

	//刷新移除某一行的游戏界面的方法
	public void reflesh(int row) {
		//通过双重for循环遍历row行以上区域
		for(int i=row;i>=1;i--) {
			for(int j=row;j<=(game_y-2);j++) {
				if(data[i][j]==1) {
					text[i][j].setBackground(Color.BLUE);
				}else {
					text[i][j].setBackground(Color.WHITE);
				}
			}
		}
	}

12.方块向下掉落一层的方法

	// 方块向下掉落一层的方法
	public void fall(int m, int n) {
		if (m > 0) {
			//消除上一层方块
			clear(m-1,n);
		}
		//重新绘制方块
		draw(m,n);
	}

13.清除方块掉落后,上一层颜色的地方的方法

// 清除方块掉落后,上一层颜色的地方的方法
	public void clear(int m, int n) {
		// 定义变量
		int temp = 0x8000;
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if ((temp & rect) != 0) {
					text[m][n].setBackground(Color.WHITE);
				}
				n++;
				temp>>=1;
			}
			m++;
			n=n-4;
		}
	}

14.重新绘制掉落后的方块的方法

	// 重新绘制掉落后的方块的方法
	public void draw(int m, int n) {
		// 定义变量
		int temp = 0x8000;
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if ((temp & rect) != 0) {
					text[m][n].setBackground(Color.BLUE);
				}
				n++;
				temp >>= 1;
			}
			m++;
			n = n - 4;
		}
	}

到处游戏基本能够运行了!
15.键盘控制左移

@Override
	public void keyPressed(KeyEvent e) {
		
		// 左移
		if (e.getKeyCode() == 87) {
			// 判断游戏是否结束
			if (!isrunning) {
				return;
			}
			// 方块是否碰到左墙壁
			if (y <= 1) {
				return;
			}
			// 判断方块左移是否碰到别的方块
			int temp = 0x8000;
			for (int i = x; i < x + 4; i++) {
				for (int j = y; j < y + 4; j++) {
					if((temp&rect)!=0) {
						if(data[i][j-1]==1) {
							return;
						}
					}
					temp>>=1;
				}
			}
			//首先清除目标方块
			clear(x,y);
			y--;
			draw(x,y);
		}
	}

16.右移

// 右移
		if (e.getKeyCode() == 39) {
			// 判断游戏是否结束
			if (!isrunning) {
				return;
			}
			// 方块是否碰到右墙壁
//			if (y >12) {
//				return;
//			}

			int temp = 0x8000;
			int m = x;
			int n = y;
			// 存储方块最右边的值
			int num = 1;
			for (int i = 0; i < 4; i++) {
				for (int j = 0; j < 4; j++) {
					if ((temp & rect) != 0) {
						if (n > num) {
							num = n;
						}
					}
					n++;
					temp >>= 1;
				}
				m++;
				n = n - 4;
			}
			// 判断是否碰到右墙壁
			if (num >= (game_y - 2)) {
				return;
			}
			// 判断方块右移是否碰到别的方块
			temp = 0x8000;
			for (int i = x; i < x + 4; i++) {
				for (int j = y; j < y + 4; j++) {
					if ((temp & rect) != 0) {
						if (data[i][j + 1] == 1) {
							return;
						}
					}
					temp >>= 1;
				}
			}
			// 首先清除目标方块
			clear(x, y);
			//右移
			y++;
			draw(x, y);
		}

17.下移

//方块下移
		if(e.getKeyCode()==40) {
			//判断游戏是否结束
			if(!isrunning) {
				return;
			}
			//判断方块是否可以下落
			if(!canFall(x,y)) {
				return;
			}
			clear(x,y);
			//改变方块的坐标
			x++;
			draw(x,y);
		}

18.变形

@Override
	public void keyTyped(KeyEvent e) {
		// 空格控制方块变形
		if (e.getKeyChar() == KeyEvent.VK_SPACE) {
			if (!isrunning) {
				return;
			}
			// 定义变量存储目前方块的索引
			int old;
			for (old = 0; old < allRect.length; old++) {
				// 判断是否是当前方块
				if (rect == allRect[old]) {
					break;
				}
			}
			// 定义变量存储变形后的方块
			int next;
			// 判断是方块
			if (old == 0 || old == 7 || old == 8 || old == 9) {
				return;
			}
			// 清除当前方块
			clear(x, y);
			if (old == 1 || old == 2) {
				next = allRect[old == 1 ? 2 : 1];
				if (canTurn(next, x, y)) {
					rect = next;
				}
			}
			if (old >= 3 && old < 6) {
				next = allRect[old + 1 > 6 ? 3 : old + 1];
				if (canTurn(next, x, y)) {
					rect = next;
				}

			}
			if (old == 10 || old == 11) {
				next = allRect[old == 10 ? 11 : 10];
				if (canTurn(next, x, y)) {
					rect = next;
				}
			}
			if (old == 12 || old == 13) {
				next = allRect[old == 12 ? 13 : 12];
				if (canTurn(next, x, y)) {
					rect = next;
				}
			}
			if (old >= 14 && old <= 17) {
				next = allRect[old + 1 > 17 ? 14 : old + 1];
				if (canTurn(next, x, y)) {
					rect = next;
				}
			}
			if (old == 18 || old == 19) {
				next = allRect[old == 18 ? 19 : 18];
				if (canTurn(next, x, y)) {
					rect = next;
				}
			}
			if (old == 20 || old == 21) {
				next = allRect[old == 20 ? 21 : 20];
				if (canTurn(next, x, y)) {
					rect = next;
				}
			}
			//重新绘制变形后的方块
			draw(x,y);
		}
	}
	
	//判断方块此时是否可以变形的方法
	public boolean canTurn(int a,int m,int n) {
		int temp=0x8000;
		//变量4*4方块
		for(int i=0;i<4;i++) {
			for(int j=0;j<4;j++) {
				if((a&temp)!=0) {
					if(data[m][n]==1) {
						return false;
					}
				}
				n++;
				temp>>=1;
			}
			m++;
			n=n-4;
		}
		//可以变形
		return true;
	}

19.暂停

//定义一个标志变量,用于判断游戏是否暂停
	boolean game_pause=false;
	//接收暂停次数
	int pausenum=0;	
	//在game_run()里面加入
	if(game_pause) {
		i--;
	}else {
				}
//在变形 左移 右移加入判断
//判断游戏是否暂停
			if(game_pause) {
				return;
			}
			//这样就完成了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值