java“俄罗斯方块”

首先新建议一个包为Tetris (俄罗斯方块)

类名也叫做Tetris;

代码运行:

package Tetris;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
 
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
 
public class Tetris extends JFrame implements KeyListener {
    private JTextArea[][] grids;// 把整个界面变为一个文本区域,整个游戏在里面进行
    private int data[][]; // 对于每个格子的数据,1代表有方块,0代表为空白区
    private int[] allRect; // 所有的方块类型,用16个字节来存储,俄罗斯方块图形都是在4*4格子里
    private int rect; // 当前游戏下落的方块类型;
    private int x, y; // 当前方块的坐标位置,x代表行,y代表列
    private int score = 0; // 记录当前游戏得分情况,每消一层得10分
    private JLabel label; // 显示分数的标签
    private JLabel label1;// 显示游戏是否结束
    private boolean running; // 用于判断游戏是否结束
    /*无参构造函数*/
    public Tetris() {
        grids = new JTextArea[26][12];//设置游戏区域行和列
        data = new int[26][12];//开辟data数组空间与游戏区域行和列一致
        allRect = new int[] { 0x00cc, 0x8888, 0x000f, 0x0c44, 0x002e, 0x088c, 0x00e8, 0x0c88, 0x00e2, 0x044c, 0x008e,
                0x08c4, 0x006c, 0x04c8, 0x00c6, 0x08c8, 0x004e, 0x04c4, 0x00e4 };//19种方块形状,如0x00cc就是   0000 表示一个2*2的正方形方块
                                                                                                        //0000 
                                                                                                        //1100 
                                                                                                        //1100
        label = new JLabel("score: 0"); //此标签存放得分情况,初始化为0分
        label1 = new JLabel("开始游戏"); //此标签为提示游戏状态:开始还是结束
        running = false; //为标志变量,false为游戏结束,true为游戏正在进行
        init(); // 游戏界面初始化
    }
    /*游戏界面初始化函数*/
    public void init() {
        JPanel center = new JPanel(); //此面板为游戏核心区域
        JPanel right = new JPanel(); //此面板为游戏说明区域
        center.setLayout(new GridLayout(26, 12, 1, 1)); //给游戏核心区域划分行、列共26行,12列
        for (int i = 0; i < grids.length; i++) {//初始化面板
            for (int j = 0; j < grids[i].length; j++) {
                grids[i][j] = new JTextArea(20, 20);
                grids[i][j].setBackground(Color.WHITE);
                grids[i][j].addKeyListener(this);// 添加键盘监听事件
                //初始化游戏边界
                if (j == 0 || j == grids[i].length - 1 || i == grids.length - 1) {
                    grids[i][j].setBackground(Color.PINK);
                    data[i][j] = 1;
                }
                grids[i][j].setEditable(false);// 文本区域不可编辑
                center.add(grids[i][j]); //把文本区域添加到主面板上
            }
        }
        //初始化游戏说明面板
        right.setLayout(new GridLayout(4, 1));
        right.add(new JLabel(" a : left        d : right"));
        right.add(new JLabel(" s : down   w : change"));
        right.add(label);
        label1.setForeground(Color.RED);// 设置标签内容为红色字体
        right.add(label1);
        //把主面板和说明面板添加到窗体中
        this.setLayout(new BorderLayout());
        this.add(center, BorderLayout.CENTER);
        this.add(right, BorderLayout.EAST);
        running = true; //初始化running状态为true,表示程序运行即游戏开始
        this.setSize(600, 850);// 设置窗体大小
        this.setVisible(true);// 窗体可见
        this.setLocationRelativeTo(null);// 设置窗体居中
        this.setResizable(false);// 窗体大小不可改变
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 释放窗体
    }
    /*主函数*/
    public static void main(String[] args) {
        Tetris m = new Tetris(); //创建Main对象,主要用于初始化数据
        m.go();// 开始游戏
    }
    /*开始游戏*/
    public void go() {// 开始游戏
        while (true) {//游戏开始直到游戏失败才结束,否则一直执行
            if (running == false) {//如果游戏失败
                break;
            }
            ranRect();// 绘制下落方格形状
            start();// 开始游戏
        }
        label1.setText("游戏结束!");//则游戏结束
    }
    /*绘制下落方格形状*/
    public void ranRect() {
        rect = allRect[(int) (Math.random() * 19)];// 随机生成方块类型(共7种,19个形状)
    }
    /*游戏开始函数*/
    public void start() {
        x = 0;
        y = 5; //初始化下落方块的位置
        for (int i = 0; i < 26; i++) {//共26层,一层一层下落
            try {
                Thread.sleep(1000);//每层延时1秒
                if (canFall(x, y) == false) {// 如果不可以掉落
                    saveData(x, y);//把此方块区域data[][]标志为1,表示有数据
                    for (int k = x; k < x + 4; k++) {//循环遍历4层,看是否有哪一层都有方块的情况,以便消除那一行方格和统计得分
                        int sum = 0;
                        for (int j = 1; j <= 10; j++) {
                            if (data[k][j] == 1) {
                                sum++;
                            }
                        }
                        if (sum == 10) {//如果k层都有方块,则消除k层方块
                            removeRow(k);
                        }
                    }
                    for (int j = 1; j <= 10; j++) {//游戏最上面的4层不能有方块,否则游戏失败
                        if (data[3][j] == 1) {
                            running = false;
                            break;
                        }
                    }
                    break;
                }
                // 如果可以掉落
                x++;// 层加一
                fall(x, y);// 掉下来一层
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
 
        }
    }
    /*判断正下落的方块是否可以下落*/
    public boolean canFall(int m, int n) {
        int temp = 0x8000;//表示1000 0000 0000 0000
        for (int i = 0; i < 4; i++) {//循环遍历16个方格(4*4)
            for (int j = 0; j < 4; j++) {
                if ((temp & rect) != 0) {// 此处有方块时
                    if (data[m + 1][n] == 1)// 如果下一个地方有方块,则直接返回false
                        return false;
                }
                n++;//列加一
                temp >>= 1;
            }
            m++;// 下一行
            n = n - 4;// 回到首列
        }
        return true;//可以掉落返回true
    }
    /*把不可下降的方块的对应的data存储为1,表示此坐标有方块*/
    public void saveData(int m, int n) {
        int temp = 0x8000;//表示1000 0000 0000 0000
        for (int i = 0; i < 4; i++) {//循环遍历16个方格(4*4)
            for (int j = 0; j < 4; j++) {
                if ((temp & rect) != 0) {// 此处有方块时
                    data[m][n] = 1;//data数组存放为1
                }
                n++;//下一列
                temp >>= 1;
            }
            m++;// 下一行
            n = n - 4;// 回到首列
        }
    }
    /*移除row行所有方块,以上的依次往下降*/
    public void removeRow(int row) {
        for (int i = row; i >= 1; i--) {
            for (int j = 1; j <= 10; j++) {
                data[i][j] = data[i - 1][j];//
            }
        }
        reflesh();// 刷新移除row行方块后的游戏主面板区域
        score += 10;// 分数加10;
        label.setText("score: " + score);//显示得分
    }
    /* 刷新移除row行方块后的游戏主面板区域*/
    public void reflesh() {
        for (int i = 1; i < 25; i++) {
            for (int j = 1; j < 11; j++) {
                if (data[i][j] == 1) {//有方块的地方把方块设置为绿色
                    grids[i][j].setBackground(Color.GREEN);
                } else {//无方块的地方把方块设置为白色
                    grids[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;//表示1000 0000 0000 0000
        for (int i = 0; i < 4; i++) {//循环遍历16个方格(4*4)
            for (int j = 0; j < 4; j++) {
                if ((temp & rect) != 0) {// 此处有方块时
                    grids[m][n].setBackground(Color.WHITE);//清除颜色,变为白色
                }
                n++;//下一列
                temp >>= 1;
            }
            m++;//下一行
            n = n - 4;//回到首列
        }
    }
    /*绘制掉落后方块图像*/
    public void draw(int m, int n) {
        int temp = 0x8000;//表示1000 0000 0000 0000
        for (int i = 0; i < 4; i++) {//循环遍历16个方格(4*4)
            for (int j = 0; j < 4; j++) {
                if ((temp & rect) != 0) {// 此处有方块时
                    grids[m][n].setBackground(Color.GREEN);//有方块的地方变为绿色
                }
                n++;//下一列
                temp >>= 1;
            }
            m++;//下一行
            n = n - 4;//回到首列
        }
    }
 
    @Override
    public void keyPressed(KeyEvent e) {
    }
 
    @Override
    public void keyReleased(KeyEvent e) {
    }
 
    @Override
    public void keyTyped(KeyEvent e) {
        if (e.getKeyChar() == 'a') {// 方格进行左移
            if (running == false) {
                return;
            }
            if (y <= 1)//碰到左边墙壁时
                return;
            int temp = 0x8000;//表示1000 0000 0000 0000
            for (int i = x; i < x + 4; i++) {//循环遍历16个方格(4*4)
                for (int j = y; j < y + 4; j++) {
                    if ((rect & temp) != 0) {// 此处有方块时
                        if (data[i][j - 1] == 1) {//如果左移一格有方块时
                            return;
                        }
                    }
                    temp >>= 1;
                }
            }
            clear(x, y);//可以进行左移操作时,清除左移前方块颜色
            y--;
            draw(x, y);//然后重新绘制左移后方块的图像
        }
        if (e.getKeyChar() == 'd') {//方块进行右移操作
            if (running == false) {
                return;
            }
            int temp = 0x8000;
            int m = x, n = y;
            int num = 7;
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if ((temp & rect) != 0) {
                        if (n > num) {
                            num = n;
                        }
                    }
                    temp >>= 1;
                    n++;
                }
                m++;
                n = n - 4;
            }
            if (num >= 10) {
                return;
            }
            temp = 0x8000;
            for (int i = x; i < x + 4; i++) {
                for (int j = y; j < y + 4; j++) {
                    if ((rect & temp) != 0) {
                        if (data[i][j + 1] == 1) {
                            return;
                        }
                    }
                    temp >>= 1;
                }
            }
            clear(x, y);//可以进行右移操作时,清除右移前方块颜色
            y++;
            draw(x, y);//然后重新绘制右移后方块的图像
        }

  if (e.getKeyChar() == 's') {//方块进行下移操作
            if (running == false) {
                return;
            }
            if (canFall(x, y) == false) {
                saveData(x, y);
                return;
            }
            clear(x, y);//可以进行下移操作时,清除下移前方块颜色
            x++;
            draw(x, y);//然后重新绘制下移后方块的图像
        }
        if (e.getKeyChar() == 'w') {//改变方块形状
            if (running == false) {
                return;
            }
            int i = 0;
            for (i = 0; i < allRect.length; i++) {//循环遍历19个方块形状
                if (allRect[i] == rect)//找到下落的方块对应的形状,然后进行形状改变
                    break;
            }
            if (i == 0)//为正方形方块无需形状改变,为方块图形种类1
                return;
            clear(x, y);
            if (i == 1 || i == 2) {//为方块图形种类2
                rect = allRect[i == 1 ? 2 : 1];
                if (y > 7)
                    y = 7;
            }
            if (i >= 3 && i <= 6) {//为方块图形种类3
                rect = allRect[i + 1 > 6 ? 3 : i + 1];
            }
            if (i >= 7 && i <= 10) {//为方块图形种类4
                rect = allRect[i + 1 > 10 ? 7 : i + 1];
            }
            if (i == 11 || i == 12) {//为方块图形种类5
                rect = allRect[i == 11 ? 12 : 11];
            }
            if (i == 13 || i == 14) {//为方块图形种类6
                rect = allRect[i == 13 ? 14 : 13];
            }
            if (i >= 15 && i <= 18) {//为方块图形种类7
                rect = allRect[i + 1 > 18 ? 15 : i + 1];
            }
            draw(x, y);
        }
    }
}

游戏测试
以上步骤都做好就可以进行测试了,先激活Fn键,然后ctrl+F11快捷运行。

1.弹出窗口,直接开始游戏,按W键改变方块的方向,按S键快速向下降落,按A键向左移动,按D键向右移动。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/576814.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

腾讯云服务器免费再领一台是什么意思?

腾讯云免费再领一台轻量应用服务器是什么意思&#xff1f;是指在腾讯云买赠专区活动 https://curl.qcloud.com/oRMoSucP 就是轻量应用服务器买一年&#xff0c;购买的时候可以选择“送同配置3个月”&#xff0c;也可以选择“免费续3个月”&#xff0c;阿腾云atengyun.com活动打…

创新5.1 7.1KX声卡驱动

———————KX声卡驱动——————— &#x1f384;声卡外观 &#x1f384;声卡介绍 &#x1f388;创新5.1 7.1声卡是网络直播&#xff0c;娱乐&#xff0c;唱歌&#xff0c;交友等一种音效内置声卡 &#x1f384;型号 &#x1f388;创新5.1内置声卡sb0060 0090 sn0105…

Web 开发技术

Web 开发技术 | MDN (mozilla.org)https://developer.mozilla.org/zh-CN/docs/Web 开放的 Web 为开发者提供了巨大的机遇&#xff0c;为了充分利用这些技术&#xff0c;你需要知道如何使用它们。在下方你可以找到相关 Web 技术的文档链接。 面向 Web 开发者的文档 Web 开…

【C# 技术】 C# 常用排序方式——常规数据排序

C# 常用排序方式——常规数据排序 前言 在最近的项目中经常会对C#中的数据进行排序&#xff0c;对于基本数据类型&#xff0c;其排序方式比较简单&#xff0c;只需要调用内置算法即可实现&#xff0c;但对于自定义数据类型以及自定义排序规则的情况实现起来就比较麻烦&#…

C++ Qt开发:Charts折线图绑定事件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍QCharts折线图的常用方法及灵活运用。 在上一…

华为OD机试 - 学生方阵 - 矩阵(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出 四、解题思路1、题目解析2、解体思路 五、Java算法源码再重新读一遍题目&#xff0c;看看能否优化一下~ 六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导…

浏览器加粗字体显示异常

浏览器加粗的字体模糊虚化 如果在css中设置了普通的字体样式 font-face&#xff0c;使用了 font-weight: bold 的字体会在浏览器页面中会显示模糊虚化的现象&#xff0c;而正常的字体没有这种情况&#xff0c;显示的情况根据不同的浏览器会有区别。 * 出现轻微模糊虚化效果&am…

设计模式--桥接模式

实验9&#xff1a;桥接模式 本次实验属于模仿型实验&#xff0c;通过本次实验学生将掌握以下内容&#xff1a; 1、理解桥接模式的动机&#xff0c;掌握该模式的结构&#xff1b; 2、能够利用桥接模式解决实际问题。 [实验任务]&#xff1a;两个维度的桥接模式 用桥接模式…

什么是OAuth2.0

前言 OAuth&#xff08;Open Authorization&#xff09;是一个关于授权&#xff08;authorization&#xff09;的开放网络标准&#xff0c;允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息&#xff0c;而不需要将用户名和密码提供给第三方移动应用或分享他们数…

Netty组件基础

Netty入门简介 netty是一个异步、基于事件驱动的网络应用框架&#xff0c;用于快速开发可维护、高性能的网络服务器和客户端。 Netty优势 Netty解决了TCP传输问题&#xff0c;如黏包、半包问题&#xff0c;解决了epoll空轮询导致CPU100%的问题。并且Netty对API进行增强&#xf…

taro小程序指定@代表

1.ts.config.json "paths": {"/*": ["./src/*"] } config/index.js const path require(path) alias: {: path.resolve(__dirname, .., src) },

Codeforces Round 917 (Div. 2)(A~D)

A - Least Product Solution 观察发现&#xff0c;对于 a i < 0 a_i<0 ai​<0&#xff0c;操作后 a i a_i ai​ 不会变得更小&#xff0c; a i > 0 a_i>0 ai​>0&#xff0c;操作后 a i a_i ai​ 不会变得更大。所以&#xff0c;当 ∏ i 1 n a i ≥ 0…

Python如何将图片转换成字符

PIL(Python Image Library)库是Python平台上一个功能强大的图像处理标准库&#xff0c;支持图像的存储、显示和处理&#xff0c;几乎可以处理所有图片格式&#xff0c;如图像的压缩、裁剪、叠加、添加文字等等。 安装PIL库:pip install pillow from PIL import Image ascii_cha…

【期末复习】微信小程序复习大纲( 1- 5 章)

前言&#xff1a; 这周开始进入期末复习周&#xff0c;没时间看C/C、linux等知识了&#xff0c;先把期末考试必考的知识捋一遍。 目录 第一章 微信小程序入门 一、填空题 二、判断题 三、选择题 四、简答题 第二章 微信小程序页面制作 一、填空题 二、判…

【Java中创建对象的方式有哪些?】

✅Java中创建对象的方式有哪些&#xff1f; ✅使用New关键字✅使用反射机制✅使用clone方法✅使用反序列化✅使用方法句柄✅ 使用Unsafe分配内存 ✅使用New关键字 这是我们最常见的也是最简单的创建对象的方式&#xff0c;通过这种方式我们还可以调用任意的构造函数 (无参的和有…

mybatis的二级缓存使用以及禁用

目录 mybatis 二级缓存配置有两处 全局设置 mapper 设置 测试代码 执行结果 源码执行逻辑 创建 SqlSession 二级缓存配置是否添加 解析 cache 标签 XMLMapperBuilder MapperBuilderAssistant CacheBuilder PerpetualCache SerializedCache LoggingCache 将 cach…

Grafana二进制部署并配置prometheus数据源

1、获取grafna二进制安装包 https://grafana.com/grafana/download?pggraf&plcmtdeploy-box-1 grafana官网下载地址 [rootambari-hadoop1 ~]# cd /opt/module/grafana/ [rootambari-hadoop1 grafana]# pwd /opt/module/grafana2、在安装自己的安装目录执行 wget https:…

在killercoda中的一次apiserver异常追查思路

笔者&#xff1a; 最近在准备cks考试&#xff0c; 然后又发现了killercoda这个能够提供模拟考试环境的平台。它提供了很棒的引导&#xff0c;教你一步步追查问题&#xff0c;形成一整套追查思路&#xff0c;我觉得很不错&#xff0c;特此分享。 准备工作 首先还是需要养成配置…

spark:RDD编程(Python版)

RDD运行原理 RDD设计背景 许多选代目前的MapReduce框架都是把中间结果写入到稳定存储 (比如磁盘)中带来了大量的数据复制、磁盘IO和序列化开销 RDD就是为了满足这种需求而出现的&#xff0c;它提供了一个抽象的数据架构&#xff0c;我们不必担心底层数据的分布式特性&#xf…

useRef语法讲解

useRef useRef 用法 import { useRef, useState } from react import ./App.cssfunction App() {const userRef useRef<HTMLInputElement>(null)const [val, setVal] useState()const handleClick () > {userRef.current?.focus()setVal(userRef.current?.valu…