1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > Java实现 俄罗斯方块(简陋版)

Java实现 俄罗斯方块(简陋版)

时间:2023-12-29 03:38:01

相关推荐

Java实现 俄罗斯方块(简陋版)

前言

参考自 尚学堂。

文末有可运行的完整代码。

步骤

窗口 initWindow(): void

游戏界面(中间面板)initGamePanel(): void

游戏说明(左右面板)initExplainPanel(): void

游戏状态控制 game_begin(): void

随机方块ranRect(): void

游戏运行 game_run(): void

方块是否可以继续下落 canFall(int, int): boolean

不可下降方块的影响 changeData(int, int): void

消行 removeRow(int): void

刷新 reflesh(int): void

下落一层 fall(int, int): void

变色 clear(int, int): void

重绘掉落方块 draw(int, int): void

键盘控制方块移动 keyPressed(KeyEvent): void - - - IKeyListener

键盘控制方块变形与暂停 keyTyped(KeyEvent): void - - - IKeyListener

初始化窗口

public void initWindow(){// 初始化窗口this.setSize(600,850);this.setVisible(true);this.setLocationRelativeTo(null); // 窗口居中this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //this.setResizable(false);this.setTitle("俄罗斯方块");}

初始化界面

// 游戏行列数private static final int game_x = 26;private static final int game_y = 12;JTextArea[][] text; // 文本域数组int[][] data; // 数据public Tertris(){text = new JTextArea[game_x][game_y];data = new int[game_x][game_y];initGamePanel();initWindow();}public void initGamePanel(){JPanel game_main = new JPanel();game_main.setLayout(new GridLayout(game_x,game_y,1,1)); // 网格布局for (int i = 0; i < text.length; i++) {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.GREEN);data[i][j] = 1;}text[i][j].setEditable(false); // 文本域不可编辑game_main.add(text[i][j]); // 文本域添加到主面板}}// 添加到窗口this.setLayout(new BorderLayout());this.add(game_main,BorderLayout.CENTER);}

说明面板

// 显示游戏状态、分数的标签JLabel label1;JLabel label;public Tertris(){text = new JTextArea[game_x][game_y];data = new int[game_x][game_y];label1 = new JLabel("游戏状态:正在游戏中...");label = new JLabel("游戏得分为: 0 ");initGamePanel();initExplainPanel();initWindow();}public void initExplainPanel(){JPanel explain_left = new JPanel(); // 创建游戏的左右说明面板JPanel explain_right = new JPanel();explain_left.setLayout(new GridLayout(4,1));explain_right.setLayout(new GridLayout(2,1));// 左面板添加说明文字explain_left.add(new JLabel("空格 -> 变形"));explain_left.add(new JLabel("左箭头 -> 左移"));explain_left.add(new JLabel("右箭头 -> 右移"));explain_left.add(new JLabel("下箭头 -> 下落"));label1.setForeground(Color.RED); // 标签内容颜色// 右面板添加游戏状态、分数标签explain_right.add(label);explain_right.add(label1);// 左右说明面板添加到窗口的左右侧this.add(explain_left,BorderLayout.WEST);this.add(explain_right,BorderLayout.EAST);}

开始游戏

boolean isrunning; // 游戏是否结束public Tertris(){text = new JTextArea[game_x][game_y];data = new int[game_x][game_y];label1 = new JLabel("游戏状态:正在游戏中...");label = new JLabel("游戏得分为: 0 ");initGamePanel();initExplainPanel();initWindow();isrunning = true; //}public void game_begin(){while (true){if (!isrunning) break;game_run();}label1.setText("游戏状态:游戏结束!"); // }

随机下落生成方块

int[] allRect; // 存储所有方块int rect; // 当前方块public Tertris(){text = new JTextArea[game_x][game_y];data = new int[game_x][game_y];label1 = new JLabel("游戏状态:正在游戏中...");label = new JLabel("游戏得分为: 0 ");initGamePanel();initExplainPanel();initWindow();isrunning = true; ////初始化存放方块的数组allRect = new int[]{0x00cc,0x8888,0x000f,0x888f,0xf888,0xf111,0x111f,0x0eee,0xffff,0x0008,0x0888,0x000e,0x0088,0x000c,0x08c8,0x00e4,0x04c4,0x004e,0x08c4,0x006c,0x04c8,0x00c6};}public void ranRect(){// 随机生成下落方块Random random = new Random();rect = allRect[random.nextInt(22)];}

游戏运行

int time = 1000; // 休眠时间int x, y; // 当前方块坐标public void game_run() {ranRect();x = 0; // 方块下落位置y = 5;for (int i = 0; i < game_x; i++) {try {Thread.sleep(time);if (!canFall(x,y)){changData(x,y); // 将data置为1,表示有方块占用for(int j = x; j < x+4; j++){// 循环遍历4层,看是否有行可以消除int sum = 0;for(int k =1; k <= (game_y - 2); k++){if (data[j][k] == 1){sum++;}}if (sum == (game_y - 2)){removeRow(j); // 消除j这一行}}for(int j = 1; j <= (game_y - 2); j++){// 游戏是否失败if (data[3][j] == 1){isrunning = false;break;}}break;}else {x ++; // 层数+1fall(x,y); // 方块下落一行}} catch (InterruptedException e) {e.printStackTrace();}}

方块是否可以继续下落

public boolean canFall(int m, int n){int temp = 0x8000; //for (int i = 0; i < 4; i++) {// 4*4for (int j = 0; j < 4; j++) {if ((temp & rect) != 0) {// 该位置下一行是否有方块if (data[m+1][n] == 1) return false;}n++;temp >>= 1;}m++;n -= 4;}return true;}

改变不可下降的方块对应的区域的值

public void changData(int m,int n) {int temp = 0x8000; //for (int i = 0;i < 4;i++) {// 4*4for (int j = 0;j < 4;j++) {if ((temp & rect) != 0) {data[m][n] = 1; // }n++;temp >>= 1;}m++;n = n - 4;}}

消行

int score;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/10);}score += temp;//显示变化后的分数label.setText("游戏得分: " + score);}

刷新消行

public void reflesh(int row) {for (int i = row;i >= 1;i--) {// 遍历row行以上的游戏区域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); // del}}}}

下落一层

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; // tempfor (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 = 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;}}

键盘控制方块移动

@overridepublic void keyPressed(KeyEvent e) {int temp = 0x8000; // tempswitch (e.getKeyCode()) {case KeyEvent.VK_LEFT -> {// leftif (!isrunning) return;if (y <= 1) return;// 碰左壁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);}case KeyEvent.VK_RIGHT -> {// rightif (!isrunning) {return;}//碰右墙壁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 = x; j < y + 4; j++) {if ((temp & rect) != 0) {if (data[i][j + 1] == 1) {return;}}temp >>= 1;}}//清除当前方块clear(x, y);y++;draw(x, y);}case KeyEvent.VK_DOWN -> {// downif (!isrunning) {return;}if (!canFall(x, y)) {return;}clear(x, y);//改变方块的坐标x++;draw(x, y);}}}

键盘控制方块变形与暂停

@Overridepublic void keyTyped(KeyEvent e) {if (e.getKeyChar() == 'p'){if (!isrunning) {return;}pause_times++;if (pause_times == 1) {game_pause = true;label1.setText("游戏状态:暂停中!");}if (pause_times == 2) {game_pause = false;pause_times = 0; // 归零label1.setText("游戏状态: 正在进行中!");}}if (e.getKeyChar() == KeyEvent.VK_SPACE) {// shapeif (!isrunning) return;//定义变量,存储目前方块的索引int old;for (old = 0;old < allRect.length;old++) {//判断是否是当前方块if (rect == allRect[old]) {break;}}//定义变量,存储变形后方块int next;//判断是方块if (old == 0 || old == 7 || old == 8 || old == 9) {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 == 10 || old == 11) {next = allRect[old == 10 ? 11 : 10];if (canTurn(next,x,y)) {rect = next;}}if (old == 12 || old == 13) {next = allRect[old == 12 ? 13 : 12];if (canTurn(next,x,y)) {rect = next;}}if (old >= 14 && old <= 17) {next = allRect[old + 1 > 17 ? 14 : old + 1];if (canTurn(next,x,y)) {rect = next;}}if (old == 18 || old == 19) {next = allRect[old == 18 ? 19 : 18];if (canTurn(next,x,y)) {rect = next;}}if (old == 20 || old == 21) {next = allRect[old == 20 ? 21 : 20];if (canTurn(next,x,y)) {rect = next;}}//重新绘制变形后方块draw(x,y);}}public boolean canTurn(int a, int m, int n){int temp = 0x8000; // tempfor (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 -= 4;}return true; // can}

暂停逻辑还要在移动方块处添加!!!

完整代码

package com.sxt;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,列数12private static final int game_x = 26;private static final int game_y = 12;//文本域数组JTextArea[][] text;//二维数组int[][] data;//显示游戏状态的标签JLabel label1;//显示游戏分数的标签JLabel label;//用于判断游戏是否结束boolean isrunning;//用于存储所有的方块的数组int[] allRect;//用于存储当前方块的变量int rect;//线程的休眠时间int time = 1000;//表示方块坐标int x, y;//该变量用于计算得分int score = 0;//定义一个标志变量,用于判断游戏是否暂停boolean game_pause = false;//定义一个变量用于记录按下暂停键的次数int pause_times = 0;public void initWindow() {//设置窗口大小this.setSize(600,850);//设置窗口是否可见this.setVisible(true);//设置窗口居中this.setLocationRelativeTo(null);//设置释放窗体this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗口大小不可变this.setResizable(false);//设置标题this.setTitle("我的俄罗斯方块游戏");}//初始化游戏界面public void initGamePanel() {JPanel game_main = new JPanel();game_main.setLayout(new GridLayout(game_x,game_y,1,1));//初始化面板for (int i = 0 ; i < text.length ; i++) {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.MAGENTA);data[i][j] = 1;}//设置文本区域不可编辑text[i][j].setEditable(false);//文本区域添加到主面板上game_main.add(text[i][j]);}}//添加到窗口中this.setLayout(new BorderLayout());this.add(game_main,BorderLayout.CENTER);}//初始化游戏的说明面板public void initExplainPanel() {//创建游戏的左说明面板JPanel explain_left = new JPanel();//创建游戏的右说明面板JPanel explain_right = new JPanel();explain_left.setLayout(new GridLayout(4,1));explain_right.setLayout(new GridLayout(2,1));//初始化左说明面板//在左说明面板,添加说明文字explain_left.add(new JLabel("按空格键,方块变形"));explain_left.add(new JLabel("按左箭头,方块左移"));explain_left.add(new JLabel("按右箭头,方块右移"));explain_left.add(new JLabel("按下箭头,方块下落"));//设置标签的内容为红色字体label1.setForeground(Color.RED);//把游戏状态标签,游戏分数标签,添加到右说明面板explain_right.add(label);explain_right.add(label1);//将左说明面板添加到窗口的左侧this.add(explain_left,BorderLayout.WEST);//将右说明面板添加到窗口的右侧this.add(explain_right,BorderLayout.EAST);}public Tertris() {text = new JTextArea[game_x][game_y];data = new int[game_x][game_y];//初始化表示游戏状态的标签label1 = new JLabel("游戏状态: 正在游戏中!");//初始化表示游戏分数的标签label = new JLabel("游戏得分为: 0");initGamePanel();initExplainPanel();initWindow();//初始化开始游戏的标志isrunning = true;//初始化存放方块的数组allRect = new int[]{0x00cc,0x8888,0x000f,0x888f,0xf888,0xf111,0x111f,0x0eee,0xffff,0x0008,0x0888,0x000e,0x0088,0x000c,0x08c8,0x00e4,0x04c4,0x004e,0x08c4,0x006c,0x04c8,0x00c6};}public static void main(String[] args) {Tertris tertris = new Tertris();tertris.game_begin();}//开始游戏的方法public void game_begin() {while (true){//判断游戏是否结束if (!isrunning) {break;}//进行游戏game_run();}//在标签位置显示"游戏结束"label1.setText("游戏状态: 游戏结束!");}//随机生成下落方块形状的方法public void ranRect() {Random random = new Random();rect = allRect[random.nextInt(22)];}//游戏运行的方法public void game_run() {ranRect();//方块下落位置x = 0;y = 5;for (int i = 0;i < game_x;i++) {try {Thread.sleep(time);if (game_pause) {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) {isrunning = false;break;}}break;} else {//层数+1x++;//方块下落一行fall(x,y);}}} catch (InterruptedException e) {e.printStackTrace();}}}//判断方块是否可以继续下落的方法public boolean canFall(int m,int n) {//定义一个变量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) {//定义一个变量int temp = 0x8000;//遍历整个4 * 4的方块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;}score += temp;//显示变化后的分数label.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 = 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;}}@Overridepublic void keyTyped(KeyEvent e) {//控制游戏暂停if (e.getKeyChar() == 'p') {//判断游戏是否结束if (!isrunning) {return;}pause_times++;//判断按下一次,暂停游戏if (pause_times == 1) {game_pause = true;label1.setText("游戏状态: 暂停中!");}//判断按下两次,继续游戏if (pause_times == 2) {game_pause = false;pause_times = 0;label1.setText("游戏状态: 正在进行中!");}}//控制方块进行变形if (e.getKeyChar() == KeyEvent.VK_SPACE) {//判断游戏是否结束if (!isrunning) {return;}//判断游戏是否暂停if (game_pause) {return;}//定义变量,存储目前方块的索引int old;for (old = 0;old < allRect.length;old++) {//判断是否是当前方块if (rect == allRect[old]) {break;}}//定义变量,存储变形后方块int next;//判断是方块if (old == 0 || old == 7 || old == 8 || old == 9) {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 == 10 || old == 11) {next = allRect[old == 10 ? 11 : 10];if (canTurn(next,x,y)) {rect = next;}}if (old == 12 || old == 13) {next = allRect[old == 12 ? 13 : 12];if (canTurn(next,x,y)) {rect = next;}}if (old >= 14 && old <= 17) {next = allRect[old + 1 > 17 ? 14 : old + 1];if (canTurn(next,x,y)) {rect = next;}}if (old == 18 || old == 19) {next = allRect[old == 18 ? 19 : 18];if (canTurn(next,x,y)) {rect = next;}}if (old == 20 || old == 21) {next = allRect[old == 20 ? 21 : 20];if (canTurn(next,x,y)) {rect = next;}}//重新绘制变形后方块draw(x,y);}}//判断方块此时是否可以变形的方法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;}@Overridepublic void keyPressed(KeyEvent e) {//方块进行左移if (e.getKeyCode() == 37) {//判断游戏是否结束if (!isrunning) {return;}//判断游戏是否暂停if (game_pause) {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() == 39) {//判断游戏是否结束if (!isrunning) {return;}//判断游戏是否暂停if (game_pause) {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() == 40) {//判断游戏是否结束if (!isrunning) {return;}//判断游戏是否暂停if (game_pause) {return;}//判断方块是否可以下落if (!canFall(x,y)) {return;}clear(x,y);//改变方块的坐标x++;draw(x,y);}}@Overridepublic void keyReleased(KeyEvent e) {}}

cv注意改包名和类名!!!

最后

UI很丑,现阶段掌握的知识还无法美化。

以后会重构,主要掌握思路。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。