Java课程设计------俄罗斯方块(Tetris)

俄罗斯方块

相信大家从小就玩过俄罗斯方块的,多余的话就不多说了,代码是有生命的,就让代码来说话好了

[java]  view plain  copy
  1. package cn.hncu.games;  
  2.   
  3. import java.awt.Color;  
  4. import java.awt.Font;  
  5. import java.awt.Graphics;  
  6. import java.awt.HeadlessException;  
  7. import java.awt.event.ActionEvent;  
  8. import java.awt.event.ActionListener;  
  9. import java.awt.event.KeyAdapter;  
  10. import java.awt.event.KeyEvent;  
  11.   
  12. import javax.swing.JFrame;  
  13. import javax.swing.JMenu;  
  14. import javax.swing.JMenuBar;  
  15. import javax.swing.JMenuItem;  
  16. import javax.swing.JOptionPane;  
  17. import javax.swing.JPanel;  
  18. import javax.swing.Timer;  
  19.   
  20. public class Tetris extends JFrame {  
  21.     private TetrisPanel a;  
  22.     private JMenuItem j1,j2,j3;  
  23.       
  24.     public Tetris() {  
  25.         // 添加菜单,此处仅示意技术,不写完善  
  26.         JMenuBar menubar = new JMenuBar();  
  27.         setJMenuBar(menubar);  
  28.         // 菜单  
  29.         JMenu menuGame = new JMenu("游戏");  
  30.         menubar.add(menuGame);  
  31.   
  32.         // 菜单项  
  33.         j1 = new JMenuItem("新游戏");  
  34.         j1.setActionCommand("newGame");  
  35.         menuGame.add(j1);  
  36.         j2 = new JMenuItem("暂停");  
  37.         j2.setActionCommand("pause");  
  38.         menuGame.add(j2);  
  39.         j3 = new JMenuItem("继续");  
  40.         j3.setActionCommand("resume");  
  41.         menuGame.add(j3);  
  42.           
  43.         // 菜单项监听  
  44.         MenuListener ml = new MenuListener();  
  45.         j1.addActionListener(ml);  
  46.         j2.addActionListener(ml);  
  47.         j3.addActionListener(ml);  
  48.           
  49.         //另一种添加方式  
  50.         menuGame.add("其它").addActionListener(ml);  
  51.           
  52.           
  53.         // 为了在菜单监听器类中访问a对象,提升作用域  
  54.         // TetrisPanel a = new TetrisPanel();  
  55.         a = new TetrisPanel();  
  56.         this.addKeyListener(a.listener);  
  57.         // this.add(a);正式开发不用this,运行效率更高  
  58.         add(a);  
  59.   
  60.         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  61.         setSize(220275);  
  62.         setLocation(400100);  
  63.         setTitle("俄罗斯方块精简版");  
  64.         setResizable(false);  
  65.     }  
  66.   
  67.     public static void main(String[] args) {  
  68.         Tetris te = new Tetris();  
  69.         te.setVisible(true);  
  70.     }  
  71.   
  72.     /* 
  73.      * 用面板当画布,界面刷新效果更好 
  74.      */  
  75.     class TetrisPanel extends JPanel {  
  76.         private int blockType; // 0-6 3  
  77.         private int turnState; // 0-3 2  
  78.         private int x;  
  79.         private int y;  
  80.   
  81.         private int score;  
  82.         private int delay;  
  83.   
  84.         private TimerListener listener = new TimerListener();  
  85.         private Timer timer;  
  86.   
  87.         // 定义地图,用来存放整个游戏方块区的状态(显示方格或不显示)  
  88.         // 存放块的位置:x=0~11 y=0~21  
  89.         // ----22行12列(其中一行两列是外框),行列的序号位置跟我们平时写的是相反的map[列号][行号]  
  90.         int[][] map = new int[13][23];// 为解决越界,在边上预留了1列  
  91.   
  92.         // 方块的形状:  
  93.         // 第一维代表方块类型(包括7种:S、Z、L、J、I、O、T)  
  94.         // 第二维代表旋转次数  
  95.         // 第三四维代表方块矩阵  
  96.         int shapes[][][] = new int[][][] {  
  97.         /* 
  98.          * 模板 { {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, 
  99.          * 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, 
  100.          * 0,0,0,0, 0,0,0,0} } 
  101.          */  
  102.                 // I (※把版本1中的横条从第1行换到第2行)  
  103.                 { { 0000111100000000 },  
  104.                         { 0100010001000100 },  
  105.                         { 0000111100000000 },  
  106.                         { 0100010001000100 } },  
  107.                 // S  
  108.                 { { 0011011000000000 },  
  109.                         { 0100011000100000 },  
  110.                         { 0011011000000000 },  
  111.                         { 0100011000100000 } },  
  112.                 // Z  
  113.                 { { 1100011000000000 },  
  114.                         { 0100110010000000 },  
  115.                         { 1100011000000000 },  
  116.                         { 0100110010000000 } },  
  117.                 // J  
  118.                 { { 0100010011000000 },  
  119.                         { 1000111000000000 },  
  120.                         { 1100100010000000 },  
  121.                         { 1110001000000000 } },  
  122.                 // O  
  123.                 { { 1100110000000000 },  
  124.                         { 1100110000000000 },  
  125.                         { 1100110000000000 },  
  126.                         { 1100110000000000 } },  
  127.                 // L  
  128.                 { { 1000100011000000 },  
  129.                         { 1110100000000000 },  
  130.                         { 1100010001000000 },  
  131.                         { 0010111000000000 } },  
  132.                 // T  
  133.                 { { 0100111000000000 },  
  134.                         { 0100110001000000 },  
  135.                         { 1110010000000000 },  
  136.                         { 0100011001000000 } } };  
  137.   
  138.         public TetrisPanel() {  
  139.             nextBlock();  
  140.             newGame();  
  141.         }  
  142.   
  143.         // 生成一个新的方块  
  144.         public void nextBlock() {  
  145.             // blockType和turnState两个变量即决定是什么样的方块  
  146.             // 每次新生成一个块就是产生为这两个变量产生一个新值  
  147.             blockType = (int) (Math.random() * 1000) % 7;  
  148.             turnState = (int) (Math.random() * 1000) % 4;  
  149.             x = 4;  
  150.             y = 0;  
  151.             if (crash(x, y, blockType, turnState) == 0) {  
  152.                 timer.stop();  
  153.                 int option = JOptionPane.showConfirmDialog(this,  
  154.                         "Game Over!!,还敢来吗...");  
  155.                 if (option == JOptionPane.OK_OPTION) {  
  156.                     newGame();  
  157.                 } else if (option == JOptionPane.NO_OPTION) {  
  158.                     System.exit(0);  
  159.                 }  
  160.             }  
  161.   
  162.         }  
  163.   
  164.         // 初始化地图(外框)  
  165.         public void newGame() {  
  166.             for (int i = 0; i < 12; i++) {// 5  
  167.                 for (int j = 0; j < 22; j++) {  
  168.                     map[i][j] = 0;  
  169.                     map[11][j] = map[0][j] = 3;  
  170.                 }  
  171.                 map[i][21] = 3;  
  172.             }  
  173.   
  174.             // timer = new Timer(300, listener);  
  175.             delay=1000;  
  176.             timer = new Timer(delay, listener);  
  177.             timer.start();  
  178.             score = 0;// 分数初始化为0  
  179.             nextBlock();  
  180.               
  181.             j3.setEnabled(false);//把“新游戏”菜单灭掉  
  182.             repaint();  
  183.         }  
  184.   
  185.         private void pause() {  
  186.             timer.stop();  
  187.         }  
  188.   
  189.         private void resume() {  
  190.             timer.restart();  
  191.         }  
  192.   
  193.         // 下落方法  
  194.         private void down() {  
  195.             if (crash(x, y + 1, blockType, turnState) == 0) {  
  196.                 add(x, y, blockType, turnState);  
  197.                 nextBlock();  
  198.             }  
  199.             y++;  
  200.             repaint();  
  201.         }  
  202.   
  203.         // 判断是否碰撞  
  204.         private int crash(int x, int y, int blockType, int turnState) {  
  205.             for (int a = 0; a < 4; a++) {  
  206.                 for (int b = 0; b < 4; b++) {  
  207.                     if ((shapes[blockType][turnState][a * 4 + b] & map[x + b  
  208.                             + 1][y + a]) == 1) {  
  209.                         return 0;  
  210.                     }  
  211.                 }  
  212.             }  
  213.             return 1;  
  214.         }  
  215.   
  216.         private void add(int x, int y, int blockType, int turnState) {  
  217.             for (int a = 0; a < 4; a++) {  
  218.                 for (int b = 0; b < 4; b++) {  
  219.                     if (shapes[blockType][turnState][a * 4 + b] == 1)  
  220.                         map[x + b + 1][y + a] = shapes[blockType][turnState][a  
  221.                                 * 4 + b];  
  222.                 }  
  223.             }  
  224.             tryDeline();  
  225.         }  
  226.   
  227.         private void turn() {  
  228.             turnState = (turnState + crash(x, y, blockType, (turnState + 1) % 4)) % 4;  
  229.             repaint();  
  230.         }  
  231.   
  232.         private void left() {  
  233.             if (x >= 0) {  
  234.                 x -= crash(x - 1, y, blockType, turnState);  
  235.                 repaint();  
  236.             }  
  237.         }  
  238.   
  239.         private void right() {  
  240.             if (x < 8) {  
  241.                 x += crash(x + 1, y, blockType, turnState);  
  242.                 repaint();  
  243.             }  
  244.         }  
  245.   
  246.         public void tryDeline() {  
  247.             for (int b = 0; b < 21; b++) {// b是行号  
  248.                 int c = 1;  
  249.                 for (int a = 0; a < 12; a++) {// 10列是真正的方块区,外面有两列是边界  
  250.                     c &= map[a][b];  
  251.                 } // 实心块是1,边界是3。这两者的最后一位都是1,和1&运算的结果是1  
  252.                 if (c == 1) {// 整行的格子要么是实心块,要么是边界。因为只要有一个0,&运算的结果就是0  
  253.                     // 消行  
  254.                     // 从上往下,逐行扫描,把下一行的格子依次往上移  
  255.                     for (int d = b; d > 0; d--) {  
  256.                         for (int e = 1; e < 11; e++) {  
  257.                             map[e][d] = map[e][d - 1];  
  258.                         }  
  259.                     }  
  260.                     // 游戏加分  
  261.                     score += 10;  
  262.                     delay /= 2;  
  263.                     timer.setDelay(delay);  
  264.                 }  
  265.             }  
  266.         }  
  267.   
  268.         @Override  
  269.         protected void paintComponent(Graphics g) {  
  270.             super.paintComponent(g);// 清除残影  
  271.   
  272.             // 画当前块  
  273.             g.setColor(Color.blue);  
  274.             for (int j = 0; j < 16; j++) {  
  275.                 if (shapes[blockType][turnState][j] == 1) {  
  276.                     g.fillRect((j % 4 + x + 1) * 10, (j / 4 + y) * 101010);  
  277.                 }  
  278.             }  
  279.   
  280.             g.setColor(Color.red);  
  281.             // 画地图(已经固定的方块)  
  282.             for (int j = 0; j < 22; j++) {  
  283.                 for (int i = 0; i < 12; i++) {  
  284.                     if (map[i][j] == 1) {  
  285.                         g.fillRect(i * 10, j * 101010);  
  286.                         // 让堆积块有分界线  
  287.                         g.setColor(Color.green);  
  288.                         g.drawRect(i * 10, j * 101010);  
  289.                         g.setColor(Color.red);  
  290.                     } else if (map[i][j] == 3) {  
  291.                         g.drawRect(i * 10, j * 101010);  
  292.                     }  
  293.                 }  
  294.             }  
  295.   
  296.             // 画方块区右侧部分  
  297.             g.setColor(Color.blue);  
  298.             g.setFont(new Font("aa", Font.BOLD, 18));  
  299.             g.drawString("score=" + score, 13020);  
  300.             g.setFont(new Font("aa", Font.PLAIN, 13));  
  301.             g.drawString("拒绝盗版游戏"13070);  
  302.             g.drawString("注意自我保护"13090);  
  303.             g.drawString("谨防受骗上当。"125110);  
  304.             g.drawString("适度游戏益脑,"125130);  
  305.             g.drawString("沉迷游戏伤身。"125150);  
  306.             g.drawString("合理安排时间,"125170);  
  307.             g.drawString("享受健康生活。"125190);  
  308.         }  
  309.   
  310.         class TimerListener extends KeyAdapter implements ActionListener {  
  311.             @Override  
  312.             public void actionPerformed(ActionEvent e) {  
  313.                 down();  
  314.             }  
  315.   
  316.             @Override  
  317.             public void keyPressed(KeyEvent e) {  
  318.                 int keyCode = e.getKeyCode();  
  319.                 switch (keyCode) {  
  320.                 case KeyEvent.VK_DOWN:  
  321.                     down();  
  322.                     break;  
  323.                 case KeyEvent.VK_UP:  
  324.                     turn();  
  325.                     break;  
  326.                 case KeyEvent.VK_LEFT:  
  327.                     left();  
  328.                     break;  
  329.                 case KeyEvent.VK_RIGHT:  
  330.                     right();  
  331.   
  332.                 }  
  333.             }  
  334.   
  335.         }  
  336.   
  337.     }  
  338.   
  339.     class MenuListener implements ActionListener {  
  340.         @Override  
  341.         public void actionPerformed(ActionEvent e) {  
  342.             if (e.getActionCommand().equals("newGame")) {  
  343.                 a.newGame();  
  344.             } else if (e.getActionCommand().equals("pause")) {  
  345.                 a.pause();  
  346.                 j2.setEnabled(false);  
  347.                 j3.setEnabled(true);  
  348.                   
  349.             } else if (e.getActionCommand().equals("resume")) {  
  350.                 a.resume();  
  351.                 j3.setEnabled(false);  
  352.                 j2.setEnabled(true);  
  353.             }  
  354.         }  
  355.   
  356.     }  
  357. }  


你可能感兴趣的:(java,图形界面,俄罗斯方块)