这个是简单俄罗斯方块的java实现
代码:
package cn.hncu.tetris;
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 java.util.Calendar;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Tetris extends JFrame{
private MyPanel gamePanel;
public Tetris() {
super("dragon版 俄罗斯方块");
setSize(200, 275);
setLocationRelativeTo(this);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false); //设置大小不可变
gamePanel=new MyPanel();
getContentPane().add(gamePanel);
addKeyListener(gamePanel.getListener());
setVisible(true);
}
public static void main(String[] args) {
new Tetris();
}
}
class MyPanel extends JPanel{
private int map[][]=new int[13][23]; //游戏框架,实际为21行,10列(2列一行的边框),行列各预留一行防止越界
/*
* 三维数组表示产生的方块形状,
* 第一维表示种类 type
* 第二维表示变形 turnState
* 第三维表示方块矩阵(4行,4列的矩阵代表一个方块。)
* shaps[type][turnState][i] i==>[i/4][i%4]
*/
private int shaps[][][]={
/*
* {
* {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
* {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
* {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
* {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
* }
*/
// I (※把版本1中的横条从第1行换到第2行)
{ { 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 } },
// S
{ { 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, 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 } },
// Z 第3行: shapes[2][2][]
{ { 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, 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 } },
// 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 } },
// 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 } },
// 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 } }
};
private int type;
private int turnState;
private int x; //当前块的位置:列
private int y; //当前块的位置:行
private Timer timer;
private int delay;
private int score;
private TimerListener listener;
public TimerListener getListener() {
return listener;
}
public MyPanel() {
newGames();//初始化,map[][]
nextBlock();//出现随机的方块
}
private void newGames() {
for(int i=0;i<12;i++){
for(int j=0;j<22;j++){
if(i==0 || i==11 ||j==21){
map[i][j]=3; //游戏框架
}else{
map[i][j]=0;
}
}
}
//因为这个listener要加到框架上,所以可以定义为成员变量,用实例调
listener=new TimerListener();
delay=1000;
score = 0;
timer=new Timer(delay, listener);
timer.start();
}
private void nextBlock() {
type=(int) (Calendar.getInstance().getTime().getTime()%7);
turnState=(int) (Calendar.getInstance().getTime().getTime()%4);
x=4;
y=0; //初始出现位置(4,0)
//在随机出现方块之后需要 马上 进行判断是否会相撞
if(crash(x, y, type, turnState)==0){
timer.stop();
int op = JOptionPane.showConfirmDialog(this, "Game Over~ 是否在来一局");
if(op==JOptionPane.YES_OPTION){
newGames();
}else if(op==JOptionPane.NO_OPTION){
System.exit(0);
}
}
}
class TimerListener extends KeyAdapter implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
down(); //使方块下落
}
@Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_DOWN :
down();break;
case KeyEvent.VK_UP :
turn();break;
case KeyEvent.VK_LEFT :
left();break;
case KeyEvent.VK_RIGHT :
right();
}
}
}
private void down() {
// y++; 如果下落的这个位置:越界,或者与其他已经在落下的方块碰撞时,不能再落
if(crash(x,y+1,type,turnState)==0){
//如果相撞,或者越界,则把这个方块加入到map中
add(x,y,type,turnState);
//然后在随机出现一个方块
nextBlock();
}else{
y++;
}
repaint();
}
private void right() {
if(x<8){
if(crash(x+1, y, type, turnState)==1){
x++;
repaint();
}
}
}
private void left() {
if(x>=0){
if(crash(x-1, y, type, turnState)==1){
x--;
repaint();
}
}
}
private void turn() {
if(crash(x, y, type, (turnState+1)%4)==1){
//如果下一个要变化的形状,不会相撞则可以变化
turnState=(turnState+1)%4;
repaint();
}
}
private int crash(int x, int y, int type, int turnState) {
for(int i=0;i<4;i++){ //表示行
for(int j=0;j<4;j++){ //表示列
if( (map[x+1+j][y+i] & shaps[type][turnState][i*4+j] ) == 1){
//当shapes为1 map为1或者3 时,表示相撞、或者越界(超过下边框)
return 0;
}
}
}
return 1;
}
private void add(int x, int y, int type, int turnState) {
for(int i=0;i<4;i++){ //行号
for(int j=0;j<4;j++){ //列号
if(shaps[type][turnState][i*4+j]==1){
map[x+1+j][y+i]=1;
}
}
}
//每次添加一个,判断一下是否可以消除一行。
tryDelLine();
}
private void tryDelLine() {
for(int i=0;i<21;i++){
boolean boo=true;
for(int j=0;j<11;j++){
if(map[j][i]!=1 && map[j][i]!=3){
//只有当一行都不是方块,或者框架的时候才是能消除的
boo=false;
}
}
if(boo){
//如果能消除,则需要把这一行以上的每一行都往下移动一行
for(int j=i;j>0;j--){
for(int k=0;k<11;k++){
map[k][j]=map[k][j-1];
}
}
if(delay>200){
delay=delay-100;
}
score+=10;
}
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
//画出框架==>相当于初始化map[][]
for(int i=0;i<12;i++){
for(int j=0;j<22;j++){
if(map[i][j]==3){
g.setColor(Color.red);
g.drawRect(i*10, j*10, 10, 10);
}
if(map[i][j]==1){
g.setColor(Color.red);
g.fillRect(i*10, j*10, 10, 10);
g.setColor(Color.yellow);
g.drawRect(i*10, j*10, 10, 10);
}
}
}
//画出当前出现的方块
//下面这样写就写死了。
// int type=3; int turnSate=2; int x=4; int y=5;
for(int i=0;i<16;i++){
if(shaps[type][turnState][i]==1){
g.fillRect((x+1+i%4)*10, (y+i/4)*10, 10, 10);
}
}
g.setColor(Color.black);
g.setFont(new Font("aa", Font.BOLD, 15));
g.drawString("Socre:"+score, 125, 20);
g.drawString("当前速度:"+delay/1000+"秒每行", 125, 50);
g.drawString(delay*1.0/1000+"秒每行", 125, 80);
}
}