Java实现俄罗斯方块
规则
1.方块会从上方缓慢下落,玩家可以通过键盘上的上下左右键来控制方块。
2.方块移到区域最下方或是着地到其他方块上无法移动时,就会固定在该处,而新的方块出现在区域上方开始落下。
3.当区域中某一列横向格子全部由方块填满,则该列会消失并成为玩家的得分。同时删除的列数越多,得分指数上升。
4.当固定的方块堆到区域最上方而无法消除层数时或者大于游戏区域时,则游戏结束。
代码目录

实现代码







import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;//俄罗斯方块主类
public class Tetris extends JPanel {static int ROW = 18;static int COL = 9;//声明正在下落的方块private Tetromino currentOne = Tetromino.randomOne();//声明将要下落的方块private Tetromino nextOne = Tetromino.randomOne();//声明游戏主区域private Cell[][] wall = new Cell[ROW][COL];//声明单元格像素为48像素private static final int CELL_SIZE = 48;//游戏分数池int[] scores_pool = {0, 1, 2, 5, 10};//游戏总分private int totalScore = 0;//游戏消除总行数private int totalLine = 0;//游戏的状态:游戏中,游戏暂停,游戏结束private static final int PLAYING = 0;private static final int PAUSE = 1;private static final int GAMEOVER = 2;//声明变量来存放当前游戏状态private int game_state;//数组显示当前游戏状态String[] show_state = {"P[暂停]","C[继续]","R[重开]"};//静态载入图片public static BufferedImage I;public static BufferedImage J;public static BufferedImage L;public static BufferedImage O;public static BufferedImage S;public static BufferedImage T;public static BufferedImage Z;public static BufferedImage backImage;static {try {I = ImageIO.read(new File("images/I.png"));J = ImageIO.read(new File("images/J.png"));L = ImageIO.read(new File("images/L.png"));O = ImageIO.read(new File("images/O.png"));S = ImageIO.read(new File("images/S.png"));T = ImageIO.read(new File("images/T.png"));Z = ImageIO.read(new File("images/Z.png"));backImage = ImageIO.read(new File("images/background.png"));} catch (IOException e) {e.printStackTrace();}}@Overridepublic void paint(Graphics g) {g.drawImage(backImage,0,0,null);//平移坐标轴g.translate(22,15);//绘制游戏主区域paintWall(g);//绘制正在下落的四方格paintCurrentOne(g);//绘制下一个下落的四方格paintNextOne(g);//绘制游戏得分paintScore(g);//绘制游戏当前状态paintState(g);}//start 方法,用于调用游戏操作逻辑并监听键盘和描述游戏主要逻辑public void start() {game_state = PLAYING;KeyListener listener = new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {int code = e.getKeyCode();switch (code) {case KeyEvent.VK_DOWN: //↓sortDropAction(); //下落一格break;case KeyEvent.VK_LEFT://←moveLeftAction(); //左移一格break;case KeyEvent.VK_RIGHT: //→moveRightAction(); //右移一格break;case KeyEvent.VK_UP://↑rotateRightAction();//顺时针旋转break;case KeyEvent.VK_SPACE://空格handDropAction();//瞬间下落break;case KeyEvent.VK_P: //p//判断游戏是否在运行,没有才能暂停if (game_state == PLAYING) {game_state = PAUSE;}break;case KeyEvent.VK_C://游戏暂停后,才能继续if (game_state == PAUSE) {game_state = PLAYING;}break;case KeyEvent.VK_R://重新开始游戏,把游戏状态变为正在游戏game_state = PLAYING;//界面清空wall = new Cell[ROW][COL];currentOne = Tetromino.randomOne();nextOne = Tetromino.randomOne();//数据清空totalLine = 0;totalScore = 0;break;}}};//把俄罗斯方块窗口设置为焦点this.addKeyListener(listener);this.requestFocus();while(true){//判断,当前游戏状态在游戏中时,每隔0.5秒下落if(game_state == PLAYING){try {Thread.sleep(700);} catch (InterruptedException e) {e.printStackTrace();}//判断能否下落if(canDrop()){currentOne.softDrop();}else{//嵌入到墙中landToWall();//判断能否消行destroyLine();//判断游戏是否结束if(isGameOver()){game_state = GAMEOVER;}else{currentOne = nextOne;nextOne = Tetromino.randomOne();}}}//重新绘制repaint();}}//顺时针旋转public void rotateRightAction() {currentOne.rotateRight();//判断是否越界或者重合,否则恢复原来的状态if (outOfBounds() || coincide()) {currentOne.rotateLeft();}}//瞬间下落public void handDropAction() {while (canDrop()) {currentOne.softDrop();}//把四方格嵌入墙中landToWall();//判断能否销行destroyLine();//判断游戏是否结束if (isGameOver()) {game_state = GAMEOVER;} else {//继续生成四方格currentOne = nextOne;nextOne = Tetromino.randomOne();}}//按键一次四方格下落一个public void sortDropAction() {//判断能否下落if (canDrop()) {//当前四方格下落一格currentOne.softDrop();} else {//把四方格嵌入墙中landToWall();//判断能否销行destroyLine();//判断游戏是否结束if (isGameOver()) {game_state = GAMEOVER;} else {//继续生成四方格currentOne = nextOne;nextOne = Tetromino.randomOne();}}}//把四方格嵌入墙中private void landToWall() {Cell[] cells = currentOne.cells;for (Cell cell : cells) {int row = cell.getRow();int col = cell.getCol();wall[row][col] = cell;}}//判断四方格能否下落public boolean canDrop() {Cell[] cells = currentOne.cells;for (Cell cell : cells) {int row = cell.getRow();int col = cell.getCol();//判断能否全部到达底部if (row == wall.length - 1) {return false;} else if(wall[row + 1][col] != null) { //判断该位置是否有方块return false;}}return true;}//创建销行方法public void destroyLine() {//统计当前形参行数int line = 0;Cell[] cells = currentOne.cells;for (Cell cell : cells) {int row = cell.getRow();//判断当前行是否满if (isFullLine(row)) {line++;//将消除行以上的方块下落到对应行数for (int i = row; i > 0; i--) {System.arraycopy(wall[i - 1],0,wall[i],0,wall[0].length);}//重新创造第一行wall[0] = new Cell[9];}}//更新分数totalScore += scores_pool[line];//更新消除行数totalLine += line;}//判断当前行是否满,满返回true,没有满返回falsepublic boolean isFullLine(int row) {Cell[] cells = wall[row];for (Cell cell : cells) {if (cell == null) {return false;}}return true;}//判断游戏是否结束,结束返回true,继续返回falsepublic boolean isGameOver() {Cell[] cells = nextOne.cells;for (Cell cell : cells) {int row = cell.getRow();int col = cell.getCol();if (wall[row][col] != null) {return true;}}return false;}//按键←触发左移public void moveLeftAction() {currentOne.moveLeft();//判断是否越界或者重合,如果是则右移恢复原来的状态,不是则左移if (outOfBounds() || coincide()) {currentOne.moveRight();}}//按键→触发右移public void moveRightAction() {currentOne.moveRight();//判断是否越界或者重合,如果是则左移恢复原来的状态,不是则右移if (outOfBounds() || coincide()) {currentOne.moveLeft();}}//判断方块是否重合,重合返回true,没有返回falsepublic boolean coincide() {Cell[] cells = currentOne.cells;for (Cell cell : cells) {int col = cell.getCol();int row = cell.getRow();if (wall[row][col] != null) {return true;}}return false;}//判断方块是否出界,出界返回true,没有则返回falsepublic boolean outOfBounds() {Cell[] cells = currentOne.cells;for (Cell cell : cells) {int col = cell.getCol();int row = cell.getRow();if (col < 0 || col > COL - 1 || row < 0 || row > ROW - 1) {return true;}}return false;}//绘制游戏当前状态private void paintState(Graphics g) {if (game_state == PLAYING) {g.drawString(show_state[0],500,660);} else if (game_state == PAUSE) {g.drawString(show_state[1],500,660);} else if (game_state == GAMEOVER) {g.drawString(show_state[2],500,660);g.setColor(Color.red);g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,60));g.drawString("GAMEOVER!",30,400);}}//绘制游戏得分private void paintScore(Graphics g) {g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,40));g.drawString("得分:" + totalScore,500,248);g.drawString("行数:"+ totalLine,500,440);}//绘制下一个下落的四方格private void paintNextOne(Graphics g) {Cell[] cells = nextOne.cells;for (Cell cell : cells) {int x = cell.getCol() * CELL_SIZE + 370;int y = cell.getRow() * CELL_SIZE + 25;g.drawImage(cell.getImage(),x,y,null);}}//绘制正在下落的四方格private void paintCurrentOne(Graphics g) {Cell[] cells = currentOne.cells;for (Cell cell : cells) {int x = cell.getCol() * CELL_SIZE;int y = cell.getRow() * CELL_SIZE;g.drawImage(cell.getImage(),x,y,null);}}//绘制游戏主区域private void paintWall(Graphics g) {for (int i = 0; i < wall.length; i++) {for (int j = 0; j < wall[i].length; j++) {int x = j * CELL_SIZE;int y = i * CELL_SIZE;Cell cell = wall[i][j];//判断当前单元格是否有小方格,如果无则绘制矩形,否则将小方块嵌到墙中if (cell == null) {g.drawRect(x,y,CELL_SIZE,CELL_SIZE);} else {g.drawImage(cell.getImage(),x,y,null);}}}}public static void main(String[] args) {//创建窗口对象JFrame frame = new JFrame("俄罗斯方块");//创建游戏窗口(即面板)Tetris panel = new Tetris();//把面板嵌入到窗口中frame.add(panel);//设置可见frame.setVisible(true);//设置窗口尺寸frame.setSize(810,940);//设置窗口居中frame.setLocationRelativeTo(null);//设置窗口关闭时程序中止frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//游戏逻辑封装在方法中panel.start();}
}
/*** 描述:四方格父类* 属性:Cell[]数组用于创建4个小方块* 方法:左移一格,右移一格,下移一格,变形(等会写)*/public class Tetromino {protected Cell[] cells = new Cell[4];//编写旋转状态protected State[] states;//声明旋转次数protected int count = 10000;//编写顺时针旋转四方格方法public void rotateRight() {if (states.length == 0) {return;}//旋转次数加1count++;//获取当前状态State s = states[count % states.length];Cell cell = cells[0];int row = cell.getRow();int col = cell.getCol();//变形cells[1].setRow(row + s.row1);cells[1].setCol(col + s.col1);cells[2].setRow(row + s.row2);cells[2].setCol(col + s.col2);cells[3].setRow(row + s.row3);cells[3].setCol(col + s.col3);}//逆时针旋转四方格方法public void rotateLeft() {//旋转次数加1count--;//获取当前状态State s = states[count % states.length];Cell cell = cells[0];int row = cell.getRow();int col = cell.getCol();//变形cells[1].setRow(row + s.row1);cells[1].setCol(col + s.col1);cells[2].setRow(row + s.row2);cells[2].setCol(col + s.col2);cells[3].setRow(row + s.row3);cells[3].setCol(col + s.col3);}/**描述:四方格旋转状态的内部类* 属性:记录四方格的相对位置*/class State {int row0,col0,row1,col1,row2,col2,row3,col3;public State(){}public State(int row0, int col0, int row1, int col1, int row2, int col2, int row3, int col3) {this.row0 = row0;this.col0 = col0;this.row1 = row1;this.col1 = col1;this.row2 = row2;this.col2 = col2;this.row3 = row3;this.col3 = col3;}public int getRow0() {return row0;}public void setRow0(int row0) {this.row0 = row0;}public int getRow1() {return row1;}public void setRow1(int row1) {this.row1 = row1;}public int getRow2() {return row2;}public void setRow2(int row2) {this.row2 = row2;}public int getRow3() {return row3;}public void setRow3(int row3) {this.row3 = row3;}public int getCol0() {return col0;}public void setCol0(int col0) {this.col0 = col0;}public int getCol1() {return col1;}public void setCol1(int col1) {this.col1 = col1;}public int getCol2() {return col2;}public void setCol2(int col2) {this.col2 = col2;}public int getCol3() {return col3;}public void setCol3(int col3) {this.col3 = col3;}}//左移public void moveLeft() {for (Cell cell : cells) {cell.left();}}//右移public void moveRight() {for (Cell cell : cells) {cell.right();}}//下移public void softDrop() {for (Cell cell : cells) {cell.drop();}}//随机生成四方格public static Tetromino randomOne() {int num = (int)(Math.random() * 7);Tetromino tetromino = null;switch (num) {case 0 :tetromino = new I();break;case 1 :tetromino = new J();break;case 2 :tetromino = new L();break;case 3 :tetromino = new O();break;case 4 :tetromino = new S();break;case 5 :tetromino = new T();break;case 6 :tetromino = new Z();break;}return tetromino;}
}
游戏界面

