使用Java语言编写的经典游戏俄罗斯方块,能够调整游戏难度、加快下落速度、左右旋转方块等全部功能。(代码已集成在一个class内,如下所示,点击即可运行。内容水平有限,欢迎指正批评。)

演示视频 https://www.bilibili.com/video/BV1Yi4y1R7Xn/

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Timer;
import java.util.TimerTask;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;public class Tetris extends JFrame{/*** D、F变形,方向键移动,空格暂停,Esc退出游戏。*/private static final long serialVersionUID = 1L;private JButton[][] grid = new JButton[20][10];//背景private int[][][][] relativePosition={{{{0,0},{0,1},{0,2},{0,3}},{{0,0},{1,0},{2,0},{3,0}}},{{{0,0},{1,0},{1,1},{1,2}},{{0,1},{1,1},{2,0},{2,1}},{{0,0},{0,1},{0,2},{1,2}},{{0,0},{0,1},{1,0},{2,0}}},{{{0,1},{1,0},{1,1},{1,2}},{{0,1},{1,0},{1,1},{2,1}},{{0,0},{0,1},{0,2},{1,1}},{{0,0},{1,0},{1,1},{2,0}}},{{{0,2},{1,0},{1,1},{1,2}},{{0,0},{0,1},{1,1},{2,1}},{{0,0},{0,1},{0,2},{1,0}},{{0,0},{1,0},{2,0},{2,1}}},{{{0,0},{0,1},{1,1},{1,2}},{{0,1},{1,0},{1,1},{2,0}}},{{{0,0},{0,1},{1,0},{1,1}}},{{{0,1},{0,2},{1,0},{1,1}},{{0,0},{1,0},{1,1},{2,1}}}};//七种不同方块组合,每种方块组合的旋转角度,每种旋转角度的四个不同方块,每个方块的行列坐标private boolean[][] gridState = new boolean[20][10];//网格是否被填充,true表示被填充,false表示没有被填充private boolean falling = false;//当前是否有方块下降private boolean pause = false;//当前游戏是否暂停private boolean token = false;//当前令牌是否被占用private boolean fallToTheGround;//当前是否落到地上或者其他方格上private boolean transformative;//当前能否变形private boolean removable;//当前能否左右移动private boolean gameOver = false;//当前游戏是否结束(结束条件两个,一个是达到了10000分,一个是触到了天花板)private int[][] location = new int[4][2];//下降的四个方块各自坐标private int time = 1000;//方块停留时间,与游戏难度相关private int score = 0;//游戏得分private int realTimePlaceL, realTimePlaceR;//方块整体的基准点private int shapeKind, angle, angle_ = -1, angleNum;//形状的种类,旋转角度,将要旋转到的角度,此种类能够旋转的角度数private Color lightColor = new Color(210,210,210);//浅色方块private Color darkColor = new Color(20,20,20);//深色背景private String difficulty;//游戏难度public Tetris() {chooseDifficulty();//选择难度interfaceMethod();//渲染UIsystemTimer();//系统控制方块定时下降play();//玩家用键盘操作方块}void chooseDifficulty() {//选择难度Object[] possibleValues = {"青铜", "白银", "黄金", "白金", "钻石"};Object selectedValue = JOptionPane.showInputDialog(null, "按键说明:\n\n                D、F变形,方向键移动,\n               空格暂停,Esc退出游戏。\n\n请选择难度等级:","开始",JOptionPane.PLAIN_MESSAGE, null,possibleValues, possibleValues[1]);if(selectedValue == null) {System.exit(0);}else {switch(difficulty = selectedValue.toString()) {case "青铜":time = 1500;//每个位置方块组合停留1500msbreak;case "白银":time = 1000;//每个位置方块组合停留1000msbreak;case "黄金":time = 500;//每个位置方块组合停留500msbreak;case "白金":time = 300;//每个位置方块组合停留300msbreak;case "钻石":time = 150;//每个位置方块组合停留150msbreak;}}}void interfaceMethod() {//渲染UIsetTitle("Tetris    难度: " + difficulty + "  得分: " + String.valueOf(score));//设置窗口标题setResizable(false);//首先隐藏窗口,等全部组件渲染完一起显示setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//设置窗口关闭按钮不起作用,便于下面重写关闭功能int width = Toolkit.getDefaultToolkit().getScreenSize().width;//获取屏幕宽度int height = Toolkit.getDefaultToolkit().getScreenSize().height;//获取屏幕高度int windowsWedth =360, windowsHeight = 700;//窗口大小setBounds((width - windowsWedth) / 2,(height - windowsHeight) / 2,windowsWedth,windowsHeight);//设置屏幕居中setLayout(new GridLayout(0,10));//网格布局,10列addWindowListener(new WindowAdapter() {//重写窗口关闭public void windowClosing(WindowEvent e) {pause = true;//暂停游戏Object[] options = {"继续游戏", "重新开始", "退出游戏"}; Object selectedValue = JOptionPane.showOptionDialog(null, "是否退出游戏?", "游戏已暂停", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);switch(selectedValue.toString()) {case "-1"://关闭弹窗case "0"://继续游戏pause = false;break;case "1"://重新开始dispose();//释放当前窗口new Tetris();//重新加载break;default:System.exit(0);//退出程序break;}}});for(int i=0; i<20; i++) {for(int j=0; j<10; j++) {grid[i][j] = new JButton("");//创建按钮getContentPane().add(grid[i][j]);//添加进网格布局grid[i][j].setBackground(darkColor);//设置为深色背景grid[i][j].setEnabled(false);//去除按钮可操作性,单纯作为背景(用按钮比图片或者面板更方便一些,时间差别不大)}}setVisible(true);//显示窗口}void systemTimer() {//系统控制方块定时下降Timer timer = new Timer(); //创建一个定时器timer.schedule(new TimerTask() {//为该定时器添加任务public void run() {if(!pause) {//游戏未暂停while(true) {if(!token) {//如果令牌忙碌,则等待令牌;如果令牌空闲,占据令牌。token = true;if(falling) {fall();//方块处于下落状态则调用下落方法,不处于则调用生成新方块方法}else {generate();}token = false;//释放令牌break;}}}if(gameOver) {//游戏结束timer.cancel();Object[] options = {"重新开始", "退出游戏"}; int re = JOptionPane.showOptionDialog(null, "是否重新开始", "游戏结束", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]); if(re == JOptionPane.YES_OPTION){ dispose();new Tetris();}else{System.exit(0);}}}}, 0, time);}void play() {//玩家用键盘操作方块addKeyListener(new KeyAdapter(){//添加键盘事件public void keyPressed(KeyEvent e){if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {//直接退出游戏System.exit(0);}else {if(!gameOver) {//首先判断游戏是否结束if(e.getKeyCode() == KeyEvent.VK_SPACE){//空格将游戏设置为暂停if(pause) {pause = false;}else {pause = true;}}else {if(!pause) {//暂停时不能使用方向键,只能使用Esc键和空格键while(falling && true) {//只有在方块下落过程中才可以申请令牌,响应键盘操作(方块落地一段时间还属于下落状态还能移动,if(!token) {        //但是如果方块组合的一部分和下面的一行消除掉,则不属于下落状态不能移动了)token = true;//占据令牌switch(e.getKeyCode()) {case KeyEvent.VK_LEFT:if(location[0][1]-1>-1 && location[1][1]-1>-1 && location[2][1]-1>-1 && location[3][1]-1>-1) {//判断左移后是否超过地图removable = true;//判断左移后是否和其他方块组合重叠for(int i=0; i<4; i++) {//考察方块组合的每个方块if(gridState[location[i][0]][location[i][1]-1]) {removable = false;break;}}if(removable) {//未重叠则允许左移realTimePlaceR--;//方块整体的基准点左移for(int i=0; i<4; i++) {grid[location[i][0]][location[i][1]].setBackground(darkColor);//原来方块位置恢复成背景location[i][1]--;//方块整体左移}for(int i=0; i<4; i++) {grid[location[i][0]][location[i][1]].setBackground(lightColor);//渲染方块}}}break;case KeyEvent.VK_RIGHT:if(location[0][1]+1<10 && location[1][1]+1<10 && location[2][1]+1<10 && location[3][1]+1<10) {//判断右移后是否超过地图removable = true;//判断右移后是否和其他方块组合重叠for(int i=0; i<4; i++) {//考察方块组合的每个方块if(gridState[location[i][0]][location[i][1]+1]) {removable = false;break;}}if(removable) {//未重叠则允许右移realTimePlaceR++;//方块整体的基准点右移for(int i=0; i<4; i++) {grid[location[i][0]][location[i][1]].setBackground(darkColor);//原来方块位置恢复成背景location[i][1]++;//方块整体右移}for(int i=0; i<4; i++) {grid[location[i][0]][location[i][1]].setBackground(lightColor);//渲染方块}}}break;case KeyEvent.VK_DOWN:fall();//下落方法break;case KeyEvent.VK_D:angle_ = (angle + 1) % angleNum;//将要逆时针旋转到的位置case KeyEvent.VK_F:if(angle_ == -1) {//如果不为-1说明点击的是D,为-1说明点击的是F(顺时针)angle_ = (angle + angleNum - 1) % angleNum;}if(angleNum != 1) {//旋转角度只有一个的话就不转了(正方形方块组合)transformative = true;//预先假设能变形for(int i=0; i<4; i++) {//考察方块组合的每个方块int L = relativePosition[shapeKind][angle_][i][0] + realTimePlaceL;//变形后的行坐标int R = relativePosition[shapeKind][angle_][i][1] + realTimePlaceR;//变形后的列坐标if(L>19 || R>9 || gridState[L][R]) {//超过地图或者该位置有其他方块则不能变形transformative = false;break;}}if(transformative) {//符合变形要求angle = angle_;//更新角度for(int i=0; i<4; i++) {grid[location[i][0]][location[i][1]].setBackground(darkColor);//原来方块位置恢复成背景location[i][0]++;}for(int i=0; i<4; i++) {location[i][0] = relativePosition[shapeKind][angle][i][0] + realTimePlaceL;//更新行位置location[i][1] = relativePosition[shapeKind][angle][i][1] + realTimePlaceR;//更新列位置grid[location[i][0]][location[i][1]].setBackground(lightColor);//渲染方块}}}angle_ = -1;//重新设置为-1break;}token = false;//释放令牌break;}}}}}}}});}void fall() {fallToTheGround = false;//是否落到地上或者其他方格上for(int i=0; i<4; i++) {if(location[i][0] == 19 || gridState[location[i][0]+1][location[i][1]]) {fallToTheGround = true;break;}}if(fallToTheGround) {falling = false;for(int i=0; i<4; i++) {gridState[location[i][0]][location[i][1]] = true;}removeLine(19);for(int j=0; j<9; j++) {if(gridState[0][j]) {gameOver = true;break;}}}else {realTimePlaceL++;for(int i=0; i<4; i++) {grid[location[i][0]][location[i][1]].setBackground(darkColor);location[i][0]++;}for(int i=0; i<4; i++) {grid[location[i][0]][location[i][1]].setBackground(lightColor);}}}void generate() {realTimePlaceL = 0;realTimePlaceR = 4;falling = true;shapeKind = (int) (Math.random()*7);switch(shapeKind) {case 5:angleNum = 1;angle = 0;break;case 0:case 4:case 6:angleNum = 2;angle = (int) (Math.random()*2);break;default:angleNum = 4;angle = (int) (Math.random()*4);break;}for(int i=0; i<4; i++) {location[i][0] = relativePosition[shapeKind][angle][i][0] + realTimePlaceL;location[i][1] = relativePosition[shapeKind][angle][i][1] + realTimePlaceR;grid[location[i][0]][location[i][1]].setBackground(lightColor);}}void removeLine(int line) {boolean removed = true, allBlank;int line_=line;for(int i=line; i>=0; i--) {removed = true;allBlank = true;for(int j=0; j<10; j++) {if(gridState[i][j]) {allBlank = false;}else {removed = false;}if(!removed && !allBlank) {break;}}if(removed || allBlank) {line_ = i;break;}}if(removed) {for(int i=line_; i>0; i--) {for(int j=0; j<10; j++) {if(gridState[i][j] ^ gridState[i-1][j]) {gridState[i][j] = gridState[i-1][j];if(gridState[i][j]) {grid[i][j].setBackground(lightColor);}else {grid[i][j].setBackground(darkColor);}}}}score += 10;if(score == 10000) {gameOver = true;}else {setTitle("Tetris    难度: " + difficulty + "  得分: " + String.valueOf(score));//设置窗口标题removeLine(line_);}}}public static void main(String[] args) {new Tetris();}}

Java语言实现经典游戏俄罗斯方块相关推荐

  1. java赛马游戏,用JAVA语言实现赛马游戏

    用JAVA语言实现赛马游戏 用JAVA语言实现赛马游戏 在大二下半学期,学校举办了一场编程比赛.其中一个选题就是:用JAVA语言实现一个赛马游戏程序.此程序即为当时的参赛完成的程序. 程序界面风格在当 ...

  2. java语言开发手机游戏_手机上的JAVA游戏和JAVA软件,是电脑上的JAVA语言编写的吗?他们之间有什么联系...

    手机上的JAVA游戏和JAVA软件,是电脑上的JAVA语言编写的吗?他们之间有什么联系以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起 ...

  3. Java语言中 (游戏:彩票)修改程序清单3-8,产生三位整数的彩票。程序提示用户输入一个三位整数,依照以下规则判定用户是否赢得奖金:

    游戏:(彩票)修改程序清单3-8,产生三位整数的彩票.程序提示用户输入一个三位整数,然后依照以下规则判定用户是否赢得奖金: (1)如果用户输入的所有数包括顺序完全匹配彩票数字,奖金是10 000美元 ...

  4. 拼图java 源代码,Java语言实现拼图游戏源代码

    /* * JAVA小游戏-拼图 我做的第一个小游戏 * Cell类是继承的按钮类,并加上相应图形,形成方格 *MyCanvas是一个面板,加载Cell类的对象(方格),是这三个类中的核心 */ imp ...

  5. 绕圈报数游戏Java算法_经典游戏(围圈数数,数到3者出圈,求最后幸存者)

    [java]代码库import java.util.Scanner; /** * 约瑟夫问题 * 有n个人围成一圈,顺序排号.从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,下个人继续开始从 ...

  6. 如何用java语言编写小游戏?(贪吃蛇)

    自己做了个贪吃蛇,效果图如下" 素材和图片是网上找的,在做这游戏的过程中其实最麻烦的是像素的调整,需要一点点去试....所以大家做的时候像素方面自己试就行了,根据自己的实际情况判断. 先说一 ...

  7. 用java编写连连看_用java语言编写连连看游戏

    展开全部 我以前自己写一个玩的.没有把你要求的功能全部实现,不过你看了后可以改32313133353236313431303231363533e4b893e5b19e31333238646335一下就 ...

  8. 【纯JAVA语言做RPG游戏】1.做个瓷砖地图生成器

    开个坑,想做个JAVA游戏. 虽然现在有着各种游戏引擎,使得做游戏的效率提高了很多,但是用着别人的代码来做感觉对自己也没啥提升,而且在游戏的模式上也不得不去迎合别人的思维,所以露珠准备应用前面学到的所 ...

  9. 连连看游戏的设计与实现——基于JAVA语言的小游戏

    说明:本篇博客主要讲述练练看游戏的设计与实现.前半部分为分析与类和属性的说明,后半部分为程序的实现与程序代码.第一次写小游戏,仍存在许多问题,也借鉴了CSDN前辈的代码想法,如有不妥,还望多批评指正. ...

最新文章

  1. 使用Nginx的proxy_cache缓存功能取代Squid
  2. F1~F12在Windows系统中的作用
  3. spring:如何用代码动态向容器中添加或移除Bean ?
  4. optee的Share Memory介绍
  5. 信息系统项目管理师论文范文-质量管理
  6. c++学习笔记之指向对象的指针以及对象数组
  7. 什么是地址译码 理解二进制编码
  8. 吉他谱----see you again
  9. linux kde中文输入法,linux 下的中文输入法是不是只能在KDE下啊?Gnome下有吗?名字?怎么装?...
  10. 话费充值 php,话费充值示例代码
  11. Windows 搭建ARM虚拟机 UOS系统
  12. 基于小脑模型神经网络轨迹跟踪matlab程序
  13. C#WinForm实现对前一篇文章中的SFTP工具类的使用
  14. vs2008怎么创建c语言程序,VS2008的使用
  15. javaweb框架 一些底层实现
  16. ## STAMP使用中数据上传注意事项
  17. Java图片上传Base64 类型上传 后台转换工具类
  18. 【无机纳米材料科研制图——OriginLab 0209】Origin散点图线性拟合与非线性拟合
  19. win11禁用内置的administrator本地帐户
  20. csgo社区服务器维护2021,CSGO国际服启动软件

热门文章

  1. 部署zinnia的问题
  2. 面向对象设计原则之三--依赖倒置(转)原则
  3. 小米手环7添加校园卡(门禁)
  4. 游戏汉化教程1-汉化流程
  5. 拼多多获得搜索词推荐 API
  6. vue项目适配 rem
  7. 《必然》四、不可复制性决定所有价值
  8. JDBC的传统连接弊端
  9. 搭建Android开发环境Win7-64位
  10. Linux socket设置mark的必要性