俄罗斯方块代码
package Game1;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Tetris extends JFrame {
public Tetris(){
TetrisPanel tetris=new TetrisPanel();
this.addKeyListener(tetris.listener);
add(tetris);
setSize(220, 275);
setLocation(400, 100);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setTitle("俄罗斯方块");
setResizable(false);
}
public static void main(String[] args) {
Tetris te=new Tetris();
te.setVisible(true);
}
class TetrisPanel extends JPanel{
private int x,y; //用来表示方块位置
private int blockType; //用来表示方块形态,如:L型,J型,Z型。。。0-6
private int turnState; //用来表示每个形态的变化方法,以下每个形态4种变化0-3
private TimeListerner listener=new TimeListerner();
private Timer timer;
private int delay;
private int score;
int map[][]=new int[13][23]; //表示地图,游戏背景
//以下用三维数组存储,第一维用取随机数来生成方块表示blockType,第二维用来表示方块旋转次数,三维代表方块矩阵
int shape[][][]=new int[][][]{
{
//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}
},
//L型方块
{
{1,0,0,0,1,0,0,0,1,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,0,1,0,0,0,1,0,0,0,0,0,0},
{0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0}
},
//S型方块
{
{ 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 }
},
//O型方块
{
{ 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 }
},
//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 }
},
//J型方块
{
{ 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 1, 1, 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, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
}
};
public TetrisPanel(){
nextBlock();
newGame();
}
public void down(){ //向下控制
if(crash(x,y+1,blockType,turnState)==0){
add( x, y, blockType, turnState);
nextBlock();
}
y++;
repaint();
}
public void upturn() { //按键上的控制(即变换形态)
turnState=(turnState+crash(x, y, blockType, (turnState+1)%4))%4;
repaint();
}
public void left(){ //左控制
if(x>=0){
x-=+crash(x-1, y, blockType, turnState);
repaint();
}
}
public void right(){ //右控制
if(x<8){
x+=crash(x+1, y, blockType, turnState);
repaint();
}
}
//判断是否碰撞
public int crash(int x,int y,int blockType,int turnState){
for(int a=0;a<4;a++){
for(int b=0;b<4;b++){
if((shape[blockType][turnState][a*4+b] & map[x+b+1][y+a])==1){
return 0;
}
}
}
return 1;
}
//把增加的方块搞到地图上面去,用表示方块形状的三维数组和地图的二维数组控制,如果碰到,则把方块此时的坐标和地图的坐标相加,得出新的值(即新的地图)
public void add(int x,int y,int blockType,int turnState){
for(int a=0;a<4;a++){
for(int b=0;b<4;b++){
if(shape[blockType][turnState][a*4+b]==1){
map[x + b + 1][y + a] = shape[blockType][turnState][a * 4 + b];
}
}
}
TryDeline();
}
private void newGame() {
for(int i=0;i<12;i++){ //初始化地图,地图看成是由12*22的方块构成
for(int j=0;j<22;j++){
map[i][j]=0;
map[11][j]=map[0][j]=3; //边界赋值3,用于下面画出边界,下面代码思想是如果map[i][j]=3,那么就画一个红色格子当分界线
}
map[i][21]=3; //此处赋值最下面一层的值
}
delay=1000; //速度初始值
timer=new Timer(delay, listener);
timer.start();
nextBlock(); //下一个方块
repaint(); //刷新地图
}
//消行的代码
private void TryDeline(){
//先遍历整个map看map中有没有一行整个都是满的,如果都是满的,那么map【a】【b】=1,与1(以下代码用的一个整形c)相&就是1;否则为0
for(int b=0;b<21;b++){ //表示多少行
int c=1;
for(int a=0;a<12;a++){ //表示每列,用来看该行是否满的格子
c&=map[a][b];
}
//以下是消除,如果满了(即c=1),就把上一行的赋给下一行,
if(c==1){
for(int d=b;d>0;d--){
for(int e=1;e<11;e++){
map[e][d]=map[e][d-1];
}
}
//以下是分数的加法和速度的变化
score+=10;
if(delay>500){
delay-=50;
}else if(delay>200){
delay-=40;
}else {
delay=200;
}
}
}
}
private void nextBlock() {
blockType=(int) (Math.random()*1000)%7; //用随机数生成新的类型
turnState=(int) (Math.random()*1000)%4; //用随机数生成新类型中的形态
x=4; //表示生成位置的X坐标
y=0; //表示生成位置的Y坐标
if (crash(x, y, blockType, turnState) == 0) {
timer.stop();
int option = JOptionPane.showConfirmDialog(this,
"Game Over!!您的最后得分是:"+score);
if (option == JOptionPane.OK_OPTION) {
newGame();
score=0;
} else if (option == JOptionPane.NO_OPTION) {
System.exit(0);
}
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.blue);
//画出当前形态
for(int j=0;j<16;j++){
if(shape[blockType][turnState][j]==1){
g.fillRect((j%4+x+1)*10,(j/4+y)*10, 10, 10);
}
}
//画地图
g.setColor(Color.red);
for(int j=0;j<22;j++){
for(int i=0;i<12;i++){
if(map[i][j]==1){
g.fillRect(i*10, j*10, 10, 10);
// 让堆积块有分界线
g.setColor(Color.green);
g.drawRect(i * 10, j * 10, 10, 10);
g.setColor(Color.red);
}else if(map[i][j]==3){
g.drawRect(i*10, j*10, 10, 10);
}
}
}
//设置界面左右边的显示界面
g.setColor(Color.blue);
g.setFont(new Font("aa", Font.BOLD, 15));
g.drawString("score="+score, 130, 20);
g.setFont(new Font("aa", Font.ITALIC,13));
g.drawString("关爱残疾人", 130, 70);
g.drawString("远离鲁阿鲁", 130, 90);
g.drawString("俄罗斯方块", 130, 110);
g.drawString("益身心健康", 130, 130);
g.drawString("防受骗上当", 130, 150);
g.drawString("这游戏益脑", 130, 170);
}
//以下是添加的键盘监听
class TimeListerner extends KeyAdapter implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
down();
}
@Override
public void keyPressed(KeyEvent e) {
int keycode=e.getKeyCode();
switch (keycode) {
case KeyEvent.VK_DOWN: //方向键下的监听
down(); //方法在上面
break;
case KeyEvent.VK_UP: //方向键上的监听
upturn(); //方法在上面
break;
case KeyEvent.VK_LEFT: //方向键左的监听
left();
break;
case KeyEvent.VK_RIGHT: //方向键右的监听
right();
break;
}
}
}
}
}