相关文章:
Java实现俄罗斯方块
规则 1.方块会从上方缓慢下落,玩家可以通过键盘上的上下左右键来控制方块。 2.方块移到区域最下方或是着地到其他方块上无法移动时,就会固定在该处,而新的方块出现在区域上方开始落下。 3.当区域中某一列横向格子全部由方块填满,…...
【计算思维】少儿编程蓝桥杯青少组计算思维题考试真题及解析B
STEMA考试-计算思维-U8级(样题) 1.浩浩的左⼿边是( )。 A.兰兰 B.⻉⻉ C.⻘⻘ D.浩浩 2.2时30分,钟⾯上时针和分针形成的⻆是什么⻆?( ) A.钝⻆ B.锐⻆ C.直⻆ D.平⻆ 3.下⾯是⼀年级同学最喜欢的《⻄游记》…...
第三章 栈和队列【24王道数据结构笔记】
1.栈 1.1 栈的基本概念 只允许在一端(栈顶top)进行插入或删除操作的受限的线性表。后进先出(Last In First Out)LIFO。或者说先进后出FILO。 进栈顺序:a1 > a2 > a3 > a4 > a5出栈顺序:a5 > a4 > a3 > a2 …...
保姆级教程之SABO-VMD-CNN-SVM的分类诊断,特征可视化
今天出一期基于SABO-VMD-CNN-SVM的分类诊断。 依旧是采用经典的西储大学轴承数据。基本流程如下: 首先是以最小包络熵为适应度函数,采用SABO优化VMD的两个参数。其次对每种状态的数据进行特征向量的求取,并为每组数据打上标签。然后将数据送入…...
跳跃游戏(贪心思想)
题解 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 输入样例 示例 1…...
【JavaSE语法】类和对象(二)
六、 封装 6.1 封装的概念 面向对象程序三大特性:封装、继承、多态。而类和对象阶段,主要研究的就是封装特性。 封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互…...
【SA8295P 源码分析 (三)】121 - MAX9295A 加串器芯片手册分析 及初始化参数分析
【SA8295P 源码分析】121 - MAX9295A 加串器芯片手册分析 及初始化参数分析 一、MAX9295A 芯片特性1.1 GPIO 引脚说明1.2 功能模块框图1.3 时序分析1.3.1 GMSL2 Lock Time:25 ms1.3.2 视频初始化延时:1.1ms + 17000 x t(PCLK)1.3.3 High-Speed Data Transmission in Bursts1.…...
Maya 2024 for Mac(3D建模软件)
Maya 2024是一款三维计算机图形软件,具有强大的建模、动画、渲染、特效等功能,广泛应用于影视、游戏、广告等行业。以下是Maya 2024软件的主要功能介绍: 建模:Maya 2024具有强大的建模工具,包括多边形建模、曲面建模、…...
9. 深度学习——GAN
机器学习面试题汇总与解析——GAN 本章讲解知识点 从 GAN 讲起本专栏适合于Python已经入门的学生或人士,有一定的编程基础。本专栏适合于算法工程师、机器学习、图像处理求职的学生或人士。本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅。这才是一份面试题总结的正…...
BeanUtils中的copyProperties方法使用
一、Beanutils中的copyProperties是我们在日常开发中常用的一个方法。 作用: 将a实体类中的属性赋值到b实体类中相对于的字段上 1.我们前端传参的时候我们后端通常会用vo实体类来接收,但是更新数据库的时候需要用do去操作 2.我们将vo的属性copy到do中可…...
hivesql连续日期统计最大逾期/未逾期案例
1、虚表(测试表和数据) create test_table as select a.cust_no, a.r_date, a.yqts from ( select 123 as cust_no, 20231101 as r_date, 0 as yqts union all select 123 as cust_no, 20231102 as r_date, 1 as yqts union all select 123 as cust_no, 20231103 as r_d…...
基于STM32的无线通信系统设计与实现
【引言】 随着物联网的迅速发展,无线通信技术逐渐成为现代通信领域的关键技术之一。STM32作为一款广受欢迎的微控制器,具有丰富的外设资源和强大的计算能力,在无线通信系统设计中具有广泛的应用。本文将介绍如何基于STM32实现一个简单的无线通…...
kubernetes--pod详解
目录 一、pod简介: 1. Pod基础概念: 2. Kubrenetes集群中Pod的两种使用方式: 3. pod资源中包含的容器: 4. pause容器的两个核心功能: 5. Kubernetes中使用pause容器概念的用意: 二、pod的分类࿱…...
WPF提供了哪些不同类型的画刷
在WPF中,画刷(Brush)用于填充图形对象(如形状、控件的背景和前景)的颜色和样式。WPF提供了几种不同类型的画刷: SolidColorBrush:这是最简单的画刷,它提供了一个单一的、固定的颜色。…...
STM32与ZigBee技术在智能家居无线通信中的应用研究
一、引言 智能家居系统是利用物联网技术将家庭各种设备进行互联互通,实现智能化控制和管理的系统。在智能家居系统中,无线通信技术起着至关重要的作用,而STM32微控制器和ZigBee技术则是实现智能家居无线通信的关键技术。本文将对STM32与ZigB…...
【Apache Doris】审计日志插件 | 快速体验
【Apache Doris】审计日志插件 | 快速体验 一、 环境信息1.1 硬件信息1.2 软件信息 二、 审计日志插件介绍三、 快速 体验3.1 AuditLoader 配置3.1.1 下载 Audit Loader 插件3.1.2 解压安装包3.1.3 修改 plugin.conf 3.2 创建库表3.3 初始化3.4 验证 一、 环境信息 1.1 硬件信…...
Web安全:Vulfocus 靶场搭建.(漏洞集成平台)
Web安全:Vulfocus 靶场搭建.(漏洞集成平台) Vulfocus 是一个包含了多种漏洞靶场的镜像。每个靶场都有具体的漏洞环境和攻击点。Vulfocus 的靶场包括了 Web 安全漏洞、系统安全漏洞、网络安全漏洞、密码学漏洞等多种类型。通关这个靶场我们可以…...
Go ZIP压缩文件读写操作
创建zip文件 golang提供了archive/zip包来处理zip压缩文件,下面通过一个简单的示例来展示golang如何创建zip压缩文件: func createZip(filename string) {// 缓存压缩文件内容buf : new(bytes.Buffer)// 创建zipwriter : zip.NewWriter(buf)defer writ…...
全堆栈图像生成器专为Multiverse后端Bootcamp设计,结合了React、Firebase和Hugging Face API
目录 1 Full Stack Image Generator 1.1 Features 1.2 Technologies Used 1.3 Setup Instructions 1.4 Contributing 1.5 Acknowledgements Full Stack Image Generator This is a full-stack image generator built as a part of the Multiverse Backend Bootcam…...
【C#学习】button:只显示图片
第一步:设置按钮背景图片,并且图片随按钮大小变化 第二步:设置按钮使之只显示图片 button1.FlatStyle FlatStyle.Flat;//stylebutton1.ForeColor Color.Transparent;//前景button1.BackColor Color.Transparent;//去背景button1.FlatAppe…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
