【Java】俄罗斯方块小游戏(附源码)_500行可运行小游戏代码-CSDN博客https://blog.csdn.net/weixin_48701521/article/details/121709104本文是对上面文章代码的解释。
一:一些包和类
package 俄罗斯方块;//定义了一个名为俄罗斯方块的包。包是用来组织类和接口的一种机制,通常为了避免类名冲突和方便管理代码
import java.awt.*;//导入Java AWT(Abstract Window Toolkit)库中的所有类。AWT是Java用于创建图形用户界面的工具包。*指所有
import java.awt.event.*;//这些类用于处理事件(例如鼠标点击、键盘输入等)
import javax.swing.*; //Swing用于创建图形用户界面的更现代化的工具包,相对于AWT提供了更丰富的组件和更强的功能。
import java.applet.*;//Applet是用于创建嵌入在网页中的小型应用程序的类,不过在现代Java应用中已经很少使用
import java.lang.String.*;//导入java.lang.String类中的所有嵌套类,java.lang.String:用于处理字符串的类
import java.lang.*;//包含了Java语言的核心类(例如基本类型的包装类、基本的数学函数、系统相关的实用工具类等
import java.io.*;//这些类用于处理输入和输出操作,例如文件读写、数据流操作等
public class Block extends JPanel implements ActionListener,KeyListener//应该是继承JPanel
{
//定义了一个名为 Block 的类,该类继承自 JPanel 并实现了 ActionListener 和 KeyListener 接口。
Block
类继承自JPanel
,意味着它是一个可以作为 Swing 容器使用的组件。Block
类实现了ActionListener
和KeyListener
接口,意味着它将实现这些接口定义的方法,用于处理操作和键盘事件。
static Button but[] = new Button[6];
static Button noStop = new Button("取 消 暂 停");//定义了一个静态的Button对象,命名为noStop,按钮上的标签为“取消暂停”。这是一个用来创建图形用户界面按钮的组件,当用户点击这个按钮时,程序可以取消当前的暂停状态。
static Label scoreLab = new Label("分数:");//定静Label对象,名scoreLab,标签的文本内容为“分数:”。用于在图形用户界面上显示文本的组件,这里用于显示分数的标签说明。
static Label infoLab = new Label("提示:");//同scoreLab,显示提示信息的标签说明。
static Label speedLab = new Label("级数:");//显示游戏级别(速度)的标签说明。
static Label scoreTex = new Label("0");//显示当前分数的组件,初始分数为0
static Label infoTex = new Label(" ");//提示信息内容的组件,初始内容为空
static Label speedTex = new Label("1");//显示当前游戏级别(速度)的组件,初始级别为1。
static JFrame jf = new JFrame();//定义并初始化 JFrame 对象 jf,用作游戏的主窗口
static MyTimer timer; //声明一个静态的 MyTimer 对象 timer,用于游戏的计时。
static ImageIcon icon=new ImageIcon("resource/Block.jpg");//初始化,加载位于 "resource/Block.jpg" 的图像,
static JMenuBar mb = new JMenuBar();//静态的 JMenuBar 对象 mb,这是一个菜单栏。
static JMenu menu0 = new JMenu("游 戏 ");//初始化,菜单的标题为“游戏”。
static JMenu menu1 = new JMenu("帮 助 ");//菜单的标题为“帮助”
static JMenuItem mi0 = new JMenuItem("新 游 戏");//同上
static JMenuItem mi1 = new JMenuItem("退 出");//同上
static JMenuItem mi1_0 = new JMenuItem("关 于");//同上
static JDialog dlg_1;//JDialog 对象 dlg_1,可能用于弹出对话框。
static JTextArea dlg_1_text = new JTextArea();//表示游戏的状态。0 表示未开始,1 表示开始,2 表示暂停。
static int startSign = 0;//游戏开始标志 0 未开始 1 开始 2 暂停
static String butLab[] = {"开 始 游 戏","重 新 开 始","降 低 级 数","提 高 级 数","游 戏 暂 停","退 出 游 戏"};
static int game_body[][] = new int[19][10];//初始化二维数组 game_body,用于表示游戏的主要区域。
static int game_sign_x[] = new int[4];//用于记录4个方格的水平位置
static int game_sign_y[] = new int[4];//用于记录4个方格的垂直位置
static boolean downSign = false;//是否落下
static int blockNumber = 1;//砖块的编号
static int gameScore = 0;//游戏分数
static int speedMark = 1;//游戏速度等级
public static void main(String args[])
{
Block myBlock = new Block();//是游戏的主要组件,负责绘制和管理游戏逻辑。
mb.add(menu0);
mb.add(menu1);//将两个菜单 menu0(“游戏”)和 menu1(“帮助”)添加到菜单栏 mb
menu0.add(mi0);
menu0.add(mi1);//菜单项 mi0(“新游戏”)和 mi1(“退出”)添加到 menu0(“游戏”)菜单中。
menu1.add(mi1_0);//将菜单项 mi1_0(“关于”)添加到 menu1(“帮助”)菜单中。
jf.setJMenuBar(mb); //将菜单栏 mb 设置为主窗口 jf 的菜单栏。
myBlock.init();//初始化 Block 对象,设置游戏的初始状态
jf.add(myBlock);//将 myBlock 添加到主窗口 jf 中,使其成为窗口的一个组件。
jf.setSize(565,501);//设置主窗口 jf 的大小,宽,高
jf.setResizable(false);//禁止用户调整主窗口 jf 的大小
jf.setTitle("俄罗斯方块");//设置主窗口 jf 的标题
jf.setIconImage(icon.getImage());//设置主窗口 jf 的图标为加载的 icon 图像。
jf.setLocation(200,100);//设置主窗口 jf 的初始位置,显示在屏幕上坐标 (200, 100)
jf.show();//这个方法已经过时,用jf.setVisible(true)!!!!!!!!!!!!!!!!!
timer = new MyTimer(myBlock); //启动线程,创建一个 MyTimer 类的实例 timer,传递 myBlock 作为参数,假设 MyTimer 是一个用于控制游戏时间和逻辑的线程。
timer.setDaemon(true);//timer 线程设置为守护线程,这意味着当所有非守护线程结束时,程序将自动退出。
java
timer.start();//启动 timer 线程
timer.suspend();//挂起 timer 线程的执行。请注意,suspend 方法是过时的且不安全的,在现代Java应用中应使用其他方式来控制线程的执行(例如,使用 wait 和 notify 方法)
}
public void init()//公共方法 init,用于初始化界面组件和布局
{
setLayout(null);//布局管理器设置为 null,表示使用绝对布局,即手动设置每个组件的位置和大小。
for(int i = 0;i < 6;i++)//使用一个循环初始化 6 个按钮
{
but[i] = new Button(butLab[i]);//创建一个按钮,标签为 butLab 数组中的第 i 个元素。
add(but[i]);//将按钮添加到当前容器中
but[i].addActionListener(this);//为按钮添加一个动作事件监听器。
but[i].addKeyListener(this);//添加键盘事件监听器
but[i].setBounds(360,(240 + 30 * i),160,25);//设置按钮的位置和大小
}
add(scoreLab);//将标签和文本框组件添加到当前容器中。
add(scoreTex);
add(speedLab);
add(speedTex);
add(infoLab);
add(infoTex);
add(scoreLab);//重复添加了!!!!!!!!!!!
scoreLab.setBounds(320,15,30,20);//scoreLab 的位置和大小。
scoreTex.setBounds(360,15,160,20);//scoreTex 的位置和大小。
scoreTex.setBackground(Color.white);//设置 scoreTex 的背景颜色为白色。
speedLab.setBounds(320,45,30,20);//同上
speedTex.setBounds(360,45,160,20);
speedTex.setBackground(Color.white);
infoLab.setBounds(320,75,30,20);//同上
infoTex.setBounds(360,75,160,20);
infoTex.setBackground(Color.white);
but[1].setEnabled(false);//禁用 but 数组中的第 1 和第 4 个按钮。
but[4].setEnabled(false);
noStop.setBounds(360,360,160,25);
noStop.addActionListener(this);//为 noStop 按钮添加一个动作事件监听器。
noStop.addKeyListener(this);//添加一个键盘事件监听器。
mi0.addActionListener(this);// mi0、mi1 和 mi1_0 添加动作事件监听器。
mi1.addActionListener(this);
mi1_0.addActionListener(this);
num_csh_game();//始化游戏数字缓存。
rand_block();//调用 rand_block 用于生成随机方块
}
public void actionPerformed(ActionEvent e)//处理按钮和菜单项的点击事件。
{
if(e.getSource() == but[0])//开始游戏检查事件源是否为 but[0] 按钮(开始游戏按钮)。
{
startSign = 1;//表示游戏开始。
infoTex.setText("游戏已经开始!");//在 infoTex 文本框中显示 "游戏已经开始!"。
but[0].setEnabled(false);//禁用 but[0](开始游戏 )按钮。
but[1].setEnabled(true);//启用 but[1] 和 but[4] 按钮。
but[4].setEnabled(true);
timer.resume(); //调用 timer.resume() 恢复计时器(启动游戏计时)。
}
if(e.getSource() == but[1]||e.getSource() == mi0)//重新开始游戏或 mi0 菜单项。
{
startSign = 0;//游戏停止。
gameScore = 0;//重置游戏分数 gameScore 为 0。
timer.suspend();//暂停计时器
num_csh_restart();//重置游戏状态。
repaint();//重新绘制游戏界面。
rand_block();//生成新的方块。
scoreTex.setText("0");//scoreTex 文本框中显示 "0"。
infoTex.setText("新游戏!");//infoTex 文本框中显示 "新游戏!"。
but[0].setEnabled(true);//启用 开始游戏 按钮
but[1].setEnabled(false);//禁用 重新开始 和 but[4] 按钮。
but[4].setEnabled(false);
}
if(e.getSource() == but[2])//降低级数
{
infoTex.setText("降低级数!");显示 "降低级数!"。
speedMark--;//减少 speedMark 值
if(speedMark <= 1)
{//如果 speedMark 小于或等于 1,将其设置为 1,并在 infoTex 文本框中显示 "已经是最低级数!"。
speedMark = 1;
infoTex.setText("已经是最低级数!");
}
speedTex.setText(speedMark + "");//在 speedTex 文本框中显示 speedMark 的值
}
if(e.getSource() == but[3])//提高级数 同上
{
infoTex.setText("提高级数!");
speedMark++;
if(speedMark >= 9)
{
speedMark = 9;
infoTex.setText("已经是最高级数!");
}
speedTex.setText(speedMark + "");
}
if(e.getSource() == but[4])//游戏暂停
{
this.add(noStop);将 noStop 按钮添加到当前容器。
this.remove(but[4]);//从当前容器中移除暂停游戏 按钮。
infoTex.setText("游戏暂停!");//infoTex 文本框显示 "游戏暂停!"。
timer.suspend();//暂停计时器。
}
if(e.getSource() == noStop)//取消暂停
{
this.remove(noStop);从当前容器中移除 noStop 按钮。
this.add(but[4]);//将 游戏暂停 按钮添加到当前容器。
infoTex.setText("继续游戏!");
timer.resume();//恢复计时器
}
if(e.getSource() == but[5]||e.getSource() == mi1)//退出游戏
{
jf.dispose();//调用 jf.dispose() 关闭游戏窗口并退出程序。
}
if(e.getSource() == mi1_0)/创建一个新的 JDialog 对象 dlg_1,标题为 "关 于"。
{
dlg_1 = new JDialog(jf,"关 于");
try{//尝试读取文件 resource/guanyu.txt 中的内容:
FileInputStream io = new FileInputStream("resource/guanyu.txt");//得到路径//创建 FileInputStream 对象 io。
byte a[] = new byte[io.available()];
io.read(a);//读取文件内容到字节数组 a 中。
io.close();//关闭输入流 io。
String str = new String(a);//将字节数组 a 转换为字符串 str 并设置到 dlg_1_text 文本框中
dlg_1_text.setText(str);
}
catch(Exception g){g.printStackTrace();}//如果读取文件时出现异常,打印堆栈跟踪信息。
dlg_1_text.setEditable(false);//文本框为不可编辑。
dlg_1.add(dlg_1_text);//文本框添加到 dlg_1 对话框中
dlg_1.pack();//调整对话框大小以适应内容。
dlg_1.setResizable(false);//设置对话框不可调整大小。
dlg_1.setSize(200, 120);//设置对话框的大小为 200x120 像素。
dlg_1.setLocation(400, 240);//设置对话框的位置为 (400, 240)。
dlg_1.show();//显示对话框 dlg_1
}
}
public void change_body(int blockNumber)//改变砖块状态
{
dingwei();
if(blockNumber == 1&&downSign == false)//变换长条2种情况
{
if(game_sign_y[0] == game_sign_y[1]&&game_sign_y[3] <= 16)//说明长条是横着的
{
if(game_body[game_sign_y[0] - 1][game_sign_x[0] + 1] != 2&&game_body[game_sign_y[3] + 2][game_sign_x[3] - 2] != 2)
{
num_csh_game();
game_body[game_sign_y[0] - 1][game_sign_x[0] + 1] = 1;
game_body[game_sign_y[1]][game_sign_x[1]] = 1;
game_body[game_sign_y[2] + 1][game_sign_x[2] - 1] = 1;
game_body[game_sign_y[3] + 2][game_sign_x[3] - 2] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_x[0] == game_sign_x[1]&&game_sign_x[0] >= 1&&game_sign_x[3] <= 7)//说明长条是竖着的
{
if(game_body[game_sign_y[0] + 1][game_sign_x[0]-1] != 2&&game_body[game_sign_y[3] - 2][game_sign_x[3] + 2] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 1][game_sign_x[0] - 1] = 1;
game_body[game_sign_y[1]][game_sign_x[1]]=1;
game_body[game_sign_y[2] - 1][game_sign_x[2] + 1] = 1;
game_body[game_sign_y[3] - 2][game_sign_x[3] + 2] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
}
if(blockNumber == 3&&downSign == false)//变换转弯1有4种情况
{
if(game_sign_x[0] == game_sign_x[1]&&game_sign_x[0] == game_sign_x[2]&&game_sign_y[2] == game_sign_y[3]&&game_sign_x[0] >= 1)
{
if(game_body[game_sign_y[0] + 1][game_sign_x[0] - 1] != 2&&game_body[game_sign_y[2] - 1][game_sign_x[2] + 1] != 2&&game_body[game_sign_y[3] - 2][game_sign_x[3]] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 1][game_sign_x[0] - 1] = 1;
game_body[game_sign_y[1]][game_sign_x[1]] = 1;
game_body[game_sign_y[2] - 1][game_sign_x[2] + 1] = 1;
game_body[game_sign_y[3] - 2][game_sign_x[3]] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_y[1] == game_sign_y[2]&&game_sign_y[2] == game_sign_y[3]&&game_sign_x[0] == game_sign_x[3]&&game_sign_y[1] <= 17)
{
if(game_body[game_sign_y[0]][game_sign_x[0] - 2] != 2&&game_body[game_sign_y[1] + 1][game_sign_x[1] + 1] != 2&&game_body[game_sign_y[3] - 1][game_sign_x[3] - 1] != 2)
{
num_csh_game();
game_body[game_sign_y[0]][game_sign_x[0] - 2] = 1;
game_body[game_sign_y[1] + 1][game_sign_x[1] + 1] = 1;
game_body[game_sign_y[2]][game_sign_x[2]] = 1;
game_body[game_sign_y[3] - 1][game_sign_x[3] - 1] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_x[1] == game_sign_x[2]&&game_sign_x[1] == game_sign_x[3]&&game_sign_y[0] == game_sign_y[1]&&game_sign_x[3] <= 8)
{
if(game_body[game_sign_y[0] + 2][game_sign_x[0]] != 2&&game_body[game_sign_y[1] + 1][game_sign_x[1] - 1] != 2&&game_body[game_sign_y[3] - 1][game_sign_x[3] + 1] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 2][game_sign_x[0]] = 1;
game_body[game_sign_y[1] + 1][game_sign_x[1] - 1] = 1;
game_body[game_sign_y[2]][game_sign_x[2]] = 1;
game_body[game_sign_y[3] - 1][game_sign_x[3] + 1] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_y[0] == game_sign_y[1]&&game_sign_y[1] == game_sign_y[2]&&game_sign_x[0] == game_sign_x[3])
{
if(game_body[game_sign_y[0] + 1][game_sign_x[0] + 1] != 2&&game_body[game_sign_y[2] - 1][game_sign_x[2] - 1] != 2&&game_body[game_sign_y[3]][game_sign_x[3] + 2] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 1][game_sign_x[0] + 1] = 1;
game_body[game_sign_y[1]][game_sign_x[1]] = 1;
game_body[game_sign_y[2] - 1][game_sign_x[2] - 1] = 1;
game_body[game_sign_y[3]][game_sign_x[3] + 2] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
}
if(blockNumber == 4&&downSign == false)//变换转弯2有4种情况
{
if(game_sign_x[0] == game_sign_x[1]&&game_sign_x[0] == game_sign_x[3]&&game_sign_y[1] == game_sign_y[2]&&game_sign_x[3] <= 7)
{
if(game_body[game_sign_y[0] + 2][game_sign_x[0]] != 2&&game_body[game_sign_y[1] + 1][game_sign_x[1] + 1] != 2&&game_body[game_sign_y[3]][game_sign_x[3] + 2] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 2][game_sign_x[0]] = 1;
game_body[game_sign_y[1] + 1][game_sign_x[1] + 1] = 1;
game_body[game_sign_y[2]][game_sign_x[2]] = 1;
game_body[game_sign_y[3]][game_sign_x[3] + 2] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_y[1] == game_sign_y[2]&&game_sign_y[1] == game_sign_y[3]&&game_sign_x[0] == game_sign_x[2])
{
if(game_body[game_sign_y[1]][game_sign_x[1] + 2] != 2&&game_body[game_sign_y[2] - 1][game_sign_x[2] + 1] != 2&&game_body[game_sign_y[3] - 2][game_sign_x[3]] != 2)
{
num_csh_game();
game_body[game_sign_y[0]][game_sign_x[0]] = 1;
game_body[game_sign_y[1]][game_sign_x[1] + 2] = 1;
game_body[game_sign_y[2] - 1][game_sign_x[2] + 1] = 1;
game_body[game_sign_y[3] - 2][game_sign_x[3]] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_x[0] == game_sign_x[2]&&game_sign_x[0] == game_sign_x[3]&&game_sign_y[1] == game_sign_y[2]&&game_sign_x[0] >= 2)
{
if(game_body[game_sign_y[0]][game_sign_x[0] - 2] != 2&&game_body[game_sign_y[2] - 1][game_sign_x[2] - 1] != 2&&game_body[game_sign_y[3] - 2][game_sign_x[3]] != 2)
{
num_csh_game();
game_body[game_sign_y[0]][game_sign_x[0] - 2] = 1;
game_body[game_sign_y[1]][game_sign_x[1]] = 1;
game_body[game_sign_y[2] - 1][game_sign_x[2] - 1] = 1;
game_body[game_sign_y[3] - 2][game_sign_x[3]] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_y[0] == game_sign_y[1]&&game_sign_y[0] == game_sign_y[2]&&game_sign_x[1] == game_sign_x[3]&&game_sign_y[0] <= 16)
{
if(game_body[game_sign_y[0] + 2][game_sign_x[0]] != 2&&game_body[game_sign_y[1] + 1][game_sign_x[1] - 1] != 2&&game_body[game_sign_y[2]][game_sign_x[2] - 2] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 2][game_sign_x[0]] = 1;
game_body[game_sign_y[1] + 1][game_sign_x[1] - 1] = 1;
game_body[game_sign_y[2]][game_sign_x[2] - 2] = 1;
game_body[game_sign_y[3]][game_sign_x[3]] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
}
if(blockNumber == 5&&downSign == false)//变换转弯3有4种情况
{
if(game_sign_x[0] == game_sign_x[2]&&game_sign_x[2] == game_sign_x[3]&&game_sign_y[0] == game_sign_y[1]&&game_sign_x[1] >= 2)
{
if(game_body[game_sign_y[0] + 1][game_sign_x[0] - 1] != 2&&game_body[game_sign_y[1]][game_sign_x[1] - 2] != 2&&game_body[game_sign_y[3] - 1][game_sign_x[3] + 1] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 1][game_sign_x[0] - 1] = 1;
game_body[game_sign_y[1]][game_sign_x[1] - 2] = 1;
game_body[game_sign_y[2]][game_sign_x[2]] = 1;
game_body[game_sign_y[3] - 1][game_sign_x[3] + 1] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_y[1] == game_sign_y[2]&&game_sign_y[2] == game_sign_y[3]&&game_sign_x[0] == game_sign_x[1]&&game_sign_y[0] <= 16)
{
if(game_body[game_sign_y[0] + 2][game_sign_x[0]] != 2&&game_body[game_sign_y[1] + 1][game_sign_x[1] + 1] != 2&&game_body[game_sign_y[3] - 1][game_sign_x[3] - 1] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 2][game_sign_x[0]] = 1;
game_body[game_sign_y[1] + 1][game_sign_x[1] + 1] = 1;
game_body[game_sign_y[2]][game_sign_x[2]] = 1;
game_body[game_sign_y[3] - 1][game_sign_x[3] - 1] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_x[0] == game_sign_x[1]&&game_sign_x[1] == game_sign_x[3]&&game_sign_y[2] == game_sign_y[3])
{
if(game_body[game_sign_y[0] + 1][game_sign_x[0] - 1] != 2&&game_body[game_sign_y[2]][game_sign_x[2] + 2] != 2&&game_body[game_sign_y[3] - 1][game_sign_x[3] + 1] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 1][game_sign_x[0] - 1] = 1;
game_body[game_sign_y[1]][game_sign_x[1]] = 1;
game_body[game_sign_y[2]][game_sign_x[2] + 2] = 1;
game_body[game_sign_y[3] - 1][game_sign_x[3] + 1] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_y[0] == game_sign_y[1]&&game_sign_y[1] == game_sign_y[2]&&game_sign_x[2] == game_sign_x[3])
{
if(game_body[game_sign_y[0] + 1][game_sign_x[0] + 1] != 2&&game_body[game_sign_y[2] - 1][game_sign_x[2] - 1] != 2&&game_body[game_sign_y[3] - 2][game_sign_x[3]] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 1][game_sign_x[0] + 1] = 1;
game_body[game_sign_y[1]][game_sign_x[1]] = 1;
game_body[game_sign_y[2] - 1][game_sign_x[2] - 1] = 1;
game_body[game_sign_y[3] - 2][game_sign_x[3]] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
}
if(blockNumber == 6&&downSign == false)//变换两层砖块1的2种情况
{
if(game_sign_x[0] == game_sign_x[2]&&game_sign_x[0] >= 2)
{
if(game_body[game_sign_y[0]][game_sign_x[0] - 2] != 2&&game_body[game_sign_y[2] - 1][game_sign_x[2] -1 ] != 2&&game_body[game_sign_y[3] - 1][game_sign_x[3] + 1] != 2)
{
num_csh_game();
game_body[game_sign_y[0]][game_sign_x[0] - 2] = 1;
game_body[game_sign_y[1]][game_sign_x[1]] = 1;
game_body[game_sign_y[2] - 1][game_sign_x[2] - 1] = 1;
game_body[game_sign_y[3] - 1][game_sign_x[3] + 1] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_y[0] == game_sign_y[1]&&game_sign_y[3] <= 17)
{
if(game_body[game_sign_y[0]][game_sign_x[0] + 2] != 2&&game_body[game_sign_y[1] + 1][game_sign_x[1] + 1] != 2&&game_body[game_sign_y[3] + 1][game_sign_x[3] - 1] != 2)
{
num_csh_game();
game_body[game_sign_y[0]][game_sign_x[0] + 2] = 1;
game_body[game_sign_y[1] + 1][game_sign_x[1] + 1] = 1;
game_body[game_sign_y[2]][game_sign_x[2]] = 1;
game_body[game_sign_y[3] + 1][game_sign_x[3] - 1] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
}
if(blockNumber == 7&&downSign == false)//变换两层砖块2的2种情况
{
if(game_sign_x[0] == game_sign_x[1]&&game_sign_x[0] <= 16)
{
if(game_body[game_sign_y[0]][game_sign_x[0] + 2] != 2&&game_body[game_sign_y[1] - 1][game_sign_x[1] + 1] != 2&&game_body[game_sign_y[3] - 1][game_sign_x[3] - 1] != 2)
{
num_csh_game();
game_body[game_sign_y[0]][game_sign_x[0] + 2] = 1;
game_body[game_sign_y[1] - 1][game_sign_x[1] + 1] = 1;
game_body[game_sign_y[2]][game_sign_x[2]] = 1;
game_body[game_sign_y[3] - 1][game_sign_x[3] - 1] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
if(game_sign_y[0] == game_sign_y[1]&&game_sign_y[2] <= 17)
{
if(game_body[game_sign_y[0] + 1][game_sign_x[0] - 1] != 2&&game_body[game_sign_y[1]][game_sign_x[1] - 2] != 2&&game_body[game_sign_y[2] + 1][game_sign_x[2] + 1] != 2)
{
num_csh_game();
game_body[game_sign_y[0] + 1][game_sign_x[0] - 1] = 1;
game_body[game_sign_y[1]][game_sign_x[1] - 2] = 1;
game_body[game_sign_y[2] + 1][game_sign_x[2] + 1] = 1;
game_body[game_sign_y[3]][game_sign_x[3]] = 1;
infoTex.setText("游戏进行中!");
repaint();
}
}
}
}
public void num_csh_game()//数组清零 用于将游戏数组 game_body 中的值重置
{
for(int i = 0;i < 19;i++)//开始一个外层 for 循环,循环变量 i 从 0 到 18,用于遍历 game_body 数组的行(共 19 行)。
{
for(int j = 0;j < 10;j++)//遍历 game_body 数组的列(共 10 列)。
{
if(game_body[i][j] == 2)//如果 game_body 数组中位于 [i][j] 位置的元素等于 2,保持 game_body[i][j] 的值为 2。
{
game_body[i][j] = 2;
}
else
{//不等于 2,则将其重置为 0
game_body[i][j] = 0;
}
}
}
}
public void num_csh_restart()//重新开始时数组清零
{
for(int i = 0;i < 19;i++)
{
for(int j = 0;j < 10;j++)
{
game_body[i][j] = 0;//清空所有位置
}
}
}
public void keyTyped(KeyEvent e){}
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_DOWN&&startSign == 1)//处理下键
{
this.down();
}
if(e.getKeyCode() == KeyEvent.VK_LEFT&&startSign == 1)//处理左键
{
this.left();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT&&startSign == 1)//处理右键
{
this.right();
}
if(e.getKeyCode() == KeyEvent.VK_UP&&startSign == 1)//处理上键转换
{
this.change_body(blockNumber);
}
if(startSign == 0)
{
infoTex.setText("游戏未开始或已结束!");
}
}
public void keyReleased(KeyEvent e){}
public void paint(Graphics g)//接收一个 Graphics 对象 g 作为参数,用于绘制图形。
{
g.setColor(Color.black);//绘图颜色为黑色。
g.fill3DRect(0,0,300,450,true);//绘制3D矩形,左上角坐标为 (0, 0),宽度为 300,高度为 450,并且绘制凸起效果的3D矩形背景。
for(int i = 0;i < 19;i++)
{
for(int j = 0;j < 10;j++)
{
if(game_body[i][j] == 1)//若game_body [i][j] 等于 1,
{
g.setColor(Color.blue);//将绘图颜色设置为蓝色。
g.fill3DRect(30*j,30*(i-4),30,30,true);//绘制一个填充的3D矩形,左上角坐标为 (30 * j, 30 * (i - 4)),宽度和高度均为 30,并且绘制凸起效果的3D矩形。
}
if(game_body[i][j] == 2)//等于 2。
{
g.setColor(Color.magenta);//将绘图颜色设置为品红色
g.fill3DRect(30*j,30*(i-4),30,30,true);//绘制矩形
}
}
}
}
public void left()//向左移动
{
int sign = 0;//标记是否可以向左移动
dingwei();//更新或获取当前方块的位置信息。
for(int k = 0;k < 4;k++)//遍历当前方块的四个方格
{
if(game_sign_x[k] == 0||game_body[game_sign_y[k]][game_sign_x[k] - 1] == 2)
{
sign = 1;//检查当前方块的每个方格是否位于最左边的列(game_sign_x[k] == 0)。
//或者检查当前方格左边的格子是否已经被占用(game_body[game_sign_y[k]][game_sign_x[k] - 1] == 2)。
//如果上述任一条件为真,将 sign 设置为 1,表示不能向左移动。
}
}
if(sign == 0&&downSign == false)
{//检查 sign 是否仍然为 0(表示可以向左移动),并且 downSign 是否为 false(表示当前方块还未落下)。
num_csh_game();//重置游戏数组 game_body,但保留值为 2 的元素(已固定的方块)。
for(int k = 0;k < 4;k++)
{//将当前方块的每个方格在游戏数组中向左移动一格,即将当前位置左边的格子设置为 1。
game_body[game_sign_y[k]][game_sign_x[k] - 1] = 1;
}
infoTex.setText("向左移动!");
repaint();
}
}
public void right()//向右移动
{
int sign = 0;
dingwei();
for(int k = 0;k < 4;k++)
{
if(game_sign_x[k] == 9||game_body[game_sign_y[k]][game_sign_x[k] + 1] == 2)
{
sign = 1;
}
}
if(sign == 0&&downSign == false)
{
num_csh_game();
for(int k = 0;k < 4;k++)
{
game_body[game_sign_y[k]][game_sign_x[k] + 1] = 1;
}
infoTex.setText("向右移动!");
repaint();
}
}
public void down()//下落
{
int sign = 0;
dingwei();
for(int k = 0;k < 4;k++)
{
if(game_sign_y[k] == 18||game_body[game_sign_y[k] + 1][game_sign_x[k]] == 2)
{
sign = 1;
downSign = true;
changeColor();
cancelDW();
getScore();
if(game_over() == false)
{
rand_block();
repaint();
}
}
}
if(sign == 0)
{
num_csh_game();
for(int k = 0;k < 4;k++)
{
game_body[game_sign_y[k] + 1][game_sign_x[k]] = 1;
}
infoTex.setText("游戏进行中!");
repaint();
}
}
public boolean game_over()//判断游戏是否结束
{
int sign=0;//标记游戏是否结束
for(int i = 0;i < 10;i++)//用于检测是否有方块到达顶部
{
if(game_body[4][i] == 2)
{
sign = 1;
}
}
if(sign == 1)
{
infoTex.setText("游戏结束!");
changeColor();//用于改变界面的颜色以表示游戏结束(
repaint();//重绘组件以显示游戏结束的状态。
startSign = 0;//startSign 设置为 0,表示游戏停止
timer.suspend();
return true;//。
}
else
return false;//没有结束。
}
public void getScore()//满行消除方法
{
for(int i = 0;i < 19;i++)
{
int sign = 0;//记录当前行被填满的方块数量。
for(int j = 0;j < 10;j++)
{
if(game_body[i][j] == 2)
{//如果当前格子是否被固定方块占据,将 sign 增加 1。
sign++;
}
}
if(sign == 10) //是否当前行的所有格子都被填满)
{
gameScore += 100;//gameScore 增加 100。
scoreTex.setText(gameScore+"");
infoTex.setText("恭喜得分!");
for(int j = i;j >= 1;j--)
{
for(int k = 0;k < 10;k++)
{
game_body[j][k] = game_body[j - 1][k];
//将上面一行的内容复制到当前行,以清除当前行并将上面的行向下移动。
}
}
}
}
}
public void changeColor()//给已经落下的块换色
{
downSign = false;// downSign 变量设置为 false,表示当前方块不再下落。
for(int k = 0;k < 4;k++)
{
game_body[game_sign_y[k]][game_sign_x[k]] = 2;
//将当前方块的每个方格在 game_body 数组中的值设置为 2,表示方块已经固定
}
}
public void dingwei()//确定其位置
{
int k = 0;//记录当前方块的格子数目。
cancelDW();//将定位数组初始化。
for(int i = 0;i < 19;i++)
{
for(int j = 0;j < 10;j++)
{
if(game_body[i][j] == 1)
{//如果当前格子属于当前活动方块,将当前格子的列索引 j 赋值给 game_sign_x[k],行索引 i 赋值给 game_sign_y[k]。将 k 增加 1,记录下一个方块的位置。
game_sign_x[k] = j;
game_sign_y[k] = i;
k++;
}
}
}
}
public void cancelDW()//将定位数组初始化
{
for(int k = 0;k < 4;k++)//遍历定位数组的所有元素
{
game_sign_x[k] = 0;
game_sign_y[k] = 0;
}
}
public void block1()//长条
{
game_body[0][4] = 1;
game_body[1][4] = 1;
game_body[2][4] = 1;
game_body[3][4] = 1;
}
public void block2()//正方形
{
game_body[3][4] = 1;
game_body[2][4] = 1;
game_body[3][5] = 1;
game_body[2][5] = 1;
}
public void block3()//3加1(下)
{
game_body[1][4] = 1;
game_body[2][4] = 1;
game_body[3][4] = 1;
game_body[3][5] = 1;
}
public void block4()//3加1(中)
{
game_body[1][4] = 1;
game_body[2][4] = 1;
game_body[3][4] = 1;
game_body[2][5] = 1;
}
public void block5()//3加1(上)
{
game_body[1][4] = 1;
game_body[2][4] = 1;
game_body[3][4] = 1;
game_body[1][5] = 1;
}
public void block6()//转折1
{
game_body[1][5] = 1;
game_body[2][5] = 1;
game_body[2][4] = 1;
game_body[3][4] = 1;
}
public void block7()//转折2
{
game_body[1][4] = 1;
game_body[2][4] = 1;
game_body[2][5] = 1;
game_body[3][5] = 1;
}
}
}
class MyTimer extends Thread
{
Block myBlock; //声明一个 Block 类型的成员变量,引用游戏中的方块对象
public MyTimer(Block myBlock)//构造方法
{
this.myBlock = myBlock;
}
public void run()//线程执行的入口点,重写了 Thread 类的 run 方法。
{
while(myBlock.startSign == 1)//只要 myBlock.startSign 等于 1,循环将继续执行。startSign 是一个标志位,表示游戏是否正在进行。
{
try{
sleep((10-myBlock.speedMark + 1)*100); //使当前线程休眠一段时间,休眠时间由 (10 - myBlock.speedMark + 1) * 100 计算得出,单位是毫秒。
myBlock.down();//使方块向下移动一格
}
catch(InterruptedException e){}// 异常,线程在休眠期间被中断。
}
}
}