前言
欢迎阅读本文,本文将介绍如何使用Java语言实现一个简易的俄罗斯方块游戏。俄罗斯方块,作为一种经典的益智游戏,不仅操作简单,而且富有娱乐性,深受很多玩家喜欢。通过本文,读者将了解到如何利用Java编程语言,结合GUI技术,实现一个基本的俄罗斯方块游戏。本文参考b站尚学堂博主代码,在此基础上有些改动。
代码解释
初始化游戏窗口
生成一个宽650,高850的窗口。
public void initWindow() {
//设置窗口大小
this.setSize(650, 850);
//设置窗口是否可见
this.setVisible(true);
//设置窗口居中
this.setLocationRelativeTo(null);
//设置释放窗体(点击差号正常退出)
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口大小不变
this.setResizable(false);
//设置标题
this.setTitle("俄罗斯方块");
}
初始化游戏界面
生成一个26*12的方格面板添加到窗口上
public void initGamePanel() {
JPanel game = new JPanel();
game.setLayout(new GridLayout(game_x, game_y, 1, 1));//水平竖直间距为1
//初始化面板
for (int i = 0; i < text.length; i++) {//两个for循环遍历游戏界面
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.RED);
data[i][j] = 1;
}
//设置文本区域不可编辑
text[i][j].setEditable(false);
//文本区域添加到主面板上
game.add(text[i][j]);
}
}
//添加到窗口中
this.setLayout(new BorderLayout());
this.add(game, BorderLayout.CENTER);
}
初始化游戏说明面板
在游戏窗口的左边和右边添加面板,左边是操作方法,右边是分数和状态。
public void initExplainPanel() {
//创建游戏的左右说明面板
JPanel left = new JPanel();
JPanel right = new JPanel();
//初始化说明面板
left.setLayout(new GridLayout(4, 1));
right.setLayout(new GridLayout(2, 1));
//在左说明面板添加声明文字
left.add(new JLabel("按空格键,方块翻转"));
left.add(new JLabel("按左键,方块左移"));
left.add(new JLabel("按右键,方块右移"));
left.add(new JLabel("按下键,方块下落"));
//设置标签的内容为黑色
label1.setForeground(Color.black);
//把状态和分数添加到右面板
right.add(label2);
right.add(label1);
//说明面板的添加
this.add(left, BorderLayout.WEST);
this.add(right, BorderLayout.EAST);
}
开始游戏的方法
来判断此时的游戏状态
public void begin() {
while (true) {
//判断游戏是否结束
if (!running) {
break;
}
//进行游戏
run();
}
//在标签位置显示游戏结束
label1.setText("游戏状态:游戏结束");
}
随机生成下落方块形状的方法
本文采用十六进制的方法在4*4的区域内表示方块。有方块的数字为1,无方块为0.
以下是所有可能的形状(变形都是经过顺逆时针旋转,无逆时针旋转)
public void Rect() {
Random random = new Random();
rect = allRect[random.nextInt(19)];
}
游戏运行的方法
调用多个方法来实现游戏。
public void run() {
Rect();
//方块下落位置
x = 0;
y = 5;
for (int i = 0; i < game_x; i++) {
try {
Thread.sleep(time);
if (zanting) {
i--;
} else {
//判断方块是否可以下落
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) {
running = false;
jieshu over=new jieshu();
break;
}
}
break;
} else {
//层数+1
x++;
//方块下落一格
fall(x, y);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
判断方块是否可以继续下落的方法
定义一个temp变量,从左上角开始遍历4*4区域,确定方块位置,看下一行是否有方块。
public boolean canFall(int m, int n) {//用0x8000的不断右移一位来与rect中存储的图形相比较
//定义一个变量
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;
}
改变不可下降的方块的区域的值
将不可下降方块的区域的值设置为1.
public void changData(int m, int n) {//用0x8000的不断右移,来获取到每一个方块的位置,然后我么将他的data值设置为1
//定义一个变量
int temp = 0x8000;
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;
}
m++;
n = n - 4;
}
}
移除某一行,上面方块掉落的方法
经过判断某一行可以消除,通过该行以上的所有位置往下移动,用上一行的值,覆盖下一行的值,达到消除该行的目的
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[i][j] = data[i - 1][j];
}
}
//刷新游戏区域
reflesh(row);
//方块加速
if (time > temp) {
time -= (temp/2);
}
score += temp;
//显示变化后的分数
label2.setText("游戏的分:" + score);
}
刷新移除某一行后的游戏界面方法
消除某一行后,仅仅改变了消除行以上区域的值,需要对其变化进行上色
public void reflesh(int row) {
//遍历row行以上的游戏区域
for (int i = row; i >= 1; i--) {
for (int j = 1; j <= (game_y - 2); j++) {
if (data[i][j] == 1) {
text[i][j].setBackground(Color.blue);
} else {
text[i][j].setBackground(Color.white);
}
}
}
}
//方块向下掉落一层的方法
public void fall(int m, int n) {
if (m > 0) {
//清除上一层方块
clear(m - 1, n);
}
//重新绘制方块
draw(m, n);
}
方块向下掉落一层的方法
用clear和draw两个方法实现方块掉落
public void fall(int m, int n) {
if (m > 0) {
//清除上一层方块
clear(m - 1, n);
}
//重新绘制方块
draw(m, n);
}
清除方块掉落后,上一层有颜色地方的方法
方块掉落,原有的位置要清除,替换成背景颜色白色
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 -= 4;
}
}
重新绘制掉落后方快的方法
清除后,当前在当前已经掉落的位置进行方块的重新绘制
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;
}
}
键盘控制方块的移动
1.控制方块左移,新定义temp,0x8000,temp位于4*4矩阵的左上角,左移时,要判定好移动是否超界,没有超界,判定左侧是否有方块,若没有,则用之前写的clear和draw方法,清除原来位置的方块,重新绘制新方块
2.控制方块右移,与左移有稍微不同,先确定该方块最右侧的位置,然后才能判定方块是否碰到右壁其余和左移一样。
3.方块下移,直接判定是否可以下落,可以下落则调用fall方法直接让方块下落
public void keyPressed(KeyEvent e) {
//方块进行左移
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
//判断游戏是否结束
if (!running) {
return;
}
//判断游戏是否暂停
if (zanting) {
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);
}
//方块进行右移
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
//判断游戏是否结束
if (!running) {
return;
}
//判断游戏是否暂停
if (zanting) {
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);
}
//方块进行下落
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
//判断游戏是否结束
if (!running) {
return;
}
//判断游戏是否暂停
if (zanting) {
return;
}
//判断方块是否可以下落
if (!canFall(x,y)) {
return;
}
clear(x,y);
//改变方块的坐标
x++;
draw(x,y);
}
}
控制方块变形
每个方块提前标好了序号,记住序号。
定义old,确定方块的形状后,进而确定方块的序号,用old存储。
将可相互变形的方块放一起,用三目运算符,进行变换。
public void keyTyped(KeyEvent e) {
//控制游戏暂停
if (e.getKeyChar() == 'p') {
//判断游戏是否结束
if (!running) {
return;
}
cishu++;
//判断按下一次,暂停游戏
if (cishu == 1) {
zanting = true;
label1.setText("游戏状态: 暂停中!");
}
//判断按下两次,继续游戏
if (cishu == 2) {
zanting = false;
cishu = 0;
label1.setText("游戏状态: 正在进行中!");
}
}
//控制方块进行变形
if (e.getKeyChar() == KeyEvent.VK_SPACE) {
//判断游戏是否结束
if (!running) {
return;
}
//判断游戏是否暂停
if (zanting) {
return;
}
//定义变量,存储目前方块的索引
int old;
for (old = 0;old < allRect.length;old++) {
//判断是否是当前方块
if (rect == allRect[old]) {
break;
}
}
//定义变量,存储变形后方块
int next;
//判断是方块
if (old == 0) {
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 == 7 || old == 8) {
next = allRect[old == 7 ? 8 : 7];
if (canTurn(next,x,y)) {
rect = next;
}
}
if (old == 9 || old == 10) {
next = allRect[old == 9 ? 10 : 9];
if (canTurn(next,x,y)) {
rect = next;
}
}
if (old >= 11 && old <= 14) {
next = allRect[old + 1 > 14 ? 11 : old + 1];
if (canTurn(next,x,y)) {
rect = next;
}
}
if (old >= 15 && old <= 18) {
next = allRect[old+1 > 18 ? 15 : old+1];
if (canTurn(next,x,y)) {
rect = next;
}
}
if (old == 19 || old == 20) {
next = allRect[old == 19 ? 20 : 19];
if (canTurn(next,x,y)) {
rect = next;
}
}
//重新绘制变形后方块
draw(x,y);
}
}
判断方块此时是否可以变形的方法
要实现方块的变形,要事先确定方块是否可以变化。
原因是,我们定义所有的方块时,都是将所有的方块放到了4*4矩阵的左下角,进行变换的过程中,可能会导致方块的横向长度变大。当我们方块紧贴着左侧边界时,进行变换,会使方块超过边界。所以我们需要事先判定好方块是否可以进行变形。
根据我们当前方块的位置,确定好4*4矩阵的左上角位置。我们设置边界框的时候,将所有边界框所在的区域的方格设置值为1,因此,判断4*4矩阵右侧的位置是否存在值为1方格,判断方块是否可以进行变形。
public boolean canTurn(int a,int m,int n) {
//创建变量
int temp = 0x8000;
//遍历整个方块
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;
}
完整代码展示
package 初始化游戏窗口;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class Tertris extends JFrame implements KeyListener {
//游戏的行数26 列数12(常量)
private static final int game_x = 26;
private static final int game_y = 12;
//文本域数组
JTextArea[][] text;//定义每个格子是个文本域
//每个格子的值的数组->二维数组
int[][] data; //定义每个格子的值 规定1代表有方块,0代表空白
//显示游戏状态标签
JLabel label1;
//显示游戏分数标签
JLabel label2;
//判断游戏结束
boolean running;
//用于储存所有方块的数组
int[] allRect;
//用于储存当前方块的变量
int rect;
//线程的休眠时间
int time = 1000;
//表示方块坐标
int x, y;
//该变量用于计算得分
int score = 0;
//定义一个标志变量,用于判断游戏是否暂停
boolean zanting = false;
//定义一个变量用于记录按下暂停键的次数
int cishu = 0;
//创建初始化窗口的方法
public void initWindow() {
//设置窗口大小
this.setSize(650, 850);
//设置窗口是否可见
this.setVisible(true);
//设置窗口居中
this.setLocationRelativeTo(null);
//设置释放窗体(点击差号正常退出)
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口大小不变
this.setResizable(false);
//设置标题
this.setTitle("俄罗斯方块");
}
//初始化游戏界面
public void initGamePanel() {
JPanel game = new JPanel();
game.setLayout(new GridLayout(game_x, game_y, 1, 1));//水平竖直间距为1
//初始化面板
for (int i = 0; i < text.length; i++) {//两个for循环遍历游戏界面
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.RED);
data[i][j] = 1;
}
//设置文本区域不可编辑
text[i][j].setEditable(false);
//文本区域添加到主面板上
game.add(text[i][j]);
}
}
//添加到窗口中
this.setLayout(new BorderLayout());
this.add(game, BorderLayout.CENTER);
}
//初始化游戏说明面板
public void initExplainPanel() {
//创建游戏的左右说明面板
JPanel left = new JPanel();
JPanel right = new JPanel();
//初始化说明面板
left.setLayout(new GridLayout(4, 1));
right.setLayout(new GridLayout(2, 1));
//在左说明面板添加声明文字
left.add(new JLabel("按空格键,方块翻转"));
left.add(new JLabel("按左键,方块左移"));
left.add(new JLabel("按右键,方块右移"));
left.add(new JLabel("按下键,方块下落"));
//设置标签的内容为黑色
label1.setForeground(Color.black);
//把状态和分数添加到右面板
right.add(label2);
right.add(label1);
//说明面板的添加
this.add(left, BorderLayout.WEST);
this.add(right, BorderLayout.EAST);
}
public Tertris() {
//变量初始化
text = new JTextArea[game_x][game_y];
data = new int[game_x][game_y];
//初始化状态标签
label1 = new JLabel("游戏状态:正在游戏中");
//初始化分数标签
label2 = new JLabel("得分:0");
initGamePanel();
initExplainPanel();
initWindow();
//初始化开始游戏标志
running = true;
//初始化存放方块的数组
allRect = new int[]{0x00cc, 0x8888, 0x000f, 0x08c8, 0x00e4, 0x04c4, 0x004e, 0x08c4, 0x006c, 0x04c8, 0x00c6, 0x008e,0x0c88,0x00e2,0x044c,0x0c44,0x002e,0x088c,0x00e8,0x8888, 0x000f};
}
public static void main(String[] args) {
Tertris tertris = new Tertris();
tertris.begin();
}
//开始游戏的方法
public void begin() {
while (true) {
//判断游戏是否结束
if (!running) {
break;
}
//进行游戏
run();
}
//在标签位置显示游戏结束
label1.setText("游戏状态:游戏结束");
}
//随机生成下落方块形状的方法
public void Rect() {
Random random = new Random();
rect = allRect[random.nextInt(19)];
}
//游戏运行的方法
public void run() {
Rect();
//方块下落位置
x = 0;
y = 5;
for (int i = 0; i < game_x; i++) {
try {
Thread.sleep(time);
if (zanting) {
i--;
} else {
//判断方块是否可以下落
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) {
running = false;
jieshu over=new jieshu();
break;
}
}
break;
} else {
//层数+1
x++;
//方块下落一格
fall(x, y);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//判断方块是否可以继续下落
public boolean canFall(int m, int n) {//用0x8000的不断右移一位来与rect中存储的图形相比较
//定义一个变量
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;
}
//改变不可下降的方块对应的区域的值的方法
public void changData(int m, int n) {//用0x8000的不断右移,来获取到每一个方块的位置,然后我么将他的data值设置为1
//定义一个变量
int temp = 0x8000;
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;
}
m++;
n = n - 4;
}
}
//消除某一行的所有方块,令以上的方块掉落的方法
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[i][j] = data[i - 1][j];
}
}
//刷新游戏区域
reflesh(row);
//方块加速
if (time > temp) {
time -= (temp/2);
}
score += temp;
//显示变化后的分数
label2.setText("游戏的分:" + score);
}
//刷新移除某一行后的游戏界面方法
public void reflesh(int row) {
//遍历row行以上的游戏区域
for (int i = row; i >= 1; i--) {
for (int j = 1; j <= (game_y - 2); j++) {
if (data[i][j] == 1) {
text[i][j].setBackground(Color.blue);
} else {
text[i][j].setBackground(Color.white);
}
}
}
}
//方块向下掉落一层的方法
public void fall(int m, int n) {
if (m > 0) {
//清除上一层方块
clear(m - 1, n);
}
//重新绘制方块
draw(m, n);
}
//清除方块掉落后,上一层有颜色地方的方法
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 -= 4;
}
}
//重新绘制掉落后方快的方法
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;
}
}
//判断方块此时是否可以变形的方法
public boolean canTurn(int a,int m,int n) {
//创建变量
int temp = 0x8000;
//遍历整个方块
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;
}
@Override
public void keyTyped(KeyEvent e) {
//控制游戏暂停
if (e.getKeyChar() == 'p') {
//判断游戏是否结束
if (!running) {
return;
}
cishu++;
//判断按下一次,暂停游戏
if (cishu == 1) {
zanting = true;
label1.setText("游戏状态: 暂停中!");
}
//判断按下两次,继续游戏
if (cishu == 2) {
zanting = false;
cishu = 0;
label1.setText("游戏状态: 正在进行中!");
}
}
//控制方块进行变形
if (e.getKeyChar() == KeyEvent.VK_SPACE) {
//判断游戏是否结束
if (!running) {
return;
}
//判断游戏是否暂停
if (zanting) {
return;
}
//定义变量,存储目前方块的索引
int old;
for (old = 0;old < allRect.length;old++) {
//判断是否是当前方块
if (rect == allRect[old]) {
break;
}
}
//定义变量,存储变形后方块
int next;
//判断是方块
if (old == 0) {
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 == 7 || old == 8) {
next = allRect[old == 7 ? 8 : 7];
if (canTurn(next,x,y)) {
rect = next;
}
}
if (old == 9 || old == 10) {
next = allRect[old == 9 ? 10 : 9];
if (canTurn(next,x,y)) {
rect = next;
}
}
if (old >= 11 && old <= 14) {
next = allRect[old + 1 > 14 ? 11 : old + 1];
if (canTurn(next,x,y)) {
rect = next;
}
}
if (old >= 15 && old <= 18) {
next = allRect[old+1 > 18 ? 15 : old+1];
if (canTurn(next,x,y)) {
rect = next;
}
}
if (old == 19 || old == 20) {
next = allRect[old == 19 ? 20 : 19];
if (canTurn(next,x,y)) {
rect = next;
}
}
//重新绘制变形后方块
draw(x,y);
}
}
@Override
public void keyPressed(KeyEvent e) {
//方块进行左移
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
//判断游戏是否结束
if (!running) {
return;
}
//判断游戏是否暂停
if (zanting) {
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);
}
//方块进行右移
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
//判断游戏是否结束
if (!running) {
return;
}
//判断游戏是否暂停
if (zanting) {
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);
}
//方块进行下落
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
//判断游戏是否结束
if (!running) {
return;
}
//判断游戏是否暂停
if (zanting) {
return;
}
//判断方块是否可以下落
if (!canFall(x,y)) {
return;
}
clear(x,y);
//改变方块的坐标
x++;
draw(x,y);
}
}
@Override
public void keyReleased(KeyEvent e) {
}
}
package 初始化游戏窗口;
import javax.swing.*;
import java.awt.*;
public class jieshu extends JFrame {
public static void main(String[] args) {
jieshu over=new jieshu();
}
jieshu(){
initText();
initwindow();
}
public void initText(){
JPanel jPanel=new JPanel();
jPanel.setLayout(null);
JLabel jLabel=new JLabel("游戏结束");
Font font=new Font("SansSerif",Font.BOLD,24);
jLabel.setFont(font);
jPanel.add(jLabel);
jLabel.setBounds(25,35,100,30);
this.add(jPanel);
}
public void initwindow(){
//设置窗口大小
this.setSize(160, 150);
//设置窗口是否可见
this.setVisible(true);
//设置窗口居中
this.setLocationRelativeTo(null);
//设置释放窗体(点击差号正常退出)
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口大小不变
this.setResizable(false);
}
}
成果展示
小结
通过分割为多个方法,实现了用户与游戏界面的交互。游戏娱乐性可适当增加,可以增加一些难度和模式的选择。这是较为简易的俄罗斯方块,读者在阅读之后可以适当添加代码来优化程序,感谢阅读。