欢迎光临
我们一直在努力

Java实现俄罗斯方块小游戏。(附完整源代码)

大家好,我是百思不得小赵。

创作时间:2022 年 5 月 12 日
博客主页: 🔍点此进入博客主页
—— 新时代的农民工 🙊
—— 换一种思维逻辑去看待这个世界 👀
今天是加入CSDN的第1167天。觉得有帮助麻烦👏点赞、🍀评论、❤️收藏


目录

一、游戏背景

二、功能实现

三、效果展示


Java实现俄罗斯方块小游戏。(附完整源代码)

一、游戏背景

俄罗斯方块是俄罗斯人发明的。这人叫阿列克谢·帕基特诺夫(Алексей Пажитнов 英文:Alexey Pazhitnov)。俄罗斯方块原名是俄语Тетрис(英语是Tetris),这个名字来源于希腊语tetra,意思是“四”,而游戏的作者最喜欢网球(tennis)。于是,他把两个词tetra和tennis合而为一,命名为Tetris,这也就是俄罗斯方块名字的由来。

规则说明:

由小方块组成的不同形状的板块陆续从屏幕上方落下来,玩家通过调整板块的位置和方向,使它们在屏幕底部拼出完整的一条或几条。这些完整的横条会随即消失,给新落下来的板块腾出空间,与此同时,玩家得到分数奖励。没有被消除掉的方块不断堆积起来,一旦堆到屏幕顶端,玩家便告输,游戏结束。

二、功能实现

开发工具:idea、jdk8

技术汇总:Java基础知识、数组、面向对象、多线程、IO流、Swing。

整体代码分为三个模块:方格模块,七种图形模块,俄罗斯方块主模块。

小方块类:cell

