使用java实现一个俄罗斯方块游戏

发布时间:2021-05-24 18:06:22 作者:Leah
来源:亿速云 阅读:127

本篇文章为大家展示了使用java实现一个俄罗斯方块游戏,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

键盘操作:

左键:左移; 右键:右移;
上键:变换造型 下键:加速下掉(没毛病吧,没有继续整)

任意一行的方块满格,这一行就消除,消除一行方块得10分,目前小主我还没有设置关卡,各位喜欢的宝宝们可以自己设置关卡哦;

那么那些方块的造型到底从哪里来的呢,那就是我们自己设计的,常见的几种造型就是:I型,T型,L型,田字格型等等吧,自己个加呗!
那么到底咋整的咧?其实啊就是一个4*4的数组,当然了你开心设计n*n也可以,你牛皮你说了算!
那么下面举了一个例子,用来告诉你们为啥你们看见的造型可以变换的原因就是这样提前设计好,0为空,1为填充格,这样你就可以在你的游戏里面凹造型了!

使用java实现一个俄罗斯方块游戏

算了:直接放图先看代码运行结果吧:

使用java实现一个俄罗斯方块游戏

喜欢吗?喜欢就直接做吧,可能代码写的不够好,请各位大神多多包涵,我回头也会多总结,会不断更新代码的;

GamePanel类:游戏界面类,整个方块掉落和显示,游戏的逻辑斯洛都在这个类里面实现;

package tetris;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;

public class GamePanel extends JPanel implements KeyListener{
 private int mapRow = 21;
 private int mapCol = 12;
 private int mapGame[][] = new int[mapRow][mapCol];//开辟一个二维数组空间,用来存放我们的地图信息

 private Timer timer;
 private int score = 0;//记录成绩
 Random random = new Random();
 private int curShapeType = -1;
 private int curShapeState = -1;//设置当前的形状类型和当前的形状状态
 private int nextShapeType = -1;
 private int nextShapeState = -1;//设置下一次出现的方块组的类型和状态

 private int posx = 0;
 private int posy = 0;

