import sun.audio.*;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
/**
* Description:a simple tetric game
* <br/>Program Name:Tetric Game
* <br/>Date:2012.08.24
* @author  Garth   http://xiaojia.me
* @version  1.0
*/
@SuppressWarnings("serial")
public class TetricGame extends JFrame{
    
    public static void main(String[] args){
        final TetricBlock tetricBlock = new TetricBlock();
        final TetricGame tetricGame = new TetricGame();
        
        //工具栏按钮动作
        Action startAction = new AbstractAction("start" , 
                new ImageIcon(TetricGame.class.getClassLoader().getResource("res/start.png"))) {
            public void actionPerformed(ActionEvent e) {
                tetricBlock.setIsGaming(true);
                tetricGame.requestFocus();
            }
        };
        Action pauseAction = new AbstractAction("pause" , 
                new ImageIcon(TetricGame.class.getClassLoader().getResource("res/pause.png"))) {
            public void actionPerformed(ActionEvent a) {
                tetricBlock.setIsGaming(false);
                tetricGame.requestFocus();
            }
        };
        Action aboutAction = new AbstractAction("about" , 
                new ImageIcon(TetricGame.class.getClassLoader().getResource("res/about.png"))) {
            public void actionPerformed(ActionEvent e) {
                tetricBlock.setIsGaming(false);
                JOptionPane.showMessageDialog(null , "Java新手练习项目:俄罗斯方块\n" +
                		"作者:Garth\n" +
                        "博客:http://xiaojia.me");
                tetricBlock.setIsGaming(true);
                tetricGame.requestFocus();
            }
        };
        Action closeAction = new AbstractAction("close" , 
                new ImageIcon(TetricGame.class.getClassLoader().getResource("res/close.png"))) {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        };
        JToolBar jtb = new JToolBar();
        //工具栏垂直并不可拖动
        jtb.setOrientation(JToolBar.VERTICAL);
        jtb.setFloatable(false);
        jtb.add(startAction);
        jtb.add(pauseAction);
        jtb.add(aboutAction);
        jtb.add(closeAction);
        
        tetricGame.add(jtb , BorderLayout.EAST);
        tetricGame.add(tetricBlock);
        tetricGame.addKeyListener(tetricBlock);
        tetricGame.setSize( 323 , 474);
        tetricGame.setLocationRelativeTo(null);
        tetricGame.setTitle("俄罗斯方块");
        tetricGame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        tetricGame.setVisible(true);
        //必不可少的一句,让主窗口获得焦点以监听键盘
        tetricGame.requestFocus();
    }
}

//方块类,继承JPanel类,实现KeyListener接口
@SuppressWarnings("serial")
class TetricBlock extends JPanel  implements KeyListener{
    
    //游戏得分
    private int score = 0;
    //方块下落的时间触发器
    private Timer timer;
    //方块下落速度值,值越小,速度越快
    private int speed = 1000;
    //游戏状态
    private boolean isGaming = true;
    //背景音乐
    private MusicPlayer bkMusic;
    //正在移动的方块坐标
    private int x , y;
    //方块类型与状态
    private int blockType , blockState;
    private int i = 0 , j = 0;
    //已经下落固定的方块map,0-11 ,0-21
    private int[][] map = new int[13][23];
    //方块,一维代表类型,二维代表状态,三维代表组成方块矩阵
    private final int[][][] block = new int[][][] {
            {   //一横一竖
                { 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 },
                { 1,0,0,0 , 1,1,0,0 , 0,1,0,0 , 0,0,0,0 },
                { 0,0,1,1 , 0,1,1,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,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 }
            },
            {   //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 }
            },
            {   //T型
                { 1,1,1,0 , 0,1,0,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 },
                { 0,1,0,0 , 1,1,1,0 , 0,0,0,0 , 0,0,0,0 },
                { 1,0,0,0 , 1,1,0,0 , 1,0,0,0 , 0,0,0,0 }
            }
    };
    
    public TetricBlock() {
      
        newBlock();
        newMap();
        drawWall();
        timer = new Timer( speed , new TimerListener() );
        timer.start();
    }