public class Cell { // 行 private int row; // 列 private int col; private BufferedImage image; public Cell() { } public Cell(int row, int col, BufferedImage image) { this.row = row; this.col = col; this.image = image; } public int getRow() { return row; } public void setRow(int row) { this.row = row; } public int getCol() { return col; } public void setCol(int col) { this.col = col; } public BufferedImage getImage() { return image; } public void setImage(BufferedImage image) { this.image = image; } @Override public String toString() { return "Cell{" + "row=" + row + ", col=" + col + ", image=" + image + '}'; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof Cell)) { return false; } Cell cell = (Cell) o; return getRow() == cell.getRow() && getCol() == cell.getCol() && Objects.equals(getImage(), cell.getImage()); } @Override public int hashCode() { return Objects.hash(getRow(), getCol(), getImage()); } //左移动一格 public void left(){ col--; } //右移动一格 public void right(){ col++; } //下移动一格 public void down(){ row++; } } 

四方格图形的父类:Tetromino

public class Tetromino { public Cell[] cells = new Cell[4]; //旋转的状态 protected State[] states; //声明旋转次数 protected int count = 10000; //左移方法 public void moveLeft() { for (Cell cell : cells) { cell.left(); } } //右移方法 public void moveRight() { for (Cell cell : cells) { cell.right(); } } //单元格下落 public void moveDrop() { for (Cell cell : cells) { cell.down(); } } //编写随机生成四方格 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; } //顺时针旋转的方法 public void rotateRight() { if (states.length == 0) { return; } //旋转次数+1 count++; 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() { if (states.length == 0) { return; } //旋转次数+1 count--; 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); } //四方格旋转状态的内部类 protected 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 getCol0() { return col0; } public void setCol0(int col0) { this.col0 = col0; } public int getRow1() { return row1; } public void setRow1(int row1) { this.row1 = row1; } public int getCol1() { return col1; } public void setCol1(int col1) { this.col1 = col1; } public int getRow2() { return row2; } public void setRow2(int row2) { this.row2 = row2; } public int getCol2() { return col2; } public void setCol2(int col2) { this.col2 = col2; } public int getRow3() { return row3; } public void setRow3(int row3) { this.row3 = row3; } public int getCol3() { return col3; } public void setCol3(int col3) { this.col3 = col3; } @Override public String toString() { return "State{" + "row0=" + row0 + ", col0=" + col0 + ", row1=" + row1 + ", col1=" + col1 + ", row2=" + row2 + ", col2=" + col2 + ", row3=" + row3 + ", col3=" + col3 + '}'; } } }

七种图形类:I、J、L、O、S、T、Z

public class I extends Tetromino { public I() { cells[0] = new Cell(0,4, Tetris.I); cells[1] = new Cell(0,3, Tetris.I); cells[2] = new Cell(0,5, Tetris.I); cells[3] = new Cell(0,6, Tetris.I); //共有两种旋转状态 states =new State[2]; //初始化两种状态的相对坐标 states[0]=new State(0,0,0,-1,0,1,0,2); states[1]=new State(0,0,-1,0,1,0,2,0); } }
public class J extends Tetromino { public J() { cells[0] = new Cell(0,4, Tetris.J); cells[1] = new Cell(0,3, Tetris.J); cells[2] = new Cell(0,5, Tetris.J); cells[3] = new Cell(1,5, Tetris.J); states=new State[4]; states[0]=new State(0,0,0,-1,0,1,1,1); states[1]=new State(0,0,-1,0,1,0,1,-1); states[2]=new State(0,0,0,1,0,-1,-1,-1); states[3]=new State(0,0,1,0,-1,0,-1,1); } }
public class L extends Tetromino { public L() { cells[0] = new Cell(0,4, Tetris.L); cells[1] = new Cell(0,3, Tetris.L); cells[2] = new Cell(0,5, Tetris.L); cells[3] = new Cell(1,3, Tetris.L); states=new State[4]; states[0]=new State(0,0,0,-1,0,1,1,-1); states[1]=new State(0,0,-1,0,1,0,-1,-1); states[2]=new State(0,0,0,1,0,-1,-1,1); states[3]=new State(0,0,1,0,-1,0,1,1); } }
public class O extends Tetromino { public O() { cells[0] = new Cell(0, 4, Tetris.O); cells[1] = new Cell(0, 5, Tetris.O); cells[2] = new Cell(1, 4, Tetris.O); cells[3] = new Cell(1, 5, Tetris.O); //无旋转状态 states = new State[0]; } }
public class S extends Tetromino { public S() { cells[0] = new Cell(0,4, Tetris.S); cells[1] = new Cell(0,5, Tetris.S); cells[2] = new Cell(1,3, Tetris.S); cells[3] = new Cell(1,4, Tetris.S); //共有两种旋转状态 states =new State[2]; //初始化两种状态的相对坐标 states[0]=new State(0,0,0,1,1,-1,1,0); states[1]=new State(0,0,1,0,-1,-1,0,-1); } } 
public class T extends Tetromino { public T() { cells[0] = new Cell(0,4, Tetris.T); cells[1] = new Cell(0,3, Tetris.T); cells[2] = new Cell(0,5, Tetris.T); cells[3] = new Cell(1,4, Tetris.T); states=new State[4]; states[0]=new State(0,0,0,-1,0,1,1,0); states[1]=new State(0,0,-1,0,1,0,0,-1); states[2]=new State(0,0,0,1,0,-1,-1,0); states[3]=new State(0,0,1,0,-1,0,0,1); } }
public class Z extends Tetromino { public Z() { cells[0] = new Cell(1,4, Tetris.Z); cells[1] = new Cell(0,3, Tetris.Z); cells[2] = new Cell(0,4, Tetris.Z); cells[3] = new Cell(1,5, Tetris.Z); //共有两种旋转状态 states =new State[2]; //初始化两种状态的相对坐标 states[0]=new State(0,0,-1,-1,-1,0,0,1); states[1]=new State(0,0,-1,1,0,1,1,0); } } 

俄罗斯方块游戏主类:Tetris

public class Tetris extends JPanel { //正在下落的方块 private Tetromino currentOne = Tetromino.randomOne(); //将要下落的方块 private Tetromino nextOne = Tetromino.randomOne(); //游戏主区域 private Cell[][] wall = new Cell[18][9]; //声明单元格的值 private static final int CELL_SIZE = 48; //游戏分数池 int[] scores_pool = {0, 1, 2, 5, 10}; //当前游戏的分数 private int totalScore = 0; //当前消除的行数 private int totalLine = 0; //游戏三种状态 游戏中、暂停、结束 public static final int PLING = 0; public static final int STOP = 1; public static final int OVER = 2; //当前游戏状态值 private int game_state; //显示游戏状态 String[] show_state = {"P[pause]", "C[continue]", "S[replay]"}; //载入方块图片 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 background; 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")); background = ImageIO.read(new File("images/background.png")); } catch (IOException e) { e.printStackTrace(); } } @Override public void paint(Graphics g) { g.drawImage(background, 0, 0, null); //平移坐标轴 g.translate(22, 15); //绘制游戏主区域 paintWall(g); //绘制正在下落的四方格 paintCurrentOne(g); //绘制下一个将要下落的四方格 paintNextOne(g); //绘制游戏得分 paintSource(g); //绘制当前游戏状态 paintState(g); } public void start() { game_state = PLING; KeyListener l = new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { int code = e.getKeyCode(); switch (code) { case KeyEvent.VK_DOWN: sortDropActive(); break; case KeyEvent.VK_LEFT: moveleftActive(); break; case KeyEvent.VK_RIGHT: moveRightActive(); break; case KeyEvent.VK_UP: rotateRightActive(); break; case KeyEvent.VK_SPACE: hadnDropActive(); break; case KeyEvent.VK_P: //判断当前游戏状态 if (game_state == PLING) { game_state = STOP; } break; case KeyEvent.VK_C: if (game_state == STOP) { game_state = PLING; } break; case KeyEvent.VK_S: //重新开始 game_state = PLING; wall = new Cell[18][9]; currentOne = Tetromino.randomOne(); nextOne = Tetromino.randomOne(); totalScore = 0; totalLine = 0; break; } } }; //将窗口设置为焦点 this.addKeyListener(l); this.requestFocus(); while (true) { if (game_state == PLING) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } if (camDrop()) { currentOne.moveDrop(); } else { landToWall(); destroyLine(); if (isGameOver()) { game_state = OVER; } else { //游戏没有结束 currentOne = nextOne; nextOne = Tetromino.randomOne(); } } } repaint(); } } //创建顺时针旋转 public void rotateRightActive() { currentOne.rotateRight(); if (outOFBounds() || coincide()) { currentOne.rotateLeft(); } } //瞬间下落 public void hadnDropActive() { while (true) { //判断能否下落 if (camDrop()) { currentOne.moveDrop(); } else { break; } } //嵌入到墙中 landToWall(); destroyLine(); if (isGameOver()) { game_state = OVER; } else { //游戏没有结束 currentOne = nextOne; nextOne = Tetromino.randomOne(); } } //按键一次,下落一格 public void sortDropActive() { if (camDrop()) { //当前四方格下落一格 currentOne.moveDrop(); } else { landToWall(); destroyLine(); if (isGameOver()) { game_state = OVER; } 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 camDrop() { 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; } //判断当前行是否已经满了 public boolean isFullLine(int row) { Cell[] cells = wall[row]; for (Cell cell : cells) { if (cell == null) { return false; } } return true; } //判断游戏是否结束 public 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; } private void paintState(Graphics g) { if (game_state == PLING) { g.drawString(show_state[PLING], 500, 660); } else if (game_state == STOP) { g.drawString(show_state[STOP], 500, 660); } else { g.drawString(show_state[OVER], 500, 660); g.setColor(Color.RED); g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 60)); g.drawString("GAME OVER!", 30, 400); } } private void paintSource(Graphics g) { g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 30)); g.drawString("分数: " + totalScore, 500, 250); g.drawString("行数: " + totalLine, 500, 430); } 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 boolean outOFBounds() { Cell[] cells = currentOne.cells; for (Cell cell : cells) { int col = cell.getCol(); int row = cell.getRow(); if (row < 0 || row > wall.length - 1 || col < 0 || col > wall[0].length-1) { return true; } } return false; } //按键一次,左移一次 public void moveleftActive() { currentOne.moveLeft(); //判断是否越界或重合 if (outOFBounds() || coincide()) { currentOne.moveRight(); } } //按键一次,右移一次 public void moveRightActive() { currentOne.moveRight(); //判断是否越界或重合 if (outOFBounds() || coincide()) { currentOne.moveLeft(); } } //判断是否重合 public boolean coincide() { Cell[] cells = currentOne.cells; for (Cell cell : cells) { int row = cell.getRow(); int col = cell.getCol(); if (wall[row][col] != null) { return true; } } return false; } public static void main(String[] args) { JFrame jFrame = new JFrame("俄罗斯方块"); //创建游戏界面 Tetris panel = new Tetris(); jFrame.add(panel); //设置可见 jFrame.setVisible(true); //设置窗口大小 jFrame.setSize(810, 940); //设置剧中 jFrame.setLocationRelativeTo(null); //设置窗口关闭时停止 jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //游戏主要开始逻辑 panel.start(); } }

三、效果展示

游戏开始,方快下落,右边区域展示即将下落的方块图、分数、消除的行数以及游戏切换的状态。

Java实现俄罗斯方块小游戏。(附完整源代码)

按下空格键,方块瞬间下落, 按下P键游戏暂停,消除一行分数为1(此处由分数池进行控制)

Java实现俄罗斯方块小游戏。(附完整源代码)

按下C键游戏继续。

Java实现俄罗斯方块小游戏。(附完整源代码)

按下S键,游戏重新开始。

Java实现俄罗斯方块小游戏。(附完整源代码)

方块占满,游戏结束,此时可以按下S键重新开始游戏。

Java实现俄罗斯方块小游戏。(附完整源代码)

本次游戏中所使用的素材文件以及所有的源代码文件都已经同步到Github,小伙伴们点击下方链接直接获取。

Github链接地址:点击获取完整源代码,下载到本地即可运行Java实现俄罗斯方块小游戏。(附完整源代码)https://github.com/xiaoZ-zhao/Tetris

Gitee地址:Tetris: 【开箱即用】使用Java实现俄罗斯方块,开发工具idea - Gitee.comJava实现俄罗斯方块小游戏。(附完整源代码)https://gitee.com/xiaoZcode/Tetris/tree/master

Java实现俄罗斯方块小游戏。(附完整源代码)

  • 海报
海报图正在生成中...
赞(0) 打赏
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
文章名称:《Java实现俄罗斯方块小游戏。(附完整源代码)》
文章链接:https://www.456zj.com/36749.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址