Java实现的简易俄罗斯方块游戏

前言

欢迎阅读本文,本文将介绍如何使用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);

    }


}

成果展示

小结

通过分割为多个方法,实现了用户与游戏界面的交互。游戏娱乐性可适当增加,可以增加一些难度和模式的选择。这是较为简易的俄罗斯方块,读者在阅读之后可以适当添加代码来优化程序,感谢阅读。

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值