    //设置游戏状态
    public void setIsGaming(boolean is) {
        isGaming = is;
    }
    //画围墙
    public void drawWall(){
        
        //底部围墙
        for(i = 0 ; i < 12 ; i ++) {
            map[i][21] = 2;
        }
        //两边的围墙
        for(i = 0 ; i < 22 ; i++) {
            map[0][i] = 2;
            map[11][i] = 2;
        }
    }

    //初始化数组
    public void newMap(){
        
        for(i = 0 ; i < 12 ; i++) {
            for(j = 0 ; j < 22 ; j++) {
                map[i][j] = 0;
            }
        }
      //循环播放背景音乐
        try {
            bkMusic = new MusicPlayer(TetricGame.class.getClassLoader().getResource("res/background.wav"));
            bkMusic.loop();
        }
        catch(Exception e) {
        }
    }

    //产生新的方块
    public void newBlock(){
        
        blockType = (int) (( Math.random() * 1000 ) % 7 );
        blockState = (int) (( Math.random() * 1000) % 4 );
        x = 4;
        y = 0;
        if(gameOver(x , y)){
            JOptionPane.showMessageDialog(null, "Game Over! Score: " + score);
            newMap();
            drawWall();
            score = 0;
            speed = 1000;
            timer.setDelay(speed);
            isGaming = true;
        }
    }
    
    //判断移动方块是否合法
    public boolean canMove( int x , int y , int blockType , int blockState ) {
        
        for( i = 0 ; i < 4 ; i++)
            for( j = 0 ; j < 4 ; j++) 
                if(( block[blockType][blockState][ i * 4 + j ] == 1 &&
                        map[ j + x + 1][ i + y ] == 1 ) ||
                        ( block[blockType][blockState][ i * 4 + j ] == 1 &&
                        map[ j + x + 1][ i + y ] == 2 )) 
                    return false;
        return true;
    }
    
    //判断游戏是否结束
    public boolean gameOver( int x , int y ) {
        
        if( !canMove( x , y , blockType , blockState ) ) {
            isGaming = false;
            //播放音乐
            try {
                bkMusic.stopLoop();
                new MusicPlayer(TetricGame.class.getClassLoader().getResource("res/gameover.wav")).start();
            }
            catch(Exception e) {
            }
            return true;
        }
        return false;
    }
    
    //方块左移
    public void moveLeft() {
        
        if( isGaming && canMove( x - 1 , y , blockType , blockState ))
            x--;
        repaint();
    }
    
    //方块向右移
    public void moveRight() {
        
        if( isGaming && canMove( x + 1 , y , blockType , blockState ))
            x++;
        repaint();
    }
    
    //方块向下移
    public void moveDown() {
        
        if( isGaming ) {
            if( canMove( x , y + 1 , blockType , blockState) ) {
                y++;
                dellLine();
            }
            else {
                addBlock( x , y , blockType , blockState );
                dellLine();
                newBlock();
            }
            repaint();
        }
    }
    
    //改变方块状态
    public void turnState() {
        if( isGaming ) {
            int tempState = blockState;
            blockState = ( blockState + 1 ) % 4;
            if( !canMove( x , y , blockType , blockState ) )
                blockState = tempState;
            repaint();
        }
    }
    
    //把不能再继续下落的方块加到固定方块里
    public void addBlock( int x , int y , int blockType , int blockState ) {
        
        try {
            new MusicPlayer(TetricGame.class.getClassLoader().getResource("res/addblock.wav")).start();
        }
        catch(Exception e){
        }
        int k = 0;
        for( i = 0 ; i < 4 ; i++){
            for( j = 0 ; j < 4 ; j++) {
                if(map[ j + x + 1 ][ i + y ] == 0) {
                    map[ j + x + 1 ][ i + y ] = block[blockType][blockState][k];
                }
                k++;
            }
        }
    }
    
    //消行
    public void dellLine() {
        int k = 0;
        for( i = 0 ; i < 22 ; i++ ) {
            for( j = 0 ; j < 12 ; j++ ) {
                if( map[j][i] == 1) {
                    k++;
                    if( k >= 10 ) {
                        //播放声音
                        try {
                            new MusicPlayer(TetricGame.class.getClassLoader().getResource("res/delline.wav")).start();
                        }
                        catch(Exception e) {
                        }
                        //游戏分数添加分数
                        score += 10;
                        //速度越来越快
                        speed -= 15;
                        timer.setDelay( speed );
                        //消行后,把上面固定的方块下移
                        for( int a = i ; a > 0 ; a--) 
                            for( int b = 0 ; b < 11 ; b++ ) {
                                map[b][a] = map[b][a - 1];
                            }
                    }
                }
            }
            k = 0;
        }
        repaint();
    }
    