 private final int shapes[][][] = new int[][][]{
 //T字形按逆时针的顺序存储
 {
 {0,1,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0},
 {0,1,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0},
 {1,1,1,0, 0,1,0,0, 0,0,0,0, 0,0,0,0},
 {0,1,0,0, 0,1,1,0, 0,1,0,0, 0,0,0,0}
 },
 //I字形按逆时针的顺序存储
 {
 {0,0,0,0, 1,1,1,1, 0,0,0,0, 0,0,0,0},
 {0,1,0,0, 0,1,0,0, 0,1,0,0, 0,1,0,0},
 {0,0,0,0, 1,1,1,1, 0,0,0,0, 0,0,0,0},
 {0,1,0,0, 0,1,0,0, 0,1,0,0, 0,1,0,0}
 },
 //倒Z形按逆时针的顺序存储
 {
 {0,1,1,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
 {1,0,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0},
 {0,1,1,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
 {1,0,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0}
 },
 //Z形按逆时针的顺序存储
 {
 {1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0},
 {0,1,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0},
 {1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0},
 {0,1,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0}
 },
 //J字形按逆时针的顺序存储
 {
 {0,1,0,0, 0,1,0,0, 1,1,0,0, 0,0,0,0},
 {1,1,1,0, 0,0,1,0, 0,0,0,0, 0,0,0,0},
 {1,1,0,0, 1,0,0,0, 1,0,0,0, 0,0,0,0},
 {1,0,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0}
 },
 //L字形按逆时针的顺序存储
 {
 {1,0,0,0, 1,0,0,0, 1,1,0,0, 0,0,0,0},
 {0,0,1,0, 1,1,1,0, 0,0,0,0, 0,0,0,0},
 {1,1,0,0, 0,1,0,0, 0,1,0,0, 0,0,0,0},
 {1,1,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0}
 },
 //田字形按逆时针的顺序存储
 {
 {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
 {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
 {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
 {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0}
 }
 };
 private int rowRect = 4;
 private int colRect = 4;//这里我们把存储的图像看成是一个4*4的二维数组,虽然在上面我们采用一维数组来存储,但实际还是要看成二维数组来实现
 private int RectWidth = 10;

 public GamePanel()//构造函数----创建好地图
 {
 CreateRect();
 initMap();//初始化这个地图
 SetWall();//设置墙
// CreateRect();
 timer = new Timer(500,new TimerListener());
 timer.start();
 }

 class TimerListener implements ActionListener{
 public void actionPerformed(ActionEvent e)
 {
 MoveDown();
 }
 }

 public void SetWall()//第0列和第11列都是墙,第20行也是墙
 {
 for(int i = 0; i < mapRow; i++)//先画列
 {
 mapGame[i][0] = 2;
 mapGame[i][11] = 2;
 }
 for(int j = 1; j < mapCol-1; j++)//画最后一行
 {
 mapGame[20][j] = 2;
 }
 }

 public void initMap()//初始化这个地图,墙的ID是2,空格的ID是0,方块的ID是1
 {
 for(int i = 0; i < mapRow; i++)
 {
 for(int j = 0; j < mapCol; j++)
 {
 mapGame[i][j] = 0;
 }
 }
 }

 public void CreateRect()//创建方块---如果当前的方块类型和状态都存在就设置下一次的,如果不存在就设置当前的并且设置下一次的状态和类型
 {
 if(curShapeType == -1 && curShapeState == -1)//当前的方块状态都为1,表示游戏才开始
 {
 curShapeType = random.nextInt(shapes.length);
 curShapeState = random.nextInt(shapes[0].length);
 }
 else
 {
 curShapeType = nextShapeType;
 curShapeState = nextShapeState;
 }
 nextShapeType = random.nextInt(shapes.length);
 nextShapeState = random.nextInt(shapes[0].length);
 posx = 0; 
 posy = 1;//墙的左上角创建方块
 if(GameOver(posx,posy,curShapeType,curShapeState))
 {
 JOptionPane.showConfirmDialog(null, "游戏结束!", "提示", JOptionPane.OK_OPTION);
 System.exit(0);
 }
 }


 public boolean GameOver(int x, int y, int ShapeType, int ShapeState)//判断游戏是否结束
 {
 if(IsOrNoMove(x,y,ShapeType,ShapeState))
 {
 return false;
 }
 return true;
 }

 public boolean IsOrNoMove(int x, int y, int ShapeType, int ShapeState)//判断当前的这个图形是否可以移动,这里重点强调x,y的坐标是指4*4的二维数组(描述图形的那个数组)的左上角目标
 {
 for(int i = 0; i < rowRect ; i++)
 {
 for(int j = 0; j < colRect; j++)
 {
 if(shapes[ShapeType][ShapeState][i*colRect+j] == 1 && mapGame[x+i][y+j] == 1
 || shapes[ShapeType][ShapeState][i*colRect+j] == 1 && mapGame[x+i][y+j] == 2)
 {
  return false;
 }
 }
 }
 return true;
 }


 public void Turn()//旋转
 {
 int temp = curShapeState;
 curShapeState = (curShapeState+1) % shapes[0].length;
 if(IsOrNoMove(posx,posy,curShapeType,curShapeState))
 {
 }
 else
 {
 curShapeState = temp;
 }
 repaint();
 }

 public void MoveDown()//向下移动
 {
 if(IsOrNoMove(posx+1,posy,curShapeType,curShapeState))
 {
 posx++;
 }
 else
 {
 AddToMap();//将此行固定在地图中
 CheckLine();
 CreateRect();//重新创建一个新的方块
 }
 repaint();
 }

 public void MoveLeft()//向左移动
 {
 if(IsOrNoMove(posx,posy-1,curShapeType,curShapeState))
 {
 posy--;
 }
 repaint();
 }

 public void MoveRight()//向右移动
 {
 if(IsOrNoMove(posx,posy+1,curShapeType,curShapeState))
 {
 posy++;
 }
 repaint();
 }

 public void AddToMap()//固定掉下来的这一图像到地图中
 {
 for(int i = 0; i < rowRect; i++)
 {
 for(int j = 0; j < colRect; j++)
 {
 if(shapes[curShapeType][curShapeState][i*colRect+j] == 1)
 {
  mapGame[posx+i][posy+j] = shapes[curShapeType][curShapeState][i*colRect+j];
 }
 }
 }
 }

 public void CheckLine()//检查一下这些行中是否有满行的
 {
 int count = 0;
 for(int i = mapRow-2; i >= 0; i--)
 {
 count = 0;
 for(int j = 1; j < mapCol-1; j++)
 {
 if(mapGame[i][j] == 1)
 {
  count++;
 }
 else
  break;
 }
 if(count >= mapCol-2)
 {
 for(int k = i; k > 0; k--)
 {
  for(int p = 1; p < mapCol-1; p++)
  {
  mapGame[k][p] = mapGame[k-1][p];
  }
 }
 score += 10;
 i++;
 }
 }
 }

 public void paint(Graphics g)//重新绘制窗口
 {
 super.paint(g);
 for(int i = 0; i < rowRect; i++)//绘制正在下落的方块
 {
 for(int j = 0; j < colRect; j++)
 {
 if(shapes[curShapeType][curShapeState][i*colRect+j] == 1)
 {
  g.fillRect((posy+j+1)*RectWidth, (posx+i+1)*RectWidth, RectWidth, RectWidth);
 }
 }
 }
 for(int i = 0; i < mapRow; i++)//绘制地图上面已经固定好的方块信息
 {
 for(int j = 0; j < mapCol; j++)
 {
 if(mapGame[i][j] == 2)//画墙
 {
  g.drawRect((j+1)*RectWidth, (i+1)*RectWidth, RectWidth, RectWidth);
 }
 if(mapGame[i][j] == 1)//画小方格
 {
  g.fillRect((j+1)*RectWidth, (i+1)*RectWidth, RectWidth, RectWidth);
 }
 }
 }
 g.drawString("score = "+ score, 225, 15);
 g.drawString("下一个方块:", 225, 50);
 for(int i = 0; i < rowRect; i++)
 {
 for(int j = 0; j < colRect; j++)
 {
 if(shapes[nextShapeType][nextShapeState][i*colRect+j] == 1)
 {
  g.fillRect(225+(j*RectWidth), 100+(i*RectWidth), RectWidth, RectWidth);
 }
 }
 }
 }

 public void NewGame()//游戏重新开始
 {
 score = 0;
 initMap();
 SetWall();
 CreateRect();
 repaint();
 }

 public void StopGame()//游戏暂停
 {
 timer.stop();
 }

 public void ContinueGame()
 {
 timer.start();
 }

 @Override
 public void keyTyped(KeyEvent e) {

 }

 @Override
 public void keyPressed(KeyEvent e) {
 switch(e.getKeyCode())
 {
 case KeyEvent.VK_UP://上----旋转
 Turn();
 break;
 case KeyEvent.VK_DOWN://下----向下移动
 MoveDown();
 break;
 case KeyEvent.VK_LEFT://左----向左移动
 MoveLeft();
 break;
 case KeyEvent.VK_RIGHT://右----向右移动
 MoveRight();
 break;
 }

 }

 @Override
 public void keyReleased(KeyEvent e) {
 // TODO Auto-generated method stub

 }

}

GameFrame类:整个游戏的进入口,好吧,说白了就是有main()函数的类,这个类里面实现游戏界面的一些设计,你可以理解为一个小小小小的UI;

package tetris;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;

public class GameFrame extends JFrame implements ActionListener{
 private int widthFrame = 500;
 private int heightFrame = 600;
 private JMenu menuone = new JMenu("游戏");//创建一个菜单
 private JMenuItem newGame = menuone.add("重新开始");//创建一个内置菜单选项
 private JMenuItem exitGame = menuone.add("游戏退出");
 private JMenuItem stopGame = menuone.add("游戏暂停");
 private JMenuItem goOnGame = menuone.add("游戏继续");

 private JMenu menutwo = new JMenu("帮助");//创建第二个菜单
 private JMenuItem aboutGame = menutwo.add("关于游戏");
 GamePanel gamepanel = new GamePanel();

 public GameFrame()//构造函数
 {
 addKeyListener(gamepanel);
 newGame.addActionListener(this);
 exitGame.addActionListener(this);
 stopGame.addActionListener(this);
 goOnGame.addActionListener(this);
 aboutGame.addActionListener(this);

 this.add(gamepanel);

 JMenuBar menu = new JMenuBar();
 menu.add(menuone);
 menu.add(menutwo);
 this.setJMenuBar(menu);

 this.setTitle("俄罗斯方块");
 this.setBounds(50, 10, widthFrame, heightFrame);
 this.setVisible(true);
 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 }

 public void actionPerformed(ActionEvent e)
 {
 if(e.getSource() == newGame)//游戏重新开始
 {
 gamepanel.NewGame();
 }
 if(e.getSource() == exitGame)//游戏退出
 {
 System.exit(0);
 }
 if(e.getSource() == stopGame)//游戏暂停
 {
 gamepanel.StopGame();
 }
 if(e.getSource() == goOnGame)//游戏继续
 {
 gamepanel.ContinueGame();
 }
 if(e.getSource() == aboutGame)//关于游戏信息
 {
 JOptionPane.showMessageDialog(null, "左右键移动,向上建旋转", "提示", JOptionPane.OK_OPTION);
 }
 }


 public static void main(String[] args) {
 new GameFrame();
 }
}

Java有哪些集合类

Java中的集合主要分为四类:1、List列表:有序的,可重复的;2、Queue队列:有序,可重复的;3、Set集合:不可重复;4、Map映射:无序,键唯一,值不唯一。

上述内容就是使用java实现一个俄罗斯方块游戏,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. 使用pygame怎么实现一个俄罗斯方块游戏
  2. 使用pygame怎么实现俄罗斯方块游戏

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:怎么在Android中通过自定义控件实现不规则区域点击事件

下一篇:怎么在Android中利用ExpandableListView实现下拉刷新功能

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》