    public void paintComponent(Graphics g) {
        
        super.paintComponent(g);
        //方块图像
        Image blockImage = null;
        try{
            blockImage = ImageIO.read(TetricGame.class.getClassLoader().getResource("res/block.png"));
        }
        catch (IOException e){
            e.printStackTrace();
        }
        //正在下落的方块
        for(i = 0 ; i < 16 ; i++) {
            if( block[blockType][blockState][i] == 1 ) {
                g.drawImage(blockImage, ((i % 4) + x + 1) * 20 , ((i / 4) + y) * 20,20,20 ,null);
            }
        }
        
        //已经下落的固定的方块以及围墙
        for(i = 0 ; i < 22 ; i++)
            for(j = 0 ; j < 12 ; j++) {
                if(map[j][i] == 1)
                    g.drawImage(blockImage , j * 20 , i * 20 , 20 , 20 , null);
                
                if(map[j][i] == 2) {
                    g.setColor(new Color(9 , 106 , 187));
                    g.fillRect(j * 20 , i * 20 , 20 , 20);
                }
            }
    }
    
    //监听键盘上下左右方向键
    public void keyPressed(KeyEvent e){
        switch( e.getKeyCode() ) {
            case KeyEvent.VK_UP:
                turnState();
                break;
            case KeyEvent.VK_DOWN:
                moveDown();
                break;
            case KeyEvent.VK_LEFT:
                moveLeft();
                break;
            case KeyEvent.VK_RIGHT:
                moveRight();
                break;
        }
    }

    public void keyReleased(KeyEvent arg0){
    }

    public void keyTyped(KeyEvent arg0){
    }
    
    //内部类,时间监听器
    class TimerListener implements ActionListener{

        public void actionPerformed(ActionEvent e){
            repaint();
            moveDown();
        }
    }
    
    //内部类,音乐播放器
    class MusicPlayer{
        //单次播放的声音
        private AudioStream as = null;
        //循环播放的声音
        private ContinuousAudioDataStream cas = null;
        
        public MusicPlayer(URL url) {
            try {
                as = new AudioStream(url.openStream());
            }
            catch(Exception e) {
                
            }
        }
        //播放单次声音
        public void start() {
            if(as != null) {
                AudioPlayer.player.start(as);
            }
        }
        //停止单次播放的声音
        public void stop() {
            if(as != null) {
                AudioPlayer.player.stop(as);
            }
        }
        //循环播放声音
        public void loop() {
            AudioData data = null;
            try {
                data = as.getData();
            }
            catch(Exception e) {
                
            }
            if(data != null) {
                cas = new ContinuousAudioDataStream(data);
                AudioPlayer.player.start(cas);
            }
            
        }
        //停止循环播放的声音
        public void stopLoop() {
            if(cas != null) {
                AudioPlayer.player.stop(cas);
            }
        }
    }
}
最近下载更多
1112WHQ  LV7 2023年11月3日
caohanren  LV11 2022年12月9日
voiuoi  LV1 2021年3月6日
qazzaq123  LV20 2021年2月4日
薛成志  LV6 2020年7月27日
15239707080  LV3 2020年6月28日
77329TT  LV21 2020年6月12日
一笑奈何兄  LV13 2020年6月9日
chen519168  LV9 2020年6月1日
落笙520  LV1 2020年4月1日
最近浏览更多
dawang  LV2 3月15日
ClydeSon  LV5 2023年12月27日
微信网友_6784965344677888 2023年12月19日
暂无贡献等级
一眼丁真  LV1 2023年12月16日
1112WHQ  LV7 2023年11月3日
微信网友_6699076084797440  LV7 2023年10月30日
大白8加3  LV1 2023年8月18日
lmml2307831267  LV2 2023年6月25日
小安同学  LV7 2023年5月11日
微信网友_6268131861106688  LV5 2022年12月21日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友